primary_display.c 286 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597
  1. #include <linux/delay.h>
  2. #include <linux/sched.h>
  3. #include <linux/semaphore.h>
  4. #include <linux/module.h>
  5. #include <linux/wait.h>
  6. #include <linux/kthread.h>
  7. #include <linux/mutex.h>
  8. #include <linux/types.h>
  9. #include <linux/ktime.h>
  10. #include <linux/of.h>
  11. #include <linux/of_irq.h>
  12. #include <linux/vmalloc.h>
  13. #include <linux/slab.h>
  14. #include <linux/switch.h>
  15. #include "disp_drv_platform.h"
  16. #include "ion_drv.h"
  17. #include "mtk_ion.h"
  18. #include "m4u.h"
  19. #include "mt_idle.h"
  20. #include "mt_spm_idle.h"
  21. #include "mt_spm.h" /* for sodi reg addr define */
  22. #define mt_eint_set_hw_debounce(eint_num, ms) (void)0
  23. /* #include <linux/rtpm_prio.h> */
  24. /* #include "mach/eint.h" */
  25. #include <mt-plat/mt_gpio.h>
  26. #ifdef CONFIG_MTK_CLKMGR
  27. #include <mach/mt_clkmgr.h>
  28. #endif
  29. #if defined(CONFIG_MTK_LEGACY)
  30. /* #include <cust_eint.h> */
  31. /* #include <cust_gpio_usage.h> */
  32. #endif
  33. #include "mtk_sync.h"
  34. #include "mtkfb.h"
  35. #include "mtkfb_fence.h"
  36. #include "disp_session.h"
  37. #include "debug.h"
  38. #include "disp_drv_log.h"
  39. #include "disp_lcm.h"
  40. #include "disp_utils.h"
  41. #include "display_recorder.h"
  42. #include "fbconfig_kdebug.h"
  43. #include "primary_display.h"
  44. #include "disp_helper.h"
  45. #include "ddp_hal.h"
  46. #include "ddp_dump.h"
  47. #include "ddp_path.h"
  48. #include "ddp_drv.h"
  49. #include "ddp_ovl.h"
  50. #include "ddp_rdma.h"
  51. #include "ddp_manager.h"
  52. #include "ddp_mmp.h"
  53. #include "ddp_reg.h"
  54. #include "ddp_debug.h"
  55. #include "ddp_irq.h"
  56. #ifndef MTK_FB_CMDQ_DISABLE
  57. #include "cmdq_def.h"
  58. #include "cmdq_record.h"
  59. #include "cmdq_reg.h"
  60. #include "cmdq_core.h"
  61. #endif
  62. #include "disp_assert_layer.h"
  63. #include "ddp_dsi.h"
  64. #include "mtk_disp_mgr.h"
  65. #include "ddp_wdma.h"
  66. #include "ddp_wdma_ex.h"
  67. #include "mt_clk_id.h"
  68. #include "mmdvfs_mgr.h"
  69. #include "mt_smi.h"
  70. #include <mach/mt_freqhopping.h>
  71. typedef void (*fence_release_callback) (unsigned int data);
  72. unsigned int is_hwc_enabled = 0;
  73. static int is_hwc_update_frame;
  74. unsigned int gEnableLowPowerFeature = 0;
  75. /* int _trigger_display_interface(int blocking, void *callback, unsigned int userdata); */
  76. int primary_display_use_cmdq = CMDQ_DISABLE;
  77. int primary_display_use_m4u = 1;
  78. #if defined(MTK_OVL_DECOUPLE_SUPPORT)
  79. DISP_PRIMARY_PATH_MODE primary_display_mode = DECOUPLE_MODE;
  80. #else
  81. DISP_PRIMARY_PATH_MODE primary_display_mode = DIRECT_LINK_MODE;
  82. #endif
  83. static unsigned long dim_layer_mva;
  84. /* wdma dump thread */
  85. static unsigned int primary_dump_wdma;
  86. static struct task_struct *primary_display_wdma_out;
  87. static unsigned long dc_vAddr[DISP_INTERNAL_BUFFER_COUNT];
  88. static disp_internal_buffer_info *decouple_buffer_info[DISP_INTERNAL_BUFFER_COUNT];
  89. static RDMA_CONFIG_STRUCT decouple_rdma_config;
  90. static WDMA_CONFIG_STRUCT decouple_wdma_config;
  91. static disp_mem_output_config mem_config;
  92. static unsigned int primary_session_id = MAKE_DISP_SESSION(DISP_SESSION_PRIMARY, 0);
  93. unsigned int ext_session_id = MAKE_DISP_SESSION(DISP_SESSION_MEMORY, 2);
  94. /* primary display uses itself's abs macro */
  95. #ifdef abs
  96. #undef abs
  97. #define abs(a) (((a) < 0) ? -(a) : (a))
  98. #endif
  99. #define FRM_UPDATE_SEQ_CACHE_NUM (DISP_INTERNAL_BUFFER_COUNT+1)
  100. static disp_frm_seq_info frm_update_sequence[FRM_UPDATE_SEQ_CACHE_NUM];
  101. static unsigned int frm_update_cnt;
  102. /* DDP_SCENARIO_ENUM ddp_scenario = DDP_SCENARIO_SUB_RDMA1_DISP; */
  103. #ifdef DISP_SWITCH_DST_MODE
  104. int primary_display_def_dst_mode = 0;
  105. int primary_display_cur_dst_mode = 0;
  106. #endif
  107. #ifdef CONFIG_OF
  108. /* extern unsigned int islcmconnected; */
  109. #endif
  110. #define ALIGN_TO(x, n) \
  111. (((x) + ((n) - 1)) & ~((n) - 1))
  112. int primary_trigger_cnt = 0;
  113. #define PRIMARY_DISPLAY_TRIGGER_CNT (1)
  114. unsigned int gEnterSodiAfterEOF = 0;
  115. unsigned int WDMA0_FRAME_START_FLAG = 0;
  116. unsigned int NEW_BUF_IDX = 0;
  117. unsigned int ALL_LAYER_DISABLE_STEP = 0;
  118. unsigned long long last_primary_trigger_time = 0xffffffffffffffff;
  119. unsigned int isIdlePowerOff = 0;
  120. unsigned int isDSIOff = 0;
  121. unsigned int gPresentFenceIndex = 0;
  122. unsigned int gTriggerDispMode = 0; /* 0: normal, 1: lcd only, 2: none of lcd and lcm */
  123. disp_ddp_path_config last_primary_config;
  124. static atomic_t DvfsIsHPM = ATOMIC_INIT(1);
  125. #ifdef CONFIG_TRUSTONIC_TRUSTED_UI
  126. static struct switch_dev disp_switch_data;
  127. #endif
  128. void enqueue_buffer(display_primary_path_context *ctx, struct list_head *head,
  129. disp_internal_buffer_info *buf)
  130. {
  131. if (ctx && head && buf)
  132. list_add_tail(&buf->list, head);
  133. /* DISPMSG("enqueue_buffer, head=0x%08x, buf=0x%08x, mva=0x%08x\n", head, buf, buf->mva); */
  134. }
  135. void reset_buffer(display_primary_path_context *ctx, disp_internal_buffer_info *buf)
  136. {
  137. if (ctx && buf)
  138. list_del_init(&buf->list);
  139. /* DISPMSG("reset_buffer, buf=0x%08x, mva=0x%08x\n", buf, buf->mva); */
  140. }
  141. disp_internal_buffer_info *dequeue_buffer(display_primary_path_context *ctx,
  142. struct list_head *head)
  143. {
  144. disp_internal_buffer_info *temp = NULL;
  145. if (ctx && head) {
  146. if (!list_empty(head)) {
  147. temp = list_entry(head->prev, disp_internal_buffer_info, list);
  148. /* DISPMSG("dequeue_buffer, head=0x%08x, buf=0x%08x, mva=0x%08x\n", head, temp, temp->mva); */
  149. list_del_init(&temp->list);
  150. if (list_empty(head))
  151. ; /* DISPMSG("after dequeue_buffer, head:0x%08x is empty\n", head); */
  152. } else {
  153. DISPMSG("list is empty, alloc new buffer\n");
  154. return NULL;
  155. }
  156. }
  157. return temp;
  158. }
  159. disp_internal_buffer_info *find_buffer_by_mva(display_primary_path_context *ctx,
  160. struct list_head *head, uint32_t mva)
  161. {
  162. disp_internal_buffer_info *buf = NULL;
  163. disp_internal_buffer_info *temp = NULL;
  164. if (ctx && head && mva) {
  165. if (!list_empty(head)) {
  166. list_for_each_entry(temp, head, list) {
  167. /* DISPMSG("find buffer: temp=0x%08x, mva=0x%08x\n", temp, temp->mva); */
  168. if (mva == temp->mva) {
  169. buf = temp;
  170. break;
  171. }
  172. }
  173. }
  174. /* DISPMSG("find buffer by mva, head=0x%08x, buf=0x%08x\n", head, buf); */
  175. }
  176. return buf;
  177. }
  178. #define pgc _get_context()
  179. static display_primary_path_context *_get_context(void)
  180. {
  181. static int is_context_inited;
  182. static display_primary_path_context g_context;
  183. if (!is_context_inited) {
  184. memset((void *)&g_context, 0, sizeof(display_primary_path_context));
  185. is_context_inited = 1;
  186. }
  187. return &g_context;
  188. }
  189. static inline int _is_mirror_mode(DISP_MODE mode)
  190. {
  191. if (mode == DISP_SESSION_DIRECT_LINK_MIRROR_MODE || mode == DISP_SESSION_DECOUPLE_MIRROR_MODE)
  192. return 1;
  193. else
  194. return 0;
  195. }
  196. static inline int _is_decouple_mode(DISP_MODE mode)
  197. {
  198. if (mode == DISP_SESSION_DECOUPLE_MODE || mode == DISP_SESSION_DECOUPLE_MIRROR_MODE)
  199. return 1;
  200. else
  201. return 0;
  202. }
  203. struct mutex esd_mode_switch_lock;
  204. static void _primary_path_esd_check_lock(void)
  205. {
  206. mutex_lock(&esd_mode_switch_lock);
  207. }
  208. static void _primary_path_esd_check_unlock(void)
  209. {
  210. mutex_unlock(&esd_mode_switch_lock);
  211. }
  212. display_primary_path_context *primary_display_path_lock(const char *caller)
  213. {
  214. dprec_logger_start(DPREC_LOGGER_PRIMARY_MUTEX, 0, 0);
  215. disp_sw_mutex_lock(&(pgc->lock));
  216. pgc->mutex_locker = (char *)caller;
  217. return pgc;
  218. }
  219. void primary_display_path_unlock(const char *caller)
  220. {
  221. pgc->mutex_locker = NULL;
  222. disp_sw_mutex_unlock(&(pgc->lock));
  223. dprec_logger_done(DPREC_LOGGER_PRIMARY_MUTEX, 0, 0);
  224. }
  225. static void _primary_path_cmd_lock(void)
  226. {
  227. mutex_lock(&(pgc->cmd_lock));
  228. }
  229. static void _primary_path_cmd_unlock(void)
  230. {
  231. mutex_unlock(&(pgc->cmd_lock));
  232. }
  233. static void _primary_path_lock(const char *caller)
  234. {
  235. dprec_logger_start(DPREC_LOGGER_PRIMARY_MUTEX, 0, 0);
  236. disp_sw_mutex_lock(&(pgc->lock));
  237. pgc->mutex_locker = (char *)caller;
  238. }
  239. static void _primary_path_unlock(const char *caller)
  240. {
  241. pgc->mutex_locker = NULL;
  242. disp_sw_mutex_unlock(&(pgc->lock));
  243. dprec_logger_done(DPREC_LOGGER_PRIMARY_MUTEX, 0, 0);
  244. }
  245. static DECLARE_WAIT_QUEUE_HEAD(display_state_wait_queue);
  246. static DISP_POWER_STATE primary_get_state(void)
  247. {
  248. return pgc->state;
  249. }
  250. static DISP_POWER_STATE primary_set_state(DISP_POWER_STATE new_state)
  251. {
  252. DISP_POWER_STATE old_state = pgc->state;
  253. pgc->state = new_state;
  254. DISPMSG("%s %d to %d\n", __func__, old_state, new_state);
  255. wake_up(&display_state_wait_queue);
  256. return old_state;
  257. }
  258. /* use MAX_SCHEDULE_TIMEOUT to wait for ever
  259. * NOTES: primary_path_lock should NOT be held when call this func !!!!!!!!
  260. */
  261. #define __primary_display_wait_state(condition, timeout) \
  262. ({ \
  263. wait_event_timeout(display_state_wait_queue, condition, timeout);\
  264. })
  265. long primary_display_wait_state(DISP_POWER_STATE state, long timeout)
  266. {
  267. long ret;
  268. ret = __primary_display_wait_state(primary_get_state() == state, timeout);
  269. return ret;
  270. }
  271. long primary_display_wait_not_state(DISP_POWER_STATE state, long timeout)
  272. {
  273. long ret;
  274. ret = __primary_display_wait_state(primary_get_state() != state, timeout);
  275. return ret;
  276. }
  277. static void _primary_path_vsync_lock(void)
  278. {
  279. mutex_lock(&(pgc->vsync_lock));
  280. }
  281. static void _primary_path_vsync_unlock(void)
  282. {
  283. mutex_unlock(&(pgc->vsync_lock));
  284. }
  285. static void _primary_path_set_dvfsHPM(bool bForcedinHPM, unsigned int needLock)
  286. {
  287. if (needLock)
  288. _primary_path_lock(__func__);
  289. if (bForcedinHPM)
  290. atomic_set(&DvfsIsHPM, 1);
  291. else
  292. atomic_set(&DvfsIsHPM, 0);
  293. if (needLock)
  294. _primary_path_unlock(__func__);
  295. }
  296. #ifdef MTK_DISP_IDLE_LP
  297. static bool _primary_path_IsForcedHPM(unsigned int needLock)
  298. {
  299. bool bResult;
  300. if (needLock)
  301. _primary_path_lock(__func__);
  302. if (atomic_read(&DvfsIsHPM) == 1)
  303. bResult = true;
  304. else
  305. bResult = false;
  306. if (needLock)
  307. _primary_path_unlock(__func__);
  308. return bResult;
  309. }
  310. #endif
  311. static void _cmdq_flush_config_handle_mira(void *handle, int blocking);
  312. #ifdef MTK_DISP_IDLE_LP
  313. static atomic_t isDdp_Idle = ATOMIC_INIT(0);
  314. static atomic_t idle_detect_flag = ATOMIC_INIT(0);
  315. static struct mutex idle_lock;
  316. static struct task_struct *primary_display_idle_detect_task;
  317. #define DISP_DSI_REG_VFP 0x28
  318. static DECLARE_WAIT_QUEUE_HEAD(idle_detect_wq);
  319. static int _disp_primary_path_idle_clock_on(unsigned int level)
  320. {
  321. dpmgr_path_idle_on(pgc->dpmgr_handle, NULL, level);
  322. return 0;
  323. }
  324. static int _disp_primary_path_idle_clock_off(unsigned int level)
  325. {
  326. dpmgr_path_idle_off(pgc->dpmgr_handle, NULL, level);
  327. return 0;
  328. }
  329. #ifdef CONFIG_SINGLE_PANEL_OUTPUT
  330. static void primary_suspend_release_present_fence(void)
  331. {
  332. int fence_increment = 0;
  333. disp_sync_info *layer_info = NULL;
  334. /* if session not created, do not release present fence*/
  335. if (pgc->session_id == 0) {
  336. DISPDBG("_get_sync_info fail in present_fence_release thread\n");
  337. return;
  338. }
  339. layer_info = _get_sync_info(pgc->session_id, disp_sync_get_present_timeline_id());
  340. if (layer_info == NULL) {
  341. DISPERR("_get_sync_info fail in present_fence_release thread\n");
  342. return;
  343. }
  344. _primary_path_lock(__func__);
  345. fence_increment = gPresentFenceIndex-layer_info->timeline->value;
  346. if (fence_increment > 0) {
  347. timeline_inc(layer_info->timeline, fence_increment);
  348. MMProfileLogEx(ddp_mmp_get_events()->present_fence_release,
  349. MMProfileFlagPulse, gPresentFenceIndex, fence_increment);
  350. }
  351. _primary_path_unlock(__func__);
  352. DISPPR_FENCE("RPF/%d/%d\n", gPresentFenceIndex, gPresentFenceIndex-layer_info->timeline->value);
  353. }
  354. #endif
  355. static DEFINE_SPINLOCK(gLockTopClockOff);
  356. static int _disp_primary_path_dsi_clock_on(unsigned int level)
  357. {
  358. if (!primary_display_is_video_mode()) {
  359. unsigned long flags;
  360. #ifndef CONFIG_MTK_CLKMGR
  361. ddp_clk_prepare(DISP_MTCMOS_CLK);
  362. #endif
  363. spin_lock_irqsave(&gLockTopClockOff, flags);
  364. isDSIOff = 0;
  365. dpmgr_path_dsi_on(pgc->dpmgr_handle, NULL, level);
  366. spin_unlock_irqrestore(&gLockTopClockOff, flags);
  367. }
  368. return 0;
  369. }
  370. static int _disp_primary_path_dsi_clock_off(unsigned int level)
  371. {
  372. if (!primary_display_is_video_mode()) {
  373. unsigned long flags;
  374. spin_lock_irqsave(&gLockTopClockOff, flags);
  375. dpmgr_path_dsi_off(pgc->dpmgr_handle, NULL, level);
  376. isDSIOff = 1;
  377. spin_unlock_irqrestore(&gLockTopClockOff, flags);
  378. #ifndef CONFIG_MTK_CLKMGR
  379. ddp_clk_unprepare(DISP_MTCMOS_CLK);
  380. #endif
  381. }
  382. return 0;
  383. }
  384. int _disp_primary_path_set_vfp(int enter)
  385. {
  386. int ret = 0;
  387. if (primary_display_is_video_mode()) {
  388. LCM_PARAMS *lcm_param = disp_lcm_get_params(pgc->plcm);
  389. cmdqRecHandle cmdq_handle_vfp = NULL;
  390. ret = cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &cmdq_handle_vfp);
  391. if (ret != 0) {
  392. DISPCHECK("fail to create primary cmdq handle for set vfp\n");
  393. return -1;
  394. }
  395. DISPCHECK("primary set vfp, handle=%p\n", cmdq_handle_vfp);
  396. cmdqRecReset(cmdq_handle_vfp);
  397. _cmdq_insert_wait_frame_done_token_mira(cmdq_handle_vfp);
  398. if (enter)
  399. dpmgr_path_ioctl(pgc->dpmgr_handle, cmdq_handle_vfp, DDP_DSI_VFP_LP,
  400. (unsigned long *)&(lcm_param->dsi.vertical_vfp_lp));
  401. else
  402. dpmgr_path_ioctl(pgc->dpmgr_handle, cmdq_handle_vfp, DDP_DSI_VFP_LP,
  403. (unsigned long *)&(lcm_param->dsi.vertical_frontporch));
  404. MMProfileLogEx(ddp_mmp_get_events()->dal_clean, MMProfileFlagPulse, 0, enter);
  405. _cmdq_flush_config_handle_mira(cmdq_handle_vfp, 1);
  406. DISPCHECK("[VFP]cmdq_handle_vfp ret=%d\n", ret);
  407. cmdqRecDestroy(cmdq_handle_vfp);
  408. cmdq_handle_vfp = NULL;
  409. } else {
  410. DISPCHECK("CMD mode don't set vfp for lows\n");
  411. }
  412. return ret;
  413. }
  414. int primary_display_save_power_for_idle(int enter, unsigned int need_primary_lock)
  415. {
  416. static unsigned int isLowPowerMode;
  417. if (is_hwc_enabled == 0)
  418. return 0;
  419. if (need_primary_lock) /* if outer api has add primary lock, do not have to lock again */
  420. _primary_path_lock(__func__);
  421. if (primary_get_state() == DISP_SLEPT) {
  422. DISPMSG("suspend mode can not enable low power.\n");
  423. goto end;
  424. }
  425. if (enter == 1 && isLowPowerMode == 1) {
  426. DISPMSG("already in low power mode.\n");
  427. goto end;
  428. }
  429. if (enter == 0 && isLowPowerMode == 0) {
  430. DISPMSG("already not in low power mode.\n");
  431. goto end;
  432. }
  433. isLowPowerMode = enter;
  434. if (pgc->plcm == NULL) {
  435. DISPERR("lcm handle is null\n");
  436. goto end;
  437. }
  438. DISPMSG("low power in, enter=%d.\n", enter);
  439. if (disp_low_power_enlarge_blanking == 1) {
  440. #if 0
  441. if (pgc->plcm->params) {
  442. vfp_for_low_power = pgc->plcm->params->dsi.vertical_frontporch_for_low_power;
  443. vfp_original = pgc->plcm->params->dsi.vertical_frontporch;
  444. }
  445. if (enter)
  446. DISP_REG_SET(pgc->cmdq_handle_config, dispsys_reg[DISP_REG_DSI0] + DISP_DSI_REG_VFP,
  447. vfp_for_low_power);
  448. else
  449. DISP_REG_SET(pgc->cmdq_handle_config, dispsys_reg[DISP_REG_DSI0] + DISP_DSI_REG_VFP,
  450. vfp_original);
  451. #else
  452. if (primary_display_is_video_mode() == 1)
  453. _disp_primary_path_set_vfp(enter);
  454. #endif
  455. }
  456. if (1 == disp_low_power_disable_ddp_clock) {/* open */
  457. if (primary_display_is_video_mode() == 0 /* && gEnableLowPowerFeature==1 */) {
  458. static unsigned int disp_low_power_disable_ddp_clock_cnt;
  459. DISPDBG("MM clock, disp_low_power_disable_ddp_clock enter %d.\n",
  460. disp_low_power_disable_ddp_clock_cnt++);
  461. if (1 == enter) { /* only for command mode */
  462. if (isIdlePowerOff == 0) {
  463. /* extern void clk_stat_bug(void); */
  464. unsigned long flags;
  465. DISPMSG("off MM clock start.\n");
  466. spin_lock_irqsave(&gLockTopClockOff, flags);
  467. _disp_primary_path_idle_clock_off(0); /* parameter represent level */
  468. isIdlePowerOff = 1;
  469. spin_unlock_irqrestore(&gLockTopClockOff, flags);
  470. #ifndef CONFIG_MTK_CLKMGR
  471. ddp_clk_unprepare(DISP_MTCMOS_CLK);
  472. #endif
  473. /* DISPMSG("off MM clock end.\n"); */
  474. DISPMSG("***start dump regs! clk_stat_check\n");
  475. #ifdef CONFIG_MTK_CLKMGR
  476. clk_stat_check(SYS_DIS);
  477. #endif
  478. /*DISPMSG("---- start dump regs! clk_stat_bug.\n"); */
  479. /* clk_stat_bug(); */
  480. }
  481. } else {
  482. if (isIdlePowerOff == 1) {
  483. unsigned long flags;
  484. DISPMSG("on MM clock start.\n");
  485. #ifndef CONFIG_MTK_CLKMGR
  486. ddp_clk_prepare(DISP_MTCMOS_CLK);
  487. #endif
  488. spin_lock_irqsave(&gLockTopClockOff, flags);
  489. isIdlePowerOff = 0;
  490. _disp_primary_path_idle_clock_on(0); /* parameter represent level */
  491. spin_unlock_irqrestore(&gLockTopClockOff, flags);
  492. DISPMSG("on MM clock end.\n");
  493. }
  494. }
  495. }
  496. }
  497. if (disp_low_power_disable_fence_thread == 1)
  498. ; /* already implemented. */
  499. /* no need idle lock, cause primary lock will be used inside switch_mode */
  500. if (disp_low_power_remove_ovl == 1) {
  501. if (primary_display_is_video_mode() == 1) {/* only for video mode */
  502. /* DISPMSG("[LP] OVL pgc->session_mode=%d, enter=%d\n", pgc->session_mode, enter); */
  503. if (enter) {
  504. if (pgc->session_mode == DISP_SESSION_DIRECT_LINK_MODE) {
  505. DISPDBG("[LP]remove ovl.\n");
  506. primary_display_switch_mode_nolock(DISP_SESSION_DECOUPLE_MODE,
  507. pgc->session_id, 1);
  508. }
  509. /* DISPMSG("disp_low_power_remove_ovl 2\n"); */
  510. } else {
  511. if (pgc->session_mode == DISP_SESSION_DECOUPLE_MODE) {
  512. DISPDBG("[LP]add ovl.\n");
  513. primary_display_switch_mode_nolock(DISP_SESSION_DIRECT_LINK_MODE,
  514. pgc->session_id, 1);
  515. }
  516. /* DISPMSG("disp_low_power_remove_ovl 4\n"); */
  517. }
  518. }
  519. }
  520. if (is_mmdvfs_supported() && mmdvfs_get_mmdvfs_profile() == MMDVFS_PROFILE_D1_PLUS) {
  521. if (_primary_path_IsForcedHPM(0) == false) {
  522. DISPMSG("MMDVFS enter:%d\n", enter);
  523. if (enter)
  524. mmdvfs_set_step(MMDVFS_SCEN_DISP, MMDVFS_VOLTAGE_LOW); /* Vote to LPM mode */
  525. else if (primary_display_get_width() > 800)
  526. mmdvfs_set_step(MMDVFS_SCEN_DISP, MMDVFS_VOLTAGE_HIGH); /* Enter HPM mode */
  527. } else {
  528. DISPMSG("MMDVFS is forced into HPM\n");
  529. mmdvfs_set_step(MMDVFS_SCEN_DISP, MMDVFS_VOLTAGE_HIGH); /* Enter HPM mode */
  530. }
  531. }
  532. end:
  533. if (enter)
  534. atomic_set(&isDdp_Idle, 1);
  535. if (need_primary_lock)
  536. _primary_path_unlock(__func__);
  537. return 0;
  538. }
  539. #if defined(CONFIG_MTK_GMO_RAM_OPTIMIZE)
  540. static int release_idle_lp_dc_buffer(unsigned int need_primary_lock);
  541. static int allocate_idle_lp_dc_buffer(void);
  542. #endif
  543. void _disp_primary_path_exit_idle(const char *caller, unsigned int need_primary_lock)
  544. {
  545. /* _disp_primary_idle_lock(); */
  546. if (atomic_read(&isDdp_Idle) == 1) {
  547. DISPMSG("[ddp_idle_on]_disp_primary_path_exit_idle (%s) &&&\n", caller);
  548. primary_display_save_power_for_idle(0, need_primary_lock);
  549. #if defined(CONFIG_MTK_GMO_RAM_OPTIMIZE)
  550. if (primary_display_is_video_mode())
  551. release_idle_lp_dc_buffer(need_primary_lock);
  552. #endif
  553. atomic_set(&isDdp_Idle, 0);
  554. atomic_set(&idle_detect_flag, 1);
  555. wake_up(&idle_detect_wq);
  556. }
  557. /* _disp_primary_idle_unlock(); */
  558. }
  559. /* used by aal/pwm to exit idle before config register(for "screen idle top clock off" feature) */
  560. void disp_exit_idle_ex(const char *caller)
  561. {
  562. if (primary_display_is_video_mode() == 0) {
  563. disp_update_trigger_time();
  564. _disp_primary_path_exit_idle(caller, 0);
  565. }
  566. }
  567. static int _disp_primary_path_idle_detect_thread(void *data)
  568. {
  569. int ret = 0, idle_time;
  570. static int enter_cnt;
  571. static int end_cnt;
  572. static int stop_cnt;
  573. #if defined(CONFIG_MTK_GMO_RAM_OPTIMIZE)
  574. idle_time = 2000;
  575. #else
  576. idle_time = 500;
  577. #endif
  578. while (1) {
  579. msleep(idle_time); /* 0.5s trigger once */
  580. /* DISPMSG("[ddp_idle]_disp_primary_path_idle_detect start 1\n"); */
  581. if (gSkipIdleDetect || atomic_read(&isDdp_Idle) == 1 ||
  582. is_hwc_update_frame == 0) /* skip is already in idle mode */
  583. continue;
  584. _primary_path_lock(__func__);
  585. if (primary_get_state() != DISP_ALIVE) {
  586. MMProfileLogEx(ddp_mmp_get_events()->esd_check_t, MMProfileFlagPulse, 1, 0);
  587. /* DISPCHECK("[ddp_idle]primary display path is slept?? -- skip ddp_idle\n"); */
  588. _primary_path_unlock(__func__);
  589. continue;
  590. }
  591. if (pgc->session_mode != DISP_SESSION_DIRECT_LINK_MODE) {
  592. DISPCHECK("[ddp_idle]primary display path is decouple mode. -- skip ddp_idle\n");
  593. _primary_path_unlock(__func__);
  594. continue;
  595. }
  596. _primary_path_unlock(__func__);
  597. /* _disp_primary_idle_lock(); */
  598. _primary_path_esd_check_lock();
  599. if (((sched_clock() - last_primary_trigger_time) / 1000) > idle_time * 1000) {
  600. #if defined(CONFIG_MTK_GMO_RAM_OPTIMIZE)
  601. /* Dynamically allocate decouple buffer. */
  602. if (primary_display_is_video_mode()) {
  603. ret = 0;
  604. if (decouple_buffer_info[0] == NULL)
  605. ret = allocate_idle_lp_dc_buffer();
  606. if (ret < 0) {
  607. DISPCHECK("[ddp_idle]allocate dc buffer fail\n");
  608. _primary_path_esd_check_unlock();
  609. continue;
  610. }
  611. }
  612. #endif
  613. enter_cnt++;
  614. pr_debug("[LP] - enter: %d, flag:%d,%d\n", enter_cnt,
  615. atomic_read(&isDdp_Idle), atomic_read(&idle_detect_flag));
  616. primary_display_save_power_for_idle(1, 1);
  617. _primary_path_set_dvfsHPM(false, 0);
  618. _primary_path_esd_check_unlock();
  619. } else {
  620. /* _disp_primary_idle_unlock(); */
  621. _primary_path_set_dvfsHPM(false, 0);
  622. _primary_path_esd_check_unlock();
  623. continue;
  624. }
  625. /* _disp_primary_idle_unlock(); */
  626. ret = wait_event_interruptible(idle_detect_wq, (atomic_read(&idle_detect_flag) != 0));
  627. atomic_set(&idle_detect_flag, 0);
  628. /* printk("[ddp_idle]ret=%d\n", ret); */
  629. if (kthread_should_stop()) {
  630. stop_cnt++;
  631. pr_debug("[LP] stop: %d, flag:%d,%d\n", stop_cnt,
  632. atomic_read(&isDdp_Idle), atomic_read(&idle_detect_flag));
  633. break;
  634. }
  635. end_cnt++;
  636. pr_debug("[LP] end: %d, flag:%d,%d\n", end_cnt, atomic_read(&isDdp_Idle),
  637. atomic_read(&idle_detect_flag));
  638. if (enter_cnt != end_cnt) {
  639. pr_err("[LP][ASSERT]%d, %d, %d\n", enter_cnt, end_cnt, stop_cnt);
  640. ASSERT(0);
  641. }
  642. }
  643. return ret;
  644. }
  645. int primary_display_cmdq_set_reg(unsigned int addr, unsigned int val)
  646. {
  647. int ret = 0;
  648. cmdqRecHandle handle = NULL;
  649. ret = cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &handle);
  650. cmdqRecReset(handle);
  651. _cmdq_insert_wait_frame_done_token_mira(handle);
  652. cmdqRecWrite(handle, addr & 0x1fffffff, val, ~0);
  653. cmdqRecFlushAsync(handle);
  654. cmdqRecDestroy(handle);
  655. return 0;
  656. }
  657. #endif
  658. unsigned int dvfs_test = 0xFF;
  659. static atomic_t gMmsysClk = ATOMIC_INIT(0xFF);
  660. static void set_mmsys_clk(unsigned int clk)
  661. {
  662. if (atomic_read(&gMmsysClk) != clk)
  663. atomic_set(&gMmsysClk, clk);
  664. }
  665. static unsigned int get_mmsys_clk(void)
  666. {
  667. return atomic_read(&gMmsysClk);
  668. }
  669. static int _switch_mmsys_clk(int mmsys_clk_old, int mmsys_clk_new)
  670. {
  671. int ret = -1;
  672. cmdqRecHandle handle;
  673. DISPMSG("[LP]: %s\n", __func__);
  674. if (mmsys_clk_new == get_mmsys_clk())
  675. return ret;
  676. if (pgc->state == DISP_SLEPT) {
  677. DISP_REG_MASK(NULL, DISP_REG_CONFIG_C13, 0x07000000, 0x07000000); /* clear */
  678. DISP_REG_MASK(NULL, DISP_REG_CONFIG_C12, 0x06000000, 0x07000000); /* set syspll2_d2 */
  679. DISPMSG("[DISP] DVFS mode=%d, profile=%d, state=0x%x\n", mmsys_clk_new,
  680. mmdvfs_get_mmdvfs_profile(), pgc->state);
  681. switch (mmsys_clk_new) {
  682. case MMSYS_CLK_LOW:
  683. DISP_REG_MASK(NULL, DISP_REG_VENCPLL_CON1, 0x830E0000, 0xFFFFFFFF); /* update */
  684. break;
  685. case MMSYS_CLK_MEDIUM:
  686. /* by frequency hopping */
  687. goto cpu_d;
  688. case MMSYS_CLK_HIGH:
  689. if (mmdvfs_get_mmdvfs_profile() == MMDVFS_PROFILE_D2_P_PLUS) {
  690. DISP_REG_MASK(NULL, DISP_REG_VENCPLL_CON1, 0x82110000, 0xFFFFFFFF); /* update */
  691. } else if (mmdvfs_get_mmdvfs_profile() == MMDVFS_PROFILE_D2_M_PLUS) {
  692. DISP_REG_MASK(NULL, DISP_REG_VENCPLL_CON1, 0x820F0000, 0xFFFFFFFF); /* update */
  693. }
  694. break;
  695. default:
  696. DISPERR("[DISP] DVFS mode=%d\n", mmsys_clk_new);
  697. goto cpu_d;
  698. }
  699. udelay(40);
  700. DISP_REG_MASK(NULL, DISP_REG_CONFIG_C13, 0x07000000, 0x07000000); /* clear */
  701. DISP_REG_MASK(NULL, DISP_REG_CONFIG_C12, 0x01000000, 0x07000000); /* set vencpll_ck */
  702. cpu_d:
  703. /* set rdma golden setting parameters */
  704. set_mmsys_clk(mmsys_clk_new);
  705. return get_mmsys_clk();
  706. }
  707. /* 1.create and reset cmdq */
  708. cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &handle);
  709. cmdqRecReset(handle);
  710. /* wait eof */
  711. _cmdq_insert_wait_frame_done_token_mira(handle);
  712. cmdqRecWrite(handle, 0x10210048, 0x07000000, 0x07000000); /* clear */
  713. cmdqRecWrite(handle, 0x10210044, 0x06000000, 0x07000000); /* set syspll2_d2 */
  714. DISPMSG("[DISP] DVFS mode=%d, profile=%d, state=0x%x\n", mmsys_clk_new,
  715. mmdvfs_get_mmdvfs_profile(), pgc->state);
  716. switch (mmsys_clk_new) {
  717. case MMSYS_CLK_LOW:
  718. cmdqRecWrite(handle, 0x10209254, 0x830E0000, 0xFFFFFFFF); /* update */
  719. break;
  720. case MMSYS_CLK_MEDIUM:
  721. /* by frequency hopping */
  722. goto cmdq_d;
  723. case MMSYS_CLK_HIGH:
  724. if (mmdvfs_get_mmdvfs_profile() == MMDVFS_PROFILE_D2_P_PLUS) {
  725. cmdqRecWrite(handle, 0x10209254, 0x82110000, 0xFFFFFFFF); /* update */
  726. } else if (mmdvfs_get_mmdvfs_profile() == MMDVFS_PROFILE_D2_M_PLUS) {
  727. cmdqRecWrite(handle, 0x10209254, 0x820F0000, 0xFFFFFFFF); /* update */
  728. }
  729. break;
  730. default:
  731. DISPERR("[DISP] DVFS mode=%d\n", mmsys_clk_new);
  732. goto cmdq_d;
  733. }
  734. /* wait rdma0_sof: only used for video mode & trigger loop need wait and clear rdma0 sof */
  735. cmdqRecWaitNoClear(handle, CMDQ_EVENT_DISP_RDMA0_SOF);
  736. cmdqRecWrite(handle, 0x10210048, 0x07000000, 0x07000000); /* clear */
  737. cmdqRecWrite(handle, 0x10210044, 0x01000000, 0x07000000); /* set vencpll_ck */
  738. cmdqRecFlush(handle);
  739. cmdq_d:
  740. cmdqRecDestroy(handle);
  741. /* set rdma golden setting parameters */
  742. set_mmsys_clk(mmsys_clk_new);
  743. return get_mmsys_clk();
  744. }
  745. int primary_display_switch_mmsys_clk(int mmsys_clk_old, int mmsys_clk_new)
  746. {
  747. int ret = -1;
  748. /* need lock */
  749. DISPMSG("[LP] %s\n", __func__);
  750. primary_display_manual_lock();
  751. ret = _switch_mmsys_clk(mmsys_clk_old, mmsys_clk_new);
  752. primary_display_manual_unlock();
  753. return ret;
  754. }
  755. int primary_display_set_secondary_display(int add, DISP_SESSION_TYPE type)
  756. {
  757. if (add) {
  758. #ifdef MTK_DISP_IDLE_LP
  759. gSkipIdleDetect = 1;
  760. _disp_primary_path_exit_idle(__func__, 0);
  761. #endif
  762. } else {
  763. #ifdef MTK_DISP_IDLE_LP
  764. gSkipIdleDetect = 0;
  765. #endif
  766. }
  767. return 0;
  768. }
  769. static void update_frm_seq_info(unsigned int addr, unsigned int addr_offset, unsigned int seq,
  770. DISP_FRM_SEQ_STATE state)
  771. {
  772. int i = 0;
  773. if (FRM_CONFIG == state) {
  774. frm_update_sequence[frm_update_cnt].state = state;
  775. frm_update_sequence[frm_update_cnt].mva = addr;
  776. frm_update_sequence[frm_update_cnt].max_offset = addr_offset;
  777. if (seq > 0)
  778. frm_update_sequence[frm_update_cnt].seq = seq;
  779. MMProfileLogEx(ddp_mmp_get_events()->primary_seq_config, MMProfileFlagPulse, addr, seq);
  780. } else if (FRM_TRIGGER == state) {
  781. frm_update_sequence[frm_update_cnt].state = FRM_TRIGGER;
  782. MMProfileLogEx(ddp_mmp_get_events()->primary_seq_trigger, MMProfileFlagPulse,
  783. frm_update_cnt, frm_update_sequence[frm_update_cnt].seq);
  784. dprec_logger_frame_seq_begin(pgc->session_id, frm_update_sequence[frm_update_cnt].seq);
  785. frm_update_cnt++;
  786. frm_update_cnt %= FRM_UPDATE_SEQ_CACHE_NUM;
  787. } else if (FRM_START == state) {
  788. for (i = 0; i < FRM_UPDATE_SEQ_CACHE_NUM; i++) {
  789. if ((abs(addr - frm_update_sequence[i].mva) <= frm_update_sequence[i].max_offset) &&
  790. (frm_update_sequence[i].state == FRM_TRIGGER)) {
  791. MMProfileLogEx(ddp_mmp_get_events()->primary_seq_rdma_irq, MMProfileFlagPulse,
  792. frm_update_sequence[i].mva | seq, frm_update_sequence[i].state);
  793. frm_update_sequence[i].state = FRM_START;
  794. /* break; */
  795. }
  796. }
  797. } else if (FRM_END == state) {
  798. for (i = 0; i < FRM_UPDATE_SEQ_CACHE_NUM; i++) {
  799. if (FRM_START == frm_update_sequence[i].state) {
  800. frm_update_sequence[i].state = FRM_END;
  801. dprec_logger_frame_seq_end(pgc->session_id, frm_update_sequence[i].seq);
  802. MMProfileLogEx(ddp_mmp_get_events()->primary_seq_release, MMProfileFlagPulse,
  803. frm_update_sequence[i].mva, frm_update_sequence[i].seq);
  804. }
  805. }
  806. }
  807. }
  808. static int _config_wdma_output(WDMA_CONFIG_STRUCT *wdma_config, disp_path_handle disp_handle,
  809. cmdqRecHandle cmdq_handle)
  810. {
  811. disp_ddp_path_config *pconfig = dpmgr_path_get_last_config(disp_handle);
  812. pconfig->wdma_config = *wdma_config;
  813. pconfig->wdma_dirty = 1;
  814. dpmgr_path_config(disp_handle, pconfig, cmdq_handle);
  815. return 0;
  816. }
  817. static int _config_rdma_input_data(RDMA_CONFIG_STRUCT *rdma_config, disp_path_handle disp_handle,
  818. cmdqRecHandle cmdq_handle)
  819. {
  820. disp_ddp_path_config *pconfig = dpmgr_path_get_last_config(disp_handle);
  821. pconfig->rdma_config = *rdma_config;
  822. pconfig->rdma_dirty = 1;
  823. dpmgr_path_config(disp_handle, pconfig, cmdq_handle);
  824. return 0;
  825. }
  826. #if 0
  827. /**
  828. * Defined but not used, avoid build warning. (2015.1.30 Rynn Wu)
  829. */
  830. static unsigned int get_frm_seq_by_addr(unsigned int addr, DISP_FRM_SEQ_STATE state)
  831. {
  832. int i = 0;
  833. for (i = 0; i < FRM_UPDATE_SEQ_CACHE_NUM; i++) {
  834. if (addr == frm_update_sequence[i].mva)
  835. return frm_update_sequence[i].seq;
  836. }
  837. return 0;
  838. }
  839. #endif
  840. #if 0
  841. /**
  842. * Defined but not used, avoid build warning. (2015.1.30 Rynn Wu)
  843. */
  844. static unsigned int release_started_frm_seq(unsigned int addr, DISP_FRM_SEQ_STATE FRM_END)
  845. {
  846. int i = 0;
  847. for (i = 0; i < FRM_UPDATE_SEQ_CACHE_NUM; i++) {
  848. if (FRM_END == frm_update_sequence[i].state)
  849. return frm_update_sequence[i].seq;
  850. }
  851. return 0;
  852. }
  853. #endif
  854. #ifdef DISP_SWITCH_DST_MODE
  855. unsigned long long last_primary_trigger_time;
  856. bool is_switched_dst_mode = false;
  857. static struct task_struct *primary_display_switch_dst_mode_task;
  858. static void _primary_path_switch_dst_lock(void)
  859. {
  860. mutex_lock(&(pgc->switch_dst_lock));
  861. }
  862. static void _primary_path_switch_dst_unlock(void)
  863. {
  864. mutex_unlock(&(pgc->switch_dst_lock));
  865. }
  866. static int _disp_primary_path_switch_dst_mode_thread(void *data)
  867. {
  868. int ret = 0;
  869. while (1) {
  870. msleep(1000);
  871. if (((sched_clock() - last_primary_trigger_time) / 1000) > 500000) { /* 500ms not trigger disp */
  872. primary_display_switch_dst_mode(0); /* switch to cmd mode */
  873. is_switched_dst_mode = true;
  874. }
  875. if (kthread_should_stop())
  876. break;
  877. }
  878. return 0;
  879. }
  880. #endif
  881. unsigned long long idlemgr_last_kick_time = 0xffffffffffffffff;
  882. bool is_switched_dst_mode = false;
  883. /*----------------------------------------------------------------
  884. defined but not used because some functions are not used either.
  885. ----------------------------------------------------------------
  886. static wait_queue_head_t idlemgr_wq; // For display idle manager
  887. static atomic_t idlemgr_wakeup = ATOMIC_INIT(0); // For display idle manager
  888. ----------------------------------------------------------------*/
  889. struct task_struct *primary_display_idlemgr_task = NULL;
  890. #if 0
  891. /**
  892. * Defined but not used, avoid build warning. (2015.1.30 Rynn Wu)
  893. */
  894. static void _idlemgr_wait_for_wakeup(void)
  895. {
  896. int ret = 0;
  897. atomic_set(&idlemgr_wakeup, 0);
  898. ret = wait_event_interruptible(idlemgr_wq, atomic_read(&idlemgr_wakeup));
  899. if (ret < 0)
  900. DISPERR("display idle manager thread waked up by signal\n");
  901. }
  902. #endif
  903. #if 0
  904. /**
  905. * Defined but not used, avoid build warning. (2015.1.30 Rynn Wu)
  906. */
  907. static void _idlemgr_wakeup(void)
  908. {
  909. atomic_set(&idlemgr_wakeup, 1);
  910. wake_up_interruptible(&idlemgr_wq);
  911. }
  912. #endif
  913. #if 0
  914. /**
  915. * Defined but not used, avoid build warning. (2015.1.30 Rynn Wu)
  916. */
  917. static void _idlemgr_update_last_kick_time(void)
  918. {
  919. idlemgr_last_kick_time = sched_clock();
  920. }
  921. #endif
  922. #if 0
  923. void primary_display_idlemgr_enter_idle(void)
  924. {
  925. MMProfileLogEx(ddp_mmp_get_events()->idlemgr_enter_idle, MMProfileFlagPulse, 0, 0);
  926. if (!primary_display_is_video_mode()) {
  927. spm_enable_sodi(1);
  928. spm_sodi_mempll_pwr_mode(0);
  929. MMProfileLogEx(ddp_mmp_get_events()->sodi_enable, MMProfileFlagPulse, 0, 0);
  930. }
  931. }
  932. void primary_display_idlemgr_leave_idle(void)
  933. {
  934. MMProfileLogEx(ddp_mmp_get_events()->idlemgr_leave_idle, MMProfileFlagPulse, 0, 0);
  935. if (!primary_display_is_video_mode()) {
  936. spm_enable_sodi(0);
  937. MMProfileLogEx(ddp_mmp_get_events()->sodi_disable, MMProfileFlagPulse, 0, 0);
  938. }
  939. }
  940. static int _primary_path_idlemgr_monitor_thread(void *data)
  941. {
  942. int ret = 0;
  943. init_waitqueue_head(&idlemgr_wq);
  944. while (1) {
  945. msleep(100);
  946. if (((sched_clock() - idlemgr_last_kick_time) / 1000) > 500000) {/* 500ms not trigger disp */
  947. primary_display_idlemgr_enter_idle(); /* switch to cmd mode */
  948. _idlemgr_wait_for_wakeup();
  949. }
  950. if (kthread_should_stop())
  951. break;
  952. }
  953. return 0;
  954. }
  955. #else
  956. void primary_display_idlemgr_kick(char *source)
  957. {
  958. }
  959. void primary_display_idlemgr_enter_idle(void)
  960. {
  961. }
  962. void primary_display_idlemgr_leave_idle(void)
  963. {
  964. }
  965. #if 0
  966. /**
  967. * Defined but not used, avoid build warning. (2015.1.30 Rynn Wu)
  968. */
  969. static int _primary_path_idlemgr_monitor_thread(void *data)
  970. {
  971. return 0;
  972. }
  973. #endif
  974. #endif
  975. /* extern int disp_od_is_enabled(void); */
  976. int primary_display_get_debug_state(char *stringbuf, int buf_len)
  977. {
  978. int len = 0;
  979. LCM_PARAMS *lcm_param = disp_lcm_get_params(pgc->plcm);
  980. LCM_DRIVER *lcm_drv = pgc->plcm->drv;
  981. len += scnprintf(stringbuf + len, buf_len - len,
  982. "|--------------------------------------------------------------------------------------|\n");
  983. len += scnprintf(stringbuf + len, buf_len - len,
  984. "|********Primary Display Path General Information********\n");
  985. len += scnprintf(stringbuf + len, buf_len - len, "|Primary Display is %s\n",
  986. dpmgr_path_is_idle(pgc->dpmgr_handle) ? "idle" : "busy");
  987. if (mutex_trylock(&(pgc->lock))) {
  988. mutex_unlock(&(pgc->lock));
  989. len += scnprintf(stringbuf + len, buf_len - len,
  990. "|primary path global mutex is free\n");
  991. } else {
  992. len += scnprintf(stringbuf + len, buf_len - len,
  993. "|primary path global mutex is hold by [%s]\n", pgc->mutex_locker);
  994. }
  995. if (lcm_param && lcm_drv)
  996. len += scnprintf(stringbuf + len, buf_len - len,
  997. "|LCM Driver=[%s]\tResolution=%dx%d,Interface:%s\n", lcm_drv->name,
  998. lcm_param->width, lcm_param->height,
  999. (lcm_param->type == LCM_TYPE_DSI) ? "DSI" : "Other");
  1000. /* no OD */
  1001. /* len += scnprintf(stringbuf+len, buf_len - len, "|OD is %s\n", disp_od_is_enabled()?"enabled":"disabled"); */
  1002. len += scnprintf(stringbuf + len, buf_len - len, "|session_mode is 0x%08x\n", pgc->session_mode);
  1003. len += scnprintf(stringbuf + len, buf_len - len,
  1004. "|State=%s\tlcm_fps=%d\tmax_layer=%d\tmode:%d\tvsync_drop=%d\n",
  1005. pgc->state == DISP_ALIVE ? "Alive" : "Sleep", pgc->lcm_fps, pgc->max_layer,
  1006. pgc->mode, pgc->vsync_drop);
  1007. len += scnprintf(stringbuf + len, buf_len - len,
  1008. "|cmdq_handle_config=%p\tcmdq_handle_trigger=%p\tdpmgr_handle=%p\tovl2mem_path_handle=%p\n",
  1009. pgc->cmdq_handle_config, pgc->cmdq_handle_trigger, pgc->dpmgr_handle,
  1010. pgc->ovl2mem_path_handle);
  1011. len += scnprintf(stringbuf + len, buf_len - len, "|Current display driver status=%s + %s\n",
  1012. primary_display_is_video_mode() ? "video mode" : "cmd mode",
  1013. primary_display_cmdq_enabled() ? "CMDQ Enabled" : "CMDQ Disabled");
  1014. return len;
  1015. }
  1016. static char _dump_buffer_string[512];
  1017. static void _dump_internal_buffer_into(display_primary_path_context *ctx, char *dump_reason)
  1018. {
  1019. int n = 0;
  1020. int len = 0;
  1021. disp_internal_buffer_info *buf = NULL;
  1022. struct list_head *head = NULL;
  1023. int i = 0;
  1024. len = sizeof(_dump_buffer_string);
  1025. n += scnprintf(_dump_buffer_string + n, len - n, "dump for %s\n",
  1026. dump_reason ? dump_reason : "unknown");
  1027. if (ctx) {
  1028. mutex_lock(&(pgc->dc_lock));
  1029. head = &(pgc->dc_free_list);
  1030. i = 0;
  1031. n += scnprintf(_dump_buffer_string + n, len - n, "free list: ");
  1032. if (!list_empty(head)) {
  1033. list_for_each_entry(buf, head, list)
  1034. n += scnprintf(_dump_buffer_string + n, len - n, "\t0x%08x", buf->mva);
  1035. }
  1036. n += scnprintf(_dump_buffer_string + n, len - n, "\n");
  1037. #if 0
  1038. head = &(pgc->dc_writing_list);
  1039. i = 0;
  1040. n += scnprintf(_dump_buffer_string + n, len - n, "writing list: ");
  1041. if (!list_empty(head)) {
  1042. list_for_each_entry(buf, head, list)
  1043. n += scnprintf(_dump_buffer_string + n, len - n, "\t0x%08x", buf->mva);
  1044. }
  1045. n += scnprintf(_dump_buffer_string + n, len - n, "\n");
  1046. #endif
  1047. head = &(pgc->dc_reading_list);
  1048. i = 0;
  1049. n += scnprintf(_dump_buffer_string + n, len - n, "reading list: ");
  1050. if (!list_empty(head)) {
  1051. list_for_each_entry(buf, head, list)
  1052. n += scnprintf(_dump_buffer_string + n, len - n, "\t0x%08x", buf->mva);
  1053. }
  1054. n += scnprintf(_dump_buffer_string + n, len - n, "\n");
  1055. DISPMSG("%s", _dump_buffer_string);
  1056. mutex_unlock(&(pgc->dc_lock));
  1057. }
  1058. }
  1059. int32_t decouple_rdma_worker_callback(unsigned long data)
  1060. {
  1061. disp_internal_buffer_info *reading_buf = NULL;
  1062. disp_internal_buffer_info *temp = NULL;
  1063. disp_internal_buffer_info *n = NULL;
  1064. unsigned int current_reading_addr = 0;
  1065. mutex_lock(&(pgc->dc_lock));
  1066. current_reading_addr = ddp_ovl_get_cur_addr(1, 0);
  1067. DISPMSG("rdma applied, 0x%lx, 0x%08x\n", data, current_reading_addr);
  1068. reading_buf = find_buffer_by_mva(pgc, &pgc->dc_reading_list, data);
  1069. if (!reading_buf) {
  1070. /* DISPERR("fatal error, we can't find related buffer info with callback data:0x%08x\n", data); */
  1071. mutex_unlock(&(pgc->dc_lock));
  1072. return 0;
  1073. }
  1074. list_for_each_entry_safe(temp, n, &(pgc->dc_reading_list), list) {
  1075. if (temp && temp->mva != current_reading_addr) {
  1076. DISPMSG("temp=0x%p, temp->mva=0x%08x, temp->list=0x%lx\n", temp, temp->mva,
  1077. (unsigned long)(&temp->list));
  1078. reset_buffer(pgc, temp);
  1079. enqueue_buffer(pgc, &(pgc->dc_free_list), temp);
  1080. }
  1081. }
  1082. mutex_unlock(&(pgc->dc_lock));
  1083. _dump_internal_buffer_into(pgc, "interface applied");
  1084. return 0;
  1085. }
  1086. #if 0
  1087. /**
  1088. * Defined but not used, avoid build warning. (2015.1.30 Rynn Wu)
  1089. */
  1090. static int _disp_primary_path_decouple_worker_thread(void *data)
  1091. {
  1092. int ret = 0;
  1093. primary_disp_input_config input;
  1094. disp_internal_buffer_info *writing_buf = NULL;
  1095. disp_internal_buffer_info *reading_buf = NULL;
  1096. uint32_t current_writing_mva = 0;
  1097. disp_ddp_path_config *pconfig = NULL;
  1098. struct sched_param param = { .sched_priority = 90 };
  1099. sched_setscheduler(current, SCHED_RR, &param);
  1100. while (1) {
  1101. /* shuold wait FRAME_START here, but MUTEX1's sof always issued with MUTEX0's sof,
  1102. * root cause still unkonwn. so use FRAME_COMPLETE instead
  1103. */
  1104. dpmgr_wait_event(pgc->ovl2mem_path_handle, DISP_PATH_EVENT_FRAME_COMPLETE);
  1105. pconfig = dpmgr_path_get_last_config(pgc->ovl2mem_path_handle);
  1106. current_writing_mva = pconfig->wdma_config.dstAddress;
  1107. _dump_internal_buffer_into(pgc, "ovl2mem done");
  1108. disp_sw_mutex_lock(&(pgc->dc_lock));
  1109. writing_buf = find_buffer_by_mva(pgc, &pgc->dc_writing_list, current_writing_mva);
  1110. if (!writing_buf) {
  1111. DISPERR("fatal error, we can't find related buffer info with current_writing_mva:0x%08x\n",
  1112. current_writing_mva);
  1113. disp_sw_mutex_unlock(&(pgc->dc_lock));
  1114. continue;
  1115. } else {
  1116. reset_buffer(pgc, writing_buf);
  1117. enqueue_buffer(pgc, &(pgc->dc_reading_list), writing_buf);
  1118. reading_buf = dequeue_buffer(pgc, &(pgc->dc_free_list));
  1119. if (!reading_buf) {
  1120. DISPERR("dc_free_list is empty!!\n");
  1121. disp_sw_mutex_unlock(&(pgc->dc_lock));
  1122. continue;
  1123. } else {
  1124. enqueue_buffer(pgc, &(pgc->dc_writing_list), reading_buf);
  1125. }
  1126. disp_sw_mutex_unlock(&(pgc->dc_lock));
  1127. }
  1128. _dump_internal_buffer_into(pgc, "trigger interface");
  1129. pconfig->wdma_config.dstAddress = reading_buf->mva;
  1130. pconfig->wdma_config.srcHeight = primary_display_get_height();
  1131. pconfig->wdma_config.srcWidth = primary_display_get_width();
  1132. pconfig->wdma_config.clipX = 0;
  1133. pconfig->wdma_config.clipY = 0;
  1134. pconfig->wdma_config.clipHeight = primary_display_get_height();
  1135. pconfig->wdma_config.clipWidth = primary_display_get_width();
  1136. pconfig->wdma_config.outputFormat = eRGB888;
  1137. pconfig->wdma_config.useSpecifiedAlpha = 1;
  1138. pconfig->wdma_config.alpha = 0xFF;
  1139. pconfig->wdma_config.dstPitch = primary_display_get_width() *
  1140. DP_COLOR_BITS_PER_PIXEL(eRGB888) / 8;
  1141. pconfig->wdma_dirty = 1;
  1142. ret = dpmgr_path_config(pgc->ovl2mem_path_handle, pconfig, CMDQ_DISABLE);
  1143. memset((void *)&input, 0, sizeof(primary_disp_input_config));
  1144. input.addr = (unsigned int) writing_buf->mva;
  1145. input.src_x = 0;
  1146. input.src_y = 0;
  1147. input.src_w = primary_display_get_width();
  1148. input.src_h = primary_display_get_height();
  1149. input.dst_x = 0;
  1150. input.dst_y = 0;
  1151. input.dst_w = primary_display_get_width();
  1152. input.dst_h = primary_display_get_height();
  1153. input.fmt = eRGB888;
  1154. input.alpha = 0xFF;
  1155. input.src_pitch = primary_display_get_width() * 3;
  1156. input.isDirty = 1;
  1157. MMProfileLogEx(ddp_mmp_get_events()->interface_trigger, MMProfileFlagPulse,
  1158. input.addr, pconfig->wdma_config.dstAddress);
  1159. ret = primary_display_config_interface_input(&input);
  1160. ret = _trigger_display_interface(FALSE, decouple_rdma_worker_callback, ddp_ovl_get_cur_addr(1, 0));
  1161. if (kthread_should_stop())
  1162. break;
  1163. }
  1164. return 0;
  1165. }
  1166. #endif
  1167. static DISP_MODULE_ENUM _get_dst_module_by_lcm(disp_lcm_handle *plcm)
  1168. {
  1169. if (plcm == NULL) {
  1170. DISPERR("plcm is null\n");
  1171. return DISP_MODULE_UNKNOWN;
  1172. }
  1173. if (plcm->params->type == LCM_TYPE_DSI) {
  1174. if (plcm->lcm_if_id == LCM_INTERFACE_DSI0)
  1175. return DISP_MODULE_DSI0;
  1176. else if (plcm->lcm_if_id == LCM_INTERFACE_DSI1)
  1177. return DISP_MODULE_DSI1;
  1178. else if (plcm->lcm_if_id == LCM_INTERFACE_DSI_DUAL)
  1179. return DISP_MODULE_DSIDUAL;
  1180. else
  1181. return DISP_MODULE_DSI0;
  1182. } else if (plcm->params->type == LCM_TYPE_DPI) {
  1183. return DISP_MODULE_DPI;
  1184. }
  1185. DISPERR("can't find primary path dst module\n");
  1186. return DISP_MODULE_UNKNOWN;
  1187. }
  1188. #define AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  1189. /**
  1190. * trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU
  1191. * 1.wait idle: N N Y Y
  1192. * 2.lcm update: N Y N Y
  1193. * 3.path start: idle->Y Y idle->Y Y
  1194. * 4.path trigger: idle->Y Y idle->Y Y
  1195. * 5.mutex enable: N N idle->Y Y
  1196. * 6.set cmdq dirty: N Y N N
  1197. * 7.flush cmdq: Y Y N N
  1198. */
  1199. /**
  1200. * trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU
  1201. * 1.wait idle: N N Y Y
  1202. */
  1203. int _should_wait_path_idle(void)
  1204. {
  1205. if (primary_display_cmdq_enabled()) {
  1206. if (primary_display_is_video_mode())
  1207. return 0;
  1208. else
  1209. return 0;
  1210. } else {
  1211. if (primary_display_is_video_mode())
  1212. return dpmgr_path_is_busy(pgc->dpmgr_handle);
  1213. else
  1214. return dpmgr_path_is_busy(pgc->dpmgr_handle);
  1215. }
  1216. }
  1217. /**
  1218. * trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU
  1219. * 2.lcm update: N Y N Y
  1220. */
  1221. int _should_update_lcm(void)
  1222. {
  1223. if (primary_display_cmdq_enabled()) {
  1224. if (primary_display_is_video_mode())
  1225. return 0;
  1226. /* TODO: lcm_update can't use cmdq now */
  1227. return 0;
  1228. }
  1229. if (primary_display_is_video_mode())
  1230. return 0;
  1231. else
  1232. return 1;
  1233. }
  1234. /**
  1235. * trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU
  1236. * 3.path start: idle->Y Y idle->Y Y
  1237. */
  1238. int _should_start_path(void)
  1239. {
  1240. if (primary_display_cmdq_enabled()) {
  1241. if (primary_display_is_video_mode())
  1242. return 0;
  1243. /* return dpmgr_path_is_idle(pgc->dpmgr_handle); */
  1244. else
  1245. return 0;
  1246. } else {
  1247. if (primary_display_is_video_mode())
  1248. return dpmgr_path_is_idle(pgc->dpmgr_handle);
  1249. else
  1250. return 1;
  1251. }
  1252. }
  1253. /**
  1254. * trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU
  1255. * 4.path trigger: idle->Y Y idle->Y Y
  1256. * 5.mutex enable: N N idle->Y Y
  1257. */
  1258. int _should_trigger_path(void)
  1259. {
  1260. /* this is not a perfect design, we can't decide path trigger(ovl/rdma/dsi..) separately with mutex enable */
  1261. /* but it's lucky because path trigger and mutex enable is the same w/o cmdq, and it's correct w/ CMDQ(Y+N). */
  1262. if (primary_display_cmdq_enabled()) {
  1263. if (primary_display_is_video_mode())
  1264. return 0;
  1265. /* return dpmgr_path_is_idle(pgc->dpmgr_handle); */
  1266. else
  1267. return 0;
  1268. } else {
  1269. if (primary_display_is_video_mode())
  1270. return dpmgr_path_is_idle(pgc->dpmgr_handle);
  1271. else
  1272. return 1;
  1273. }
  1274. }
  1275. /**
  1276. * trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU
  1277. * 6.set cmdq dirty: N Y N N
  1278. */
  1279. int _should_set_cmdq_dirty(void)
  1280. {
  1281. if (primary_display_cmdq_enabled()) {
  1282. if (primary_display_is_video_mode())
  1283. return 0;
  1284. else
  1285. return 1;
  1286. } else {
  1287. if (primary_display_is_video_mode())
  1288. return 0;
  1289. else
  1290. return 0;
  1291. }
  1292. }
  1293. /**
  1294. * trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU
  1295. * 7.flush cmdq: Y Y N N
  1296. */
  1297. int _should_flush_cmdq_config_handle(void)
  1298. {
  1299. if (primary_display_cmdq_enabled()) {
  1300. if (primary_display_is_video_mode())
  1301. return 1;
  1302. else
  1303. return 1;
  1304. } else {
  1305. if (primary_display_is_video_mode())
  1306. return 0;
  1307. else
  1308. return 0;
  1309. }
  1310. }
  1311. int _should_reset_cmdq_config_handle(void)
  1312. {
  1313. if (primary_display_cmdq_enabled()) {
  1314. if (primary_display_is_video_mode())
  1315. return 1;
  1316. else
  1317. return 1;
  1318. } else {
  1319. if (primary_display_is_video_mode())
  1320. return 0;
  1321. else
  1322. return 0;
  1323. }
  1324. }
  1325. /**
  1326. * trigger operation: VDO+CMDQ CMD+CMDQ VDO+CPU CMD+CPU
  1327. * 7.flush cmdq: Y Y N N
  1328. */
  1329. int _should_insert_wait_frame_done_token(void)
  1330. {
  1331. if (primary_display_cmdq_enabled()) {
  1332. if (primary_display_is_video_mode())
  1333. return 1;
  1334. else
  1335. return 1;
  1336. } else {
  1337. if (primary_display_is_video_mode())
  1338. return 0;
  1339. else
  1340. return 0;
  1341. }
  1342. }
  1343. int _should_trigger_interface(void)
  1344. {
  1345. if (pgc->mode == DECOUPLE_MODE)
  1346. return 0;
  1347. else
  1348. return 1;
  1349. }
  1350. int _should_config_ovl_input(void)
  1351. {
  1352. /* should extend this when display path dynamic switch is ready */
  1353. if (pgc->mode == SINGLE_LAYER_MODE || pgc->mode == DEBUG_RDMA1_DSI0_MODE)
  1354. return 0;
  1355. else
  1356. return 1;
  1357. }
  1358. int _should_config_ovl_to_memory(display_primary_path_context *ctx)
  1359. {
  1360. if (ctx == NULL) {
  1361. DISP_FATAL_ERR("DISP", "Context is NULL!\n");
  1362. return 0;
  1363. }
  1364. if (ctx->mode == DECOUPLE_MODE)
  1365. return 1;
  1366. else
  1367. return 0;
  1368. }
  1369. #define OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
  1370. static unsigned long get_current_time_us(void)
  1371. {
  1372. struct timeval t;
  1373. do_gettimeofday(&t);
  1374. return (t.tv_sec & 0xFFF) * 1000000 + t.tv_usec;
  1375. }
  1376. static struct hrtimer cmd_mode_update_timer;
  1377. static int is_fake_timer_inited;
  1378. static enum hrtimer_restart _DISP_CmdModeTimer_handler(struct hrtimer *timer)
  1379. {
  1380. dpmgr_signal_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC);
  1381. #if 0
  1382. if ((get_current_time_us() - pgc->last_vsync_tick) > 16666) {
  1383. dpmgr_signal_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC);
  1384. pgc->last_vsync_tick = get_current_time_us();
  1385. }
  1386. #endif
  1387. hrtimer_forward_now(timer, ns_to_ktime(16666666));
  1388. return HRTIMER_RESTART;
  1389. }
  1390. int _init_vsync_fake_monitor(int fps)
  1391. {
  1392. if (is_fake_timer_inited)
  1393. return 0;
  1394. is_fake_timer_inited = 1;
  1395. if (fps == 0)
  1396. fps = 6000;
  1397. hrtimer_init(&cmd_mode_update_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
  1398. cmd_mode_update_timer.function = _DISP_CmdModeTimer_handler;
  1399. hrtimer_start(&cmd_mode_update_timer, ns_to_ktime(16666666), HRTIMER_MODE_REL);
  1400. DISPMSG("fake timer, init\n");
  1401. return 0;
  1402. }
  1403. #define DISP_REG_SODI_PA 0x10006b0c
  1404. /* extern unsigned int gEnableSODIControl; */
  1405. /* extern unsigned int gPrefetchControl; */
  1406. void disp_set_sodi(unsigned int enable, void *cmdq_handle)
  1407. {
  1408. #ifndef CONFIG_FPGA_EARLY_PORTING
  1409. #ifdef FORCE_SODI_BY_SW
  1410. if (gEnableSODIControl == 1) {
  1411. if (cmdq_handle != NULL) {
  1412. if (enable == 1)
  1413. cmdqRecWrite(cmdq_handle, DISP_REG_SODI_PA, 0, 1);
  1414. else
  1415. cmdqRecWrite(cmdq_handle, DISP_REG_SODI_PA, 1, 1);
  1416. } else {
  1417. if (enable == 1)
  1418. DISP_REG_SET(0, SPM_PCM_SRC_REQ,
  1419. DISP_REG_GET(SPM_PCM_SRC_REQ) & (~0x1));
  1420. else
  1421. DISP_REG_SET(0, SPM_PCM_SRC_REQ,
  1422. DISP_REG_GET(SPM_PCM_SRC_REQ) | 0x1);
  1423. }
  1424. }
  1425. #endif
  1426. #endif
  1427. }
  1428. /* extern unsigned int gEnableSWTrigger; */
  1429. /* extern unsigned int gEnableMutexRisingEdge; */
  1430. /* extern unsigned int gDisableSODIForTriggerLoop; */
  1431. static void _cmdq_build_trigger_loop(void)
  1432. {
  1433. #ifndef MTK_FB_CMDQ_DISABLE
  1434. int ret = 0;
  1435. int i = 0;
  1436. if (pgc->cmdq_handle_trigger == NULL) {
  1437. cmdqRecCreate(CMDQ_SCENARIO_TRIGGER_LOOP, &(pgc->cmdq_handle_trigger));
  1438. DISPMSG("primary path trigger thread cmd handle=%p\n", pgc->cmdq_handle_trigger);
  1439. }
  1440. cmdqRecReset(pgc->cmdq_handle_trigger);
  1441. if (primary_display_is_video_mode()) {
  1442. /* wait and clear stream_done, HW will assert mutex enable automatically in frame done reset. */
  1443. /* todo: should let dpmanager to decide wait which mutex's eof. */
  1444. ret = cmdqRecWait(pgc->cmdq_handle_trigger, CMDQ_EVENT_DISP_RDMA0_EOF);
  1445. ret = cmdqRecWait(pgc->cmdq_handle_trigger,
  1446. dpmgr_path_get_mutex(pgc->dpmgr_handle) +
  1447. CMDQ_EVENT_MUTEX0_STREAM_EOF);
  1448. /* wait and clear rdma0_sof for vfp change */
  1449. cmdqRecClearEventToken(pgc->cmdq_handle_trigger, CMDQ_EVENT_DISP_RDMA0_SOF);
  1450. if (gEnableSWTrigger == 1)
  1451. DISP_REG_SET(pgc->cmdq_handle_trigger, DISP_REG_CONFIG_MUTEX_EN(DISP_OVL_SEPARATE_MUTEX_ID), 1);
  1452. /* for some module(like COLOR) to read hw register to GPR after frame done */
  1453. dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_trigger,
  1454. CMDQ_AFTER_STREAM_EOF);
  1455. } else {
  1456. ret = cmdqRecWaitNoClear(pgc->cmdq_handle_trigger, CMDQ_SYNC_TOKEN_CABC_EOF);
  1457. /* DSI command mode doesn't have mutex_stream_eof, need use CMDQ token instead */
  1458. ret = cmdqRecWait(pgc->cmdq_handle_trigger, CMDQ_SYNC_TOKEN_CONFIG_DIRTY);
  1459. if (_need_wait_esd_eof())
  1460. /* Wait esd config thread done. */
  1461. ret = cmdqRecWaitNoClear(pgc->cmdq_handle_trigger, CMDQ_SYNC_TOKEN_ESD_EOF);
  1462. /* ret = cmdqRecWait(pgc->cmdq_handle_trigger, CMDQ_EVENT_MDP_DSI0_TE_SOF); */
  1463. /* for operations before frame transfer, such as waiting for DSI TE */
  1464. if (islcmconnected)
  1465. dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_trigger, CMDQ_BEFORE_STREAM_SOF);
  1466. /* pull DSI clk lane back to HS */
  1467. DSI_manual_enter_HS(pgc->cmdq_handle_trigger);
  1468. /* cleat frame done token, now the config thread will not allowed to config registers. */
  1469. /* remember that config thread's priority is higher than trigger thread,
  1470. * so all the config queued before will be applied then STREAM_EOF token be cleared
  1471. */
  1472. /* this is what CMDQ did as "Merge" */
  1473. ret = cmdqRecClearEventToken(pgc->cmdq_handle_trigger, CMDQ_SYNC_TOKEN_STREAM_EOF);
  1474. ret = cmdqRecClearEventToken(pgc->cmdq_handle_trigger, CMDQ_SYNC_TOKEN_CONFIG_DIRTY);
  1475. /* enable mutex, only cmd mode need this */
  1476. /* this is what CMDQ did as "Trigger" */
  1477. /* clear rdma EOF token before wait */
  1478. ret = cmdqRecClearEventToken(pgc->cmdq_handle_trigger, CMDQ_EVENT_DISP_RDMA0_EOF);
  1479. #ifdef FORCE_SODI_BY_SW
  1480. /* TODO: use separate api for sodi control flow later */
  1481. /* Enable EMI Force On(Equal to SODI Disable) */
  1482. cmdqRecWrite(pgc->cmdq_handle_trigger, 0x10006b0c, 1, 1);
  1483. #endif
  1484. #ifndef FORCE_SODI_CG_MODE
  1485. /* Enable SPM CG Mode(Force 30+ times to ensure write success, need find root cause and fix later) */
  1486. cmdqRecWrite(pgc->cmdq_handle_trigger, 0x10006b04, 0x80, 0x80);
  1487. /* Polling EMI Status to ensure EMI is enabled */
  1488. cmdqRecPoll(pgc->cmdq_handle_trigger, 0x100063b4, 0, 0x00200000);
  1489. #endif
  1490. #ifdef FORCE_SODI_BY_SW
  1491. /* Clear EMI Force on, Let SPM control EMI state now */
  1492. cmdqRecWrite(pgc->cmdq_handle_trigger, 0x10006b0c, 0, 1);
  1493. #endif
  1494. dpmgr_path_trigger(pgc->dpmgr_handle, pgc->cmdq_handle_trigger, CMDQ_ENABLE);
  1495. /* ret = cmdqRecWrite(pgc->cmdq_handle_trigger,
  1496. (unsigned int)(DISP_REG_CONFIG_MUTEX_EN(0))&0x1fffffff, 1, ~0);
  1497. */
  1498. /* backup DSI state register to slot */
  1499. if (gEnableDSIStateCheck == 1) {
  1500. for (i = 0; i < 10; i++) {
  1501. cmdqRecBackupRegisterToSlot(pgc->cmdq_handle_trigger, pgc->dsi_state_info, i,
  1502. DISP_REG_DSI_STATE);
  1503. cmdqRecBackupRegisterToSlot(pgc->cmdq_handle_trigger, pgc->rdma_state_info, i * 5 + 0,
  1504. DISP_REG_RDMA_INT_STATUS);
  1505. cmdqRecBackupRegisterToSlot(pgc->cmdq_handle_trigger, pgc->rdma_state_info, i * 5 + 1,
  1506. DISP_REG_RDMA_IN_P_CNT);
  1507. cmdqRecBackupRegisterToSlot(pgc->cmdq_handle_trigger, pgc->rdma_state_info, i * 5 + 2,
  1508. DISP_REG_RDMA_IN_LINE_CNT);
  1509. cmdqRecBackupRegisterToSlot(pgc->cmdq_handle_trigger, pgc->rdma_state_info, i * 5 + 3,
  1510. DISP_REG_RDMA_OUT_P_CNT);
  1511. cmdqRecBackupRegisterToSlot(pgc->cmdq_handle_trigger, pgc->rdma_state_info, i * 5 + 4,
  1512. DISP_REG_RDMA_OUT_LINE_CNT);
  1513. }
  1514. }
  1515. /* SODI is disabled in config thread, so mutex enable/dsi start/CPU wait
  1516. * TE will not be blocked by SODI
  1517. */
  1518. /* should enable SODI here, */
  1519. if (gDisableSODIForTriggerLoop == 1)
  1520. disp_set_sodi(1, pgc->cmdq_handle_trigger);
  1521. /* waiting for frame done, because we can't use mutex stream eof here,
  1522. * so need to let dpmanager help to decide which event to wait
  1523. */
  1524. /* most time we wait rdmax frame done event. */
  1525. ret = cmdqRecWait(pgc->cmdq_handle_trigger, CMDQ_EVENT_DISP_RDMA0_EOF);
  1526. dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_trigger, CMDQ_WAIT_STREAM_EOF_EVENT);
  1527. /* dsi is not idle rightly after rdma frame done,
  1528. * so we need to polling about 1us for dsi returns to idle
  1529. */
  1530. /* do not polling dsi idle directly which will decrease CMDQ performance */
  1531. dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_trigger, CMDQ_CHECK_IDLE_AFTER_STREAM_EOF);
  1532. /* for some module(like COLOR) to read hw register to GPR after frame done */
  1533. dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_trigger, CMDQ_AFTER_STREAM_EOF);
  1534. #ifndef FORCE_SODI_CG_MODE
  1535. /* Enable EMI Power Down Mode */
  1536. cmdqRecWrite(pgc->cmdq_handle_trigger, 0x10006b04, 0, 0x80);
  1537. #endif
  1538. /* pull DSI clk lane to LP */
  1539. DSI_sw_clk_trail_cmdq(0, pgc->cmdq_handle_trigger);
  1540. /* polling DSI idle */
  1541. /* ret = cmdqRecPoll(pgc->cmdq_handle_trigger, 0x1401b00c, 0, 0x80000000); */
  1542. /* polling wdma frame done */
  1543. /* ret = cmdqRecPoll(pgc->cmdq_handle_trigger, 0x140060A0, 1, 0x1); */
  1544. /* now frame done, config thread is allowed to config register now */
  1545. ret = cmdqRecSetEventToken(pgc->cmdq_handle_trigger, CMDQ_SYNC_TOKEN_STREAM_EOF);
  1546. /* RUN forever!!!! */
  1547. BUG_ON(ret < 0);
  1548. }
  1549. /* dump trigger loop instructions to check whether dpmgr_path_build_cmdq works correctly */
  1550. DISPPRINT("primary display BUILD cmdq trigger loop finished\n");
  1551. return;
  1552. #endif
  1553. }
  1554. void disp_spm_enter_cg_mode(void)
  1555. {
  1556. MMProfileLogEx(ddp_mmp_get_events()->cg_mode, MMProfileFlagPulse, 0, 0);
  1557. }
  1558. void disp_spm_enter_power_down_mode(void)
  1559. {
  1560. MMProfileLogEx(ddp_mmp_get_events()->power_down_mode, MMProfileFlagPulse, 0, 0);
  1561. }
  1562. #if 0
  1563. /**
  1564. * Defined but not used, avoid build warning. (2015.1.30 Rynn Wu)
  1565. */
  1566. static void _cmdq_build_monitor_loop(void)
  1567. {
  1568. int ret = 0;
  1569. cmdqRecHandle g_cmdq_handle_monitor;
  1570. cmdqRecCreate(CMDQ_SCENARIO_DISP_SCREEN_CAPTURE, &(g_cmdq_handle_monitor));
  1571. DISPMSG("primary path monitor thread cmd handle=%p\n", g_cmdq_handle_monitor);
  1572. cmdqRecReset(g_cmdq_handle_monitor);
  1573. /* wait and clear stream_done, HW will assert mutex enable automatically in frame done reset. */
  1574. /* todo: should let dpmanager to decide wait which mutex's eof. */
  1575. ret = cmdqRecWait(g_cmdq_handle_monitor, CMDQ_EVENT_DISP_RDMA0_UNDERRUN);
  1576. cmdqRecReadToDataRegister(g_cmdq_handle_monitor, 0x10006b0c, CMDQ_DATA_REG_2D_SHARPNESS_1_DST);
  1577. cmdqRecWriteFromDataRegister(g_cmdq_handle_monitor, CMDQ_DATA_REG_2D_SHARPNESS_1_DST, 0x1401b280);
  1578. cmdqRecReadToDataRegister(g_cmdq_handle_monitor, 0x10006b08, CMDQ_DATA_REG_2D_SHARPNESS_1_DST);
  1579. cmdqRecWriteFromDataRegister(g_cmdq_handle_monitor, CMDQ_DATA_REG_2D_SHARPNESS_1_DST, 0x1401b284);
  1580. cmdqRecReadToDataRegister(g_cmdq_handle_monitor, 0x10006b04, CMDQ_DATA_REG_2D_SHARPNESS_1_DST);
  1581. cmdqRecWriteFromDataRegister(g_cmdq_handle_monitor, CMDQ_DATA_REG_2D_SHARPNESS_1_DST, 0x1401b288);
  1582. cmdqRecReadToDataRegister(g_cmdq_handle_monitor, 0x1401b16c, CMDQ_DATA_REG_2D_SHARPNESS_1_DST);
  1583. cmdqRecWriteFromDataRegister(g_cmdq_handle_monitor, CMDQ_DATA_REG_2D_SHARPNESS_1_DST, 0x1401b28C);
  1584. ret = cmdqRecStartLoop(g_cmdq_handle_monitor);
  1585. }
  1586. #endif
  1587. static void _cmdq_start_trigger_loop(void)
  1588. {
  1589. #ifndef MTK_FB_CMDQ_DISABLE
  1590. int ret = 0;
  1591. cmdqRecDumpCommand(pgc->cmdq_handle_trigger);
  1592. /* this should be called only once because trigger loop will nevet stop */
  1593. ret = cmdqRecStartLoop(pgc->cmdq_handle_trigger);
  1594. if (!primary_display_is_video_mode()) {
  1595. /* Need set esd check eof synctoken to let trigger loop go. */
  1596. if (_need_wait_esd_eof())
  1597. cmdqCoreSetEvent(CMDQ_SYNC_TOKEN_ESD_EOF);
  1598. /* need to set STREAM_EOF for the first time, otherwise we will stuck in dead loop */
  1599. cmdqCoreSetEvent(CMDQ_SYNC_TOKEN_STREAM_EOF);
  1600. cmdqCoreSetEvent(CMDQ_SYNC_TOKEN_CABC_EOF);
  1601. dprec_event_op(DPREC_EVENT_CMDQ_SET_EVENT_ALLOW);
  1602. } else {
  1603. #if 0
  1604. if (dpmgr_path_is_idle(pgc->dpmgr_handle))
  1605. cmdqCoreSetEvent(CMDQ_EVENT_MUTEX0_STREAM_EOF);
  1606. #endif
  1607. }
  1608. if (_is_decouple_mode(pgc->session_mode))
  1609. cmdqCoreSetEvent(CMDQ_EVENT_DISP_WDMA0_EOF);
  1610. DISPPRINT("primary display START cmdq trigger loop finished\n");
  1611. #endif
  1612. }
  1613. static void _cmdq_stop_trigger_loop(void)
  1614. {
  1615. #ifndef MTK_FB_CMDQ_DISABLE
  1616. int ret = 0;
  1617. /* this should be called only once because trigger loop will nevet stop */
  1618. ret = cmdqRecStopLoop(pgc->cmdq_handle_trigger);
  1619. DISPCHECK("primary display STOP cmdq trigger loop finished\n");
  1620. #endif
  1621. }
  1622. static void _cmdq_set_config_handle_dirty(void)
  1623. {
  1624. #ifndef MTK_FB_CMDQ_DISABLE
  1625. if (!primary_display_is_video_mode()) {
  1626. dprec_logger_start(DPREC_LOGGER_PRIMARY_CMDQ_SET_DIRTY, 0, 0);
  1627. /* only command mode need to set dirty */
  1628. cmdqRecSetEventToken(pgc->cmdq_handle_config, CMDQ_SYNC_TOKEN_CONFIG_DIRTY);
  1629. dprec_event_op(DPREC_EVENT_CMDQ_SET_DIRTY);
  1630. dprec_logger_done(DPREC_LOGGER_PRIMARY_CMDQ_SET_DIRTY, 0, 0);
  1631. }
  1632. #endif
  1633. }
  1634. static void _cmdq_set_config_handle_dirty_mira(void *handle)
  1635. {
  1636. #ifndef MTK_FB_CMDQ_DISABLE
  1637. if (!primary_display_is_video_mode()) {
  1638. dprec_logger_start(DPREC_LOGGER_PRIMARY_CMDQ_SET_DIRTY, 0, 0);
  1639. /* only command mode need to set dirty */
  1640. cmdqRecSetEventToken(handle, CMDQ_SYNC_TOKEN_CONFIG_DIRTY);
  1641. dprec_event_op(DPREC_EVENT_CMDQ_SET_DIRTY);
  1642. dprec_logger_done(DPREC_LOGGER_PRIMARY_CMDQ_SET_DIRTY, 0, 0);
  1643. }
  1644. #endif
  1645. }
  1646. static void _cmdq_reset_config_handle(void)
  1647. {
  1648. #ifndef MTK_FB_CMDQ_DISABLE
  1649. cmdqRecReset(pgc->cmdq_handle_config);
  1650. dprec_event_op(DPREC_EVENT_CMDQ_RESET);
  1651. #endif
  1652. }
  1653. static void _cmdq_flush_config_handle(int blocking, void *callback, unsigned int userdata)
  1654. {
  1655. #ifndef MTK_FB_CMDQ_DISABLE
  1656. dprec_logger_start(DPREC_LOGGER_PRIMARY_CMDQ_FLUSH, blocking,
  1657. (unsigned int)(unsigned long)callback);
  1658. if (blocking) {
  1659. /* DISPERR("Should not use blocking cmdq flush,
  1660. * may block primary display path for 1 frame period\n");
  1661. */
  1662. cmdqRecFlush(pgc->cmdq_handle_config);
  1663. } else {
  1664. if (callback)
  1665. cmdqRecFlushAsyncCallback(pgc->cmdq_handle_config, callback, userdata);
  1666. else
  1667. cmdqRecFlushAsync(pgc->cmdq_handle_config);
  1668. }
  1669. dprec_event_op(DPREC_EVENT_CMDQ_FLUSH);
  1670. dprec_logger_done(DPREC_LOGGER_PRIMARY_CMDQ_FLUSH, userdata, 0);
  1671. #endif
  1672. }
  1673. static void _cmdq_flush_config_handle_mira(void *handle, int blocking)
  1674. {
  1675. #ifndef MTK_FB_CMDQ_DISABLE
  1676. dprec_logger_start(DPREC_LOGGER_PRIMARY_CMDQ_FLUSH, 0, 0);
  1677. if (blocking)
  1678. cmdqRecFlush(handle);
  1679. else
  1680. cmdqRecFlushAsync(handle);
  1681. dprec_event_op(DPREC_EVENT_CMDQ_FLUSH);
  1682. dprec_logger_done(DPREC_LOGGER_PRIMARY_CMDQ_FLUSH, 0, 0);
  1683. #endif
  1684. }
  1685. static void _cmdq_insert_wait_frame_done_token(void)
  1686. {
  1687. #ifndef MTK_FB_CMDQ_DISABLE
  1688. if (primary_display_is_video_mode())
  1689. cmdqRecWaitNoClear(pgc->cmdq_handle_config, CMDQ_EVENT_MUTEX0_STREAM_EOF);
  1690. else
  1691. cmdqRecWaitNoClear(pgc->cmdq_handle_config, CMDQ_SYNC_TOKEN_STREAM_EOF);
  1692. dprec_event_op(DPREC_EVENT_CMDQ_WAIT_STREAM_EOF);
  1693. #endif
  1694. }
  1695. void _cmdq_insert_wait_frame_done_token_mira(void *handle)
  1696. {
  1697. #ifndef MTK_FB_CMDQ_DISABLE
  1698. if (primary_display_is_video_mode())
  1699. cmdqRecWaitNoClear(handle, CMDQ_EVENT_MUTEX0_STREAM_EOF);
  1700. else
  1701. cmdqRecWaitNoClear(handle, CMDQ_SYNC_TOKEN_STREAM_EOF);
  1702. dprec_event_op(DPREC_EVENT_CMDQ_WAIT_STREAM_EOF);
  1703. #endif
  1704. }
  1705. static int primary_display_is_secure_path(DISP_SESSION_TYPE session_type)
  1706. {
  1707. int i;
  1708. disp_session_input_config *session_input;
  1709. session_input = &cached_session_input[session_type - 1];
  1710. for (i = 0; i < session_input->config_layer_num; i++) {
  1711. if (session_input->config[i].layer_enable &&
  1712. (session_input->config[i].security == DISP_SECURE_BUFFER))
  1713. return 1;
  1714. }
  1715. return 0;
  1716. }
  1717. static void directlink_path_add_memory(WDMA_CONFIG_STRUCT *p_wdma)
  1718. {
  1719. int ret = 0;
  1720. int secure_path_on = primary_display_is_secure_path(DISP_SESSION_PRIMARY);
  1721. cmdqRecHandle cmdq_handle = NULL;
  1722. cmdqRecHandle cmdq_wait_handle = NULL;
  1723. disp_ddp_path_config *pconfig = NULL;
  1724. /*create config thread*/
  1725. ret = cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &cmdq_handle);
  1726. if (ret != 0) {
  1727. DISPCHECK("dl_to_dc capture:Fail to create cmdq handle\n");
  1728. ret = -1;
  1729. goto out;
  1730. }
  1731. cmdqRecReset(cmdq_handle);
  1732. /*create wait thread*/
  1733. ret = cmdqRecCreate(CMDQ_SCENARIO_DISP_SCREEN_CAPTURE, &cmdq_wait_handle);
  1734. if (ret != 0) {
  1735. DISPCHECK("dl_to_dc capture:Fail to create cmdq wait handle\n");
  1736. ret = -1;
  1737. goto out;
  1738. }
  1739. cmdqRecReset(cmdq_wait_handle);
  1740. /*configure config thread*/
  1741. if (!secure_path_on)
  1742. cmdqRecEnablePrefetch(cmdq_handle);
  1743. _cmdq_insert_wait_frame_done_token_mira(cmdq_handle);
  1744. dpmgr_path_add_memout(pgc->dpmgr_handle, ENGINE_OVL0, cmdq_handle);
  1745. pconfig = dpmgr_path_get_last_config(pgc->dpmgr_handle);
  1746. pconfig->wdma_config = *p_wdma;
  1747. pconfig->wdma_dirty = 1;
  1748. ret = dpmgr_path_config(pgc->dpmgr_handle, pconfig, cmdq_handle);
  1749. _cmdq_set_config_handle_dirty_mira(cmdq_handle);
  1750. dpmgr_wdma_path_force_power_on();
  1751. if (!secure_path_on)
  1752. cmdqRecDisablePrefetch(cmdq_handle);
  1753. _cmdq_flush_config_handle_mira(cmdq_handle, 0);
  1754. DISPMSG("dl_to_dc capture:Flush add memout mva(0x%lx)\n", p_wdma->dstAddress);
  1755. /*wait wdma0 sof*/
  1756. cmdqRecWait(cmdq_wait_handle, CMDQ_EVENT_DISP_WDMA0_SOF);
  1757. cmdqRecFlush(cmdq_wait_handle);
  1758. DISPMSG("dl_to_dc capture:Flush wait wdma sof\n");
  1759. #if 0
  1760. cmdqRecReset(cmdq_handle);
  1761. _cmdq_insert_wait_frame_done_token_mira(cmdq_handle);
  1762. dpmgr_path_remove_memout(pgc->dpmgr_handle, cmdq_handle);
  1763. _cmdq_set_config_handle_dirty_mira(cmdq_handle);
  1764. /* flush remove memory to cmdq */
  1765. _cmdq_flush_config_handle_mira(cmdq_handle, 0);
  1766. DISPMSG("dl_to_dc capture: Flush remove memout\n");
  1767. dpmgr_path_memout_clock(pgc->dpmgr_handle, 0);
  1768. #endif
  1769. out:
  1770. cmdqRecDestroy(cmdq_handle);
  1771. cmdqRecDestroy(cmdq_wait_handle);
  1772. }
  1773. static unsigned int _get_switch_dc_buffer(void)
  1774. {
  1775. #ifdef CONFIG_MTK_GMO_RAM_OPTIMIZE
  1776. return pgc->dc_buf[0];
  1777. #else
  1778. if (primary_display_is_secure_path(DISP_SESSION_PRIMARY))
  1779. return pgc->session_buf[pgc->session_buf_id];
  1780. else
  1781. return pgc->dc_buf[pgc->dc_buf_id];
  1782. #endif
  1783. }
  1784. static int _DL_switch_to_DC_fast(void)
  1785. {
  1786. int ret = 0;
  1787. int secure_path_on = primary_display_is_secure_path(DISP_SESSION_PRIMARY);
  1788. RDMA_CONFIG_STRUCT rdma_config = decouple_rdma_config;
  1789. WDMA_CONFIG_STRUCT wdma_config = decouple_wdma_config;
  1790. disp_ddp_path_config *data_config_dl = NULL;
  1791. disp_ddp_path_config *data_config_dc = NULL;
  1792. unsigned int mva;
  1793. mva = _get_switch_dc_buffer();
  1794. wdma_config.dstAddress = mva;
  1795. if (secure_path_on)
  1796. wdma_config.security = DISP_SECURE_BUFFER;
  1797. else
  1798. wdma_config.security = DISP_NORMAL_BUFFER;
  1799. /* disable SODI by CPU to prevent underflow */
  1800. #if defined(MTK_FB_SODI_SUPPORT) && !defined(CONFIG_FPGA_EARLY_PORTING)
  1801. spm_enable_sodi(0);
  1802. #endif
  1803. /* 1.save a temp frame to intermediate buffer */
  1804. directlink_path_add_memory(&wdma_config);
  1805. /* 2.reset primary handle */
  1806. _cmdq_reset_config_handle();
  1807. if (!secure_path_on)
  1808. cmdqRecEnablePrefetch(pgc->cmdq_handle_config);
  1809. _cmdq_insert_wait_frame_done_token();
  1810. /* 3.modify interface path handle to new scenario(rdma->dsi) */
  1811. #ifdef CONFIG_FOR_SOURCE_PQ
  1812. dpmgr_modify_path(pgc->dpmgr_handle, DDP_SCENARIO_PRIMARY_RDMA0_DISP, pgc->cmdq_handle_config,
  1813. primary_display_is_video_mode() ? DDP_VIDEO_MODE : DDP_CMD_MODE);
  1814. #else
  1815. dpmgr_modify_path(pgc->dpmgr_handle, DDP_SCENARIO_PRIMARY_RDMA0_COLOR0_DISP, pgc->cmdq_handle_config,
  1816. primary_display_is_video_mode() ? DDP_VIDEO_MODE : DDP_CMD_MODE);
  1817. #endif
  1818. /* 4.config rdma from directlink mode to memory mode */
  1819. rdma_config.address = mva;
  1820. rdma_config.security = DISP_NORMAL_BUFFER;
  1821. rdma_config.pitch = primary_display_get_width() * DP_COLOR_BITS_PER_PIXEL(rdma_config.inputFormat) >> 3;
  1822. if (secure_path_on) {
  1823. rdma_config.address = pgc->session_buf[pgc->session_buf_id];
  1824. rdma_config.security = DISP_SECURE_BUFFER;
  1825. }
  1826. data_config_dl = dpmgr_path_get_last_config(pgc->dpmgr_handle);
  1827. data_config_dl->rdma_config = rdma_config;
  1828. data_config_dl->rdma_dirty = 1;
  1829. ret = dpmgr_path_config(pgc->dpmgr_handle, data_config_dl, pgc->cmdq_handle_config);
  1830. /* 5. backup rdma address to slots */
  1831. cmdqRecBackupUpdateSlot(pgc->cmdq_handle_config, pgc->rdma_buff_info, 0, mva);
  1832. /* 6 .flush to cmdq */
  1833. _cmdq_set_config_handle_dirty();
  1834. if (!secure_path_on)
  1835. cmdqRecDisablePrefetch(pgc->cmdq_handle_config);
  1836. _cmdq_flush_config_handle(1, NULL, 0);
  1837. /* ddp_mmp_rdma_layer(&rdma_config, 0, 20, 20); */
  1838. /* 7.reset cmdq */
  1839. _cmdq_reset_config_handle();
  1840. _cmdq_insert_wait_frame_done_token();
  1841. /* 9. create ovl2mem path handle */
  1842. cmdqRecReset(pgc->cmdq_handle_ovl1to2_config);
  1843. #ifdef CONFIG_FOR_SOURCE_PQ
  1844. pgc->ovl2mem_path_handle = dpmgr_create_path(DDP_SCENARIO_PRIMARY_DITHER_MEMOUT,
  1845. pgc->cmdq_handle_ovl1to2_config);
  1846. #else
  1847. pgc->ovl2mem_path_handle = dpmgr_create_path(DDP_SCENARIO_PRIMARY_OVL_MEMOUT,
  1848. pgc->cmdq_handle_ovl1to2_config);
  1849. #endif
  1850. if (pgc->ovl2mem_path_handle) {
  1851. DISPCHECK("dpmgr create ovl memout path SUCCESS(%p)\n", pgc->ovl2mem_path_handle);
  1852. } else {
  1853. DISPCHECK("dpmgr create path FAIL\n");
  1854. return -1;
  1855. }
  1856. dpmgr_path_set_video_mode(pgc->ovl2mem_path_handle, 0);
  1857. #ifndef CONFIG_MTK_CLKMGR
  1858. ddp_clk_prepare(DISP_MTCMOS_CLK);
  1859. #endif
  1860. dpmgr_path_init(pgc->ovl2mem_path_handle, CMDQ_ENABLE);
  1861. data_config_dc = dpmgr_path_get_last_config(pgc->ovl2mem_path_handle);
  1862. data_config_dc->dst_w = rdma_config.width;
  1863. data_config_dc->dst_h = rdma_config.height;
  1864. data_config_dc->dst_dirty = 1;
  1865. /* move ovl config info from dl to dc */
  1866. memcpy(data_config_dc->ovl_config, data_config_dl->ovl_config, sizeof(data_config_dl->ovl_config));
  1867. ret = dpmgr_path_config(pgc->ovl2mem_path_handle, data_config_dc, pgc->cmdq_handle_ovl1to2_config);
  1868. ret = dpmgr_path_start(pgc->ovl2mem_path_handle, CMDQ_ENABLE);
  1869. /* use blocking flush to make sure all config is done. */
  1870. /* cmdqRecDumpCommand(pgc->cmdq_handle_ovl1to2_config); */
  1871. cmdqRecClearEventToken(pgc->cmdq_handle_ovl1to2_config, CMDQ_EVENT_DISP_WDMA0_EOF);
  1872. _cmdq_flush_config_handle_mira(pgc->cmdq_handle_ovl1to2_config, 1);
  1873. cmdqRecReset(pgc->cmdq_handle_ovl1to2_config);
  1874. /* 11..enable event for new path */
  1875. /* dpmgr_enable_event(pgc->ovl2mem_path_handle, DISP_PATH_EVENT_FRAME_COMPLETE); */
  1876. /* dpmgr_map_event_to_irq(pgc->ovl2mem_path_handle, DISP_PATH_EVENT_FRAME_START, DDP_IRQ_WDMA0_FRAME_COMPLETE); */
  1877. /* dpmgr_enable_event(pgc->ovl2mem_path_handle, DISP_PATH_EVENT_FRAME_START); */
  1878. if (primary_display_is_video_mode())
  1879. dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, DDP_IRQ_RDMA0_DONE);
  1880. dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC);
  1881. /* dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE); */
  1882. dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_START);
  1883. /* enable SODI after switch */
  1884. #if defined(MTK_FB_SODI_SUPPORT) && !defined(CONFIG_FPGA_EARLY_PORTING)
  1885. spm_enable_sodi(1);
  1886. #endif
  1887. return ret;
  1888. }
  1889. static int _DC_switch_to_DL_fast(void)
  1890. {
  1891. int ret = 0;
  1892. int layer = 0;
  1893. int secure_path_on = primary_display_is_secure_path(DISP_SESSION_PRIMARY);
  1894. disp_ddp_path_config *data_config_dl = NULL;
  1895. disp_ddp_path_config *data_config_dc = NULL;
  1896. OVL_CONFIG_STRUCT ovl_config[OVL_LAYER_NUM];
  1897. if(!pgc->ovl2mem_path_handle)
  1898. return -1;
  1899. /* 1. disable SODI */
  1900. #if defined(MTK_FB_SODI_SUPPORT) && !defined(CONFIG_FPGA_EARLY_PORTING)
  1901. spm_enable_sodi(0);
  1902. #endif
  1903. /* 2.enable ovl/wdma clock */
  1904. /* 3.destroy ovl->mem path. */
  1905. #if defined(OVL_TIME_SHARING)
  1906. data_config_dc = &last_primary_config;
  1907. #else
  1908. data_config_dc = dpmgr_path_get_last_config(pgc->ovl2mem_path_handle);
  1909. #endif
  1910. /*save ovl info */;
  1911. memcpy(ovl_config, data_config_dc->ovl_config, sizeof(ovl_config));
  1912. dpmgr_path_deinit(pgc->ovl2mem_path_handle,
  1913. (int)(unsigned long)pgc->cmdq_handle_ovl1to2_config);
  1914. #ifndef CONFIG_MTK_CLKMGR
  1915. ddp_clk_unprepare(DISP_MTCMOS_CLK);
  1916. #endif
  1917. dpmgr_destroy_path(pgc->ovl2mem_path_handle, pgc->cmdq_handle_ovl1to2_config);
  1918. pgc->ovl2mem_path_handle = NULL;
  1919. /*clear sof token for next dl to dc */
  1920. cmdqRecClearEventToken(pgc->cmdq_handle_ovl1to2_config, CMDQ_EVENT_DISP_WDMA0_SOF);
  1921. _cmdq_flush_config_handle_mira(pgc->cmdq_handle_ovl1to2_config, 1);
  1922. cmdqRecReset(pgc->cmdq_handle_ovl1to2_config);
  1923. /* release output buffer */
  1924. layer = disp_sync_get_output_timeline_id();
  1925. mtkfb_release_layer_fence(primary_session_id, layer);
  1926. /* 4.modify interface path handle to new scenario(rdma->dsi) */
  1927. _cmdq_reset_config_handle();
  1928. if (!secure_path_on)
  1929. cmdqRecEnablePrefetch(pgc->cmdq_handle_config);
  1930. _cmdq_insert_wait_frame_done_token();
  1931. dpmgr_modify_path(pgc->dpmgr_handle, DDP_SCENARIO_PRIMARY_DISP, pgc->cmdq_handle_config,
  1932. primary_display_is_video_mode() ? DDP_VIDEO_MODE : DDP_CMD_MODE);
  1933. /* 5.config rdma from memory mode to directlink mode */
  1934. data_config_dl = dpmgr_path_get_last_config(pgc->dpmgr_handle);
  1935. data_config_dl->rdma_config = decouple_rdma_config;
  1936. data_config_dl->rdma_config.address = 0;
  1937. data_config_dl->rdma_config.pitch = 0;
  1938. data_config_dl->rdma_config.security = DISP_NORMAL_BUFFER;
  1939. data_config_dl->rdma_dirty = 1;
  1940. memcpy(data_config_dl->ovl_config, ovl_config, sizeof(ovl_config));
  1941. data_config_dl->ovl_dirty = 1;
  1942. ret = dpmgr_path_config(pgc->dpmgr_handle, data_config_dl, pgc->cmdq_handle_config);
  1943. /* use blocking flush to make sure all config is done, then stop/start trigger loop */
  1944. cmdqRecBackupUpdateSlot(pgc->cmdq_handle_config, pgc->rdma_buff_info, 0, 0);
  1945. /* cmdqRecDumpCommand(pgc->cmdq_handle_config); */
  1946. _cmdq_set_config_handle_dirty();
  1947. if (!secure_path_on)
  1948. cmdqRecDisablePrefetch(pgc->cmdq_handle_config);
  1949. _cmdq_flush_config_handle(1, NULL, 0);
  1950. /* release output buffer */
  1951. layer = disp_sync_get_output_interface_timeline_id();
  1952. mtkfb_release_layer_fence(primary_session_id, layer);
  1953. _cmdq_reset_config_handle();
  1954. _cmdq_insert_wait_frame_done_token();
  1955. /* 9.enable event for new path */
  1956. if (primary_display_is_video_mode())
  1957. dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, DDP_IRQ_RDMA0_DONE);
  1958. dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC);
  1959. dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE);
  1960. dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_START);
  1961. /* 1. enable SODI */
  1962. #if defined(MTK_FB_SODI_SUPPORT) && !defined(CONFIG_FPGA_EARLY_PORTING)
  1963. spm_enable_sodi(1);
  1964. #endif
  1965. return ret;
  1966. }
  1967. const char *session_mode_spy(unsigned int mode)
  1968. {
  1969. switch (mode) {
  1970. case DISP_SESSION_DIRECT_LINK_MODE:
  1971. return "DIRECT_LINK";
  1972. case DISP_SESSION_DIRECT_LINK_MIRROR_MODE:
  1973. return "DIRECT_LINK_MIRROR";
  1974. case DISP_SESSION_DECOUPLE_MODE:
  1975. return "DECOUPLE";
  1976. case DISP_SESSION_DECOUPLE_MIRROR_MODE:
  1977. return "DECOUPLE_MIRROR";
  1978. default:
  1979. return "UNKNOWN";
  1980. }
  1981. }
  1982. static int config_display_m4u_port(void)
  1983. {
  1984. int ret = 0;
  1985. M4U_PORT_STRUCT sPort;
  1986. sPort.ePortID = M4U_PORT_DISP_OVL0;
  1987. sPort.Virtuality = primary_display_use_m4u;
  1988. sPort.Security = 0;
  1989. sPort.Distance = 1;
  1990. sPort.Direction = 0;
  1991. ret = m4u_config_port(&sPort);
  1992. if (ret == 0) {
  1993. DISPCHECK("config M4U Port %s to %s SUCCESS\n",
  1994. ddp_get_module_name(DISP_MODULE_OVL0),
  1995. primary_display_use_m4u ? "virtual" : "physical");
  1996. } else {
  1997. DISPCHECK("config M4U Port %s to %s FAIL(ret=%d)\n",
  1998. ddp_get_module_name(DISP_MODULE_OVL0),
  1999. primary_display_use_m4u ? "virtual" : "physical", ret);
  2000. return -1;
  2001. }
  2002. #ifdef OVL_CASCADE_SUPPORT
  2003. sPort.ePortID = M4U_PORT_DISP_OVL1;
  2004. ret = m4u_config_port(&sPort);
  2005. if (ret) {
  2006. DISPCHECK("config M4U Port %s to %s FAIL(ret=%d)\n",
  2007. ddp_get_module_name(DISP_MODULE_OVL1),
  2008. primary_display_use_m4u ? "virtual" : "physical", ret);
  2009. return -1;
  2010. }
  2011. #endif
  2012. sPort.ePortID = M4U_PORT_DISP_RDMA0;
  2013. ret = m4u_config_port(&sPort);
  2014. if (ret) {
  2015. DISPCHECK("config M4U Port %s to %s FAIL(ret=%d)\n",
  2016. ddp_get_module_name(DISP_MODULE_RDMA0),
  2017. primary_display_use_m4u ? "virtual" : "physical", ret);
  2018. return -1;
  2019. }
  2020. sPort.ePortID = M4U_PORT_DISP_WDMA0;
  2021. ret = m4u_config_port(&sPort);
  2022. if (ret) {
  2023. DISPCHECK("config M4U Port %s to %s FAIL(ret=%d)\n",
  2024. ddp_get_module_name(DISP_MODULE_WDMA0),
  2025. primary_display_use_m4u ? "virtual" : "physical", ret);
  2026. return -1;
  2027. }
  2028. return ret;
  2029. }
  2030. static disp_internal_buffer_info *allocat_decouple_buffer(int size)
  2031. {
  2032. void *buffer_va = NULL;
  2033. unsigned int buffer_mva = 0;
  2034. unsigned int mva_size = 0;
  2035. struct ion_client *client = NULL;
  2036. struct ion_handle *handle = NULL;
  2037. disp_internal_buffer_info *buf_info = NULL;
  2038. struct ion_mm_data mm_data;
  2039. memset((void *)&mm_data, 0, sizeof(struct ion_mm_data));
  2040. client = ion_client_create(g_ion_device, "disp_decouple");
  2041. buf_info = kzalloc(sizeof(disp_internal_buffer_info), GFP_KERNEL);
  2042. if (buf_info) {
  2043. handle = ion_alloc(client, size, 0, ION_HEAP_MULTIMEDIA_MASK, 0);
  2044. if (IS_ERR(handle)) {
  2045. DISPERR("Fatal Error, ion_alloc for size %d failed\n", size);
  2046. ion_free(client, handle);
  2047. ion_client_destroy(client);
  2048. kfree(buf_info);
  2049. return NULL;
  2050. }
  2051. buffer_va = ion_map_kernel(client, handle);
  2052. if (buffer_va == NULL) {
  2053. DISPERR("ion_map_kernrl failed\n");
  2054. ion_free(client, handle);
  2055. ion_client_destroy(client);
  2056. kfree(buf_info);
  2057. return NULL;
  2058. }
  2059. mm_data.config_buffer_param.kernel_handle = handle;
  2060. mm_data.mm_cmd = ION_MM_CONFIG_BUFFER;
  2061. if (ion_kernel_ioctl(client, ION_CMD_MULTIMEDIA, (unsigned long)&mm_data) < 0) {
  2062. DISPERR("ion_test_drv: Config buffer failed.\n");
  2063. ion_free(client, handle);
  2064. ion_client_destroy(client);
  2065. kfree(buf_info);
  2066. return NULL;
  2067. }
  2068. ion_phys(client, handle, (ion_phys_addr_t *) &buffer_mva, (size_t *) &mva_size);
  2069. if (buffer_mva == 0) {
  2070. DISPERR("Fatal Error, get mva failed\n");
  2071. ion_free(client, handle);
  2072. ion_client_destroy(client);
  2073. kfree(buf_info);
  2074. return NULL;
  2075. }
  2076. buf_info->handle = handle;
  2077. buf_info->mva = buffer_mva;
  2078. buf_info->size = mva_size;
  2079. buf_info->va = buffer_va;
  2080. buf_info->client = client;
  2081. } else {
  2082. DISPERR("Fatal error, kzalloc internal buffer info failed!!\n");
  2083. kfree(buf_info);
  2084. return NULL;
  2085. }
  2086. return buf_info;
  2087. }
  2088. static int init_decouple_buffers(void)
  2089. {
  2090. int i = 0;
  2091. int height = primary_display_get_height();
  2092. int width = primary_display_get_width();
  2093. int bpp = primary_display_get_dc_bpp();
  2094. int buffer_size = width * height * bpp / 8;
  2095. for (i = 0; i < DISP_INTERNAL_BUFFER_COUNT; i++) {
  2096. decouple_buffer_info[i] = allocat_decouple_buffer(buffer_size);
  2097. if (decouple_buffer_info[i] != NULL) {
  2098. pgc->dc_buf[i] = decouple_buffer_info[i]->mva;
  2099. dc_vAddr[i] = (unsigned long)decouple_buffer_info[i]->va;
  2100. }
  2101. }
  2102. /*initialize rdma config */
  2103. decouple_rdma_config.height = height;
  2104. decouple_rdma_config.width = width;
  2105. decouple_rdma_config.idx = 0;
  2106. decouple_rdma_config.inputFormat = eRGB888;
  2107. decouple_rdma_config.pitch = width * DP_COLOR_BITS_PER_PIXEL(eRGB888) / 8;
  2108. decouple_rdma_config.security = DISP_NORMAL_BUFFER;
  2109. /*initialize wdma config */
  2110. decouple_wdma_config.srcHeight = height;
  2111. decouple_wdma_config.srcWidth = width;
  2112. decouple_wdma_config.clipX = 0;
  2113. decouple_wdma_config.clipY = 0;
  2114. decouple_wdma_config.clipHeight = height;
  2115. decouple_wdma_config.clipWidth = width;
  2116. decouple_wdma_config.outputFormat = eRGB888;
  2117. decouple_wdma_config.useSpecifiedAlpha = 1;
  2118. decouple_wdma_config.alpha = 0xFF;
  2119. decouple_wdma_config.dstPitch = width * DP_COLOR_BITS_PER_PIXEL(eRGB888) / 8;
  2120. decouple_wdma_config.security = DISP_NORMAL_BUFFER;
  2121. return 0;
  2122. }
  2123. #if defined(CONFIG_MTK_GMO_RAM_OPTIMIZE)
  2124. static int allocate_idle_lp_dc_buffer(void)
  2125. {
  2126. int height = primary_display_get_height();
  2127. int width = primary_display_get_width();
  2128. int bpp = primary_display_get_dc_bpp();
  2129. int buffer_size = width * height * bpp / 8;
  2130. decouple_buffer_info[0] = allocat_decouple_buffer(buffer_size);
  2131. if (decouple_buffer_info[0] != NULL) {
  2132. pgc->dc_buf[0] = decouple_buffer_info[0]->mva;
  2133. dc_vAddr[0] = (unsigned long)decouple_buffer_info[0]->va;
  2134. } else {
  2135. return -1;
  2136. }
  2137. /*initialize rdma config*/
  2138. decouple_rdma_config.height = height;
  2139. decouple_rdma_config.width = width;
  2140. decouple_rdma_config.idx = 0;
  2141. decouple_rdma_config.inputFormat = eRGB888;
  2142. decouple_rdma_config.pitch = width * DP_COLOR_BITS_PER_PIXEL(eRGB888) / 8;
  2143. decouple_rdma_config.security = DISP_NORMAL_BUFFER;
  2144. /*initialize wdma config*/
  2145. decouple_wdma_config.srcHeight = height;
  2146. decouple_wdma_config.srcWidth = width;
  2147. decouple_wdma_config.clipX = 0;
  2148. decouple_wdma_config.clipY = 0;
  2149. decouple_wdma_config.clipHeight = height;
  2150. decouple_wdma_config.clipWidth = width;
  2151. decouple_wdma_config.outputFormat = eRGB888;
  2152. decouple_wdma_config.useSpecifiedAlpha = 1;
  2153. decouple_wdma_config.alpha = 0xFF;
  2154. decouple_wdma_config.dstPitch = width * DP_COLOR_BITS_PER_PIXEL(eRGB888) / 8;
  2155. decouple_wdma_config.security = DISP_NORMAL_BUFFER;
  2156. return 0;
  2157. }
  2158. static int release_idle_lp_dc_buffer(unsigned int need_primary_lock)
  2159. {
  2160. if (need_primary_lock)
  2161. _primary_path_lock(__func__);
  2162. if (decouple_buffer_info[0]) {
  2163. ion_free(decouple_buffer_info[0]->client, decouple_buffer_info[0]->handle);
  2164. ion_client_destroy(decouple_buffer_info[0]->client);
  2165. kfree(decouple_buffer_info[0]);
  2166. decouple_buffer_info[0] = NULL;
  2167. }
  2168. if (need_primary_lock)
  2169. _primary_path_unlock(__func__);
  2170. return 0;
  2171. }
  2172. #endif
  2173. static int __build_path_direct_link(void)
  2174. {
  2175. int ret = 0;
  2176. DISP_MODULE_ENUM dst_module = 0;
  2177. /* DISPFUNC();*/
  2178. DISPPRINT("%s\n", __func__);
  2179. pgc->mode = DIRECT_LINK_MODE;
  2180. pgc->dpmgr_handle = dpmgr_create_path(DDP_SCENARIO_PRIMARY_DISP, pgc->cmdq_handle_config);
  2181. if (pgc->dpmgr_handle) {
  2182. DISPPRINT("dpmgr create path SUCCESS(0x%p)\n", pgc->dpmgr_handle);
  2183. } else {
  2184. DISPERR("dpmgr create path FAIL\n");
  2185. return -1;
  2186. }
  2187. dst_module = _get_dst_module_by_lcm(pgc->plcm);
  2188. dpmgr_path_set_dst_module(pgc->dpmgr_handle, dst_module);
  2189. DISPCHECK("dpmgr set dst module FINISHED(%s)\n", ddp_get_module_name(dst_module));
  2190. #ifndef MTKFB_NO_M4U
  2191. config_display_m4u_port();
  2192. #if !defined(CONFIG_MTK_GMO_RAM_OPTIMIZE)
  2193. init_decouple_buffers();
  2194. #endif
  2195. #endif
  2196. dpmgr_set_lcm_utils(pgc->dpmgr_handle, pgc->plcm->drv);
  2197. dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC);
  2198. dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE);
  2199. dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_START);
  2200. /* set video mode must before path_init */
  2201. dpmgr_path_set_video_mode(pgc->dpmgr_handle, primary_display_is_video_mode());
  2202. #ifndef CONFIG_MTK_CLKMGR
  2203. ddp_clk_prepare(DISP_MTCMOS_CLK);
  2204. #endif
  2205. #ifndef MTK_FB_CMDQ_DISABLE
  2206. dpmgr_path_init(pgc->dpmgr_handle, CMDQ_ENABLE);
  2207. /* cmdqRecFlush(pgc->cmdq_handle_config); */
  2208. #else
  2209. dpmgr_path_init(pgc->dpmgr_handle, CMDQ_DISABLE);
  2210. #endif
  2211. return ret;
  2212. }
  2213. static void copy_lklogo_to_dc_buf(void)
  2214. {
  2215. unsigned int line, k, src_argb8888;
  2216. unsigned int *s;
  2217. unsigned char *d;
  2218. for (line = 0; line < primary_display_get_height(); line++) {
  2219. d = (char *)(dc_vAddr[0] + line * primary_display_get_width() * DP_COLOR_BITS_PER_PIXEL(eRGB888) / 8);
  2220. s = (int *)(pgc->framebuffer_va + line * ALIGN_TO(primary_display_get_width(),
  2221. MTK_FB_ALIGNMENT) * primary_display_get_dc_bpp() / 8);
  2222. for (k = 0; k < primary_display_get_width(); k++) {
  2223. src_argb8888 = *s++;
  2224. *d++ = ((src_argb8888 & 0xFF));
  2225. *d++ = ((src_argb8888 & 0xFF00) >> 8);
  2226. *d++ = ((src_argb8888 & 0xFF0000) >> 16);
  2227. }
  2228. }
  2229. }
  2230. static int _build_path_rdma_to_dsi(void)
  2231. {
  2232. DISP_MODULE_ENUM dst_module = 0;
  2233. uint32_t writing_mva = 0;
  2234. #ifdef CONFIG_FOR_SOURCE_PQ
  2235. pgc->dpmgr_handle =
  2236. dpmgr_create_path(DDP_SCENARIO_PRIMARY_RDMA0_DISP, pgc->cmdq_handle_config);
  2237. #else
  2238. pgc->dpmgr_handle =
  2239. dpmgr_create_path(DDP_SCENARIO_PRIMARY_RDMA0_COLOR0_DISP, pgc->cmdq_handle_config);
  2240. #endif
  2241. if (pgc->dpmgr_handle) {
  2242. DISPCHECK("dpmgr create interface path SUCCESS\n");
  2243. } else {
  2244. DISPCHECK("dpmgr create path FAIL\n");
  2245. return -1;
  2246. }
  2247. /* VSYNC event will be provided to hwc for system vsync hw source
  2248. * FRAME_DONE will be used in esd/suspend/resume for path status check
  2249. */
  2250. dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC);
  2251. dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE);
  2252. dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_START);
  2253. dpmgr_set_lcm_utils(pgc->dpmgr_handle, pgc->plcm->drv);
  2254. dst_module = _get_dst_module_by_lcm(pgc->plcm);
  2255. dpmgr_path_set_dst_module(pgc->dpmgr_handle, dst_module);
  2256. dpmgr_path_set_video_mode(pgc->dpmgr_handle, primary_display_is_video_mode());
  2257. if (primary_display_is_video_mode())
  2258. _cmdq_insert_wait_frame_done_token();
  2259. #ifndef CONFIG_MTK_CLKMGR
  2260. ddp_clk_prepare(DISP_MTCMOS_CLK);
  2261. #endif
  2262. dpmgr_path_init(pgc->dpmgr_handle, CMDQ_ENABLE);
  2263. writing_mva = pgc->dc_buf[pgc->dc_buf_id];
  2264. DISPMSG("writing_mva = 0x%08x\n", writing_mva);
  2265. pgc->dc_buf_id++;
  2266. pgc->dc_buf_id %= DISP_INTERNAL_BUFFER_COUNT;
  2267. /*initialize rdma config */
  2268. decouple_rdma_config.address = (unsigned int)writing_mva;
  2269. decouple_rdma_config.width = primary_display_get_width();
  2270. decouple_rdma_config.height = primary_display_get_height();
  2271. decouple_rdma_config.idx = 0;
  2272. decouple_rdma_config.inputFormat = eRGB888;
  2273. decouple_rdma_config.pitch = primary_display_get_width() * DP_COLOR_BITS_PER_PIXEL(eRGB888) / 8;
  2274. _config_rdma_input_data(&decouple_rdma_config, pgc->dpmgr_handle, pgc->cmdq_handle_config);
  2275. cmdqRecFlush(pgc->cmdq_handle_config);
  2276. DISPCHECK("dpmgr set dst module FINISHED(%s)\n", ddp_get_module_name(dst_module));
  2277. return 0;
  2278. }
  2279. static int _build_path_ovl_to_wdma(void)
  2280. {
  2281. int ret = 0;
  2282. uint32_t writing_mva = 0;
  2283. #ifdef CONFIG_FOR_SOURCE_PQ
  2284. pgc->ovl2mem_path_handle = dpmgr_create_path(DDP_SCENARIO_PRIMARY_DITHER_MEMOUT,
  2285. pgc->cmdq_handle_ovl1to2_config);
  2286. #else
  2287. pgc->ovl2mem_path_handle = dpmgr_create_path(DDP_SCENARIO_PRIMARY_OVL_MEMOUT,
  2288. pgc->cmdq_handle_ovl1to2_config);
  2289. #endif
  2290. /*
  2291. * FRAME_START will be used in decouple-mirror mode, for post-path fence release(rdma->dsi)
  2292. */
  2293. dpmgr_enable_event(pgc->ovl2mem_path_handle, DISP_PATH_EVENT_FRAME_COMPLETE);
  2294. dpmgr_enable_event(pgc->ovl2mem_path_handle, DISP_PATH_EVENT_FRAME_START);
  2295. if (pgc->ovl2mem_path_handle) {
  2296. DISPCHECK("dpmgr create ovl memout path SUCCESS\n");
  2297. } else {
  2298. DISPCHECK("dpmgr create path FAIL\n");
  2299. return -1;
  2300. }
  2301. dpmgr_path_set_video_mode(pgc->ovl2mem_path_handle, 0);
  2302. dpmgr_path_init(pgc->ovl2mem_path_handle, CMDQ_DISABLE);
  2303. writing_mva = pgc->dc_buf[pgc->dc_buf_id];
  2304. /*initialize wdma config */
  2305. decouple_wdma_config.dstAddress = writing_mva;
  2306. decouple_wdma_config.srcHeight = primary_display_get_height();
  2307. decouple_wdma_config.srcWidth = primary_display_get_width();
  2308. decouple_wdma_config.clipX = 0;
  2309. decouple_wdma_config.clipY = 0;
  2310. decouple_wdma_config.clipHeight = primary_display_get_height();
  2311. decouple_wdma_config.clipWidth = primary_display_get_width();
  2312. decouple_wdma_config.outputFormat = eRGB888;
  2313. decouple_wdma_config.useSpecifiedAlpha = 1;
  2314. decouple_wdma_config.alpha = 0xFF;
  2315. decouple_wdma_config.dstPitch = primary_display_get_width() * DP_COLOR_BITS_PER_PIXEL(eRGB888) / 8;
  2316. dpmgr_path_reset(pgc->ovl2mem_path_handle, CMDQ_DISABLE);
  2317. _config_wdma_output(&decouple_wdma_config, pgc->ovl2mem_path_handle, NULL);
  2318. ret = dpmgr_path_start(pgc->ovl2mem_path_handle, CMDQ_DISABLE);
  2319. DISPCHECK("build rdma to dsi path finished\n");
  2320. return ret;
  2321. }
  2322. /* #define CONFIG_USE_CMDQ */
  2323. static int __build_path_decouple(void)
  2324. {
  2325. int ret = 0;
  2326. /* DISPFUNC(); */
  2327. DISPPRINT("%s\n", __func__);
  2328. pgc->mode = DECOUPLE_MODE;
  2329. /* 1. Allocate decouple buffers and copy the LK logo to dc buffer. */
  2330. init_decouple_buffers();
  2331. copy_lklogo_to_dc_buf();
  2332. mutex_init(&(pgc->dc_lock));
  2333. /*
  2334. * 2. Enable m4u of RDMA0
  2335. * The OVL engine would be used in VDO mode.
  2336. * Before turn on all the m4u of display modules,
  2337. * the data path need to change to rdma0->dsi.
  2338. */
  2339. {
  2340. M4U_PORT_STRUCT sPort;
  2341. sPort.ePortID = M4U_PORT_DISP_RDMA0;
  2342. sPort.Virtuality = primary_display_use_m4u;
  2343. sPort.Security = 0;
  2344. sPort.Distance = 1;
  2345. sPort.Direction = 0;
  2346. ret = m4u_config_port(&sPort);
  2347. if (ret == 0) {
  2348. DISPCHECK("config M4U Port %s to %s SUCCESS\n",
  2349. ddp_get_module_name(DISP_MODULE_OVL0),
  2350. primary_display_use_m4u ? "virtual" : "physical");
  2351. } else {
  2352. DISPCHECK("config M4U Port %s to %s FAIL(ret=%d)\n",
  2353. ddp_get_module_name(DISP_MODULE_OVL0),
  2354. primary_display_use_m4u ? "virtual" : "physical", ret);
  2355. return -1;
  2356. }
  2357. }
  2358. /* 3. Build and switch display data path from ovl->dsi to rdma->dsi. */
  2359. ret = _build_path_rdma_to_dsi();
  2360. if (ret) {
  2361. pr_debug("build path rdma to dsi fail\n");
  2362. return ret;
  2363. }
  2364. /*
  2365. * 4. Enable all display engine m4u.
  2366. * Since the display data path has been changed to rdma->dsi,
  2367. * all the display engine m4u can be enabled safely.
  2368. */
  2369. config_display_m4u_port();
  2370. /* 5. Build/Connect ovl->wdma display data path. */
  2371. ret = _build_path_ovl_to_wdma();
  2372. if (ret) {
  2373. pr_debug("build path ovl to wdma fail\n");
  2374. return ret;
  2375. }
  2376. DISPCHECK("build decouple path finished\n");
  2377. return ret;
  2378. }
  2379. static int __build_path_single_layer(void)
  2380. {
  2381. return 0; /* avoid build warning. */
  2382. }
  2383. static int __build_path_debug_rdma1_dsi0(void)
  2384. {
  2385. int ret = 0;
  2386. #if defined(MTK_FB_RDMA1_SUPPORT)
  2387. DISP_MODULE_ENUM dst_module = 0;
  2388. pgc->mode = DEBUG_RDMA1_DSI0_MODE;
  2389. pgc->dpmgr_handle = dpmgr_create_path(DDP_SCENARIO_SUB_RDMA1_DISP, pgc->cmdq_handle_config);
  2390. if (pgc->dpmgr_handle) {
  2391. DISPCHECK("dpmgr create path SUCCESS(0x%p)\n", pgc->dpmgr_handle);
  2392. } else {
  2393. DISPCHECK("dpmgr create path FAIL\n");
  2394. return -1;
  2395. }
  2396. dst_module = _get_dst_module_by_lcm(pgc->plcm);
  2397. dpmgr_path_set_dst_module(pgc->dpmgr_handle, dst_module);
  2398. DISPCHECK("dpmgr set dst module FINISHED(%s)\n", ddp_get_module_name(dst_module));
  2399. #ifndef MTKFB_NO_M4U
  2400. {
  2401. #ifdef MTK_FB_RDMA1_SUPPORT
  2402. M4U_PORT_STRUCT sPort;
  2403. sPort.ePortID = M4U_PORT_DISP_RDMA1;
  2404. sPort.Virtuality = primary_display_use_m4u;
  2405. sPort.Security = 0;
  2406. sPort.Distance = 1;
  2407. sPort.Direction = 0;
  2408. ret = m4u_config_port(&sPort);
  2409. if (ret == 0) {
  2410. DISPCHECK("config M4U Port %s to %s SUCCESS\n",
  2411. ddp_get_module_name(DISP_MODULE_RDMA1),
  2412. primary_display_use_m4u ? "virtual" : "physical");
  2413. } else {
  2414. DISPCHECK("config M4U Port %s to %s FAIL(ret=%d)\n",
  2415. ddp_get_module_name(DISP_MODULE_RDMA1),
  2416. primary_display_use_m4u ? "virtual" : "physical", ret);
  2417. return -1;
  2418. }
  2419. #endif
  2420. }
  2421. #endif
  2422. dpmgr_set_lcm_utils(pgc->dpmgr_handle, pgc->plcm->drv);
  2423. dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC);
  2424. dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE);
  2425. #endif
  2426. return ret;
  2427. }
  2428. int disp_fmt_to_hw_fmt(DISP_FORMAT src_fmt, unsigned int *hw_fmt,
  2429. unsigned int *Bpp, unsigned int *bpp)
  2430. {
  2431. switch (src_fmt) {
  2432. case DISP_FORMAT_YUV422:
  2433. *hw_fmt = eYUY2;
  2434. *Bpp = 2;
  2435. *bpp = 16;
  2436. break;
  2437. case DISP_FORMAT_RGB565:
  2438. *hw_fmt = eRGB565;
  2439. *Bpp = 2;
  2440. *bpp = 16;
  2441. break;
  2442. case DISP_FORMAT_RGB888:
  2443. *hw_fmt = eRGB888;
  2444. *Bpp = 3;
  2445. *bpp = 24;
  2446. break;
  2447. case DISP_FORMAT_BGR888:
  2448. *hw_fmt = eBGR888;
  2449. *Bpp = 3;
  2450. *bpp = 24;
  2451. break;
  2452. case DISP_FORMAT_ARGB8888:
  2453. *hw_fmt = eARGB8888;
  2454. *Bpp = 4;
  2455. *bpp = 32;
  2456. break;
  2457. case DISP_FORMAT_ABGR8888:
  2458. *hw_fmt = eABGR8888;
  2459. *Bpp = 4;
  2460. *bpp = 32;
  2461. break;
  2462. case DISP_FORMAT_RGBA8888:
  2463. *hw_fmt = eRGBA8888;
  2464. *Bpp = 4;
  2465. *bpp = 32;
  2466. break;
  2467. case DISP_FORMAT_BGRA8888:
  2468. /* *hw_fmt = eABGR8888; */
  2469. *hw_fmt = eBGRA8888;
  2470. *Bpp = 4;
  2471. *bpp = 32;
  2472. break;
  2473. case DISP_FORMAT_XRGB8888:
  2474. *hw_fmt = eARGB8888;
  2475. *Bpp = 4;
  2476. *bpp = 32;
  2477. break;
  2478. case DISP_FORMAT_XBGR8888:
  2479. *hw_fmt = eABGR8888;
  2480. *Bpp = 4;
  2481. *bpp = 32;
  2482. break;
  2483. case DISP_FORMAT_RGBX8888:
  2484. *hw_fmt = eRGBA8888;
  2485. *Bpp = 4;
  2486. *bpp = 32;
  2487. break;
  2488. case DISP_FORMAT_BGRX8888:
  2489. *hw_fmt = eBGRA8888;
  2490. *Bpp = 4;
  2491. *bpp = 32;
  2492. break;
  2493. case DISP_FORMAT_UYVY:
  2494. *hw_fmt = eUYVY;
  2495. *Bpp = 2;
  2496. *bpp = 16;
  2497. break;
  2498. case DISP_FORMAT_YV12:
  2499. *hw_fmt = eYV12;
  2500. *Bpp = 1;
  2501. *bpp = 8;
  2502. break;
  2503. default:
  2504. DISPERR("Invalid color format: 0x%x\n", src_fmt);
  2505. return -1;
  2506. }
  2507. return 0;
  2508. }
  2509. static int _convert_disp_input_to_ovl(OVL_CONFIG_STRUCT *dst, disp_input_config *src)
  2510. {
  2511. int ret;
  2512. unsigned int Bpp = 0;
  2513. unsigned int bpp = 0;
  2514. if (!src || !dst) {
  2515. DISP_FATAL_ERR("display", "%s src(0x%p) or dst(0x%p) is null\n",
  2516. __func__, src, dst);
  2517. return -1;
  2518. }
  2519. dst->layer = src->layer_id;
  2520. dst->isDirty = 1;
  2521. dst->buff_idx = src->next_buff_idx;
  2522. dst->layer_en = src->layer_enable;
  2523. /* if layer is disable, we just needs config above params. */
  2524. if (!src->layer_enable)
  2525. return 0;
  2526. ret = disp_fmt_to_hw_fmt(src->src_fmt, (unsigned int *)(&(dst->fmt)), (unsigned int *)(&Bpp),
  2527. (unsigned int *)(&bpp));
  2528. dst->addr = (unsigned long)src->src_phy_addr;
  2529. dst->vaddr = (unsigned long)src->src_base_addr;
  2530. dst->src_x = src->src_offset_x;
  2531. dst->src_y = src->src_offset_y;
  2532. dst->src_w = src->src_width;
  2533. dst->src_h = src->src_height;
  2534. dst->src_pitch = src->src_pitch * Bpp;
  2535. dst->dst_x = src->tgt_offset_x;
  2536. dst->dst_y = src->tgt_offset_y;
  2537. /* dst W/H should <= src W/H */
  2538. if (src->buffer_source != DISP_BUFFER_ALPHA) { /* dim layer do not care for src_width */
  2539. dst->dst_w = min(src->src_width, src->tgt_width);
  2540. dst->dst_h = min(src->src_height, src->tgt_height);
  2541. } else {
  2542. dst->dst_w = src->tgt_width;
  2543. dst->dst_h = src->tgt_height;
  2544. }
  2545. dst->keyEn = src->src_use_color_key;
  2546. dst->key = src->src_color_key;
  2547. dst->aen = src->alpha_enable;
  2548. dst->alpha = src->alpha;
  2549. dst->sur_aen = src->sur_aen;
  2550. dst->src_alpha = src->src_alpha;
  2551. dst->dst_alpha = src->dst_alpha;
  2552. #ifdef DISP_DISABLE_X_CHANNEL_ALPHA
  2553. if (DISP_FORMAT_ARGB8888 == src->src_fmt || DISP_FORMAT_ABGR8888 == src->src_fmt ||
  2554. DISP_FORMAT_RGBA8888 == src->src_fmt || DISP_FORMAT_BGRA8888 == src->src_fmt ||
  2555. src->buffer_source == DISP_BUFFER_ALPHA) {
  2556. ;/* nothing */
  2557. } else {
  2558. dst->aen = FALSE;
  2559. dst->sur_aen = FALSE;
  2560. }
  2561. #endif
  2562. dst->identity = src->identity;
  2563. dst->connected_type = src->connected_type;
  2564. dst->security = src->security;
  2565. dst->yuv_range = src->yuv_range;
  2566. if (src->buffer_source == DISP_BUFFER_ALPHA) {
  2567. dst->source = OVL_LAYER_SOURCE_RESERVED; /* dim layer, constant alpha */
  2568. } else if (src->buffer_source == DISP_BUFFER_ION || src->buffer_source == DISP_BUFFER_MVA) {
  2569. dst->source = OVL_LAYER_SOURCE_MEM; /* from memory */
  2570. } else {
  2571. DISPERR("unknown source = %d", src->buffer_source);
  2572. dst->source = OVL_LAYER_SOURCE_MEM;
  2573. }
  2574. return ret;
  2575. }
  2576. static int _convert_disp_input_to_rdma(RDMA_CONFIG_STRUCT *dst, disp_input_config *src)
  2577. {
  2578. int ret;
  2579. unsigned int Bpp = 0;
  2580. unsigned int bpp = 0;
  2581. if (!src || !dst) {
  2582. DISP_FATAL_ERR("display", "%s src(0x%p) or dst(0x%p) is null\n",
  2583. __func__, src, dst);
  2584. return -1;
  2585. }
  2586. ret = disp_fmt_to_hw_fmt(src->src_fmt, &(dst->inputFormat), &Bpp, &bpp);
  2587. dst->address = (unsigned long)src->src_phy_addr;
  2588. dst->width = src->src_width;
  2589. dst->height = src->src_height;
  2590. dst->pitch = src->src_pitch * Bpp;
  2591. return ret;
  2592. }
  2593. /* Video mode SODI CMDQ flow */
  2594. /* extern unsigned int gDumpConfigCMD; */
  2595. /* extern unsigned int gEnableOVLStatusCheck; */
  2596. #define DISP_REG_CMDQ_TOKEN_ID 0x10212060
  2597. #define DISP_REG_CMDQ_TOKEN_VALUE 0x10212064
  2598. #define DISP_MUTEX0_STREAM_EOF_ID 55
  2599. int _trigger_display_interface(int blocking, void *callback, unsigned int userdata)
  2600. {
  2601. static unsigned int cnt;
  2602. /* 4. enable SODI after config */
  2603. if (primary_display_is_video_mode() == 1)
  2604. disp_set_sodi(1, pgc->cmdq_handle_config);
  2605. #ifdef DISP_ENABLE_SODI_FOR_VIDEO_MODE
  2606. if (gPrefetchControl == 1 && cnt >= 20)
  2607. cmdqRecDisablePrefetch(pgc->cmdq_handle_config);
  2608. #endif
  2609. if (_should_wait_path_idle())
  2610. dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ * 1);
  2611. if (_should_update_lcm())
  2612. disp_lcm_update(pgc->plcm, 0, 0, pgc->plcm->params->width,
  2613. pgc->plcm->params->height, 0);
  2614. if (_should_start_path())
  2615. dpmgr_path_start(pgc->dpmgr_handle, primary_display_cmdq_enabled());
  2616. if (_should_trigger_path())
  2617. /* trigger_loop_handle is used only for build trigger loop,
  2618. * which should always be NULL for config thread
  2619. */
  2620. dpmgr_path_trigger(pgc->dpmgr_handle, NULL, primary_display_cmdq_enabled());
  2621. #ifndef MTK_FB_CMDQ_DISABLE
  2622. if (_should_set_cmdq_dirty()) {
  2623. _cmdq_set_config_handle_dirty();
  2624. /* disable SODI after set dirty */
  2625. if (primary_display_is_video_mode() == 0 && gDisableSODIForTriggerLoop == 1)
  2626. disp_set_sodi(0, pgc->cmdq_handle_config);
  2627. }
  2628. /* 1. disable SODI by CPU before flush CMDQ by CPU */
  2629. if (primary_display_is_video_mode() == 1)
  2630. disp_set_sodi(0, 0);
  2631. if (gDumpConfigCMD == 1) {
  2632. DISPMSG("primary_display_config, dump before flush:\n");
  2633. cmdqRecDumpCommand(pgc->cmdq_handle_config);
  2634. }
  2635. /* insert update ovl status slot command */
  2636. if (primary_display_is_video_mode() == 1) {
  2637. cmdqRecBackupRegisterToSlot(pgc->cmdq_handle_config, pgc->ovl_status_info,
  2638. 0, DISP_REG_OVL0_STATE_PA);
  2639. cmdqRecBackupRegisterToSlot(pgc->cmdq_handle_config, pgc->ovl_status_info,
  2640. 1, DISP_REG_OVL0_STATUS_PA);
  2641. }
  2642. if (_should_flush_cmdq_config_handle())
  2643. _cmdq_flush_config_handle(blocking, callback, userdata);
  2644. if (_should_reset_cmdq_config_handle()) {
  2645. _cmdq_reset_config_handle();
  2646. #ifdef DISP_ENABLE_SODI_FOR_VIDEO_MODE
  2647. /* do not have to enable/disable prefetch at power on stage. */
  2648. if (gPrefetchControl == 1 && cnt >= 20)
  2649. cmdqRecEnablePrefetch(pgc->cmdq_handle_config);
  2650. #endif
  2651. }
  2652. /* TODO: _is_decouple_mode() shuold be protected by mutex!!!!!!!!when dynamic switch decouple/directlink */
  2653. if (_should_insert_wait_frame_done_token() && (!_is_decouple_mode(pgc->session_mode))) {
  2654. /* 2. enable SODI by CMDQ before wait */
  2655. if (primary_display_is_video_mode() == 1)
  2656. disp_set_sodi(1, pgc->cmdq_handle_config);
  2657. if (primary_display_is_video_mode() == 1)
  2658. cmdqRecWaitNoClear(pgc->cmdq_handle_config, CMDQ_EVENT_DISP_RDMA0_EOF);
  2659. else
  2660. _cmdq_insert_wait_frame_done_token();
  2661. /* 3. disable AODI by CMDQ before config */
  2662. if (primary_display_is_video_mode() == 1)
  2663. disp_set_sodi(0, pgc->cmdq_handle_config);
  2664. }
  2665. if (cnt < 20)
  2666. cnt++;
  2667. else
  2668. gEnableLowPowerFeature = 1;
  2669. #endif
  2670. return 0;
  2671. }
  2672. int _trigger_ovl_to_memory(disp_path_handle disp_handle, cmdqRecHandle cmdq_handle,
  2673. fence_release_callback callback, unsigned int data, int blocking)
  2674. {
  2675. unsigned int rdma_pitch_sec;
  2676. dpmgr_wdma_path_force_power_on();
  2677. dpmgr_path_trigger(disp_handle, cmdq_handle, CMDQ_ENABLE);
  2678. cmdqRecWaitNoClear(cmdq_handle, CMDQ_EVENT_DISP_WDMA0_EOF);
  2679. cmdqRecBackupUpdateSlot(cmdq_handle, pgc->rdma_buff_info, 0, mem_config.addr);
  2680. /* rdma pitch only use bit[15..0], we use bit[31:30] to store secure information */
  2681. rdma_pitch_sec = mem_config.pitch | (mem_config.security << 30);
  2682. cmdqRecBackupUpdateSlot(cmdq_handle, pgc->rdma_buff_info, 1, rdma_pitch_sec);
  2683. cmdqRecBackupUpdateSlot(cmdq_handle, pgc->rdma_buff_info, 2, mem_config.fmt);
  2684. if (blocking)
  2685. cmdqRecFlush(cmdq_handle);
  2686. else
  2687. cmdqRecFlushAsyncCallback(cmdq_handle, (CmdqAsyncFlushCB) callback, data);
  2688. cmdqRecReset(cmdq_handle);
  2689. cmdqRecWait(cmdq_handle, CMDQ_EVENT_DISP_WDMA0_EOF);
  2690. MMProfileLogEx(ddp_mmp_get_events()->ovl_trigger, MMProfileFlagPulse, 0, data);
  2691. return 0;
  2692. }
  2693. int _trigger_ovl_to_memory_mirror(disp_path_handle disp_handle, cmdqRecHandle cmdq_handle,
  2694. fence_release_callback callback, unsigned int data)
  2695. {
  2696. int layer = 0;
  2697. unsigned int rdma_pitch_sec;
  2698. dpmgr_wdma_path_force_power_on();
  2699. dpmgr_path_trigger(disp_handle, cmdq_handle, CMDQ_ENABLE);
  2700. cmdqRecWaitNoClear(cmdq_handle, CMDQ_EVENT_DISP_WDMA0_EOF);
  2701. layer = disp_sync_get_output_timeline_id();
  2702. cmdqRecBackupUpdateSlot(cmdq_handle, pgc->cur_config_fence, layer, mem_config.buff_idx);
  2703. layer = disp_sync_get_output_interface_timeline_id();
  2704. cmdqRecBackupUpdateSlot(cmdq_handle, pgc->cur_config_fence, layer, mem_config.interface_idx);
  2705. cmdqRecBackupUpdateSlot(cmdq_handle, pgc->rdma_buff_info, 0, (unsigned int)mem_config.addr);
  2706. /*rdma pitch only use bit[15..0], we use bit[31:30] to store secure information */
  2707. rdma_pitch_sec = mem_config.pitch | (mem_config.security << 30);
  2708. cmdqRecBackupUpdateSlot(cmdq_handle, pgc->rdma_buff_info, 1, rdma_pitch_sec);
  2709. cmdqRecBackupUpdateSlot(cmdq_handle, pgc->rdma_buff_info, 2, mem_config.fmt);
  2710. cmdqRecFlushAsyncCallback(cmdq_handle, (CmdqAsyncFlushCB) callback, data);
  2711. cmdqRecReset(cmdq_handle);
  2712. cmdqRecWait(cmdq_handle, CMDQ_EVENT_DISP_WDMA0_EOF);
  2713. MMProfileLogEx(ddp_mmp_get_events()->ovl_trigger, MMProfileFlagPulse, 0, data);
  2714. return 0;
  2715. }
  2716. #define EEEEEEEEEEEEEEE
  2717. /******************************************************************************/
  2718. /* ESD CHECK / RECOVERY ---- BEGIN */
  2719. /******************************************************************************/
  2720. #ifdef MTK_FB_ESD_ENABLE
  2721. static struct task_struct *primary_display_esd_check_task;
  2722. #define IS_ESD_ENABLE true
  2723. #else
  2724. #define IS_ESD_ENABLE false
  2725. #endif
  2726. #ifdef MTK_FB_PULLCLK_ENABLE
  2727. static struct task_struct *primary_display_pullclk_task;
  2728. #endif
  2729. static wait_queue_head_t esd_check_task_wq; /* For Esd Check Task */
  2730. static atomic_t esd_check_task_wakeup = ATOMIC_INIT(0); /* For Esd Check Task */
  2731. static wait_queue_head_t esd_ext_te_wq; /* For Vdo Mode EXT TE Check */
  2732. static atomic_t esd_ext_te_event = ATOMIC_INIT(0); /* For Vdo Mode EXT TE Check */
  2733. static atomic_t esd_check_bycmdq = ATOMIC_INIT(0);
  2734. static inline bool _is_enable_esd_check(void)
  2735. {
  2736. return IS_ESD_ENABLE;
  2737. }
  2738. struct task_struct *primary_display_frame_update_task = NULL;
  2739. wait_queue_head_t primary_display_frame_update_wq;
  2740. atomic_t primary_display_frame_update_event = ATOMIC_INIT(0);
  2741. struct task_struct *decouple_fence_release_task = NULL;
  2742. wait_queue_head_t decouple_fence_release_wq;
  2743. atomic_t decouple_fence_release_event = ATOMIC_INIT(0);
  2744. static int eint_flag; /* For DCT Setting */
  2745. unsigned int _need_do_esd_check(void)
  2746. {
  2747. int ret = 0;
  2748. #ifdef CONFIG_OF
  2749. if ((pgc->plcm->params->dsi.esd_check_enable == 1) && (islcmconnected == 1))
  2750. ret = 1;
  2751. #else
  2752. if (pgc->plcm->params->dsi.esd_check_enable == 1)
  2753. ret = 1;
  2754. #endif
  2755. return ret;
  2756. }
  2757. unsigned int _need_register_eint(void)
  2758. {
  2759. int ret = 1;
  2760. /* 1.need do esd check */
  2761. /* 2.dsi vdo mode */
  2762. /* 3.customization_esd_check_enable = 0 */
  2763. if (_need_do_esd_check() == 0)
  2764. ret = 0;
  2765. else if (primary_display_is_video_mode() == 0)
  2766. ret = 0;
  2767. else if (pgc->plcm->params->dsi.customization_esd_check_enable == 1)
  2768. ret = 0;
  2769. return ret;
  2770. }
  2771. unsigned int _need_wait_esd_eof(void)
  2772. {
  2773. int ret = 1;
  2774. /* 1.need do esd check */
  2775. /* 2.customization_esd_check_enable = 1 */
  2776. /* 3.dsi cmd mode */
  2777. if (_need_do_esd_check() == 0)
  2778. ret = 0;
  2779. else if (pgc->plcm->params->dsi.customization_esd_check_enable == 0)
  2780. ret = 0;
  2781. else if (primary_display_is_video_mode())
  2782. ret = 0;
  2783. return ret;
  2784. }
  2785. /* For Cmd Mode Read LCM Check */
  2786. /* Config cmdq_handle_config_esd */
  2787. int _esd_check_config_handle_cmd(void)
  2788. {
  2789. int ret = 0; /* 0:success */
  2790. /* 1.reset */
  2791. cmdqRecReset(pgc->cmdq_handle_config_esd);
  2792. /* 2.write first instruction */
  2793. /* cmd mode: wait CMDQ_SYNC_TOKEN_STREAM_EOF(wait trigger thread done) */
  2794. cmdqRecWaitNoClear(pgc->cmdq_handle_config_esd, CMDQ_SYNC_TOKEN_STREAM_EOF);
  2795. /* 3.clear CMDQ_SYNC_TOKEN_ESD_EOF(trigger thread need wait this sync token) */
  2796. cmdqRecClearEventToken(pgc->cmdq_handle_config_esd, CMDQ_SYNC_TOKEN_ESD_EOF);
  2797. /* 4.write instruction(read from lcm) */
  2798. dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_config_esd, CMDQ_ESD_CHECK_READ);
  2799. /* 5.set CMDQ_SYNC_TOKE_ESD_EOF(trigger thread can work now) */
  2800. cmdqRecSetEventToken(pgc->cmdq_handle_config_esd, CMDQ_SYNC_TOKEN_ESD_EOF);
  2801. /* 6.flush instruction */
  2802. dprec_logger_start(DPREC_LOGGER_ESD_CMDQ, 0, 0);
  2803. ret = cmdqRecFlush(pgc->cmdq_handle_config_esd);
  2804. dprec_logger_done(DPREC_LOGGER_ESD_CMDQ, 0, 0);
  2805. DISPCHECK("[ESD]_esd_check_config_handle_cmd ret=%d\n", ret);
  2806. if (ret)
  2807. ret = 1;
  2808. return ret;
  2809. }
  2810. void primary_display_esd_cust_bycmdq(int enable)
  2811. {
  2812. atomic_set(&esd_check_bycmdq, enable);
  2813. }
  2814. int primary_display_esd_cust_get(void)
  2815. {
  2816. return atomic_read(&esd_check_bycmdq);
  2817. }
  2818. /* For Vdo Mode Read LCM Check */
  2819. /* Config cmdq_handle_config_esd */
  2820. /* extern unsigned int gESDEnableSODI; */
  2821. /* extern unsigned int gDumpESDCMD; */
  2822. int _esd_check_config_handle_vdo(void)
  2823. {
  2824. int ret = 0; /* 0:success , 1:fail */
  2825. primary_display_esd_cust_bycmdq(1);
  2826. _primary_path_lock(__func__);
  2827. #if defined(MTK_FB_SODI_SUPPORT) && !defined(CONFIG_FPGA_EARLY_PORTING)
  2828. spm_enable_sodi(0);
  2829. #endif
  2830. /* 1.reset */
  2831. cmdqRecReset(pgc->cmdq_handle_config_esd);
  2832. /* wait stream eof first */
  2833. cmdqRecWait(pgc->cmdq_handle_config_esd, CMDQ_EVENT_DISP_RDMA0_EOF);
  2834. cmdqRecWait(pgc->cmdq_handle_config_esd, CMDQ_EVENT_MUTEX0_STREAM_EOF);
  2835. #ifdef DISP_DUMP_EVENT_STATUS
  2836. DISP_REG_SET_PA(pgc->cmdq_handle_config_esd, DISP_REG_CMDQ_TOKEN_ID, DISP_MUTEX0_STREAM_EOF_ID);
  2837. cmdqRecBackupRegisterToSlot(pgc->cmdq_handle_config_esd, pgc->event_status, 1, DISP_REG_CMDQ_TOKEN_VALUE);
  2838. #endif
  2839. /* stop dsi vdo mode */
  2840. dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_config_esd, CMDQ_STOP_VDO_MODE);
  2841. /* write instruction(read from lcm) */
  2842. dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_config_esd, CMDQ_ESD_CHECK_READ);
  2843. /* pull DSI clock lane */
  2844. DSI_sw_clk_trail_cmdq(0, pgc->cmdq_handle_config_esd);
  2845. DSI_manual_enter_HS(pgc->cmdq_handle_config_esd);
  2846. /* start dsi vdo mode */
  2847. dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_config_esd, CMDQ_START_VDO_MODE);
  2848. /* trigger path */
  2849. cmdqRecClearEventToken(pgc->cmdq_handle_config_esd, CMDQ_EVENT_MUTEX0_STREAM_EOF);
  2850. if (gEnableSWTrigger == 1)
  2851. DISP_REG_SET(pgc->cmdq_handle_config_esd, DISP_REG_CONFIG_MUTEX_EN(DISP_OVL_SEPARATE_MUTEX_ID), 1);
  2852. dpmgr_path_trigger(pgc->dpmgr_handle, pgc->cmdq_handle_config_esd, CMDQ_ENABLE);
  2853. /* flush instruction */
  2854. dprec_logger_start(DPREC_LOGGER_ESD_CMDQ, 0, 0);
  2855. if (gDumpESDCMD == 1) {
  2856. DISPMSG("esd dump before flush:\n");
  2857. cmdqRecDumpCommand(pgc->cmdq_handle_config_esd);
  2858. }
  2859. ret = cmdqRecFlush(pgc->cmdq_handle_config_esd);
  2860. #if defined(MTK_FB_SODI_SUPPORT) && !defined(CONFIG_FPGA_EARLY_PORTING)
  2861. spm_enable_sodi(1);
  2862. #endif
  2863. _primary_path_unlock(__func__);
  2864. #ifdef DISP_DUMP_EVENT_STATUS
  2865. {
  2866. unsigned int i = 0;
  2867. unsigned int event_status[6];
  2868. DISPMSG("dump esd status: ");
  2869. for (i = 0; i < 6; i++)
  2870. cmdqBackupReadSlot(pgc->event_status, i, &event_status[i]);
  2871. DISPMSG("%d, %d, %d, %d, %d, %d\n",
  2872. event_status[0], event_status[1], event_status[2],
  2873. event_status[3], event_status[4], event_status[5]);
  2874. }
  2875. #endif
  2876. dprec_logger_done(DPREC_LOGGER_ESD_CMDQ, 0, 0);
  2877. DISPCHECK("[ESD]_esd_check_config_handle_vdo ret=%d\n", ret);
  2878. if (ret)
  2879. ret = 1;
  2880. primary_display_esd_cust_bycmdq(0);
  2881. return ret;
  2882. }
  2883. /* For Vdo Mode EXT TE Check */
  2884. static irqreturn_t _esd_check_ext_te_irq_handler(int irq, void *data)
  2885. {
  2886. MMProfileLogEx(ddp_mmp_get_events()->esd_vdo_eint, MMProfileFlagPulse, 0, 0);
  2887. atomic_set(&esd_ext_te_event, 1);
  2888. wake_up_interruptible(&esd_ext_te_wq);
  2889. return IRQ_HANDLED;
  2890. }
  2891. int primary_display_switch_esd_mode(int mode)
  2892. {
  2893. int ret = 0;
  2894. #ifdef GPIO_DSI_TE_PIN
  2895. int gpio_mode = 0;
  2896. #endif
  2897. DISPFUNC();
  2898. if (pgc->plcm->params->dsi.customization_esd_check_enable != 0)
  2899. return -1; /* avoid build warning. */
  2900. DISPMSG("switch esd mode to %d\n", mode);
  2901. #ifdef GPIO_DSI_TE_PIN
  2902. #ifndef CONFIG_FPGA_EARLY_PORTING
  2903. gpio_mode = mt_get_gpio_mode(GPIO_DSI_TE_PIN);
  2904. /* DISPMSG("[ESD]gpio_mode=%d\n", gpio_mode); */
  2905. #endif
  2906. #endif
  2907. if (mode == 1) {
  2908. #ifdef GPIO_DSI_TE_PIN
  2909. /*switch to vdo mode */
  2910. if (gpio_mode == GPIO_DSI_TE_PIN_M_DSI_TE) {
  2911. #endif
  2912. /* if(_need_register_eint()) */
  2913. {
  2914. /* DISPMSG("[ESD]switch video mode\n"); */
  2915. struct device_node *node = NULL;
  2916. int irq;
  2917. u32 ints[2] = { 0, 0 };
  2918. #ifdef GPIO_DSI_TE_PIN
  2919. #ifndef CONFIG_FPGA_EARLY_PORTING
  2920. /* 1.set GPIO107 eint mode */
  2921. mt_set_gpio_mode(GPIO_DSI_TE_PIN, GPIO_DSI_TE_PIN_M_GPIO);
  2922. #endif
  2923. #endif
  2924. /* 2.register eint */
  2925. node = of_find_compatible_node(NULL, NULL, "mediatek, DSI_TE_1-eint");
  2926. if (node) {
  2927. /* DISPMSG("node 0x%x\n", node); */
  2928. of_property_read_u32_array(node, "debounce", ints, ARRAY_SIZE(ints));
  2929. /* mt_gpio_set_debounce(ints[0], ints[1]); */
  2930. mt_eint_set_hw_debounce(ints[0], ints[1]);
  2931. irq = irq_of_parse_and_map(node, 0);
  2932. if (request_irq(irq, _esd_check_ext_te_irq_handler, IRQF_TRIGGER_RISING,
  2933. "DSI_TE_1-eint", NULL))
  2934. DISPERR("[ESD]EINT IRQ LINE NOT AVAILABLE!!\n");
  2935. } else {
  2936. DISPERR("[ESD][%s] can't find DSI_TE_1 eint compatible node\n", __func__);
  2937. }
  2938. }
  2939. #ifdef GPIO_DSI_TE_PIN
  2940. }
  2941. #endif
  2942. } else if (mode == 0) {
  2943. #ifdef GPIO_DSI_TE_PIN
  2944. /* switch to cmd mode */
  2945. if (gpio_mode == GPIO_DSI_TE_PIN_M_GPIO) {
  2946. #endif
  2947. struct device_node *node = NULL;
  2948. int irq;
  2949. /* DISPMSG("[ESD]switch cmd mode\n"); */
  2950. /* unregister eint */
  2951. node = of_find_compatible_node(NULL, NULL, "mediatek, DSI_TE_1-eint");
  2952. /* DISPMSG("node 0x%x\n", node); */
  2953. if (node) {
  2954. irq = irq_of_parse_and_map(node, 0);
  2955. free_irq(irq, NULL);
  2956. } else {
  2957. DISPERR("[ESD][%s] can't find DSI_TE_1 eint compatible node\n",
  2958. __func__);
  2959. }
  2960. #ifdef GPIO_DSI_TE_PIN
  2961. #ifndef CONFIG_FPGA_EARLY_PORTING
  2962. /* set GPIO107 DSI TE mode */
  2963. mt_set_gpio_mode(GPIO_DSI_TE_PIN, GPIO_DSI_TE_PIN_M_DSI_TE);
  2964. #endif
  2965. #endif
  2966. #ifdef GPIO_DSI_TE_PIN
  2967. }
  2968. #endif
  2969. }
  2970. /* DISPMSG("primary_display_switch_esd_mode end\n"); */
  2971. return ret;
  2972. }
  2973. /* ESD CHECK FUNCTION */
  2974. /* return 1: esd check fail */
  2975. /* return 0: esd check pass */
  2976. int primary_display_esd_check(void)
  2977. {
  2978. int ret = 0;
  2979. _primary_path_esd_check_lock();
  2980. dprec_logger_start(DPREC_LOGGER_ESD_CHECK, 0, 0);
  2981. MMProfileLogEx(ddp_mmp_get_events()->esd_check_t, MMProfileFlagStart, 0, 0);
  2982. DISPCHECK("[ESD]ESD check begin\n");
  2983. _primary_path_lock(__func__);
  2984. if (pgc->state == DISP_SLEPT) {
  2985. MMProfileLogEx(ddp_mmp_get_events()->esd_check_t, MMProfileFlagPulse, 1, 0);
  2986. DISPCHECK("[ESD]primary display path is slept?? -- skip esd check\n");
  2987. _primary_path_unlock(__func__);
  2988. /* goto done; */
  2989. DISPCHECK("[ESD]ESD check end\n");
  2990. MMProfileLogEx(ddp_mmp_get_events()->esd_check_t, MMProfileFlagEnd, 0, ret);
  2991. dprec_logger_done(DPREC_LOGGER_ESD_CHECK, 0, 0);
  2992. _primary_path_esd_check_unlock();
  2993. return ret;
  2994. }
  2995. _primary_path_unlock(__func__);
  2996. #ifdef MTK_DISP_IDLE_LP
  2997. _disp_primary_path_dsi_clock_on(0);
  2998. #endif
  2999. /* / Esd Check : EXT TE */
  3000. if (pgc->plcm->params->dsi.customization_esd_check_enable == 0) {
  3001. MMProfileLogEx(ddp_mmp_get_events()->esd_extte, MMProfileFlagStart, 0, 0);
  3002. if (primary_display_is_video_mode()) {
  3003. primary_display_switch_esd_mode(1);
  3004. /* use cmdq to pull DSI clk lane*/
  3005. if (primary_display_cmdq_enabled() ) {
  3006. _primary_path_lock(__func__);
  3007. /* 0.create esd check cmdq */
  3008. cmdqRecCreate(CMDQ_SCENARIO_DISP_ESD_CHECK, &(pgc->cmdq_handle_config_esd));
  3009. _primary_path_unlock(__func__);
  3010. primary_display_esd_cust_bycmdq(1);
  3011. /* 1.reset*/
  3012. cmdqRecReset(pgc->cmdq_handle_config_esd);
  3013. /* wait stream eof first */
  3014. ret = cmdqRecWait(pgc->cmdq_handle_config_esd, CMDQ_EVENT_DISP_RDMA0_EOF);
  3015. cmdqRecWait(pgc->cmdq_handle_config_esd, CMDQ_EVENT_MUTEX0_STREAM_EOF);
  3016. _primary_path_lock(__func__);
  3017. /* 2.stop dsi vdo mode */
  3018. dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_config_esd, CMDQ_STOP_VDO_MODE);
  3019. /* 3.pull DSI clock lane */
  3020. DSI_sw_clk_trail_cmdq(0, pgc->cmdq_handle_config_esd);
  3021. DSI_manual_enter_HS(pgc->cmdq_handle_config_esd);
  3022. /* 4.start dsi vdo mode */
  3023. dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_config_esd, CMDQ_START_VDO_MODE);
  3024. /* 5. trigger path */
  3025. cmdqRecClearEventToken(pgc->cmdq_handle_config_esd ,CMDQ_EVENT_MUTEX0_STREAM_EOF);
  3026. if (gEnableSWTrigger==1)
  3027. DISP_REG_SET(pgc->cmdq_handle_config_esd,
  3028. DISP_REG_CONFIG_MUTEX_EN(DISP_OVL_SEPARATE_MUTEX_ID), 1);
  3029. dpmgr_path_trigger(pgc->dpmgr_handle, pgc->cmdq_handle_config_esd, CMDQ_ENABLE);
  3030. _primary_path_unlock(__func__);
  3031. cmdqRecFlush(pgc->cmdq_handle_config_esd);
  3032. primary_display_esd_cust_bycmdq(0);
  3033. cmdqRecDestroy(pgc->cmdq_handle_config_esd);
  3034. pgc->cmdq_handle_config_esd = NULL;
  3035. }
  3036. if (_need_register_eint()) {
  3037. MMProfileLogEx(ddp_mmp_get_events()->esd_extte, MMProfileFlagPulse, 1, 1);
  3038. if (wait_event_interruptible_timeout
  3039. (esd_ext_te_wq, atomic_read(&esd_ext_te_event), HZ / 2) > 0) {
  3040. ret = 0; /* esd check pass */
  3041. } else {
  3042. ret = 1; /* esd check fail */
  3043. DISPCHECK("esd check fail release fence fake\n");
  3044. primary_display_release_fence_fake();
  3045. }
  3046. atomic_set(&esd_ext_te_event, 0);
  3047. }
  3048. primary_display_switch_esd_mode(0);
  3049. } else {
  3050. MMProfileLogEx(ddp_mmp_get_events()->esd_extte, MMProfileFlagPulse, 0, 1);
  3051. if (dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, HZ / 2) > 0) {
  3052. ret = 0; /* esd check pass */
  3053. } else {
  3054. ret = 1; /* esd check fail */
  3055. DISPCHECK("esd check fail release fence fake\n");
  3056. primary_display_release_fence_fake();
  3057. }
  3058. }
  3059. MMProfileLogEx(ddp_mmp_get_events()->esd_extte, MMProfileFlagEnd, 0, ret);
  3060. goto done;
  3061. }
  3062. /* / Esd Check : Read from lcm */
  3063. MMProfileLogEx(ddp_mmp_get_events()->esd_rdlcm, MMProfileFlagStart, 0, primary_display_cmdq_enabled());
  3064. if (primary_display_cmdq_enabled()) {
  3065. _primary_path_lock(__func__);
  3066. MMProfileLogEx(ddp_mmp_get_events()->esd_rdlcm, MMProfileFlagPulse, 0, 1);
  3067. /* 0.create esd check cmdq */
  3068. cmdqRecCreate(CMDQ_SCENARIO_DISP_ESD_CHECK, &(pgc->cmdq_handle_config_esd));
  3069. dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_config_esd, CMDQ_ESD_ALLC_SLOT);
  3070. MMProfileLogEx(ddp_mmp_get_events()->esd_rdlcm, MMProfileFlagPulse, 0, 2);
  3071. DISPCHECK("[ESD]ESD config thread=%p\n", pgc->cmdq_handle_config_esd);
  3072. _primary_path_unlock(__func__);
  3073. /* 1.use cmdq to read from lcm */
  3074. if (primary_display_is_video_mode())
  3075. ret = _esd_check_config_handle_vdo();
  3076. else
  3077. ret = _esd_check_config_handle_cmd();
  3078. MMProfileLogEx(ddp_mmp_get_events()->esd_rdlcm, MMProfileFlagPulse, primary_display_is_video_mode(), 3);
  3079. if (ret == 1) {/* cmdq fail */
  3080. /* Need set esd check eof synctoken to let trigger loop go. */
  3081. if (_need_wait_esd_eof())
  3082. cmdqCoreSetEvent(CMDQ_SYNC_TOKEN_ESD_EOF);
  3083. /* do dsi reset */
  3084. dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_config_esd, CMDQ_DSI_RESET);
  3085. DISPCHECK("esd check fail release fence fake\n");
  3086. primary_display_release_fence_fake();
  3087. goto destroy_cmdq;
  3088. }
  3089. DISPCHECK("[ESD]ESD config thread done~\n");
  3090. /* 2.check data(*cpu check now) */
  3091. ret = dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_config_esd, CMDQ_ESD_CHECK_CMP);
  3092. MMProfileLogEx(ddp_mmp_get_events()->esd_rdlcm, MMProfileFlagPulse, 0, 4);
  3093. if (ret) {
  3094. ret = 1; /* esd check fail */
  3095. DISPCHECK("esd check fail release fence fake\n");
  3096. primary_display_release_fence_fake();
  3097. }
  3098. destroy_cmdq:
  3099. dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_config_esd,
  3100. CMDQ_ESD_FREE_SLOT);
  3101. /* 3.destroy esd config thread */
  3102. cmdqRecDestroy(pgc->cmdq_handle_config_esd);
  3103. pgc->cmdq_handle_config_esd = NULL;
  3104. } else { /* by cpu */
  3105. /* 0: lock path */
  3106. /* 1: stop path */
  3107. /* 2: do esd check (!!!) */
  3108. /* 3: start path */
  3109. /* 4: unlock path */
  3110. MMProfileLogEx(ddp_mmp_get_events()->esd_rdlcm, MMProfileFlagPulse, 0, 1);
  3111. _primary_path_lock(__func__);
  3112. /* 1: stop path */
  3113. DISPCHECK("[ESD]display cmdq trigger loop stop[begin]\n");
  3114. _cmdq_stop_trigger_loop();
  3115. DISPCHECK("[ESD]display cmdq trigger loop stop[end]\n");
  3116. if (dpmgr_path_is_busy(pgc->dpmgr_handle)) {
  3117. DISPCHECK("[ESD]primary display path is busy\n");
  3118. ret = dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ * 1);
  3119. DISPCHECK("[ESD]wait frame done ret:%d\n", ret);
  3120. }
  3121. DISPCHECK("[ESD]stop dpmgr path[begin]\n");
  3122. dpmgr_path_stop(pgc->dpmgr_handle, CMDQ_DISABLE);
  3123. DISPCHECK("[ESD]stop dpmgr path[end]\n");
  3124. if (dpmgr_path_is_busy(pgc->dpmgr_handle)) {
  3125. DISPCHECK("[ESD]primary display path is busy after stop\n");
  3126. dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ * 1);
  3127. DISPCHECK("[ESD]wait frame done ret:%d\n", ret);
  3128. }
  3129. DISPCHECK("[ESD]reset display path[begin]\n");
  3130. dpmgr_path_reset(pgc->dpmgr_handle, CMDQ_DISABLE);
  3131. DISPCHECK("[ESD]reset display path[end]\n");
  3132. /* 2: do esd check (!!!) */
  3133. MMProfileLogEx(ddp_mmp_get_events()->esd_rdlcm, MMProfileFlagPulse, 0, 2);
  3134. if (primary_display_is_video_mode())
  3135. /* ret = 0; */
  3136. ret = disp_lcm_esd_check(pgc->plcm);
  3137. else
  3138. ret = disp_lcm_esd_check(pgc->plcm);
  3139. /* 3: start path */
  3140. MMProfileLogEx(ddp_mmp_get_events()->esd_rdlcm, MMProfileFlagPulse, primary_display_is_video_mode(), 3);
  3141. DISPCHECK("[ESD]start dpmgr path[begin]\n");
  3142. dpmgr_path_start(pgc->dpmgr_handle, CMDQ_DISABLE);
  3143. DISPCHECK("[ESD]start dpmgr path[end]\n");
  3144. DISPCHECK("[ESD]start cmdq trigger loop[begin]\n");
  3145. _cmdq_start_trigger_loop();
  3146. DISPCHECK("[ESD]start cmdq trigger loop[end]\n");
  3147. _primary_path_unlock(__func__);
  3148. }
  3149. MMProfileLogEx(ddp_mmp_get_events()->esd_rdlcm, MMProfileFlagEnd, 0, ret);
  3150. done:
  3151. #ifdef MTK_DISP_IDLE_LP
  3152. _disp_primary_path_dsi_clock_off(0);
  3153. #endif
  3154. DISPCHECK("[ESD]ESD check end\n");
  3155. MMProfileLogEx(ddp_mmp_get_events()->esd_check_t, MMProfileFlagEnd, 0, ret);
  3156. dprec_logger_done(DPREC_LOGGER_ESD_CHECK, 0, 0);
  3157. _primary_path_esd_check_unlock();
  3158. return ret;
  3159. }
  3160. #ifdef MTK_FB_ESD_ENABLE
  3161. static int primary_display_esd_check_worker_kthread(void *data)
  3162. {
  3163. int ret = 0;
  3164. int i = 0;
  3165. int esd_try_cnt = 5; /* 20; */
  3166. int count = 0;
  3167. struct sched_param param = {.sched_priority = 87 }; /* RTPM_PRIO_FB_THREAD */
  3168. sched_setscheduler(current, SCHED_RR, &param);
  3169. dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE);
  3170. dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_START);
  3171. while (1) {
  3172. if (count == 0) {
  3173. count++;
  3174. msleep(3000);
  3175. }
  3176. msleep(2000); /* esd check every 2s */
  3177. ret = wait_event_interruptible(esd_check_task_wq, atomic_read(&esd_check_task_wakeup));
  3178. if (ret < 0) {
  3179. DISPCHECK("[ESD]esd check thread waked up accidently\n");
  3180. continue;
  3181. }
  3182. #ifdef DISP_SWITCH_DST_MODE
  3183. _primary_path_switch_dst_lock();
  3184. #endif
  3185. _primary_path_cmd_lock();
  3186. ret = primary_display_esd_check();
  3187. if (ret == 1) {
  3188. DISPCHECK("[ESD]esd check fail, will do esd recovery %d\n", ret);
  3189. i = esd_try_cnt;
  3190. while (i--) {
  3191. DISPCHECK("[ESD]esd recovery try:%d\n", i);
  3192. primary_display_esd_recovery();
  3193. ret = primary_display_esd_check();
  3194. if (ret == 0) {
  3195. DISPCHECK("[ESD]esd recovery success\n");
  3196. break;
  3197. }
  3198. DISPCHECK("[ESD]after esd recovery, esd check still fail\n");
  3199. if (i == 0) {
  3200. DISPCHECK("[ESD]after esd recovery %d times, esd check still fail,\n",
  3201. esd_try_cnt);
  3202. DISPCHECK("disable esd check\n");
  3203. primary_display_esd_check_enable(0);
  3204. primary_display_esd_recovery();
  3205. }
  3206. }
  3207. }
  3208. _primary_path_cmd_unlock();
  3209. #ifdef DISP_SWITCH_DST_MODE
  3210. _primary_path_switch_dst_unlock();
  3211. #endif
  3212. if (kthread_should_stop())
  3213. break;
  3214. }
  3215. return 0;
  3216. }
  3217. #endif /* MTK_FB_ESD_ENABLE */
  3218. /* ESD RECOVERY */
  3219. int primary_display_esd_recovery(void)
  3220. {
  3221. DISP_STATUS ret = DISP_STATUS_OK;
  3222. LCM_PARAMS *lcm_param = NULL;
  3223. DISPFUNC();
  3224. dprec_logger_start(DPREC_LOGGER_ESD_RECOVERY, 0, 0);
  3225. MMProfileLogEx(ddp_mmp_get_events()->esd_recovery_t, MMProfileFlagStart, 0, 0);
  3226. DISPCHECK("[ESD]ESD recovery begin\n");
  3227. _primary_path_lock(__func__);
  3228. MMProfileLogEx(ddp_mmp_get_events()->esd_recovery_t, MMProfileFlagPulse,
  3229. primary_display_is_video_mode(), 1);
  3230. lcm_param = disp_lcm_get_params(pgc->plcm);
  3231. if (pgc->state == DISP_SLEPT) {
  3232. DISPCHECK("[ESD]esd recovery but primary display path is slept??\n");
  3233. goto done;
  3234. }
  3235. MMProfileLogEx(ddp_mmp_get_events()->esd_recovery_t, MMProfileFlagPulse, 0, 2);
  3236. if (dpmgr_path_is_busy(pgc->dpmgr_handle)) {
  3237. DISPCHECK("[ESD]primary display path is busy\n");
  3238. ret = dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ * 1);
  3239. DISPCHECK("[ESD]wait frame done ret:%d\n", ret);
  3240. }
  3241. MMProfileLogEx(ddp_mmp_get_events()->esd_recovery_t, MMProfileFlagPulse, 0, 3);
  3242. DISPCHECK("[ESD]stop dpmgr path[begin]\n");
  3243. dpmgr_path_stop(pgc->dpmgr_handle, CMDQ_DISABLE);
  3244. DISPCHECK("[ESD]stop dpmgr path[end]\n");
  3245. MMProfileLogEx(ddp_mmp_get_events()->esd_recovery_t, MMProfileFlagPulse, 0, 4);
  3246. if (dpmgr_path_is_busy(pgc->dpmgr_handle)) {
  3247. DISPCHECK("[ESD]primary display path is busy after stop\n");
  3248. dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ * 1);
  3249. DISPCHECK("[ESD]wait frame done ret:%d\n", ret);
  3250. }
  3251. MMProfileLogEx(ddp_mmp_get_events()->esd_recovery_t, MMProfileFlagPulse, 0, 5);
  3252. DISPCHECK("[ESD]display cmdq trigger loop stop[begin]\n");
  3253. _cmdq_stop_trigger_loop();
  3254. DISPCHECK("[ESD]display cmdq trigger loop stop[end]\n");
  3255. MMProfileLogEx(ddp_mmp_get_events()->esd_recovery_t, MMProfileFlagPulse, 0, 6);
  3256. DISPCHECK("[ESD]reset display path[begin]\n");
  3257. dpmgr_path_reset(pgc->dpmgr_handle, CMDQ_DISABLE);
  3258. DISPCHECK("[ESD]reset display path[end]\n");
  3259. DISPCHECK("[POWER]lcm suspend[begin]\n");
  3260. disp_lcm_suspend(pgc->plcm);
  3261. DISPCHECK("[POWER]lcm suspend[end]\n");
  3262. MMProfileLogEx(ddp_mmp_get_events()->esd_recovery_t, MMProfileFlagPulse, 0, 7);
  3263. DISPCHECK("[ESD]dsi power reset[begin]\n");
  3264. dpmgr_path_dsi_power_off(pgc->dpmgr_handle, CMDQ_DISABLE);
  3265. dpmgr_path_dsi_power_on(pgc->dpmgr_handle, CMDQ_DISABLE);
  3266. if (!primary_display_is_video_mode())
  3267. dpmgr_path_ioctl(pgc->dpmgr_handle, NULL, DDP_DSI_ENABLE_TE, NULL);
  3268. DISPCHECK("[ESD]dsi power reset[end]\n");
  3269. MMProfileLogEx(ddp_mmp_get_events()->esd_recovery_t, MMProfileFlagPulse, 0, 8);
  3270. DISPCHECK("[ESD]lcm force init[begin]\n");
  3271. disp_lcm_init(pgc->plcm, 1);
  3272. DISPCHECK("[ESD]lcm force init[end]\n");
  3273. MMProfileLogEx(ddp_mmp_get_events()->esd_recovery_t, MMProfileFlagPulse, 0, 9);
  3274. DISPCHECK("[ESD]start dpmgr path[begin]\n");
  3275. dpmgr_path_start(pgc->dpmgr_handle, CMDQ_DISABLE);
  3276. DISPCHECK("[ESD]start dpmgr path[end]\n");
  3277. if (dpmgr_path_is_busy(pgc->dpmgr_handle)) {
  3278. DISPERR("[ESD]Fatal error, we didn't trigger display path but it's already busy\n");
  3279. ret = -1;
  3280. /* goto done; */
  3281. }
  3282. MMProfileLogEx(ddp_mmp_get_events()->esd_recovery_t, MMProfileFlagPulse, 0, 10);
  3283. if (primary_display_is_video_mode()) {
  3284. /* for video mode, we need to force trigger here */
  3285. /* for cmd mode, just set DPREC_EVENT_CMDQ_SET_EVENT_ALLOW when trigger loop start */
  3286. dpmgr_path_trigger(pgc->dpmgr_handle, NULL, CMDQ_DISABLE);
  3287. }
  3288. MMProfileLogEx(ddp_mmp_get_events()->esd_recovery_t, MMProfileFlagPulse, 0, 11);
  3289. DISPCHECK("[ESD]start cmdq trigger loop[begin]\n");
  3290. _cmdq_start_trigger_loop();
  3291. DISPCHECK("[ESD]start cmdq trigger loop[end]\n");
  3292. MMProfileLogEx(ddp_mmp_get_events()->esd_recovery_t, MMProfileFlagPulse, 0, 12);
  3293. done:
  3294. _primary_path_unlock(__func__);
  3295. DISPCHECK("[ESD]ESD recovery end\n");
  3296. MMProfileLogEx(ddp_mmp_get_events()->esd_recovery_t, MMProfileFlagEnd, 0, 0);
  3297. dprec_logger_done(DPREC_LOGGER_ESD_RECOVERY, 0, 0);
  3298. return ret;
  3299. }
  3300. void primary_display_esd_check_enable(int enable)
  3301. {
  3302. /* check if enable ESD check mechanism first */
  3303. if (_is_enable_esd_check() != true) {
  3304. DISPCHECK("[ESD]Checking if ESD enable but ESD check mechanism is not enabled.\n");
  3305. return;
  3306. }
  3307. if (_need_do_esd_check()) {
  3308. if (_need_register_eint() && eint_flag != 2) {
  3309. DISPCHECK("[ESD]Please check DCT setting about GPIO107/EINT107\n");
  3310. return;
  3311. }
  3312. if (enable) {
  3313. DISPPRINT("[ESD]esd check thread wakeup\n");
  3314. atomic_set(&esd_check_task_wakeup, 1);
  3315. wake_up_interruptible(&esd_check_task_wq);
  3316. } else {
  3317. DISPCHECK("[ESD]esd check thread stop\n");
  3318. atomic_set(&esd_check_task_wakeup, 0);
  3319. }
  3320. }
  3321. }
  3322. /******************************************************************************/
  3323. /* ESD CHECK / RECOVERY ---- End */
  3324. /******************************************************************************/
  3325. #define EEEEEEEEEEEEEEEEEEEEEEEEEE
  3326. #ifdef MTK_FB_PULLCLK_ENABLE
  3327. static int primary_display_vdo_pullclk_worker_kthread(void *data)
  3328. {
  3329. int ret = 0;
  3330. int count = 0;
  3331. struct sched_param param = {.sched_priority = 87 }; /* RTPM_PRIO_FB_THREAD */
  3332. sched_setscheduler(current, SCHED_RR, &param);
  3333. while (1) {
  3334. if (count == 0) {
  3335. count++;
  3336. msleep(3000);
  3337. }
  3338. msleep(2000);
  3339. #ifdef DISP_SWITCH_DST_MODE
  3340. _primary_path_switch_dst_lock();
  3341. #endif
  3342. _primary_path_cmd_lock();
  3343. _primary_path_esd_check_lock();
  3344. _primary_path_lock(__func__);
  3345. if (pgc->state == DISP_SLEPT) {
  3346. _primary_path_unlock(__func__);
  3347. _primary_path_esd_check_unlock();
  3348. continue;
  3349. }
  3350. _primary_path_unlock(__func__);
  3351. #ifdef MTK_DISP_IDLE_LP
  3352. _disp_primary_path_dsi_clock_on(0);
  3353. #endif
  3354. _primary_path_lock(__func__);
  3355. cmdqRecCreate(CMDQ_SCENARIO_DISP_ESD_CHECK, &(pgc->cmdq_handle_config_esd));
  3356. dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_config_esd, CMDQ_ESD_ALLC_SLOT);
  3357. _primary_path_unlock(__func__);
  3358. #ifdef DISP_DUMP_EVENT_STATUS
  3359. DISP_REG_SET_PA(pgc->cmdq_handle_config_esd, DISP_REG_CMDQ_TOKEN_ID, DISP_MUTEX0_STREAM_EOF_ID);
  3360. cmdqRecBackupRegisterToSlot(pgc->cmdq_handle_config_esd, pgc->event_status, 1
  3361. , DISP_REG_CMDQ_TOKEN_VALUE);
  3362. #endif
  3363. primary_display_esd_cust_bycmdq(1);
  3364. _primary_path_lock(__func__);
  3365. #if defined(MTK_FB_SODI_SUPPORT) && !defined(CONFIG_FPGA_EARLY_PORTING)
  3366. spm_enable_sodi(0);
  3367. #endif
  3368. /* reset*/
  3369. cmdqRecReset(pgc->cmdq_handle_config_esd);
  3370. /* wait stream eof first*/
  3371. cmdqRecWait(pgc->cmdq_handle_config_esd, CMDQ_EVENT_DISP_RDMA0_EOF);
  3372. cmdqRecWait(pgc->cmdq_handle_config_esd, CMDQ_EVENT_MUTEX0_STREAM_EOF);
  3373. /*stop dsi vdo mode*/
  3374. dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_config_esd, CMDQ_STOP_VDO_MODE);
  3375. /* pull DSI clock lane */
  3376. DSI_sw_clk_trail_cmdq(0, pgc->cmdq_handle_config_esd);
  3377. DSI_manual_enter_HS(pgc->cmdq_handle_config_esd);
  3378. /* start dsi vdo mode*/
  3379. dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_config_esd, CMDQ_START_VDO_MODE);
  3380. /* trigger path*/
  3381. cmdqRecClearEventToken(pgc->cmdq_handle_config_esd, CMDQ_EVENT_MUTEX0_STREAM_EOF);
  3382. if (gEnableSWTrigger == 1)
  3383. DISP_REG_SET(pgc->cmdq_handle_config_esd
  3384. , DISP_REG_CONFIG_MUTEX_EN(DISP_OVL_SEPARATE_MUTEX_ID), 1);
  3385. dpmgr_path_trigger(pgc->dpmgr_handle, pgc->cmdq_handle_config_esd, CMDQ_ENABLE);
  3386. if (gDumpESDCMD == 1) {
  3387. DISPMSG("esd dump before flush:\n");
  3388. cmdqRecDumpCommand(pgc->cmdq_handle_config_esd);
  3389. }
  3390. ret = cmdqRecFlush(pgc->cmdq_handle_config_esd);
  3391. #if defined(MTK_FB_SODI_SUPPORT) && !defined(CONFIG_FPGA_EARLY_PORTING)
  3392. spm_enable_sodi(1);
  3393. #endif
  3394. _primary_path_unlock(__func__);
  3395. primary_display_esd_cust_bycmdq(0);
  3396. _primary_path_lock(__func__);
  3397. dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_config_esd, CMDQ_ESD_FREE_SLOT);
  3398. cmdqRecDestroy(pgc->cmdq_handle_config_esd);
  3399. pgc->cmdq_handle_config_esd = NULL;
  3400. _primary_path_unlock(__func__);
  3401. #ifdef MTK_DISP_IDLE_LP
  3402. _disp_primary_path_dsi_clock_off(0);
  3403. #endif
  3404. _primary_path_esd_check_unlock();
  3405. _primary_path_cmd_unlock();
  3406. #ifdef DISP_SWITCH_DST_MODE
  3407. _primary_path_switch_dst_unlock();
  3408. #endif
  3409. if (kthread_should_stop())
  3410. break;
  3411. }
  3412. return 0;
  3413. }
  3414. #endif
  3415. static struct task_struct *primary_path_aal_task;
  3416. void disp_update_trigger_time(void)
  3417. {
  3418. last_primary_trigger_time = sched_clock();
  3419. }
  3420. /* extern unsigned int gResetOVLInAALTrigger; */
  3421. static int _disp_primary_path_check_trigger(void *data)
  3422. {
  3423. cmdqRecHandle handle = NULL;
  3424. #ifndef MTK_FB_CMDQ_DISABLE
  3425. int ret = 0;
  3426. ret = cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &handle);
  3427. #endif
  3428. dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_TRIGGER);
  3429. while (1) {
  3430. dpmgr_wait_event(pgc->dpmgr_handle, DISP_PATH_EVENT_TRIGGER);
  3431. MMProfileLogEx(ddp_mmp_get_events()->primary_display_aalod_trigger,
  3432. MMProfileFlagPulse, 0, 0);
  3433. _primary_path_lock(__func__);
  3434. if (primary_get_state() == DISP_ALIVE) {
  3435. #ifdef MTK_DISP_IDLE_LP
  3436. last_primary_trigger_time = sched_clock();
  3437. _disp_primary_path_exit_idle(__func__, 0);
  3438. #endif
  3439. cmdqRecReset(handle);
  3440. #ifndef MTK_FB_CMDQ_DISABLE
  3441. if (primary_display_is_video_mode())
  3442. cmdqRecWaitNoClear(handle, CMDQ_EVENT_DISP_RDMA0_EOF);
  3443. else
  3444. cmdqRecWaitNoClear(handle, CMDQ_SYNC_TOKEN_STREAM_EOF);
  3445. #endif
  3446. if (gResetOVLInAALTrigger == 1) {
  3447. ovl_reset_by_cmdq(handle, DISP_MODULE_OVL0);
  3448. if (ovl_get_status() != DDP_OVL1_STATUS_SUB)
  3449. ovl_reset_by_cmdq(handle, DISP_MODULE_OVL1);
  3450. }
  3451. _cmdq_set_config_handle_dirty_mira(handle);
  3452. /* disable SODI after set dirty */
  3453. if (primary_display_is_video_mode() == 0 && gDisableSODIForTriggerLoop == 1)
  3454. disp_set_sodi(0, handle);
  3455. _cmdq_flush_config_handle_mira(handle, 0);
  3456. }
  3457. _primary_path_unlock(__func__);
  3458. if (kthread_should_stop())
  3459. break;
  3460. }
  3461. cmdqRecDestroy(handle);
  3462. return 0;
  3463. }
  3464. #define OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
  3465. /* need remove */
  3466. unsigned int cmdqDdpClockOn(uint64_t engineFlag)
  3467. {
  3468. /* DISP_LOG_I("cmdqDdpClockOff\n"); */
  3469. return 0;
  3470. }
  3471. unsigned int cmdqDdpClockOff(uint64_t engineFlag)
  3472. {
  3473. /* DISP_LOG_I("cmdqDdpClockOff\n"); */
  3474. return 0;
  3475. }
  3476. unsigned int cmdqDdpDumpInfo(uint64_t engineFlag, char *pOutBuf, unsigned int bufSize)
  3477. {
  3478. DISPERR("cmdq timeout:%llu\n", engineFlag);
  3479. primary_display_diagnose();
  3480. /* DISP_LOG_I("cmdqDdpDumpInfo\n"); */
  3481. if (primary_display_is_decouple_mode()) {
  3482. ddp_dump_analysis(DISP_MODULE_OVL0);
  3483. #if defined(OVL_CASCADE_SUPPORT)
  3484. ddp_dump_analysis(DISP_MODULE_OVL1);
  3485. #endif
  3486. }
  3487. ddp_dump_analysis(DISP_MODULE_WDMA0);
  3488. /* try to set event by CPU to avoid blocking auto test such as Monkey/MTBF */
  3489. cmdqCoreSetEvent(CMDQ_SYNC_TOKEN_STREAM_EOF);
  3490. cmdqCoreSetEvent(CMDQ_EVENT_DISP_RDMA0_EOF);
  3491. return 0;
  3492. }
  3493. unsigned int cmdqDdpResetEng(uint64_t engineFlag)
  3494. {
  3495. /* DISP_LOG_I("cmdqDdpResetEng\n"); */
  3496. return 0;
  3497. }
  3498. /* TODO: these 2 functions should be splited into another file */
  3499. unsigned int display_path_idle_cnt = 0;
  3500. #if defined(MTK_FB_SODI_SUPPORT)
  3501. static void _RDMA0_INTERNAL_IRQ_Handler(DISP_MODULE_ENUM module, unsigned int param)
  3502. {
  3503. if (!_is_decouple_mode(pgc->session_mode) && param & 0x2) {
  3504. /* RDMA Start */
  3505. display_path_idle_cnt++;
  3506. #if !defined(CONFIG_FPGA_EARLY_PORTING) && !defined(FORCE_SODI_CG_MODE)
  3507. spm_sodi_mempll_pwr_mode(1);
  3508. #endif
  3509. MMProfileLogEx(ddp_mmp_get_events()->sodi_disable, MMProfileFlagPulse, 0, 0);
  3510. }
  3511. if (param & 0x4) {
  3512. /* RDMA Done */
  3513. display_path_idle_cnt--;
  3514. if (display_path_idle_cnt == 0) {
  3515. #if !defined(CONFIG_FPGA_EARLY_PORTING) && !defined(FORCE_SODI_CG_MODE)
  3516. spm_sodi_mempll_pwr_mode(0);
  3517. #endif
  3518. MMProfileLogEx(ddp_mmp_get_events()->sodi_enable, MMProfileFlagPulse, 0, 0);
  3519. }
  3520. }
  3521. }
  3522. static void _WDMA0_INTERNAL_IRQ_Handler(DISP_MODULE_ENUM module, unsigned int param)
  3523. {
  3524. if (param & 0x1) {
  3525. /* WDMA Done */
  3526. dpmgr_wdma_path_force_power_off();
  3527. if (!primary_display_is_video_mode()) {
  3528. display_path_idle_cnt--;
  3529. if (display_path_idle_cnt == 0) {
  3530. #if !defined(CONFIG_FPGA_EARLY_PORTING) && !defined(FORCE_SODI_CG_MODE)
  3531. spm_sodi_mempll_pwr_mode(0);
  3532. #endif
  3533. }
  3534. }
  3535. }
  3536. }
  3537. static void _MUTEX_INTERNAL_IRQ_Handler(DISP_MODULE_ENUM module, unsigned int param)
  3538. {
  3539. if (param & 0x1) { /* RDMA-->DSI SOF */
  3540. display_path_idle_cnt++;
  3541. #if !defined(CONFIG_FPGA_EARLY_PORTING) && !defined(FORCE_SODI_CG_MODE)
  3542. spm_sodi_mempll_pwr_mode(1);
  3543. #endif
  3544. }
  3545. if (param & 0x2) { /* OVL->WDMA SOF */
  3546. display_path_idle_cnt++;
  3547. #if !defined(CONFIG_FPGA_EARLY_PORTING) && !defined(FORCE_SODI_CG_MODE)
  3548. spm_sodi_mempll_pwr_mode(1);
  3549. #endif
  3550. }
  3551. }
  3552. #endif
  3553. void primary_display_sodi_rule_init(void)
  3554. {
  3555. #if defined(MTK_FB_SODI_DEFEATURE)
  3556. if ((primary_display_get_width() > 800) && (primary_display_is_video_mode() == 1)) {
  3557. #ifndef CONFIG_FPGA_EARLY_PORTING
  3558. defeature_soidle_by_display();
  3559. #endif
  3560. DISPMSG("SODI defeatured!\n");
  3561. return;
  3562. }
  3563. #endif
  3564. #if defined(MTK_FB_SODI_SUPPORT)
  3565. /* if ((primary_display_mode == DECOUPLE_MODE) && primary_display_is_video_mode()) */
  3566. if (gEnableSODIControl == 0 && primary_display_is_video_mode() == 1) {
  3567. #ifndef CONFIG_FPGA_EARLY_PORTING
  3568. spm_enable_sodi(0);
  3569. #endif
  3570. DISPMSG("SODI disabled!\n");
  3571. return;
  3572. }
  3573. #ifndef CONFIG_FPGA_EARLY_PORTING
  3574. spm_enable_sodi(1);
  3575. #endif
  3576. if (primary_display_is_video_mode()) {
  3577. /* if switch to video mode, should de-register callback */
  3578. disp_unregister_module_irq_callback(DISP_MODULE_RDMA0, _RDMA0_INTERNAL_IRQ_Handler);
  3579. #ifdef WDMA_PATH_CLOCK_DYNAMIC_SWITCH
  3580. disp_register_module_irq_callback(DISP_MODULE_WDMA0, _WDMA0_INTERNAL_IRQ_Handler);
  3581. #endif
  3582. /* spm_sodi_mempll_pwr_mode(0); */
  3583. } else {
  3584. disp_register_module_irq_callback(DISP_MODULE_RDMA0, _RDMA0_INTERNAL_IRQ_Handler);
  3585. #ifdef WDMA_PATH_CLOCK_DYNAMIC_SWITCH
  3586. disp_register_module_irq_callback(DISP_MODULE_WDMA0, _WDMA0_INTERNAL_IRQ_Handler);
  3587. #endif
  3588. if (_is_decouple_mode(pgc->session_mode)) {
  3589. disp_register_module_irq_callback(DISP_MODULE_MUTEX, _MUTEX_INTERNAL_IRQ_Handler);
  3590. disp_register_module_irq_callback(DISP_MODULE_WDMA0, _WDMA0_INTERNAL_IRQ_Handler);
  3591. }
  3592. }
  3593. #endif
  3594. }
  3595. /* extern int dfo_query(const char *s, unsigned long *v); */
  3596. int primary_display_change_lcm_resolution(unsigned int width, unsigned int height)
  3597. {
  3598. if (pgc->plcm) {
  3599. DISPMSG("LCM Resolution will be changed, original: %dx%d, now: %dx%d\n",
  3600. pgc->plcm->params->width, pgc->plcm->params->height, width, height);
  3601. /* align with 4 is the minimal check, to ensure we can boot up into kernel,
  3602. * and could modify dfo setting again using meta tool
  3603. */
  3604. /* otherwise we will have a panic in lk(root cause unknown). */
  3605. if (width > pgc->plcm->params->width || height > pgc->plcm->params->height ||
  3606. width == 0 || height == 0 || width % 4 || height % 2) {
  3607. DISPERR("Invalid resolution: %dx%d\n", width, height);
  3608. return -1;
  3609. }
  3610. if (primary_display_is_video_mode()) {
  3611. DISPERR("Warning!!!Video Mode can't support multiple resolution!\n");
  3612. return -1;
  3613. }
  3614. pgc->plcm->params->width = width;
  3615. pgc->plcm->params->height = height;
  3616. return 0;
  3617. } else {
  3618. return -1;
  3619. }
  3620. }
  3621. static void primary_display_frame_update_irq_callback(DISP_MODULE_ENUM module, unsigned int param)
  3622. {
  3623. /* if (pgc->session_mode == DISP_SESSION_DIRECT_LINK_MIRROR_MODE) */
  3624. /* return; */
  3625. if (module == DISP_MODULE_RDMA0) {
  3626. if (param & 0x20) { /* rdma0 frame start */
  3627. if (pgc->session_id > 0)
  3628. update_frm_seq_info(ddp_ovl_get_cur_addr(1, 0), 0, 1, FRM_START);
  3629. }
  3630. if (param & 0x4) { /* rdma0 frame done */
  3631. atomic_set(&primary_display_frame_update_event, 1);
  3632. wake_up_interruptible(&primary_display_frame_update_wq);
  3633. }
  3634. }
  3635. if ((module == DISP_MODULE_OVL0) && (_is_decouple_mode(pgc->session_mode) == 0)) {
  3636. if (param & 0x2) { /* ov0 frame done */
  3637. atomic_set(&primary_display_frame_update_event, 1);
  3638. wake_up_interruptible(&primary_display_frame_update_wq);
  3639. }
  3640. }
  3641. #if defined(CONFIG_TRUSTONIC_TEE_SUPPORT) && defined(CONFIG_MTK_SEC_VIDEO_PATH_SUPPORT)
  3642. /* In TEE, we have to protect WDMA registers, so we can't enable WDMA interrupt */
  3643. /* here we use ovl frame done interrupt instead */
  3644. if ((module == DISP_MODULE_OVL0) && (_is_decouple_mode(pgc->session_mode) == 1)) {
  3645. if (param & 0x2) {/* OVL0 frame done */
  3646. atomic_set(&decouple_fence_release_event, 1);
  3647. wake_up_interruptible(&decouple_fence_release_wq);
  3648. }
  3649. }
  3650. #else
  3651. if ((module == DISP_MODULE_WDMA0) && (_is_decouple_mode(pgc->session_mode) == 1)) {
  3652. if (param & 0x1) {/* wdma0 frame done */
  3653. atomic_set(&decouple_fence_release_event, 1);
  3654. wake_up_interruptible(&decouple_fence_release_wq);
  3655. }
  3656. }
  3657. #endif
  3658. }
  3659. static int primary_display_frame_update_kthread(void *data)
  3660. {
  3661. struct sched_param param = {.sched_priority = 94 }; /* RTPM_PRIO_SCRN_UPDATE */
  3662. sched_setscheduler(current, SCHED_RR, &param);
  3663. for (;;) {
  3664. wait_event_interruptible(primary_display_frame_update_wq,
  3665. atomic_read(&primary_display_frame_update_event));
  3666. atomic_set(&primary_display_frame_update_event, 0);
  3667. if (pgc->session_id > 0)
  3668. update_frm_seq_info(0, 0, 0, FRM_END);
  3669. if (kthread_should_stop())
  3670. break;
  3671. }
  3672. return 0;
  3673. }
  3674. /* defined but not used */
  3675. /* static struct task_struct *if_fence_release_worker_task = NULL; */
  3676. #if 0
  3677. /**
  3678. * Defined but not used, avoid build warning. (2015.1.30 Rynn Wu)
  3679. */
  3680. static int _if_fence_release_worker_thread(void *data)
  3681. {
  3682. unsigned int session_id = MAKE_DISP_SESSION(DISP_SESSION_PRIMARY, 0);
  3683. struct sched_param param = { .sched_priority = RTPM_PRIO_SCRN_UPDATE };
  3684. sched_setscheduler(current, SCHED_RR, &param);
  3685. dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_START);
  3686. while (1) {
  3687. dpmgr_wait_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_START);
  3688. if (_is_mirror_mode(pgc->session_mode)) {
  3689. int fence_idx, subtractor, layer;
  3690. layer = disp_sync_get_output_interface_timeline_id();
  3691. cmdqBackupReadSlot(pgc->cur_config_fence, layer, &fence_idx);
  3692. cmdqBackupReadSlot(pgc->subtractor_when_free, layer, &subtractor);
  3693. mtkfb_release_fence(session_id, layer, fence_idx-1);
  3694. }
  3695. if (kthread_should_stop())
  3696. break;
  3697. }
  3698. return 0;
  3699. }
  3700. #endif
  3701. /* defined but not used. */
  3702. /* static struct task_struct *ovl2mem_fence_release_worker_task = NULL; */
  3703. #if 0
  3704. /**
  3705. * Defined but not used, avoid build warning. (2015.1.30 Rynn Wu)
  3706. */
  3707. static int _ovl2mem_fence_release_worker_thread(void *data)
  3708. {
  3709. unsigned int session_id = MAKE_DISP_SESSION(DISP_SESSION_PRIMARY, 0);
  3710. struct sched_param param = { .sched_priority = RTPM_PRIO_SCRN_UPDATE };
  3711. sched_setscheduler(current, SCHED_RR, &param);
  3712. dpmgr_enable_event(pgc->ovl2mem_path_handle, DISP_PATH_EVENT_FRAME_COMPLETE);
  3713. while (1) {
  3714. /* it's not good to use FRAME_COMPLETE here, because when CPU read wdma addr,
  3715. * maybe it's already changed by next request,
  3716. * but luckly currently we will wait rdma frame done after wdma done(in CMDQ), so it's safe now
  3717. */
  3718. dpmgr_wait_event(pgc->ovl2mem_path_handle, DISP_PATH_EVENT_FRAME_COMPLETE);
  3719. if (_is_mirror_mode(pgc->session_mode)) {
  3720. int fence_idx, subtractor, layer;
  3721. layer = disp_sync_get_output_timeline_id();
  3722. cmdqBackupReadSlot(pgc->cur_config_fence, layer, &fence_idx);
  3723. cmdqBackupReadSlot(pgc->subtractor_when_free, layer, &subtractor);
  3724. mtkfb_release_fence(session_id, layer, fence_idx);
  3725. }
  3726. if (kthread_should_stop())
  3727. break;
  3728. }
  3729. return 0;
  3730. }
  3731. #endif
  3732. /* defined but not used. */
  3733. /* static struct task_struct *fence_release_worker_task = NULL; */
  3734. /* extern unsigned int ddp_ovl_get_cur_addr(bool rdma_mode, int layerid); */
  3735. static void _wdma_fence_release_callback(uint32_t userdata)
  3736. {
  3737. int fence_idx, layer;
  3738. layer = disp_sync_get_output_timeline_id();
  3739. cmdqBackupReadSlot(pgc->cur_config_fence, layer, &fence_idx);
  3740. mtkfb_release_fence(primary_session_id, layer, fence_idx);
  3741. MMProfileLogEx(ddp_mmp_get_events()->primary_wdma_fence_release, MMProfileFlagPulse, layer,
  3742. fence_idx);
  3743. }
  3744. static int _Interface_fence_release_callback(uint32_t userdata)
  3745. {
  3746. int layer = disp_sync_get_output_interface_timeline_id();
  3747. if (userdata > 0) {
  3748. mtkfb_release_fence(primary_session_id, layer, userdata);
  3749. MMProfileLogEx(ddp_mmp_get_events()->primary_wdma_fence_release, MMProfileFlagPulse,
  3750. layer, userdata);
  3751. }
  3752. return 0;
  3753. }
  3754. static int _ovl_ext_fence_release_callback(uint32_t userdata)
  3755. {
  3756. int i = 0;
  3757. int ret = 0;
  3758. int fence_idx, layer;
  3759. MMProfileLogEx(ddp_mmp_get_events()->session_release, MMProfileFlagStart, 1, userdata);
  3760. #ifndef MTK_FB_CMDQ_DISABLE
  3761. for (i = 0; i < PRIMARY_DISPLAY_SESSION_LAYER_COUNT; i++) {
  3762. int fence_idx = 0;
  3763. int subtractor = 0;
  3764. if (i == primary_display_get_option("ASSERT_LAYER") && is_DAL_Enabled()) {
  3765. mtkfb_release_layer_fence(ext_session_id, i);
  3766. } else {
  3767. cmdqBackupReadSlot(pgc->cur_mem_config_fence, i, &fence_idx);
  3768. cmdqBackupReadSlot(pgc->mem_subtractor_when_free, i, &subtractor);
  3769. mtkfb_release_fence(ext_session_id, i, fence_idx);
  3770. }
  3771. MMProfileLogEx(ddp_mmp_get_events()->primary_ovl_fence_release, MMProfileFlagPulse, i, fence_idx);
  3772. }
  3773. #endif
  3774. if (userdata == DISP_SESSION_MEMORY) {
  3775. #ifndef MTK_FB_CMDQ_DISABLE
  3776. layer = disp_sync_get_output_timeline_id();
  3777. cmdqBackupReadSlot(pgc->cur_mem_config_fence, layer, &fence_idx);
  3778. mtkfb_release_fence(ext_session_id, layer, fence_idx);
  3779. #endif
  3780. }
  3781. return ret;
  3782. }
  3783. static int _ovl_fence_release_callback(uint32_t userdata)
  3784. {
  3785. int i = 0;
  3786. unsigned int addr = 0;
  3787. int ret = 0;
  3788. unsigned int dsi_state[10];
  3789. unsigned int rdma_state[50];
  3790. MMProfileLogEx(ddp_mmp_get_events()->session_release, MMProfileFlagStart, 1, userdata);
  3791. /* releaes OVL1 when primary setting */
  3792. if (ovl_get_status() == DDP_OVL1_STATUS_PRIMARY_RELEASED)
  3793. dpmgr_set_ovl1_status(DDP_OVL1_STATUS_SUB);
  3794. else if (ovl_get_status() == DDP_OVL1_STATUS_PRIMARY_DISABLE)
  3795. dpmgr_set_ovl1_status(DDP_OVL1_STATUS_IDLE);
  3796. #ifndef MTK_FB_CMDQ_DISABLE
  3797. for (i = 0; i < PRIMARY_DISPLAY_SESSION_LAYER_COUNT; i++) {
  3798. int fence_idx = 0;
  3799. int subtractor = 0;
  3800. if (i == primary_display_get_option("ASSERT_LAYER") && is_DAL_Enabled()) {
  3801. mtkfb_release_layer_fence(primary_session_id, i);
  3802. } else {
  3803. cmdqBackupReadSlot(pgc->cur_config_fence, i, &fence_idx);
  3804. cmdqBackupReadSlot(pgc->subtractor_when_free, i, &subtractor);
  3805. mtkfb_release_fence(primary_session_id, i, fence_idx - subtractor);
  3806. }
  3807. MMProfileLogEx(ddp_mmp_get_events()->primary_ovl_fence_release, MMProfileFlagPulse,
  3808. i, fence_idx - subtractor);
  3809. }
  3810. if (primary_display_is_video_mode() == 1) {
  3811. unsigned int ovl_status[2];
  3812. cmdqBackupReadSlot(pgc->ovl_status_info, 0, &ovl_status[0]);
  3813. cmdqBackupReadSlot(pgc->ovl_status_info, 1, &ovl_status[1]);
  3814. DISPDBG("ovl fsm state:0x%x\n", ovl_status[0]);
  3815. if ((ovl_status[1] & 0x1) != OVL_STATUS_IDLE) {
  3816. DISPERR("disp ovl status error, 0x%x, 0x%x\n", ovl_status[0],
  3817. ovl_status[1]);
  3818. /* dump cmdq cmd here */
  3819. }
  3820. }
  3821. #endif
  3822. /* backup DSI state register to slot */
  3823. if (gEnableDSIStateCheck == 1) {
  3824. for (i = 0; i < 10; i++) {
  3825. cmdqBackupReadSlot(pgc->dsi_state_info, i, &dsi_state[i]);
  3826. if ((dsi_state[i] & 0x2) == 0x2) {
  3827. DISPERR("disp DSI_STATE error, %d, 0x%x\n", i, dsi_state[i]);
  3828. cmdqBackupReadSlot(pgc->rdma_state_info, i * 5 + 0,
  3829. &rdma_state[i * 5 + 0]);
  3830. cmdqBackupReadSlot(pgc->rdma_state_info, i * 5 + 1,
  3831. &rdma_state[i * 5 + 1]);
  3832. cmdqBackupReadSlot(pgc->rdma_state_info, i * 5 + 2,
  3833. &rdma_state[i * 5 + 2]);
  3834. cmdqBackupReadSlot(pgc->rdma_state_info, i * 5 + 3,
  3835. &rdma_state[i * 5 + 3]);
  3836. cmdqBackupReadSlot(pgc->rdma_state_info, i * 5 + 4,
  3837. &rdma_state[i * 5 + 4]);
  3838. DISPERR("disp RDMA_STATE:%d, irq=0x%x, in/out=(%d,%d,%d,%d)\n",
  3839. i, rdma_state[i * 5 + 0], rdma_state[i * 5 + 1],
  3840. rdma_state[i * 5 + 2], rdma_state[i * 5 + 3], rdma_state[i * 5 + 4]);
  3841. } else {
  3842. DISPERR("disp DSI_STATE pass, %d, 0x%x\n", i, dsi_state[i]);
  3843. }
  3844. }
  3845. }
  3846. addr = ddp_ovl_get_cur_addr(!_should_config_ovl_input(), 0);
  3847. if ((_is_decouple_mode(pgc->session_mode) == 0))
  3848. update_frm_seq_info(addr, 0, 2, FRM_START);
  3849. #ifndef MTK_FB_CMDQ_DISABLE
  3850. if (userdata == 5) {
  3851. int fence_idx, subtractor, layer;
  3852. layer = disp_sync_get_output_timeline_id();
  3853. cmdqBackupReadSlot(pgc->cur_config_fence, layer, &fence_idx);
  3854. cmdqBackupReadSlot(pgc->subtractor_when_free, layer, &subtractor);
  3855. mtkfb_release_fence(primary_session_id, layer, fence_idx);
  3856. }
  3857. /* async callback, need to check if it is still decouple */
  3858. if (_is_decouple_mode(pgc->session_mode) && !_is_mirror_mode(pgc->session_mode)
  3859. && (userdata == DISP_SESSION_DECOUPLE_MODE || userdata == 5)) {
  3860. static cmdqRecHandle cmdq_handle;
  3861. unsigned int rdma_pitch_sec, rdma_fmt;
  3862. if (primary_get_state() != DISP_ALIVE)
  3863. return 0;
  3864. if (cmdq_handle == NULL)
  3865. ret = cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &cmdq_handle);
  3866. if (ret == 0) {
  3867. cmdqBackupReadSlot(pgc->rdma_buff_info, 1, &(rdma_pitch_sec));
  3868. rdma_pitch_sec = rdma_pitch_sec >> 30;
  3869. if (rdma_pitch_sec == DISP_NORMAL_BUFFER)
  3870. _primary_path_lock(__func__);
  3871. cmdqRecReset(cmdq_handle);
  3872. _cmdq_insert_wait_frame_done_token_mira(cmdq_handle);
  3873. cmdqBackupReadSlot(pgc->rdma_buff_info, 0, &addr);
  3874. decouple_rdma_config.address = addr;
  3875. /*rdma pitch only use bit[15..0], we use bit[31:30] to store secure information */
  3876. decouple_rdma_config.security = rdma_pitch_sec;
  3877. _config_rdma_input_data(&decouple_rdma_config, pgc->dpmgr_handle,
  3878. cmdq_handle);
  3879. _cmdq_set_config_handle_dirty_mira(cmdq_handle);
  3880. cmdqRecFlushAsyncCallback(cmdq_handle, NULL, 0);
  3881. cmdqBackupReadSlot(pgc->rdma_buff_info, 2, &(rdma_fmt));
  3882. decouple_rdma_config.inputFormat = rdma_fmt;
  3883. if (rdma_pitch_sec == DISP_NORMAL_BUFFER)
  3884. _primary_path_unlock(__func__);
  3885. MMProfileLogEx(ddp_mmp_get_events()->primary_rdma_config,
  3886. MMProfileFlagPulse, 0, decouple_rdma_config.address);
  3887. /* cmdqRecDestroy(cmdq_handle); */
  3888. } else {
  3889. /* ret = -1; */
  3890. DISPERR("fail to create cmdq\n");
  3891. }
  3892. }
  3893. #endif
  3894. return ret;
  3895. }
  3896. static int decouple_fence_release_kthread(void *data)
  3897. {
  3898. int interface_fence = 0;
  3899. int layer = 0;
  3900. int ret = 0;
  3901. struct sched_param param = {.sched_priority = 94 }; /* RTPM_PRIO_SCRN_UPDATE */
  3902. sched_setscheduler(current, SCHED_RR, &param);
  3903. for (;;) {
  3904. wait_event_interruptible(decouple_fence_release_wq,
  3905. atomic_read(&decouple_fence_release_event));
  3906. atomic_set(&decouple_fence_release_event, 0);
  3907. /* async callback, need to check if it is still decouple */
  3908. _primary_path_lock(__func__);
  3909. if (pgc->session_mode == DISP_SESSION_DECOUPLE_MIRROR_MODE
  3910. && pgc->state != DISP_SLEPT) {
  3911. static cmdqRecHandle cmdq_handle;
  3912. unsigned int rdma_pitch_sec, rdma_fmt;
  3913. if (cmdq_handle == NULL)
  3914. ret = cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &cmdq_handle);
  3915. if (ret == 0) {
  3916. RDMA_CONFIG_STRUCT tmpConfig = decouple_rdma_config;
  3917. cmdqRecReset(cmdq_handle);
  3918. _cmdq_insert_wait_frame_done_token_mira(cmdq_handle);
  3919. cmdqBackupReadSlot(pgc->rdma_buff_info, 0,
  3920. (uint32_t *)&(tmpConfig.address));
  3921. /*rdma pitch only use bit[15..0], we use bit[31:30] to store secure information */
  3922. cmdqBackupReadSlot(pgc->rdma_buff_info, 1, &(rdma_pitch_sec));
  3923. tmpConfig.pitch = rdma_pitch_sec & ~(3 << 30);
  3924. tmpConfig.security = rdma_pitch_sec >> 30;
  3925. cmdqBackupReadSlot(pgc->rdma_buff_info, 2, &(rdma_fmt));
  3926. tmpConfig.inputFormat = rdma_fmt;
  3927. _config_rdma_input_data(&tmpConfig, pgc->dpmgr_handle, cmdq_handle);
  3928. layer = disp_sync_get_output_timeline_id();
  3929. cmdqBackupReadSlot(pgc->cur_config_fence, layer, &interface_fence);
  3930. _cmdq_set_config_handle_dirty_mira(cmdq_handle);
  3931. cmdqRecFlushAsyncCallback(cmdq_handle,
  3932. (CmdqAsyncFlushCB)_Interface_fence_release_callback,
  3933. interface_fence > 1 ? interface_fence - 1 : 0);
  3934. MMProfileLogEx(ddp_mmp_get_events()->primary_rdma_config,
  3935. MMProfileFlagPulse, interface_fence,
  3936. decouple_rdma_config.address);
  3937. /* dump rdma input if enabled */
  3938. dprec_mmp_dump_rdma_layer(&tmpConfig, 0);
  3939. /* cmdqRecDestroy(cmdq_handle); */
  3940. } else {
  3941. DISPERR("fail to create cmdq\n");
  3942. }
  3943. }
  3944. _primary_path_unlock(__func__);
  3945. if (kthread_should_stop())
  3946. break;
  3947. }
  3948. return 0;
  3949. }
  3950. static int _olv_wdma_fence_release_callback(uint32_t userdata)
  3951. {
  3952. _ovl_fence_release_callback(userdata);
  3953. _wdma_fence_release_callback(userdata);
  3954. return 0;
  3955. }
  3956. #if 0
  3957. /**
  3958. * Defined but not used, avoid build warning. (2015.1.30 Rynn Wu)
  3959. */
  3960. static int _fence_release_worker_thread(void *data)
  3961. {
  3962. int i = 0;
  3963. unsigned int addr = 0;
  3964. unsigned int session_id = MAKE_DISP_SESSION(DISP_SESSION_PRIMARY, 0);
  3965. struct sched_param param = { .sched_priority = RTPM_PRIO_SCRN_UPDATE };
  3966. sched_setscheduler(current, SCHED_RR, &param);
  3967. if (!_is_decouple_mode(pgc->session_mode))
  3968. dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_START);
  3969. else
  3970. dpmgr_enable_event(pgc->ovl2mem_path_handle, DISP_PATH_EVENT_FRAME_START);
  3971. while (1) {
  3972. if (!_is_decouple_mode(pgc->session_mode))
  3973. dpmgr_wait_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_START);
  3974. else
  3975. dpmgr_wait_event(pgc->ovl2mem_path_handle, DISP_PATH_EVENT_FRAME_START);
  3976. if (is_hwc_enabled == 0)
  3977. continue;
  3978. /* releaes OVL1 when primary setting */
  3979. if (ovl_get_status() == DDP_OVL1_STATUS_PRIMARY_RELEASED) {
  3980. ovl_set_status(DDP_OVL1_STATUS_SUB);
  3981. wake_up_interruptible(&ovl1_wait_queue);
  3982. } else if (ovl_get_status() == DDP_OVL1_STATUS_PRIMARY_DISABLE) {
  3983. ovl_set_status(DDP_OVL1_STATUS_IDLE);
  3984. wake_up_interruptible(&ovl1_wait_queue);
  3985. }
  3986. for (i = 0; i < PRIMARY_DISPLAY_SESSION_LAYER_COUNT; i++) {
  3987. int fence_idx, subtractor;
  3988. if (i == primary_display_get_option("ASSERT_LAYER") && is_DAL_Enabled()) {
  3989. mtkfb_release_layer_fence(session_id, i);
  3990. } else {
  3991. cmdqBackupReadSlot(pgc->cur_config_fence, i, &fence_idx);
  3992. cmdqBackupReadSlot(pgc->subtractor_when_free, i, &subtractor);
  3993. mtkfb_release_fence(session_id, i, fence_idx-subtractor);
  3994. }
  3995. }
  3996. addr = ddp_ovl_get_cur_addr(!_should_config_ovl_input(), 0);
  3997. if ((_is_decouple_mode(pgc->session_mode) == 0))
  3998. update_frm_seq_info(addr, 0, 2, FRM_START);
  3999. MMProfileLogEx(ddp_mmp_get_events()->session_release, MMProfileFlagEnd, 0, 0);
  4000. if (kthread_should_stop())
  4001. break;
  4002. }
  4003. return 0;
  4004. }
  4005. #endif
  4006. static struct task_struct *present_fence_release_worker_task;
  4007. static int _present_fence_release_worker_thread(void *data)
  4008. {
  4009. int ret = 0;
  4010. disp_sync_info *layer_info = NULL;
  4011. struct sched_param param = {.sched_priority = 87 }; /* RTPM_PRIO_FB_THREAD */
  4012. sched_setscheduler(current, SCHED_RR, &param);
  4013. dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC);
  4014. while (1) {
  4015. ret = dpmgr_wait_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC);
  4016. /* release present fence in vsync callback */
  4017. {
  4018. /* extern disp_sync_info *_get_sync_info(unsigned int session_id,
  4019. unsigned int timeline_id);
  4020. */
  4021. int fence_increment = 0;
  4022. /* if session not created, do not release present fence */
  4023. if (pgc->session_id == 0) {
  4024. MMProfileLogEx(ddp_mmp_get_events()->present_fence_release,
  4025. MMProfileFlagPulse, -1, 0x4a4a4a4a);
  4026. /* DISPDBG("_get_sync_info fail in present_fence_release thread\n"); */
  4027. continue;
  4028. }
  4029. layer_info = _get_sync_info(pgc->session_id, disp_sync_get_present_timeline_id());
  4030. if (layer_info == NULL) {
  4031. MMProfileLogEx(ddp_mmp_get_events()->present_fence_release,
  4032. MMProfileFlagPulse, -1, 0x5a5a5a5a);
  4033. /* DISPERR("_get_sync_info fail in present_fence_release thread\n"); */
  4034. continue;
  4035. }
  4036. _primary_path_lock(__func__);
  4037. fence_increment = gPresentFenceIndex - layer_info->timeline->value;
  4038. if (fence_increment > 0) {
  4039. timeline_inc(layer_info->timeline, fence_increment);
  4040. MMProfileLogEx(ddp_mmp_get_events()->present_fence_release,
  4041. MMProfileFlagPulse, gPresentFenceIndex,
  4042. fence_increment);
  4043. }
  4044. _primary_path_unlock(__func__);
  4045. /* DISPPR_FENCE("RPF/%d/%d\n",
  4046. gPresentFenceIndex, gPresentFenceIndex-layer_info->timeline->value);
  4047. */
  4048. }
  4049. }
  4050. return 0;
  4051. }
  4052. int primary_display_capture_framebuffer_wdma(void *data)
  4053. {
  4054. int ret = 0;
  4055. cmdqRecHandle cmdq_handle = NULL;
  4056. disp_ddp_path_config *pconfig = NULL;
  4057. m4u_client_t *m4uClient = NULL;
  4058. unsigned int w_xres = primary_display_get_width();
  4059. unsigned int h_yres = primary_display_get_height();
  4060. unsigned int pixel_byte = primary_display_get_dc_bpp() / 8; /* bpp is either 32 or 16, can not be other value */
  4061. int buffer_size = h_yres * w_xres * pixel_byte;
  4062. int buf_idx = 0;
  4063. unsigned int mva[2] = { 0, 0 };
  4064. void *va[2] = { NULL, NULL };
  4065. unsigned int format = eRGBA8888;
  4066. struct sched_param param = {.sched_priority = 87 }; /* RTPM_PRIO_FB_THREAD */
  4067. sched_setscheduler(current, SCHED_RR, &param);
  4068. va[0] = vmalloc(buffer_size);
  4069. if (va[0] == NULL) {
  4070. DISPCHECK("wdma dump:Fail to alloc vmalloc 0\n");
  4071. ret = -1;
  4072. goto out;
  4073. }
  4074. va[1] = vmalloc(buffer_size);
  4075. if (va[1] == NULL) {
  4076. DISPCHECK("wdma dump:Fail to alloc vmalloc 1\n");
  4077. ret = -1;
  4078. goto out;
  4079. }
  4080. m4uClient = m4u_create_client();
  4081. if (m4uClient == NULL) {
  4082. DISPCHECK("wdma dump:Fail to alloc m4uClient=0x%p\n", m4uClient);
  4083. ret = -1;
  4084. goto out;
  4085. }
  4086. ret = m4u_alloc_mva(m4uClient, M4U_PORT_DISP_WDMA0, (unsigned long)va[0], NULL, buffer_size,
  4087. M4U_PROT_READ | M4U_PROT_WRITE, 0, (unsigned int *)&mva[0]);
  4088. if (ret != 0) {
  4089. DISPCHECK("wdma dump::Fail to allocate mva 0\n");
  4090. ret = -1;
  4091. goto out;
  4092. }
  4093. ret = m4u_alloc_mva(m4uClient, M4U_PORT_DISP_WDMA0, (unsigned long)va[1], NULL, buffer_size,
  4094. M4U_PROT_READ | M4U_PROT_WRITE, 0, (unsigned int *)&mva[1]);
  4095. if (ret != 0) {
  4096. DISPCHECK("wdma dump::Fail to allocate mva 1\n");
  4097. ret = -1;
  4098. goto out;
  4099. }
  4100. if (primary_display_cmdq_enabled()) {
  4101. /*create config thread */
  4102. ret = cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &cmdq_handle);
  4103. if (ret != 0) {
  4104. DISPCHECK("wdma dump:Fail to create primary cmdq handle for capture\n");
  4105. ret = -1;
  4106. goto out;
  4107. }
  4108. dpmgr_path_memout_clock(pgc->dpmgr_handle, 1);
  4109. dpmgr_enable_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_START);
  4110. cmdqRecReset(cmdq_handle);
  4111. _cmdq_insert_wait_frame_done_token_mira(cmdq_handle);
  4112. _primary_path_lock(__func__);
  4113. dpmgr_path_add_memout(pgc->dpmgr_handle, ENGINE_OVL0, cmdq_handle);
  4114. _primary_path_unlock(__func__);
  4115. while (primary_dump_wdma) {
  4116. ret = m4u_cache_sync(m4uClient, M4U_PORT_DISP_WDMA0, (unsigned long)va[buf_idx],
  4117. buffer_size, mva[buf_idx], M4U_CACHE_FLUSH_BY_RANGE);
  4118. _primary_path_lock(__func__);
  4119. pconfig = dpmgr_path_get_last_config(pgc->dpmgr_handle);
  4120. pconfig->wdma_dirty = 1;
  4121. pconfig->wdma_config.dstAddress = mva[buf_idx];
  4122. pconfig->wdma_config.srcHeight = h_yres;
  4123. pconfig->wdma_config.srcWidth = w_xres;
  4124. pconfig->wdma_config.clipX = 0;
  4125. pconfig->wdma_config.clipY = 0;
  4126. pconfig->wdma_config.clipHeight = h_yres;
  4127. pconfig->wdma_config.clipWidth = w_xres;
  4128. pconfig->wdma_config.outputFormat = format;
  4129. pconfig->wdma_config.useSpecifiedAlpha = 1;
  4130. pconfig->wdma_config.alpha = 0xFF;
  4131. pconfig->wdma_config.dstPitch = w_xres * DP_COLOR_BITS_PER_PIXEL(format) / 8;
  4132. ret = dpmgr_path_config(pgc->dpmgr_handle, pconfig, cmdq_handle);
  4133. pconfig->wdma_dirty = 0;
  4134. _primary_path_unlock(__func__);
  4135. _cmdq_set_config_handle_dirty_mira(cmdq_handle);
  4136. _cmdq_flush_config_handle_mira(cmdq_handle, 0);
  4137. ret = dpmgr_wait_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_START);
  4138. /* pconfig->wdma_config.dstAddress = va[buf_idx++]; */
  4139. /* DISPCHECK("capture wdma\n"); */
  4140. dprec_mmp_dump_wdma_layer(&pconfig->wdma_config, 0);
  4141. buf_idx = buf_idx % 2;
  4142. cmdqRecReset(cmdq_handle);
  4143. _cmdq_insert_wait_frame_done_token_mira(cmdq_handle);
  4144. }
  4145. _primary_path_lock(__func__);
  4146. dpmgr_path_remove_memout(pgc->dpmgr_handle, cmdq_handle);
  4147. _primary_path_unlock(__func__);
  4148. _cmdq_set_config_handle_dirty_mira(cmdq_handle);
  4149. /* flush remove memory to cmdq */
  4150. _cmdq_flush_config_handle_mira(cmdq_handle, 1);
  4151. DISPMSG("wdma dump: Flush remove memout\n");
  4152. dpmgr_path_memout_clock(pgc->dpmgr_handle, 0);
  4153. }
  4154. out:
  4155. cmdqRecDestroy(cmdq_handle);
  4156. if (mva[0] > 0)
  4157. m4u_dealloc_mva(m4uClient, M4U_PORT_DISP_WDMA0, mva[0]);
  4158. if (mva[1] > 0)
  4159. m4u_dealloc_mva(m4uClient, M4U_PORT_DISP_WDMA0, mva[1]);
  4160. if (va[0] != NULL)
  4161. vfree(va[0]);
  4162. if (va[1] != NULL)
  4163. vfree(va[1]);
  4164. if (m4uClient != 0)
  4165. m4u_destroy_client(m4uClient);
  4166. DISPMSG("wdma dump:end\n");
  4167. return ret;
  4168. }
  4169. int primary_display_switch_wdma_dump(int on)
  4170. {
  4171. if (on && (!primary_dump_wdma)) {
  4172. primary_dump_wdma = 1;
  4173. primary_display_wdma_out = kthread_create(primary_display_capture_framebuffer_wdma, NULL,
  4174. "display_wdma_out");
  4175. wake_up_process(primary_display_wdma_out);
  4176. } else {
  4177. primary_dump_wdma = 0;
  4178. }
  4179. return 0;
  4180. }
  4181. #define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  4182. int primary_display_set_frame_buffer_address(unsigned long va, unsigned long mva)
  4183. {
  4184. /* DISPMSG("framebuffer va %lu, mva %lu\n", va, mva); */
  4185. pgc->framebuffer_va = va;
  4186. pgc->framebuffer_mva = mva;
  4187. /*
  4188. int frame_buffer_size = ALIGN_TO(DISP_GetScreenWidth(), MTK_FB_ALIGNMENT) *
  4189. ALIGN_TO(DISP_GetScreenHeight(), MTK_FB_ALIGNMENT) * 4;
  4190. unsigned long dim_layer_va = va + 2*frame_buffer_size;
  4191. dim_layer_mva = mva + 2*frame_buffer_size;
  4192. memset_io(dim_layer_va, 0, frame_buffer_size);
  4193. */
  4194. return 0;
  4195. }
  4196. unsigned long primary_display_get_frame_buffer_mva_address(void)
  4197. {
  4198. return pgc->framebuffer_mva;
  4199. }
  4200. unsigned long primary_display_get_frame_buffer_va_address(void)
  4201. {
  4202. return pgc->framebuffer_va;
  4203. }
  4204. int primary_display_get_session_mode(void)
  4205. {
  4206. return pgc->session_mode;
  4207. }
  4208. int is_dim_layer(unsigned int long mva)
  4209. {
  4210. if (mva == dim_layer_mva)
  4211. return 1;
  4212. return 0;
  4213. }
  4214. void *primary_get_dpmgr_handle(void)
  4215. {
  4216. return pgc->dpmgr_handle;
  4217. }
  4218. unsigned long get_dim_layer_mva_addr(void)
  4219. {
  4220. if (dim_layer_mva == 0) {
  4221. int frame_buffer_size = ALIGN_TO(DISP_GetScreenWidth(),
  4222. MTK_FB_ALIGNMENT) * DISP_GetScreenHeight() * 4;
  4223. dim_layer_mva = pgc->framebuffer_mva + 2 * frame_buffer_size;
  4224. DISPMSG("init dim layer mva %lu, size %d", dim_layer_mva, frame_buffer_size);
  4225. }
  4226. return dim_layer_mva;
  4227. }
  4228. #ifndef MTK_FB_CMDQ_DISABLE
  4229. static int init_cmdq_slots(cmdqBackupSlotHandle *pSlot, int count, int init_val)
  4230. {
  4231. int i;
  4232. cmdqBackupAllocateSlot(pSlot, count);
  4233. for (i = 0; i < count; i++)
  4234. cmdqBackupWriteSlot(*pSlot, i, init_val);
  4235. return 0;
  4236. }
  4237. #endif
  4238. int primary_display_init(char *lcm_name, unsigned int lcm_fps)
  4239. {
  4240. DISP_STATUS ret = DISP_STATUS_OK;
  4241. #ifndef MTK_FB_DFO_DISABLE
  4242. unsigned int lcm_fake_width = 0;
  4243. unsigned int lcm_fake_height = 0;
  4244. #endif
  4245. LCM_PARAMS *lcm_param = NULL;
  4246. disp_ddp_path_config *data_config = NULL;
  4247. DISPPRINT("primary_display_init begin\n");
  4248. dprec_init();
  4249. dpmgr_init();
  4250. #ifndef MTK_FB_CMDQ_DISABLE
  4251. init_cmdq_slots(&(pgc->cur_config_fence), DISP_SESSION_TIMELINE_COUNT, 0);
  4252. init_cmdq_slots(&(pgc->subtractor_when_free), DISP_SESSION_TIMELINE_COUNT, 0);
  4253. init_cmdq_slots(&(pgc->cur_mem_config_fence), DISP_SESSION_TIMELINE_COUNT, 0);
  4254. init_cmdq_slots(&(pgc->mem_subtractor_when_free), DISP_SESSION_TIMELINE_COUNT, 0);
  4255. init_cmdq_slots(&(pgc->rdma_buff_info), 3, 0);
  4256. init_cmdq_slots(&(pgc->ovl_status_info), 2, 0);
  4257. init_cmdq_slots(&(pgc->dsi_state_info), 10, 0);
  4258. init_cmdq_slots(&(pgc->rdma_state_info), 50, 0);
  4259. #endif
  4260. #ifdef DISP_DUMP_EVENT_STATUS
  4261. init_cmdq_slots(&(pgc->event_status), 6, 0);
  4262. #endif
  4263. mutex_init(&(pgc->capture_lock));
  4264. mutex_init(&(pgc->lock));
  4265. mutex_init(&(pgc->cmd_lock));
  4266. mutex_init(&(pgc->vsync_lock));
  4267. mutex_init(&esd_mode_switch_lock);
  4268. #ifdef MTK_DISP_IDLE_LP
  4269. mutex_init(&idle_lock);
  4270. #endif
  4271. #ifdef DISP_SWITCH_DST_MODE
  4272. mutex_init(&(pgc->switch_dst_lock));
  4273. #endif
  4274. _primary_path_lock(__func__);
  4275. pgc->plcm = disp_lcm_probe(lcm_name, LCM_INTERFACE_NOTDEFINED);
  4276. if (pgc->plcm == NULL) {
  4277. DISPERR("disp_lcm_probe returns null\n");
  4278. ret = DISP_STATUS_ERROR;
  4279. goto done;
  4280. }
  4281. #ifndef MTK_FB_DFO_DISABLE
  4282. if ((0 == dfo_query("LCM_FAKE_WIDTH", &lcm_fake_width))
  4283. && (0 == dfo_query("LCM_FAKE_HEIGHT", &lcm_fake_height))) {
  4284. pr_debug("[DFO] LCM_FAKE_WIDTH=%d, LCM_FAKE_HEIGHT=%d\n", lcm_fake_width,
  4285. lcm_fake_height);
  4286. if (lcm_fake_width && lcm_fake_height) {
  4287. if (DISP_STATUS_OK != primary_display_change_lcm_resolution(lcm_fake_width, lcm_fake_height))
  4288. DISPMSG("[DISP\DFO]WARNING!!! Change LCM Resolution FAILED!!!\n");
  4289. }
  4290. }
  4291. #endif
  4292. lcm_param = disp_lcm_get_params(pgc->plcm);
  4293. if (lcm_param == NULL) {
  4294. DISPERR("get lcm params FAILED\n");
  4295. ret = DISP_STATUS_ERROR;
  4296. goto done;
  4297. }
  4298. #ifndef MTK_FB_CMDQ_DISABLE
  4299. ret = cmdqCoreRegisterCB(CMDQ_GROUP_DISP, (CmdqClockOnCB)cmdqDdpClockOn, (CmdqDumpInfoCB)cmdqDdpDumpInfo,
  4300. (CmdqResetEngCB)cmdqDdpResetEng, (CmdqClockOffCB)cmdqDdpClockOff);
  4301. if (ret) {
  4302. DISPERR("cmdqCoreRegisterCB failed, ret=%d\n", ret);
  4303. ret = DISP_STATUS_ERROR;
  4304. goto done;
  4305. }
  4306. ret = cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &(pgc->cmdq_handle_config));
  4307. if (ret) {
  4308. DISPCHECK("cmdqRecCreate FAIL, ret=%d\n", ret);
  4309. ret = DISP_STATUS_ERROR;
  4310. goto done;
  4311. } else {
  4312. DISPCHECK("cmdqRecCreate SUCCESS, g_cmdq_handle=0x%p\n", pgc->cmdq_handle_config);
  4313. }
  4314. /*create ovl2mem path cmdq handle */
  4315. ret = cmdqRecCreate(CMDQ_SCENARIO_DISP_COLOR, &(pgc->cmdq_handle_ovl1to2_config));
  4316. if (ret != 0) {
  4317. DISPERR("cmdqRecCreate FAIL, ret=%d\n", ret);
  4318. return -1;
  4319. }
  4320. primary_display_use_cmdq = CMDQ_ENABLE;
  4321. #else
  4322. primary_display_use_cmdq = CMDQ_DISABLE;
  4323. #endif
  4324. /* debug for bus hang issue (need to remove) */
  4325. ddp_dump_analysis(DISP_MODULE_CONFIG);
  4326. if (primary_display_mode == DIRECT_LINK_MODE) {
  4327. __build_path_direct_link();
  4328. pgc->session_mode = DISP_SESSION_DIRECT_LINK_MODE;
  4329. DISPCHECK("primary display is DIRECT LINK MODE\n");
  4330. } else if (primary_display_mode == DECOUPLE_MODE) {
  4331. __build_path_decouple();
  4332. pgc->session_mode = DISP_SESSION_DECOUPLE_MODE;
  4333. DISPCHECK("primary display is DECOUPLE MODE\n");
  4334. } else if (primary_display_mode == SINGLE_LAYER_MODE) {
  4335. __build_path_single_layer();
  4336. DISPCHECK("primary display is SINGLE LAYER MODE\n");
  4337. } else if (primary_display_mode == DEBUG_RDMA1_DSI0_MODE) {
  4338. __build_path_debug_rdma1_dsi0();
  4339. DISPCHECK("primary display is DEBUG RDMA1 DSI0 MODE\n");
  4340. } else {
  4341. DISPCHECK("primary display mode is WRONG\n");
  4342. }
  4343. #ifndef MTK_FB_CMDQ_DISABLE
  4344. primary_display_use_cmdq = CMDQ_ENABLE;
  4345. #else
  4346. primary_display_use_cmdq = CMDQ_DISABLE;
  4347. #endif
  4348. /* dpmgr_path_init(pgc->dpmgr_handle, CMDQ_DISABLE); */
  4349. dpmgr_path_set_video_mode(pgc->dpmgr_handle, primary_display_is_video_mode());
  4350. /* dpmgr_path_init(pgc->dpmgr_handle, CMDQ_DISABLE); */
  4351. /* use fake timer to generate vsync signal for cmd mode w/o LCM(originally using LCM TE Signal as VSYNC) */
  4352. /* so we don't need to modify display driver's behavior. */
  4353. if (disp_helper_get_option
  4354. (DISP_HELPER_OPTION_NO_LCM_FOR_LOW_POWER_MEASUREMENT)) {
  4355. /* only for low power measurement */
  4356. DISPCHECK("WARNING!!!!!! FORCE NO LCM MODE!!!\n");
  4357. islcmconnected = 0;
  4358. /* no need to change video mode vsync behavior */
  4359. if (!primary_display_is_video_mode()) {
  4360. _init_vsync_fake_monitor(lcm_fps);
  4361. dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC,
  4362. DDP_IRQ_UNKNOWN);
  4363. }
  4364. }
  4365. #ifdef CONFIG_FPGA_EARLY_PORTING
  4366. dpmgr_path_reset(pgc->dpmgr_handle, CMDQ_DISABLE);
  4367. #endif
  4368. if (primary_display_use_cmdq == CMDQ_ENABLE) {
  4369. _cmdq_build_trigger_loop();
  4370. _cmdq_start_trigger_loop();
  4371. _cmdq_reset_config_handle();
  4372. _cmdq_insert_wait_frame_done_token();
  4373. }
  4374. data_config = dpmgr_path_get_last_config(pgc->dpmgr_handle);
  4375. #ifdef OVL_CASCADE_SUPPORT
  4376. if (ovl_get_status() == DDP_OVL1_STATUS_IDLE || ovl_get_status() == DDP_OVL1_STATUS_PRIMARY) {
  4377. if (primary_display_mode == DECOUPLE_MODE)
  4378. dpmgr_path_enable_cascade(pgc->ovl2mem_path_handle,
  4379. pgc->cmdq_handle_config);
  4380. else
  4381. dpmgr_path_enable_cascade(pgc->dpmgr_handle, pgc->cmdq_handle_config);
  4382. }
  4383. #endif
  4384. memcpy(&(data_config->dispif_config), lcm_param, sizeof(LCM_PARAMS));
  4385. data_config->dst_w = lcm_param->width;
  4386. data_config->dst_h = lcm_param->height;
  4387. if (lcm_param->type == LCM_TYPE_DSI) {
  4388. if (lcm_param->dsi.data_format.format == LCM_DSI_FORMAT_RGB888)
  4389. data_config->lcm_bpp = 24;
  4390. else if (lcm_param->dsi.data_format.format == LCM_DSI_FORMAT_RGB565)
  4391. data_config->lcm_bpp = 16;
  4392. else if (lcm_param->dsi.data_format.format == LCM_DSI_FORMAT_RGB666)
  4393. data_config->lcm_bpp = 18;
  4394. } else if (lcm_param->type == LCM_TYPE_DPI) {
  4395. if (lcm_param->dpi.format == LCM_DPI_FORMAT_RGB888)
  4396. data_config->lcm_bpp = 24;
  4397. else if (lcm_param->dpi.format == LCM_DPI_FORMAT_RGB565)
  4398. data_config->lcm_bpp = 16;
  4399. if (lcm_param->dpi.format == LCM_DPI_FORMAT_RGB666)
  4400. data_config->lcm_bpp = 18;
  4401. }
  4402. data_config->fps = lcm_fps;
  4403. data_config->dst_dirty = 1;
  4404. #ifdef CONFIG_FPGA_EARLY_PORTING
  4405. data_config->ovl_dirty = 1;
  4406. #endif
  4407. rdma_set_target_line(DISP_MODULE_RDMA0, primary_display_get_height() * 1 / 2,
  4408. pgc->cmdq_handle_config);
  4409. rdma_set_target_line(DISP_MODULE_RDMA0, primary_display_get_height() * 1 / 2, NULL);
  4410. if (primary_display_use_cmdq == CMDQ_ENABLE) {
  4411. ret = dpmgr_path_config(pgc->dpmgr_handle, data_config, pgc->cmdq_handle_config);
  4412. /* should we set dirty here???????? */
  4413. _cmdq_flush_config_handle(0, NULL, 0);
  4414. _cmdq_reset_config_handle();
  4415. _cmdq_insert_wait_frame_done_token();
  4416. } else {
  4417. ret = dpmgr_path_config(pgc->dpmgr_handle, data_config, NULL);
  4418. }
  4419. {
  4420. #ifdef MTK_NO_DISP_IN_LK
  4421. ret = disp_lcm_init(pgc->plcm, 1);
  4422. #else
  4423. ret = disp_lcm_init(pgc->plcm, 0);
  4424. #endif
  4425. }
  4426. #ifndef MTK_NO_DISP_IN_LK
  4427. if (_is_decouple_mode(pgc->session_mode))
  4428. #endif
  4429. /* this should remove? for video mode when LK has start path */
  4430. dpmgr_path_start(pgc->dpmgr_handle, CMDQ_DISABLE);
  4431. #ifdef MTK_FB_PULLCLK_ENABLE
  4432. primary_display_pullclk_task = kthread_create(primary_display_vdo_pullclk_worker_kthread,
  4433. NULL, "display_vdo_pullclk");
  4434. wake_up_process(primary_display_pullclk_task);
  4435. #endif
  4436. #ifdef MTK_FB_ESD_ENABLE
  4437. primary_display_esd_check_task = kthread_create(primary_display_esd_check_worker_kthread,
  4438. NULL, "display_esd_check");
  4439. init_waitqueue_head(&esd_ext_te_wq);
  4440. init_waitqueue_head(&esd_check_task_wq);
  4441. if (_need_do_esd_check())
  4442. wake_up_process(primary_display_esd_check_task);
  4443. #if 0
  4444. if (_need_do_esd_check())
  4445. primary_display_esd_check_enable(1);
  4446. #endif
  4447. if (_need_register_eint()) {
  4448. struct device_node *node = NULL;
  4449. int irq;
  4450. u32 ints[2] = { 0, 0 };
  4451. #ifdef GPIO_DSI_TE_PIN
  4452. #ifndef CONFIG_FPGA_EARLY_PORTING
  4453. /* 1.set GPIO107 eint mode */
  4454. mt_set_gpio_mode(GPIO_DSI_TE_PIN, GPIO_DSI_TE_PIN_M_GPIO);
  4455. #endif
  4456. eint_flag++;
  4457. #endif
  4458. #ifndef CONFIG_MTK_LEGACY
  4459. eint_flag++;
  4460. #endif
  4461. /* 2.register eint */
  4462. node = of_find_compatible_node(NULL, NULL, "mediatek, DSI_TE_1-eint");
  4463. if (node) {
  4464. of_property_read_u32_array(node, "debounce", ints, ARRAY_SIZE(ints));
  4465. /* FIXME: find definatition of mt_gpio_set_debounce */
  4466. /* mt_gpio_set_debounce(ints[0], ints[1]); */
  4467. mt_eint_set_hw_debounce(ints[0], ints[1]);
  4468. irq = irq_of_parse_and_map(node, 0);
  4469. if (request_irq(irq, _esd_check_ext_te_irq_handler, IRQF_TRIGGER_RISING, "DSI_TE_1-eint", NULL))
  4470. DISPCHECK("[ESD]EINT IRQ LINE NOT AVAILABLE!!\n");
  4471. else
  4472. eint_flag++;
  4473. } else {
  4474. DISPCHECK("[ESD][%s] can't find DSI_TE_1 eint compatible node\n", __func__);
  4475. }
  4476. }
  4477. if (_need_do_esd_check())
  4478. primary_display_esd_check_enable(1);
  4479. #endif
  4480. #ifdef DISP_SWITCH_DST_MODE
  4481. primary_display_switch_dst_mode_task = kthread_create(_disp_primary_path_switch_dst_mode_thread, NULL,
  4482. "display_switch_dst_mode");
  4483. wake_up_process(primary_display_switch_dst_mode_task);
  4484. #endif
  4485. primary_path_aal_task = kthread_create(_disp_primary_path_check_trigger, NULL, "display_check_aal");
  4486. wake_up_process(primary_path_aal_task);
  4487. #if 0 /* Zaikuo: disable it when HWC not enable to reduce error log */
  4488. fence_release_worker_task =
  4489. kthread_create(_fence_release_worker_thread, NULL, "fence_worker");
  4490. wake_up_process(fence_release_worker_task);
  4491. if (_is_decouple_mode(pgc->session_mode)) {
  4492. if_fence_release_worker_task =
  4493. kthread_create(_if_fence_release_worker_thread, NULL, "if_fence_worker");
  4494. wake_up_process(if_fence_release_worker_task);
  4495. ovl2mem_fence_release_worker_task =
  4496. kthread_create(_ovl2mem_fence_release_worker_thread, NULL,
  4497. "ovl2mem_fence_worker");
  4498. wake_up_process(ovl2mem_fence_release_worker_task);
  4499. }
  4500. #endif
  4501. present_fence_release_worker_task = kthread_create(_present_fence_release_worker_thread, NULL,
  4502. "present_fence_worker");
  4503. wake_up_process(present_fence_release_worker_task);
  4504. if (primary_display_frame_update_task == NULL) {
  4505. init_waitqueue_head(&primary_display_frame_update_wq);
  4506. disp_register_module_irq_callback(DISP_MODULE_RDMA0, primary_display_frame_update_irq_callback);
  4507. disp_register_module_irq_callback(DISP_MODULE_OVL0, primary_display_frame_update_irq_callback);
  4508. disp_register_module_irq_callback(DISP_MODULE_WDMA0, primary_display_frame_update_irq_callback);
  4509. primary_display_frame_update_task = kthread_create(primary_display_frame_update_kthread, NULL,
  4510. "frame_update_worker");
  4511. wake_up_process(primary_display_frame_update_task);
  4512. init_waitqueue_head(&decouple_fence_release_wq);
  4513. decouple_fence_release_task = kthread_create(decouple_fence_release_kthread, NULL,
  4514. "decouple_fence_release_worker");
  4515. wake_up_process(decouple_fence_release_task);
  4516. }
  4517. /* primary_display_use_cmdq = CMDQ_ENABLE; */
  4518. /* this will be set to always enable cmdq later */
  4519. if (primary_display_is_video_mode()) {
  4520. #ifdef DISP_SWITCH_DST_MODE
  4521. primary_display_cur_dst_mode = 1; /* video mode */
  4522. primary_display_def_dst_mode = 1; /* default mode is video mode */
  4523. #endif
  4524. dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, DDP_IRQ_RDMA0_DONE);
  4525. } else {
  4526. }
  4527. #ifndef MTKFB_NO_M4U
  4528. {
  4529. M4U_PORT_STRUCT sPort;
  4530. sPort.ePortID = M4U_PORT_DISP_WDMA0;
  4531. sPort.Virtuality = primary_display_use_m4u;
  4532. sPort.Security = 0;
  4533. sPort.Distance = 1;
  4534. sPort.Direction = 0;
  4535. ret = m4u_config_port(&sPort);
  4536. if (ret != 0) {
  4537. DISPCHECK("config M4U Port %s to %s FAIL(ret=%d)\n",
  4538. ddp_get_module_name(DISP_MODULE_WDMA0),
  4539. primary_display_use_m4u ? "virtual" : "physical", ret);
  4540. return -1;
  4541. }
  4542. }
  4543. #endif
  4544. pgc->lcm_fps = lcm_fps;
  4545. if (lcm_fps > 6000) /* FIXME: if fps bigger than 60, support 8 layer? */
  4546. pgc->max_layer = OVL_LAYER_NUM;
  4547. else
  4548. pgc->max_layer = OVL_LAYER_NUM;
  4549. pgc->state = DISP_ALIVE;
  4550. #ifdef CONFIG_TRUSTONIC_TRUSTED_UI
  4551. disp_switch_data.name = "disp";
  4552. disp_switch_data.index = 0;
  4553. disp_switch_data.state = DISP_ALIVE;
  4554. ret = switch_dev_register(&disp_switch_data);
  4555. #endif
  4556. primary_display_sodi_rule_init();
  4557. #ifdef MTK_DISP_IDLE_LP
  4558. init_waitqueue_head(&idle_detect_wq);
  4559. primary_display_idle_detect_task = kthread_create(_disp_primary_path_idle_detect_thread, NULL,
  4560. "display_idle_detect");
  4561. wake_up_process(primary_display_idle_detect_task);
  4562. #endif
  4563. pgc->dc_type = DISP_OUTPUT_DECOUPLE;
  4564. if ((mmdvfs_get_mmdvfs_profile() == MMDVFS_PROFILE_D2_P_PLUS) ||
  4565. (mmdvfs_get_mmdvfs_profile() == MMDVFS_PROFILE_D2_M_PLUS))
  4566. register_mmclk_switch_cb(primary_display_switch_mmsys_clk, _switch_mmsys_clk);
  4567. done:
  4568. /* disable OVL TF in video mode, cause cmdq/sodi log is not ready, avoid too much TF issue */
  4569. {
  4570. /* extern unsigned int gDisableOVLTF; */
  4571. if (gDisableOVLTF == 1 && primary_display_is_video_mode() == 1) {
  4572. /* extern void disp_m4u_tf_disable(void); */
  4573. disp_m4u_tf_disable();
  4574. }
  4575. }
  4576. #ifndef WDMA_PATH_CLOCK_DYNAMIC_SWITCH
  4577. #ifndef CONFIG_FPGA_EARLY_PORTING
  4578. enable_soidle_by_bit(MT_CG_DISP0_DISP_WDMA0);
  4579. #endif
  4580. #endif
  4581. _primary_path_unlock(__func__);
  4582. /* DISPCHECK("primary_display_init end\n"); */
  4583. return ret;
  4584. }
  4585. int primary_display_deinit(void)
  4586. {
  4587. _primary_path_lock(__func__);
  4588. _cmdq_stop_trigger_loop();
  4589. if(!pgc->dpmgr_handle){
  4590. _primary_path_unlock(__func__);
  4591. return 0;
  4592. }else
  4593. dpmgr_path_deinit(pgc->dpmgr_handle, CMDQ_DISABLE);
  4594. #ifndef CONFIG_MTK_CLKMGR
  4595. ddp_clk_unprepare(DISP_MTCMOS_CLK);
  4596. #endif
  4597. _primary_path_unlock(__func__);
  4598. return 0;
  4599. }
  4600. /* register rdma done event */
  4601. int primary_display_wait_for_idle(void)
  4602. {
  4603. DISP_STATUS ret = DISP_STATUS_OK;
  4604. DISPFUNC();
  4605. _primary_path_lock(__func__);
  4606. /* Nothing to do ??? */
  4607. _primary_path_unlock(__func__);
  4608. return ret;
  4609. }
  4610. int primary_display_wait_for_dump(void)
  4611. {
  4612. return 0; /* avoid build warning. */
  4613. }
  4614. int primary_display_release_fence_fake(void)
  4615. {
  4616. unsigned int layer_en = 0;
  4617. unsigned int addr = 0;
  4618. unsigned int fence_idx = -1;
  4619. unsigned int session_id = MAKE_DISP_SESSION(DISP_SESSION_PRIMARY, 0);
  4620. int i = 0;
  4621. DISPFUNC();
  4622. for (i = 0; i < PRIMARY_DISPLAY_SESSION_LAYER_COUNT; i++) {
  4623. if (i == primary_display_get_option("ASSERT_LAYER") && is_DAL_Enabled()) {
  4624. mtkfb_release_layer_fence(session_id, 3);
  4625. } else {
  4626. disp_sync_get_cached_layer_info(session_id, i, &layer_en,
  4627. (unsigned long *)&addr, &fence_idx);
  4628. if (fence_idx < 0) {
  4629. if (fence_idx == -1) {
  4630. DISPPR_ERROR("find fence idx for layer %d,addr 0x%08x fail,\n", i, 0);
  4631. DISPPR_ERROR("unregistered addr%d\n", fence_idx);
  4632. } else if (fence_idx == -2) {
  4633. ;
  4634. } else {
  4635. DISPPR_ERROR("find fence idx for layer %d,addr 0x%08x fail,reason unknown%d\n",
  4636. i, 0, fence_idx);
  4637. }
  4638. } else {
  4639. if (layer_en)
  4640. mtkfb_release_fence(session_id, i, fence_idx - 1);
  4641. else
  4642. mtkfb_release_fence(session_id, i, fence_idx);
  4643. }
  4644. }
  4645. }
  4646. return 0; /* avoid build warning */
  4647. }
  4648. int primary_display_wait_for_vsync(void *config)
  4649. {
  4650. disp_session_vsync_config *c = (disp_session_vsync_config *) config;
  4651. int ret = 0;
  4652. /* kick idle manager here to ensure sodi is disabled when screen update begin(not 100% ensure) */
  4653. primary_display_idlemgr_kick((char *)__func__);
  4654. _primary_path_vsync_lock();
  4655. if (pgc->state == DISP_SLEPT) {
  4656. DISPCHECK("VSYNC DISP_SLEPT Return\n");
  4657. _primary_path_vsync_unlock();
  4658. return 0;
  4659. }
  4660. #ifdef MTK_DISP_IDLE_LP
  4661. _disp_primary_path_dsi_clock_on(0);
  4662. #endif
  4663. if (!islcmconnected) {
  4664. DISPCHECK("lcm not connect, use fake vsync\n");
  4665. /* msleep(16); */
  4666. usleep_range(16000, 17000);
  4667. goto done;
  4668. }
  4669. ret = dpmgr_wait_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC);
  4670. if (pgc->vsync_drop)
  4671. ret = dpmgr_wait_event(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC);
  4672. if (ret != 0)
  4673. DISPCHECK("vsync signaled by unknown signal ret=%d\n", ret);
  4674. c->vsync_ts = get_current_time_us();
  4675. c->vsync_cnt++;
  4676. done:
  4677. #ifdef MTK_DISP_IDLE_LP
  4678. _disp_primary_path_dsi_clock_off(0);
  4679. #endif
  4680. _primary_path_vsync_unlock();
  4681. return 0;
  4682. }
  4683. unsigned int primary_display_get_ticket(void)
  4684. {
  4685. return dprec_get_vsync_count();
  4686. }
  4687. #ifdef CONFIG_SINGLE_PANEL_OUTPUT
  4688. int primary_suspend_release_ovl_fence(disp_session_input_config *session_input)
  4689. {
  4690. unsigned int session = (unsigned int)((DISP_SESSION_PRIMARY)<<16 | (0));
  4691. unsigned int i = 0;
  4692. unsigned int layer = 0;
  4693. for (i = 0; i < session_input->config_layer_num; i++) {
  4694. unsigned int cur_fence;
  4695. disp_input_config *input_cfg = &session_input->config[i];
  4696. layer = input_cfg->layer_id;
  4697. cur_fence = input_cfg->next_buff_idx;
  4698. if (cur_fence != -1)
  4699. mtkfb_release_fence(session, i, cur_fence);
  4700. }
  4701. return 0;
  4702. }
  4703. int primary_suspend_clr_ovl_config(void)
  4704. {
  4705. disp_ddp_path_config *data_config = NULL;
  4706. disp_path_handle handle = NULL;
  4707. OVL_CONFIG_STRUCT ovl_config[OVL_LAYER_NUM];
  4708. int i = 0;
  4709. DISPFUNC();
  4710. if (0 == g_suspend_flag)
  4711. return -1;
  4712. if (_is_decouple_mode(pgc->session_mode) == 0)
  4713. handle = pgc->dpmgr_handle;
  4714. else
  4715. handle = pgc->ovl2mem_path_handle;
  4716. data_config = dpmgr_path_get_last_config(handle);
  4717. memset((void *)&(data_config->ovl_config), 0, sizeof(ovl_config));
  4718. last_primary_config = *data_config;
  4719. for (i = 0; i < OVL_LAYER_NUM; i++)
  4720. ovl_layer_switch(DISP_MODULE_OVL0, i, 0, NULL);
  4721. DISP_REG_SET(NULL, DISP_REG_OVL_SRC_CON, 0x0);
  4722. return 0;
  4723. }
  4724. #endif
  4725. int primary_suspend_release_fence(void)
  4726. {
  4727. unsigned int session = (unsigned int)((DISP_SESSION_PRIMARY) << 16 | (0));
  4728. unsigned int i = 0;
  4729. for (i = 0; i < HW_OVERLAY_COUNT; i++) {
  4730. DISPMSG("mtkfb_release_layer_fence session=0x%x,layerid=%d\n", session, i);
  4731. mtkfb_release_layer_fence(session, i);
  4732. }
  4733. return 0;
  4734. }
  4735. static void primary_display_suspend_wait_tui(void)
  4736. {
  4737. while (primary_get_state() == DISP_BLANK) {
  4738. _primary_path_vsync_unlock();
  4739. _primary_path_unlock(__func__);
  4740. _primary_path_esd_check_unlock();
  4741. disp_sw_mutex_unlock(&(pgc->capture_lock));
  4742. #ifdef CONFIG_TRUSTONIC_TRUSTED_UI
  4743. switch_set_state(&disp_switch_data, DISP_SLEPT);
  4744. #endif
  4745. primary_display_wait_state(DISP_ALIVE, MAX_SCHEDULE_TIMEOUT);
  4746. disp_sw_mutex_lock(&(pgc->capture_lock));
  4747. _primary_path_esd_check_lock();
  4748. _primary_path_lock(__func__);
  4749. _primary_path_vsync_lock();
  4750. DISPCHECK("primary_display_suspend wait tui done stat=%d\n", primary_get_state());
  4751. }
  4752. }
  4753. int primary_display_suspend(void)
  4754. {
  4755. DISP_STATUS ret = DISP_STATUS_OK;
  4756. DISPCHECK("primary_display_suspend begin\n");
  4757. MMProfileLogEx(ddp_mmp_get_events()->primary_suspend, MMProfileFlagStart, 0, 0);
  4758. #ifdef DISP_SWITCH_DST_MODE
  4759. primary_display_switch_dst_mode(primary_display_def_dst_mode);
  4760. #endif
  4761. disp_sw_mutex_lock(&(pgc->capture_lock));
  4762. _primary_path_esd_check_lock();
  4763. _primary_path_lock(__func__);
  4764. _primary_path_vsync_lock();
  4765. DISPCHECK("wait tui finish[begin]\n");
  4766. primary_display_suspend_wait_tui();
  4767. DISPCHECK("wait tui finish[end]\n");
  4768. if (pgc->state == DISP_SLEPT) {
  4769. DISPCHECK("primary display path is already sleep, skip\n");
  4770. goto done;
  4771. }
  4772. #ifdef MTK_DISP_IDLE_LP
  4773. _disp_primary_path_exit_idle(__func__, 0);
  4774. #endif
  4775. MMProfileLogEx(ddp_mmp_get_events()->primary_suspend, MMProfileFlagPulse, 0, 1);
  4776. /* msleep(16); */ /* wait last frame done */
  4777. usleep_range(16000, 17000);
  4778. if (dpmgr_path_is_busy(pgc->dpmgr_handle)) {
  4779. int event_ret = 0;
  4780. MMProfileLogEx(ddp_mmp_get_events()->primary_suspend, MMProfileFlagPulse, 1, 2);
  4781. event_ret = dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ * 1);
  4782. MMProfileLogEx(ddp_mmp_get_events()->primary_suspend, MMProfileFlagPulse, 2, 2);
  4783. DISPCHECK("[POWER]primary display path is busy now, wait frame done, event_ret=%d\n", event_ret);
  4784. if (event_ret <= 0) {
  4785. DISPERR("wait frame done in suspend timeout\n");
  4786. MMProfileLogEx(ddp_mmp_get_events()->primary_suspend, MMProfileFlagPulse, 3, 2);
  4787. primary_display_diagnose();
  4788. ret = -1;
  4789. }
  4790. }
  4791. /* for decouple mode */
  4792. if (_is_decouple_mode(pgc->session_mode)) {
  4793. if (dpmgr_path_is_busy(pgc->ovl2mem_path_handle))
  4794. dpmgr_wait_event_timeout(pgc->ovl2mem_path_handle, DISP_PATH_EVENT_FRAME_COMPLETE, HZ);
  4795. /* xuecheng, BAD WROKAROUND for decouple mode */
  4796. msleep(30);
  4797. }
  4798. MMProfileLogEx(ddp_mmp_get_events()->primary_suspend, MMProfileFlagPulse, 0, 2);
  4799. DISPCHECK("[POWER]display cmdq trigger loop stop[begin]\n");
  4800. _cmdq_stop_trigger_loop();
  4801. DISPCHECK("[POWER]display cmdq trigger loop stop[end]\n");
  4802. MMProfileLogEx(ddp_mmp_get_events()->primary_suspend, MMProfileFlagPulse, 0, 3);
  4803. #ifdef CONFIG_LCM_SEND_CMD_IN_VIDEO
  4804. DISPCHECK("[POWER]lcm suspend[begin]\n");
  4805. disp_lcm_suspend(pgc->plcm);
  4806. DISPCHECK("[POWER]lcm suspend[end]\n");
  4807. #endif
  4808. DISPCHECK("[POWER]primary display path stop[begin]\n");
  4809. dpmgr_path_stop(pgc->dpmgr_handle, CMDQ_DISABLE);
  4810. DISPCHECK("[POWER]primary display path stop[end]\n");
  4811. MMProfileLogEx(ddp_mmp_get_events()->primary_suspend, MMProfileFlagPulse, 0, 4);
  4812. #ifdef CONFIG_SINGLE_PANEL_OUTPUT
  4813. primary_suspend_clr_ovl_config();
  4814. #endif
  4815. if (dpmgr_path_is_busy(pgc->dpmgr_handle)) {
  4816. MMProfileLogEx(ddp_mmp_get_events()->primary_suspend, MMProfileFlagPulse, 1, 4);
  4817. DISPERR("[POWER]stop display path failed, still busy\n");
  4818. dpmgr_path_reset(pgc->dpmgr_handle, CMDQ_DISABLE);
  4819. ret = -1;
  4820. /* even path is busy(stop fail), we still need to continue power off other module/devices */
  4821. /* goto done; */
  4822. }
  4823. MMProfileLogEx(ddp_mmp_get_events()->primary_suspend, MMProfileFlagPulse, 0, 5);
  4824. /* remove OVL1 from display if there is more than one session, */
  4825. /* because the other session may use OVL1 in suspend mode */
  4826. #if 0
  4827. {
  4828. /* extern int disp_get_session_number(void); */
  4829. if (ovl_get_status() != DDP_OVL1_STATUS_SUB && disp_get_session_number() > 1) {
  4830. unsigned int dp_handle;
  4831. unsigned int cmdq_handle;
  4832. DISPMSG("disable cascade before suspend!\n");
  4833. dpmgr_path_get_handle(&dp_handle, &cmdq_handle);
  4834. dpmgr_path_disable_cascade(dp_handle, CMDQ_DISABLE);
  4835. if (ovl_get_status() == DDP_OVL1_STATUS_SUB_REQUESTING) {
  4836. ovl_set_status(DDP_OVL1_STATUS_SUB);
  4837. wake_up_interruptible(&ovl1_wait_queue);
  4838. } else {
  4839. ovl_set_status(DDP_OVL1_STATUS_IDLE);
  4840. }
  4841. _cmdq_build_trigger_loop();
  4842. }
  4843. }
  4844. #else
  4845. DISPMSG("disable cascade before suspend!\n");
  4846. if (_is_decouple_mode(pgc->session_mode) == 0)
  4847. dpmgr_path_disable_cascade(pgc->dpmgr_handle, CMDQ_DISABLE);
  4848. else
  4849. dpmgr_path_disable_cascade(pgc->ovl2mem_path_handle, CMDQ_DISABLE);
  4850. if (ovl_get_status() == DDP_OVL1_STATUS_SUB_REQUESTING)
  4851. dpmgr_set_ovl1_status(DDP_OVL1_STATUS_SUB);
  4852. else if (ovl_get_status() != DDP_OVL1_STATUS_SUB)
  4853. dpmgr_set_ovl1_status(DDP_OVL1_STATUS_IDLE);
  4854. #endif
  4855. #ifndef CONFIG_LCM_SEND_CMD_IN_VIDEO
  4856. DISPCHECK("[POWER]lcm suspend[begin]\n");
  4857. disp_lcm_suspend(pgc->plcm);
  4858. DISPCHECK("[POWER]lcm suspend[end]\n");
  4859. #endif
  4860. MMProfileLogEx(ddp_mmp_get_events()->primary_suspend, MMProfileFlagPulse, 0, 6);
  4861. DISPCHECK("[POWER]primary display path Release Fence[begin]\n");
  4862. primary_suspend_release_fence();
  4863. DISPCHECK("[POWER]primary display path Release Fence[end]\n");
  4864. MMProfileLogEx(ddp_mmp_get_events()->primary_suspend, MMProfileFlagPulse, 0, 7);
  4865. DISPCHECK("[POWER]dpmanager path power off[begin]\n");
  4866. dpmgr_path_power_off(pgc->dpmgr_handle, CMDQ_DISABLE);
  4867. DISPCHECK("[POWER]dpmanager path power off[end]\n");
  4868. if (_is_decouple_mode(pgc->session_mode)) {
  4869. dpmgr_path_power_off(pgc->ovl2mem_path_handle, CMDQ_DISABLE);
  4870. } else if (is_mmdvfs_supported() && mmdvfs_get_mmdvfs_profile() == MMDVFS_PROFILE_D1_PLUS) {
  4871. DISPMSG("set MMDVFS low\n");
  4872. mmdvfs_set_step(MMDVFS_SCEN_DISP, MMDVFS_VOLTAGE_LOW); /* Vote to LPM mode */
  4873. }
  4874. #ifndef CONFIG_MTK_CLKMGR
  4875. ddp_clk_unprepare(DISP_MTCMOS_CLK);
  4876. #endif
  4877. MMProfileLogEx(ddp_mmp_get_events()->primary_suspend, MMProfileFlagPulse, 0, 8);
  4878. display_path_idle_cnt = 0;
  4879. pgc->state = DISP_SLEPT;
  4880. done:
  4881. _primary_path_vsync_unlock();
  4882. _primary_path_unlock(__func__);
  4883. _primary_path_esd_check_unlock();
  4884. disp_sw_mutex_unlock(&(pgc->capture_lock));
  4885. #ifndef DISP_NO_AEE
  4886. aee_kernel_wdt_kick_Powkey_api("mtkfb_early_suspend", WDT_SETBY_Display);
  4887. #endif
  4888. primary_trigger_cnt = 0;
  4889. MMProfileLogEx(ddp_mmp_get_events()->primary_suspend, MMProfileFlagEnd, 0, 0);
  4890. DISPCHECK("primary_display_suspend end\n");
  4891. return ret;
  4892. }
  4893. int primary_display_get_lcm_index(void)
  4894. {
  4895. int index = 0;
  4896. DISPFUNC();
  4897. if (pgc->plcm == NULL) {
  4898. DISPERR("lcm handle is null\n");
  4899. return 0;
  4900. }
  4901. index = pgc->plcm->index;
  4902. DISPMSG("lcm index = %d\n", index);
  4903. return index;
  4904. }
  4905. int primary_display_resume(void)
  4906. {
  4907. DISP_STATUS ret = DISP_STATUS_OK;
  4908. DISPFUNC();
  4909. MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagStart, 0, 0);
  4910. _primary_path_lock(__func__);
  4911. if (pgc->state == DISP_ALIVE) {
  4912. DISPCHECK("primary display path is already resume, skip\n");
  4913. goto done;
  4914. }
  4915. MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 0, 1);
  4916. #ifdef CONFIG_MTK_CLKMGR
  4917. #ifdef CONFIG_SINGLE_PANEL_OUTPUT
  4918. dpmgr_reset_module_handle(pgc->dpmgr_handle);
  4919. #endif
  4920. /* For CCF, we move the power on control to noirq_restore in mtkfb */
  4921. DISPCHECK("dpmanager path power on[begin]\n");
  4922. dpmgr_path_power_on(pgc->dpmgr_handle, CMDQ_DISABLE);
  4923. DISPCHECK("dpmanager path power on[end]\n");
  4924. if (_is_decouple_mode(pgc->session_mode) && !pgc->force_on_wdma_path)
  4925. dpmgr_path_power_on(pgc->ovl2mem_path_handle, CMDQ_DISABLE);
  4926. MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 0, 2);
  4927. #endif
  4928. #ifndef CONFIG_MTK_CLKMGR
  4929. ddp_clk_prepare(DISP_MTCMOS_CLK);
  4930. #endif
  4931. if (is_ipoh_bootup) {
  4932. DISPCHECK("[primary display path] leave primary_display_resume -- IPOH\n");
  4933. DISPCHECK("ESD check start[begin]\n");
  4934. primary_display_esd_check_enable(1);
  4935. DISPCHECK("ESD check start[end]\n");
  4936. is_ipoh_bootup = false;
  4937. DISPCHECK("[POWER]start cmdq[begin]--IPOH\n");
  4938. _cmdq_start_trigger_loop();
  4939. DISPCHECK("[POWER]start cmdq[end]--IPOH\n");
  4940. pgc->state = DISP_ALIVE;
  4941. goto done;
  4942. }
  4943. #ifndef CONFIG_MTK_CLKMGR
  4944. DISPCHECK("dpmanager path power on[begin]\n");
  4945. dpmgr_path_power_on(pgc->dpmgr_handle, CMDQ_DISABLE);
  4946. DISPCHECK("dpmanager path power on[end]\n");
  4947. if (_is_decouple_mode(pgc->session_mode) && !pgc->force_on_wdma_path)
  4948. dpmgr_path_power_on(pgc->ovl2mem_path_handle, CMDQ_DISABLE);
  4949. MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 0, 2);
  4950. #endif
  4951. if (primary_display_is_video_mode()) {
  4952. DISPCHECK("mutex0 clear[begin]\n");
  4953. ddp_mutex_clear(0, NULL);
  4954. DISPCHECK("mutex0 clear[end]\n");
  4955. }
  4956. DISPCHECK("[POWER]dpmanager re-init[begin]\n");
  4957. {
  4958. LCM_PARAMS *lcm_param = NULL;
  4959. disp_ddp_path_config *data_config = NULL;
  4960. dpmgr_path_connect(pgc->dpmgr_handle, CMDQ_DISABLE);
  4961. if (_is_decouple_mode(pgc->session_mode))
  4962. dpmgr_path_connect(pgc->ovl2mem_path_handle, CMDQ_DISABLE);
  4963. MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 1, 2);
  4964. lcm_param = disp_lcm_get_params(pgc->plcm);
  4965. data_config = dpmgr_path_get_last_config(pgc->dpmgr_handle);
  4966. data_config->dst_w = lcm_param->width;
  4967. data_config->dst_h = lcm_param->height;
  4968. if (lcm_param->type == LCM_TYPE_DSI) {
  4969. if (lcm_param->dsi.data_format.format == LCM_DSI_FORMAT_RGB888)
  4970. data_config->lcm_bpp = 24;
  4971. else if (lcm_param->dsi.data_format.format == LCM_DSI_FORMAT_RGB565)
  4972. data_config->lcm_bpp = 16;
  4973. else if (lcm_param->dsi.data_format.format == LCM_DSI_FORMAT_RGB666)
  4974. data_config->lcm_bpp = 18;
  4975. } else if (lcm_param->type == LCM_TYPE_DPI) {
  4976. if (lcm_param->dpi.format == LCM_DPI_FORMAT_RGB888)
  4977. data_config->lcm_bpp = 24;
  4978. else if (lcm_param->dpi.format == LCM_DPI_FORMAT_RGB565)
  4979. data_config->lcm_bpp = 16;
  4980. if (lcm_param->dpi.format == LCM_DPI_FORMAT_RGB666)
  4981. data_config->lcm_bpp = 18;
  4982. }
  4983. data_config->fps = pgc->lcm_fps;
  4984. data_config->dst_dirty = 1;
  4985. ret = dpmgr_path_config(pgc->dpmgr_handle, data_config, NULL);
  4986. MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 2, 2);
  4987. if (_is_decouple_mode(pgc->session_mode)) {
  4988. data_config = dpmgr_path_get_last_config(pgc->ovl2mem_path_handle);
  4989. data_config->fps = pgc->lcm_fps;
  4990. data_config->dst_dirty = 1;
  4991. data_config->wdma_dirty = 1;
  4992. ret = dpmgr_path_config(pgc->ovl2mem_path_handle, data_config, NULL);
  4993. MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 2,
  4994. 2);
  4995. }
  4996. data_config->dst_dirty = 0;
  4997. }
  4998. DISPCHECK("[POWER]dpmanager re-init[end]\n");
  4999. MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 0, 3);
  5000. DISPCHECK("[POWER]lcm resume[begin]\n");
  5001. disp_lcm_resume(pgc->plcm);
  5002. DISPCHECK("[POWER]lcm resume[end]\n");
  5003. MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 0, 4);
  5004. if (dpmgr_path_is_busy(pgc->dpmgr_handle)) {
  5005. MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 1, 4);
  5006. DISPERR("[POWER]Fatal error, we didn't start display path but it's already busy\n");
  5007. ret = -1;
  5008. /* goto done; */
  5009. }
  5010. MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 0, 5);
  5011. DISPCHECK("[POWER]dpmgr path start[begin]\n");
  5012. dpmgr_path_start(pgc->dpmgr_handle, CMDQ_DISABLE);
  5013. if (_is_decouple_mode(pgc->session_mode))
  5014. dpmgr_path_start(pgc->ovl2mem_path_handle, CMDQ_DISABLE);
  5015. DISPCHECK("[POWER]dpmgr path start[end]\n");
  5016. MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 0, 6);
  5017. if (dpmgr_path_is_busy(pgc->dpmgr_handle)) {
  5018. MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 1, 6);
  5019. DISPERR
  5020. ("[POWER]Fatal error, we didn't trigger display path but it's already busy\n");
  5021. ret = -1;
  5022. /* goto done; */
  5023. }
  5024. MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 0, 7);
  5025. if (primary_display_is_video_mode()) {
  5026. MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 1, 7);
  5027. /* for video mode, we need to force trigger here */
  5028. /* for cmd mode, just set DPREC_EVENT_CMDQ_SET_EVENT_ALLOW when trigger loop start */
  5029. dpmgr_path_trigger(pgc->dpmgr_handle, NULL, CMDQ_DISABLE);
  5030. /* insert a wait token to make sure first config after resume will config to HW when HW idle */
  5031. _cmdq_insert_wait_frame_done_token();
  5032. }
  5033. MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 0, 8);
  5034. DISPCHECK("[POWER]start cmdq[begin]\n");
  5035. _cmdq_start_trigger_loop();
  5036. DISPCHECK("[POWER]start cmdq[end]\n");
  5037. MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagPulse, 0, 9);
  5038. if (!primary_display_is_video_mode()) {
  5039. /*refresh black picture of ovl bg */
  5040. DISPCHECK("[POWER]triggger cmdq[begin]\n");
  5041. _trigger_display_interface(0, NULL, 0);
  5042. DISPCHECK("[POWER]triggger cmdq[end]\n");
  5043. }
  5044. DISPCHECK("[POWER]wait frame done[begin]\n");
  5045. dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ / 10);
  5046. DISPCHECK("[POWER]wait frame done[end]\n");
  5047. /* reinit fake timer for debug, we can enable option then press powerkey to enable thsi feature. */
  5048. /* use fake timer to generate vsync signal for cmd mode w/o LCM(originally using LCM TE Signal as VSYNC) */
  5049. /* so we don't need to modify display driver's behavior. */
  5050. if (disp_helper_get_option
  5051. (DISP_HELPER_OPTION_NO_LCM_FOR_LOW_POWER_MEASUREMENT)) {
  5052. /* only for low power measurement */
  5053. DISPCHECK("WARNING!!!!!! FORCE NO LCM MODE!!!\n");
  5054. islcmconnected = 0;
  5055. /* no need to change video mode vsync behavior */
  5056. if (!primary_display_is_video_mode()) {
  5057. _init_vsync_fake_monitor(pgc->lcm_fps);
  5058. dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC,
  5059. DDP_IRQ_UNKNOWN);
  5060. }
  5061. }
  5062. if (is_mmdvfs_supported() && mmdvfs_get_mmdvfs_profile() == MMDVFS_PROFILE_D1_PLUS &&
  5063. primary_display_get_width() > 800) {
  5064. DISPMSG("set MMDVFS high\n");
  5065. mmdvfs_set_step(MMDVFS_SCEN_DISP, MMDVFS_VOLTAGE_HIGH); /* Enter HPM mode */
  5066. }
  5067. #if 0
  5068. DISPCHECK("[POWER]wakeup aal/od trigger process[begin]\n");
  5069. wake_up_process(primary_path_aal_task);
  5070. DISPCHECK("[POWER]wakeup aal/od trigger process[end]\n");
  5071. #endif
  5072. pgc->state = DISP_ALIVE;
  5073. pgc->force_on_wdma_path = 0;
  5074. #ifdef CONFIG_TRUSTONIC_TRUSTED_UI
  5075. switch_set_state(&disp_switch_data, DISP_ALIVE);
  5076. #endif
  5077. done:
  5078. _primary_path_unlock(__func__);
  5079. /* primary_display_diagnose(); */
  5080. #ifndef DISP_NO_AEE
  5081. aee_kernel_wdt_kick_Powkey_api("mtkfb_late_resume", WDT_SETBY_Display);
  5082. #endif
  5083. MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagEnd, 0, 0);
  5084. ddp_dump_analysis(DISP_MODULE_OVL0);
  5085. #if defined(OVL_CASCADE_SUPPORT)
  5086. ddp_dump_analysis(DISP_MODULE_OVL1);
  5087. #endif
  5088. ddp_dump_analysis(DISP_MODULE_RDMA0);
  5089. return 0;
  5090. }
  5091. int primary_display_resume_ovl2mem(void)
  5092. {
  5093. DISP_STATUS ret = DISP_STATUS_OK;
  5094. DISPFUNC();
  5095. #ifdef CONFIG_MTK_CLKMGR
  5096. if (_is_decouple_mode(pgc->session_mode))
  5097. dpmgr_path_power_on(pgc->ovl2mem_path_handle, CMDQ_DISABLE);
  5098. #endif
  5099. #ifndef CONFIG_MTK_CLKMGR
  5100. ddp_clk_prepare(DISP_MTCMOS_CLK);
  5101. #endif
  5102. #ifndef CONFIG_MTK_CLKMGR
  5103. if (_is_decouple_mode(pgc->session_mode))
  5104. dpmgr_path_power_on(pgc->ovl2mem_path_handle, CMDQ_DISABLE);
  5105. #endif
  5106. DISPCHECK("[POWER]dpmanager re-init[begin]\n");
  5107. {
  5108. LCM_PARAMS *lcm_param = NULL;
  5109. disp_ddp_path_config *data_config = NULL;
  5110. if (_is_decouple_mode(pgc->session_mode))
  5111. dpmgr_path_connect(pgc->ovl2mem_path_handle, CMDQ_DISABLE);
  5112. lcm_param = disp_lcm_get_params(pgc->plcm);
  5113. data_config = dpmgr_path_get_last_config(pgc->dpmgr_handle);
  5114. data_config->dst_w = lcm_param->width;
  5115. data_config->dst_h = lcm_param->height;
  5116. if (lcm_param->type == LCM_TYPE_DSI) {
  5117. if (lcm_param->dsi.data_format.format == LCM_DSI_FORMAT_RGB888)
  5118. data_config->lcm_bpp = 24;
  5119. else if (lcm_param->dsi.data_format.format == LCM_DSI_FORMAT_RGB565)
  5120. data_config->lcm_bpp = 16;
  5121. else if (lcm_param->dsi.data_format.format == LCM_DSI_FORMAT_RGB666)
  5122. data_config->lcm_bpp = 18;
  5123. } else if (lcm_param->type == LCM_TYPE_DPI) {
  5124. if (lcm_param->dpi.format == LCM_DPI_FORMAT_RGB888)
  5125. data_config->lcm_bpp = 24;
  5126. else if (lcm_param->dpi.format == LCM_DPI_FORMAT_RGB565)
  5127. data_config->lcm_bpp = 16;
  5128. if (lcm_param->dpi.format == LCM_DPI_FORMAT_RGB666)
  5129. data_config->lcm_bpp = 18;
  5130. }
  5131. data_config->fps = pgc->lcm_fps;
  5132. data_config->dst_dirty = 1;
  5133. if (_is_decouple_mode(pgc->session_mode)) {
  5134. data_config = dpmgr_path_get_last_config(pgc->ovl2mem_path_handle);
  5135. data_config->fps = pgc->lcm_fps;
  5136. data_config->dst_dirty = 1;
  5137. data_config->wdma_dirty = 1;
  5138. ret = dpmgr_path_config(pgc->ovl2mem_path_handle, data_config, NULL);
  5139. }
  5140. }
  5141. DISPCHECK("[POWER]ovl2mem path start[begin]\n");
  5142. if (_is_decouple_mode(pgc->session_mode))
  5143. dpmgr_path_start(pgc->ovl2mem_path_handle, CMDQ_DISABLE);
  5144. DISPCHECK("[POWER]ovl2mem path start[end]\n");
  5145. DISPCHECK("[POWER]start cmdq[begin]\n");
  5146. _cmdq_start_trigger_loop();
  5147. DISPCHECK("[POWER]start cmdq[end]\n");
  5148. if (is_mmdvfs_supported() && mmdvfs_get_mmdvfs_profile() == MMDVFS_PROFILE_D1_PLUS &&
  5149. primary_display_get_width() > 800) {
  5150. DISPMSG("set MMDVFS high\n");
  5151. mmdvfs_set_step(MMDVFS_SCEN_DISP, MMDVFS_VOLTAGE_HIGH); /* Enter HPM mode */
  5152. }
  5153. /* primary_display_diagnose(); */
  5154. #ifndef DISP_NO_AEE
  5155. aee_kernel_wdt_kick_Powkey_api("mtkfb_late_resume", WDT_SETBY_Display);
  5156. #endif
  5157. MMProfileLogEx(ddp_mmp_get_events()->primary_resume, MMProfileFlagEnd, 0, 0);
  5158. ddp_dump_analysis(DISP_MODULE_OVL0);
  5159. pgc->force_on_wdma_path = 1;
  5160. return 0;
  5161. }
  5162. int primary_display_ipoh_restore(void)
  5163. {
  5164. DISPMSG("primary_display_ipoh_restore In\n");
  5165. DISPCHECK("ESD check stop[begin]\n");
  5166. primary_display_esd_check_enable(0);
  5167. DISPCHECK("ESD check stop[end]\n");
  5168. if (NULL != pgc->cmdq_handle_trigger) {
  5169. struct TaskStruct *pTask = pgc->cmdq_handle_trigger->pRunningTask;
  5170. if (NULL != pTask) {
  5171. DISPCHECK("[Primary_display]display cmdq trigger loop stop[begin]\n");
  5172. _cmdq_stop_trigger_loop();
  5173. DISPCHECK("[Primary_display]display cmdq trigger loop stop[end]\n");
  5174. }
  5175. }
  5176. DISPMSG("primary_display_ipoh_restore Out\n");
  5177. return 0;
  5178. }
  5179. int primary_display_ipoh_recover(void)
  5180. {
  5181. DISPMSG("%s In\n", __func__);
  5182. _cmdq_start_trigger_loop();
  5183. DISPMSG("%s Out\n", __func__);
  5184. return 0;
  5185. }
  5186. int primary_display_start(void)
  5187. {
  5188. DISP_STATUS ret = DISP_STATUS_OK;
  5189. DISPFUNC();
  5190. _primary_path_lock(__func__);
  5191. dpmgr_path_start(pgc->dpmgr_handle, CMDQ_DISABLE);
  5192. if (dpmgr_path_is_busy(pgc->dpmgr_handle)) {
  5193. DISPCHECK("Fatal error, we didn't trigger display path but it's already busy\n");
  5194. ret = -1;
  5195. goto done;
  5196. }
  5197. done:
  5198. _primary_path_unlock(__func__);
  5199. return ret;
  5200. }
  5201. int primary_display_stop(void)
  5202. {
  5203. DISP_STATUS ret = DISP_STATUS_OK;
  5204. DISPFUNC();
  5205. _primary_path_lock(__func__);
  5206. if (dpmgr_path_is_busy(pgc->dpmgr_handle))
  5207. dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ * 1);
  5208. dpmgr_path_stop(pgc->dpmgr_handle, CMDQ_DISABLE);
  5209. if (dpmgr_path_is_busy(pgc->dpmgr_handle)) {
  5210. DISPCHECK("stop display path failed, still busy\n");
  5211. ret = -1;
  5212. goto done;
  5213. }
  5214. done:
  5215. _primary_path_unlock(__func__);
  5216. return ret;
  5217. }
  5218. static int primary_display_remove_output(void *callback, unsigned int userdata)
  5219. {
  5220. int ret = 0;
  5221. static cmdqRecHandle cmdq_handle;
  5222. static cmdqRecHandle cmdq_wait_handle;
  5223. /*create config thread */
  5224. if (cmdq_handle == NULL)
  5225. ret = cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &cmdq_handle);
  5226. if (ret == 0) {
  5227. /* capture thread wait wdma sof */
  5228. ret = cmdqRecCreate(CMDQ_SCENARIO_DISP_MIRROR_MODE, &cmdq_wait_handle);
  5229. if (ret == 0) {
  5230. cmdqRecReset(cmdq_wait_handle);
  5231. cmdqRecWait(cmdq_wait_handle, CMDQ_EVENT_DISP_WDMA0_SOF);
  5232. cmdqRecFlush(cmdq_wait_handle);
  5233. /* cmdqRecDestroy(cmdq_wait_handle); */
  5234. } else {
  5235. DISPERR("fail to create wait handle\n");
  5236. }
  5237. cmdqRecReset(cmdq_handle);
  5238. _cmdq_insert_wait_frame_done_token_mira(cmdq_handle);
  5239. /* update output fence */
  5240. cmdqRecBackupUpdateSlot(cmdq_handle, pgc->cur_config_fence,
  5241. disp_sync_get_output_timeline_id(), mem_config.buff_idx);
  5242. dpmgr_path_remove_memout(pgc->dpmgr_handle, cmdq_handle);
  5243. cmdqRecClearEventToken(cmdq_handle, CMDQ_EVENT_DISP_WDMA0_SOF);
  5244. _cmdq_set_config_handle_dirty_mira(cmdq_handle);
  5245. cmdqRecFlushAsyncCallback(cmdq_handle, callback, 0);
  5246. pgc->need_trigger_ovl1to2 = 0;
  5247. /* cmdqRecDestroy(cmdq_handle); */
  5248. } else {
  5249. ret = -1;
  5250. DISPERR("fail to remove memout out\n");
  5251. }
  5252. return ret;
  5253. }
  5254. static bool is_multipass_trigger;
  5255. static int primary_display_config_input_multiple_nolock(disp_session_input_config *session_input);
  5256. static int primary_display_config_output_nolock(disp_mem_output_config *output, unsigned int session_id);
  5257. static int primary_display_merge_session_cmd(disp_session_config *config)
  5258. {
  5259. disp_session_input_config *session_input;
  5260. disp_mem_output_config *primary_output;
  5261. unsigned int output_type = config->dc_type;
  5262. if (DISP_OUTPUT_UNKNOWN == output_type)
  5263. output_type = DISP_OUTPUT_DECOUPLE;
  5264. pgc->dc_type = output_type;
  5265. #ifdef CONFIG_ALL_IN_TRIGGER_STAGE
  5266. mutex_lock(&session_config_mutex);
  5267. session_input = &cached_session_input[config->type - 1];
  5268. cached_session_input[config->type - 1] = captured_session_input[config->type - 1];
  5269. cached_session_input[config->type - 1].session_id = config->session_id;
  5270. if (output_type == DISP_OUTPUT_MEMORY || is_multipass_trigger)
  5271. cached_session_output[config->type - 1] = captured_session_output[config->type - 1];
  5272. mutex_unlock(&session_config_mutex);
  5273. session_input->config_layer_num = OVL_LAYER_NUM;
  5274. if (isAEEEnabled) {
  5275. int aee_layer = primary_display_get_option("ASSERT_LAYER");
  5276. /*
  5277. For multipass mode, the AEE layer can only be enabled at final pass when AEE enabled.
  5278. Otherwise the AEE layer would be composed several time.
  5279. */
  5280. session_input->setter = SESSION_USER_AEE;
  5281. if (config->type == DISP_SESSION_PRIMARY) {
  5282. if (output_type == DISP_OUTPUT_MEMORY) {
  5283. session_input->config[aee_layer].layer_enable = 0;
  5284. DISPMSG("set the aee layer:%d en to 0\n",
  5285. session_input->config[aee_layer].layer_id);
  5286. } else {
  5287. session_input->config[aee_layer].layer_enable = 1;
  5288. }
  5289. }
  5290. }
  5291. primary_display_config_input_multiple_nolock(session_input);
  5292. if (output_type == DISP_OUTPUT_MEMORY || pgc->session_mode == DISP_SESSION_DECOUPLE_MIRROR_MODE ||
  5293. config->type == DISP_SESSION_MEMORY) {
  5294. mutex_lock(&session_config_mutex);
  5295. cached_session_output[config->type - 1] = captured_session_output[config->type - 1];
  5296. mutex_unlock(&session_config_mutex);
  5297. primary_output = &cached_session_output[config->type - 1];
  5298. primary_display_config_output_nolock(primary_output, config->session_id);
  5299. }
  5300. #endif
  5301. return 0;
  5302. }
  5303. void primary_display_update_present_fence(unsigned int fence_idx)
  5304. {
  5305. gPresentFenceIndex = fence_idx;
  5306. #ifdef CONFIG_SINGLE_PANEL_OUTPUT
  5307. if (pgc->state == DISP_SLEPT)
  5308. primary_suspend_release_present_fence();
  5309. #endif
  5310. }
  5311. static int config_wdma_output(disp_path_handle disp_handle, cmdqRecHandle cmdq_handle,
  5312. disp_mem_output_config *output, int is_multipass);
  5313. static int _primary_display_trigger(int blocking, void *callback, unsigned int userdata, int lock)
  5314. {
  5315. int ret = 0;
  5316. last_primary_trigger_time = sched_clock();
  5317. #ifdef DISP_SWITCH_DST_MODE
  5318. if (is_switched_dst_mode) {
  5319. primary_display_switch_dst_mode(1); /* swith to vdo mode if trigger disp */
  5320. is_switched_dst_mode = false;
  5321. }
  5322. #endif
  5323. if (gTriggerDispMode > 0) {
  5324. primary_display_release_fence_fake();
  5325. return ret;
  5326. }
  5327. primary_trigger_cnt++;
  5328. if (lock)
  5329. _primary_path_lock(__func__);
  5330. if (pgc->state == DISP_SLEPT) {
  5331. DISPMSG("%s, skip because primary dipslay is sleep\n", __func__);
  5332. goto done;
  5333. }
  5334. if (blocking)
  5335. DISPMSG("%s, change blocking to non blocking trigger\n", __func__);
  5336. _primary_path_set_dvfsHPM(true, 0);
  5337. #ifdef MTK_DISP_IDLE_LP
  5338. _disp_primary_path_exit_idle(__func__, 0);
  5339. #endif
  5340. dprec_logger_start(DPREC_LOGGER_PRIMARY_TRIGGER, pgc->session_mode, pgc->dc_type);
  5341. if (pgc->session_mode == DISP_SESSION_DIRECT_LINK_MODE) {
  5342. _trigger_display_interface(blocking, _ovl_fence_release_callback,
  5343. DISP_SESSION_DIRECT_LINK_MODE);
  5344. } else if (pgc->session_mode == DISP_SESSION_DIRECT_LINK_MIRROR_MODE) {
  5345. _trigger_display_interface(0, _ovl_fence_release_callback,
  5346. DISP_SESSION_DIRECT_LINK_MIRROR_MODE);
  5347. if (pgc->need_trigger_ovl1to2 == 0) {
  5348. DISPPR_ERROR("There is no output config when directlink mirror!!\n");
  5349. } else {
  5350. primary_display_remove_output(_wdma_fence_release_callback,
  5351. DISP_SESSION_DIRECT_LINK_MIRROR_MODE);
  5352. pgc->need_trigger_ovl1to2 = 0;
  5353. }
  5354. } else if (pgc->session_mode == DISP_SESSION_DECOUPLE_MIRROR_MODE) {
  5355. if (pgc->need_trigger_dcMirror_out == 0) {
  5356. if (cached_session_output[DISP_SESSION_PRIMARY - 1].security == DISP_SECURE_BUFFER)
  5357. config_wdma_output(pgc->ovl2mem_path_handle, pgc->cmdq_handle_ovl1to2_config,
  5358. &cached_session_output[DISP_SESSION_PRIMARY - 1], 0);
  5359. DISPPR_ERROR("There is no output config when decouple mirror!!\n");
  5360. } else {
  5361. #ifdef CONFIG_ALL_IN_TRIGGER_STAGE
  5362. is_output_buffer_set = 0;
  5363. #endif
  5364. pgc->need_trigger_dcMirror_out = 0;
  5365. _trigger_ovl_to_memory_mirror(pgc->ovl2mem_path_handle,
  5366. pgc->cmdq_handle_ovl1to2_config,
  5367. (fence_release_callback)
  5368. _olv_wdma_fence_release_callback,
  5369. DISP_SESSION_DECOUPLE_MIRROR_MODE);
  5370. }
  5371. } else if (pgc->session_mode == DISP_SESSION_DECOUPLE_MODE) {
  5372. if (pgc->dc_type == DISP_OUTPUT_DECOUPLE) {
  5373. uint32_t writing_mva = 0;
  5374. if (primary_display_is_secure_path(DISP_SESSION_PRIMARY)) {
  5375. pgc->session_buf_id++;
  5376. pgc->session_buf_id %= DISP_INTERNAL_BUFFER_COUNT;
  5377. writing_mva = pgc->session_buf[pgc->session_buf_id];
  5378. mem_config.security = DISP_SECURE_BUFFER;
  5379. decouple_wdma_config.security = DISP_SECURE_BUFFER;
  5380. } else {
  5381. pgc->dc_buf_id++;
  5382. pgc->dc_buf_id %= DISP_INTERNAL_BUFFER_COUNT;
  5383. writing_mva = pgc->dc_buf[pgc->dc_buf_id];
  5384. mem_config.security = DISP_NORMAL_BUFFER;
  5385. decouple_wdma_config.security = DISP_NORMAL_BUFFER;
  5386. }
  5387. decouple_wdma_config.dstAddress = writing_mva;
  5388. mem_config.addr = writing_mva;
  5389. mem_config.fmt = decouple_wdma_config.outputFormat;
  5390. mem_config.pitch = decouple_wdma_config.dstPitch;
  5391. _config_wdma_output(&decouple_wdma_config, pgc->ovl2mem_path_handle,
  5392. pgc->cmdq_handle_ovl1to2_config);
  5393. MMProfileLogEx(ddp_mmp_get_events()->primary_wdma_config,
  5394. MMProfileFlagPulse, pgc->dc_buf_id, writing_mva);
  5395. DISPMSG("%s, config wdma address 0x%lx\n", __func__,
  5396. decouple_wdma_config.dstAddress);
  5397. /*
  5398. * At the last round of multipass, the session mode would be configured as DECOUPLE MODE.
  5399. * Need to set data as DISP_SESSION_DECOUPLE_MULTIPASS_MODE to _ovl_fence_release_callback.
  5400. * Then the multipass output buffer fence would be release in _ovl_fence_release_callback.
  5401. */
  5402. if (is_multipass_trigger) {
  5403. _trigger_ovl_to_memory(pgc->ovl2mem_path_handle, pgc->cmdq_handle_ovl1to2_config,
  5404. (fence_release_callback)_ovl_fence_release_callback, 5, 0);
  5405. is_multipass_trigger = 0;
  5406. } else {
  5407. if (primary_display_is_secure_path(DISP_SESSION_PRIMARY)) {
  5408. _trigger_ovl_to_memory(pgc->ovl2mem_path_handle,
  5409. pgc->cmdq_handle_ovl1to2_config,
  5410. (fence_release_callback)_ovl_fence_release_callback,
  5411. DISP_SESSION_DECOUPLE_MODE, 1);
  5412. _ovl_fence_release_callback(DISP_SESSION_DECOUPLE_MODE);
  5413. } else {
  5414. _trigger_ovl_to_memory(pgc->ovl2mem_path_handle,
  5415. pgc->cmdq_handle_ovl1to2_config,
  5416. (fence_release_callback)_ovl_fence_release_callback,
  5417. DISP_SESSION_DECOUPLE_MODE, 0);
  5418. }
  5419. }
  5420. } else if (pgc->dc_type == DISP_OUTPUT_MEMORY) {
  5421. is_multipass_trigger = 1;
  5422. _trigger_ovl_to_memory(pgc->ovl2mem_path_handle, pgc->cmdq_handle_ovl1to2_config, NULL, 0, 0);
  5423. }
  5424. }
  5425. dprec_logger_done(DPREC_LOGGER_PRIMARY_TRIGGER, 0, 0);
  5426. done:
  5427. if (lock)
  5428. _primary_path_unlock(__func__);
  5429. /* FIXME: find aee_kernel_Powerkey_is_press definitation */
  5430. #ifndef DISP_NO_AEE
  5431. if ((primary_trigger_cnt > PRIMARY_DISPLAY_TRIGGER_CNT) && aee_kernel_Powerkey_is_press()) {
  5432. aee_kernel_wdt_kick_Powkey_api("primary_display_trigger", WDT_SETBY_Display);
  5433. primary_trigger_cnt = 0;
  5434. }
  5435. #endif
  5436. if (pgc->session_id > 0)
  5437. update_frm_seq_info(0, 0, 0, FRM_TRIGGER);
  5438. return ret;
  5439. }
  5440. int primary_display_trigger(int blocking, void *callback, unsigned int userdata)
  5441. {
  5442. return _primary_display_trigger(blocking, callback, userdata, 1);
  5443. }
  5444. int primary_display_trigger_nolock(int blocking, void *callback, unsigned int userdata)
  5445. {
  5446. return _primary_display_trigger(blocking, callback, userdata, 0);
  5447. }
  5448. int primary_display_memory_trigger_nolock(int blocking, void *callback, unsigned int userdata)
  5449. {
  5450. int ret = 0;
  5451. if (pgc->state == DISP_SLEPT) {
  5452. DISPMSG("%s, primary dipslay is sleep\n", __func__);
  5453. if (pgc->force_on_wdma_path == 0)
  5454. primary_display_resume_ovl2mem();
  5455. }
  5456. if (pgc->session_mode == DISP_SESSION_DECOUPLE_MODE || pgc->session_mode == DISP_SESSION_DECOUPLE_MIRROR_MODE) {
  5457. if (primary_display_is_secure_path(DISP_SESSION_MEMORY)) {
  5458. _trigger_ovl_to_memory(pgc->ovl2mem_path_handle, pgc->cmdq_handle_ovl1to2_config,
  5459. (fence_release_callback)_ovl_ext_fence_release_callback,
  5460. DISP_SESSION_MEMORY, 1);
  5461. _ovl_ext_fence_release_callback(DISP_SESSION_MEMORY);
  5462. } else {
  5463. _trigger_ovl_to_memory(pgc->ovl2mem_path_handle, pgc->cmdq_handle_ovl1to2_config,
  5464. (fence_release_callback)_ovl_ext_fence_release_callback,
  5465. DISP_SESSION_MEMORY, 0);
  5466. }
  5467. } else {
  5468. DISPMSG("Not support memory trigger using session_mode:%d\n", pgc->session_mode);
  5469. }
  5470. return ret;
  5471. }
  5472. void primary_display_trigger_and_merge(disp_session_config *config, int session_id)
  5473. {
  5474. _primary_path_lock(__func__);
  5475. primary_display_merge_session_cmd(config);
  5476. if (DISP_SESSION_TYPE(session_id) == DISP_SESSION_PRIMARY)
  5477. primary_display_trigger_nolock(0, NULL, 0);
  5478. else if (DISP_SESSION_TYPE(session_id) == DISP_SESSION_MEMORY)
  5479. primary_display_memory_trigger_nolock(0, NULL, 0);
  5480. else
  5481. DISPERR("Invalid session trigger\n");
  5482. _primary_path_unlock(__func__);
  5483. }
  5484. static int primary_display_ovl2mem_callback(unsigned int userdata)
  5485. {
  5486. disp_ddp_path_config *data_config = NULL;
  5487. unsigned int session_id = 0;
  5488. int fence_idx = userdata;
  5489. WDMA0_FRAME_START_FLAG = 0;
  5490. session_id = MAKE_DISP_SESSION(DISP_SESSION_PRIMARY, 0);
  5491. data_config = dpmgr_path_get_last_config(pgc->dpmgr_handle);
  5492. if (data_config) {
  5493. WDMA_CONFIG_STRUCT wdma_layer;
  5494. wdma_layer.dstAddress = mtkfb_query_buf_mva(session_id, 4, fence_idx);
  5495. wdma_layer.outputFormat = data_config->wdma_config.outputFormat;
  5496. wdma_layer.srcWidth = primary_display_get_width();
  5497. wdma_layer.srcHeight = primary_display_get_height();
  5498. wdma_layer.dstPitch = data_config->wdma_config.dstPitch;
  5499. dprec_mmp_dump_wdma_layer(&wdma_layer, 0);
  5500. }
  5501. if (fence_idx > 0)
  5502. mtkfb_release_fence(session_id, EXTERNAL_DISPLAY_SESSION_LAYER_COUNT, fence_idx);
  5503. #ifdef OVL_CASCADE_SUPPORT
  5504. if (fence_idx < NEW_BUF_IDX && ALL_LAYER_DISABLE_STEP == 1) {
  5505. DISPMSG("primary and memout does not match!!\n");
  5506. cmdqCoreSetEvent(CMDQ_EVENT_DISP_WDMA0_SOF);
  5507. if (_should_set_cmdq_dirty())
  5508. _cmdq_set_config_handle_dirty_mira(pgc->cmdq_handle_ovl1to2_config);
  5509. if ((fence_idx + 1) == NEW_BUF_IDX)
  5510. ALL_LAYER_DISABLE_STEP = 0;
  5511. }
  5512. #endif
  5513. DISPMSG("mem_out release fence idx:0x%x\n", fence_idx);
  5514. return 0;
  5515. }
  5516. /* extern unsigned int gDumpMemoutCmdq; */
  5517. int primary_display_mem_out_trigger(int blocking, void *callback, unsigned int userdata)
  5518. {
  5519. int ret = 0;
  5520. /* DISPFUNC(); */
  5521. if (pgc->state == DISP_SLEPT || !_is_mirror_mode(pgc->session_mode)) {
  5522. DISPMSG("mem out trigger is already slept or is not mirror mode(%d)\n",
  5523. pgc->session_mode);
  5524. return 0;
  5525. }
  5526. /* /dprec_logger_start(DPREC_LOGGER_PRIMARY_TRIGGER, 0, 0); */
  5527. /* if(blocking) */
  5528. _primary_path_lock(__func__);
  5529. if (pgc->need_trigger_ovl1to2 == 0)
  5530. goto done;
  5531. NEW_BUF_IDX = userdata;
  5532. ALL_LAYER_DISABLE_STEP = 0;
  5533. if (_should_wait_path_idle())
  5534. dpmgr_wait_event_timeout(pgc->ovl2mem_path_handle, DISP_PATH_EVENT_FRAME_DONE,
  5535. HZ * 1);
  5536. if (_should_trigger_path())
  5537. ;/* /dpmgr_path_trigger(pgc->dpmgr_handle, NULL, primary_display_cmdq_enabled()); */
  5538. if (_should_set_cmdq_dirty())
  5539. _cmdq_set_config_handle_dirty_mira(pgc->cmdq_handle_ovl1to2_config);
  5540. if (gDumpMemoutCmdq == 1) {
  5541. DISPMSG("primary_display_mem_out_trigger, dump before flush 1:\n");
  5542. cmdqRecDumpCommand(pgc->cmdq_handle_ovl1to2_config);
  5543. }
  5544. if (_should_flush_cmdq_config_handle())
  5545. _cmdq_flush_config_handle_mira(pgc->cmdq_handle_ovl1to2_config, 0);
  5546. if (_should_reset_cmdq_config_handle())
  5547. cmdqRecReset(pgc->cmdq_handle_ovl1to2_config);
  5548. cmdqRecWait(pgc->cmdq_handle_ovl1to2_config, CMDQ_EVENT_DISP_WDMA0_SOF);
  5549. WDMA0_FRAME_START_FLAG = 1;
  5550. _cmdq_insert_wait_frame_done_token_mira(pgc->cmdq_handle_ovl1to2_config);
  5551. dpmgr_path_remove_memout(pgc->ovl2mem_path_handle, pgc->cmdq_handle_ovl1to2_config);
  5552. if (gDumpMemoutCmdq == 1) {
  5553. DISPMSG("primary_display_mem_out_trigger, dump before flush 2:\n");
  5554. cmdqRecDumpCommand(pgc->cmdq_handle_ovl1to2_config);
  5555. }
  5556. if (_should_flush_cmdq_config_handle())
  5557. /* _cmdq_flush_config_handle_mira(pgc->cmdq_handle_ovl1to2_config, 0); */
  5558. cmdqRecFlushAsyncCallback(pgc->cmdq_handle_ovl1to2_config,
  5559. (CmdqAsyncFlushCB)primary_display_ovl2mem_callback,
  5560. userdata);
  5561. if (_should_reset_cmdq_config_handle())
  5562. cmdqRecReset(pgc->cmdq_handle_ovl1to2_config);
  5563. /* _cmdq_insert_wait_frame_done_token_mira(pgc->cmdq_handle_ovl1to2_config); */
  5564. done:
  5565. pgc->need_trigger_ovl1to2 = 0;
  5566. _primary_path_unlock(__func__);
  5567. /* dprec_logger_done(DPREC_LOGGER_PRIMARY_TRIGGER, 0, 0); */
  5568. return ret;
  5569. }
  5570. static int config_wdma_output(disp_path_handle disp_handle,
  5571. cmdqRecHandle cmdq_handle,
  5572. disp_mem_output_config *output, int is_multipass)
  5573. {
  5574. disp_ddp_path_config *pconfig = NULL;
  5575. ASSERT(output != NULL);
  5576. pconfig = dpmgr_path_get_last_config(disp_handle);
  5577. pconfig->wdma_config.dstAddress = output->addr;
  5578. pconfig->wdma_config.srcHeight = output->h;
  5579. pconfig->wdma_config.srcWidth = output->w;
  5580. pconfig->wdma_config.clipX = output->x;
  5581. pconfig->wdma_config.clipY = output->y;
  5582. pconfig->wdma_config.clipHeight = output->h;
  5583. pconfig->wdma_config.clipWidth = output->w;
  5584. pconfig->wdma_config.outputFormat = output->fmt;
  5585. pconfig->wdma_config.alpha = 0xFF;
  5586. pconfig->wdma_config.dstPitch = output->pitch;
  5587. pconfig->wdma_config.security = output->security;
  5588. pconfig->wdma_dirty = 1;
  5589. pconfig->dst_dirty = 1;
  5590. pconfig->dst_h = output->h;
  5591. pconfig->dst_w = output->w;
  5592. if (is_multipass)
  5593. pconfig->wdma_config.useSpecifiedAlpha = 0;
  5594. else
  5595. pconfig->wdma_config.useSpecifiedAlpha = 1;
  5596. return dpmgr_path_config(disp_handle, pconfig, cmdq_handle);
  5597. }
  5598. #ifdef CONFIG_SINGLE_PANEL_OUTPUT
  5599. int primary_suspend_outputbuf_fence_release(void)
  5600. {
  5601. int layer = 0;
  5602. layer = disp_sync_get_output_timeline_id();
  5603. mtkfb_release_layer_fence(primary_session_id, layer);
  5604. /* release rdma buffer */
  5605. layer = disp_sync_get_output_interface_timeline_id();
  5606. mtkfb_release_layer_fence(primary_session_id, layer);
  5607. return 0;
  5608. }
  5609. #endif
  5610. int _primary_display_config_output(disp_mem_output_config *output, unsigned int session_id, int lock)
  5611. {
  5612. int ret = 0;
  5613. disp_path_handle disp_handle;
  5614. cmdqRecHandle cmdq_handle = NULL;
  5615. DISPFUNC();
  5616. if (lock)
  5617. _primary_path_lock(__func__);
  5618. if (pgc->state == DISP_SLEPT && DISP_SESSION_TYPE(session_id) != DISP_SESSION_MEMORY) {
  5619. DISPMSG("mem out is already slept or mode wrong(%d)\n", pgc->session_mode);
  5620. #ifdef CONFIG_SINGLE_PANEL_OUTPUT
  5621. primary_suspend_outputbuf_fence_release();
  5622. #endif
  5623. goto done;
  5624. }
  5625. #if !defined(OVL_MULTIPASS_SUPPORT) && !defined(OVL_TIME_SHARING)
  5626. if (!_is_mirror_mode(pgc->session_mode)) {
  5627. DISPERR("should not config output if not mirror mode!!\n");
  5628. goto done;
  5629. }
  5630. #endif
  5631. if (_is_decouple_mode(pgc->session_mode)) {
  5632. disp_handle = pgc->ovl2mem_path_handle;
  5633. cmdq_handle = pgc->cmdq_handle_ovl1to2_config;
  5634. } else {
  5635. disp_handle = pgc->dpmgr_handle;
  5636. cmdq_handle = pgc->cmdq_handle_config;
  5637. }
  5638. if (_is_decouple_mode(pgc->session_mode)) {
  5639. #ifndef CONFIG_ALL_IN_TRIGGER_STAGE
  5640. if (_is_mirror_mode(pgc->session_mode))
  5641. pgc->need_trigger_dcMirror_out = 1;
  5642. #else
  5643. if (_is_mirror_mode(pgc->session_mode) && is_output_buffer_set)
  5644. pgc->need_trigger_dcMirror_out = 1;
  5645. #endif
  5646. } else {
  5647. /* direct link mirror mode should add memout first */
  5648. dpmgr_path_add_memout(pgc->dpmgr_handle, ENGINE_OVL0, cmdq_handle);
  5649. pgc->need_trigger_ovl1to2 = 1;
  5650. }
  5651. if (_is_decouple_mode(pgc->session_mode) && !_is_mirror_mode(pgc->session_mode))
  5652. /* Multipass Trigger */
  5653. ret = config_wdma_output(disp_handle, cmdq_handle, output, 1);
  5654. else
  5655. ret = config_wdma_output(disp_handle, cmdq_handle, output, 0);
  5656. if ((pgc->session_id > 0) && _is_decouple_mode(pgc->session_mode))
  5657. update_frm_seq_info(output->addr, 0, mtkfb_query_frm_seq_by_addr(pgc->session_id, 0, 0), FRM_CONFIG);
  5658. if (DISP_SESSION_TYPE(session_id) == DISP_SESSION_PRIMARY) {
  5659. mem_config = *output;
  5660. } else {
  5661. int layer;
  5662. layer = disp_sync_get_output_timeline_id();
  5663. cmdqRecBackupUpdateSlot(cmdq_handle, pgc->cur_mem_config_fence, layer, output->buff_idx);
  5664. layer = disp_sync_get_output_interface_timeline_id();
  5665. cmdqRecBackupUpdateSlot(cmdq_handle, pgc->cur_mem_config_fence, layer, output->interface_idx);
  5666. }
  5667. MMProfileLogEx(ddp_mmp_get_events()->primary_wdma_config, MMProfileFlagPulse,
  5668. output->buff_idx, (unsigned int)output->addr);
  5669. done:
  5670. if (lock)
  5671. _primary_path_unlock(__func__);
  5672. /* dprec_logger_done(DPREC_LOGGER_PRIMARY_CONFIG, output->src_x, output->src_y); */
  5673. return ret;
  5674. }
  5675. int primary_display_config_output(disp_mem_output_config *output, unsigned int session_id)
  5676. {
  5677. return _primary_display_config_output(output, session_id, 1);
  5678. }
  5679. static int primary_display_config_output_nolock(disp_mem_output_config *output, unsigned int session_id)
  5680. {
  5681. return _primary_display_config_output(output, session_id, 0);
  5682. }
  5683. #if 0
  5684. /**
  5685. * Defined but not used, avoid build warning. (2015.1.30 Rynn Wu)
  5686. */
  5687. static int _config_interface_input(primary_disp_input_config *input)
  5688. {
  5689. int ret = 0;
  5690. void *cmdq_handle = NULL;
  5691. disp_ddp_path_config *data_config;
  5692. /* all dirty should be cleared in dpmgr_path_get_last_config() */
  5693. data_config = dpmgr_path_get_last_config(pgc->dpmgr_handle);
  5694. dprec_logger_start(DPREC_LOGGER_PRIMARY_CONFIG, input->layer|(input->layer_en<<16), input->addr);
  5695. ret = _convert_disp_input_to_rdma(&(data_config->rdma_config), (disp_input_config *)input);
  5696. data_config->rdma_dirty = 1;
  5697. if (_should_wait_path_idle()) {
  5698. if (dpmgr_path_is_busy(pgc->dpmgr_handle))
  5699. dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ*1);
  5700. }
  5701. if (primary_display_cmdq_enabled())
  5702. cmdq_handle = pgc->cmdq_handle_config;
  5703. ret = dpmgr_path_config(pgc->dpmgr_handle, data_config, cmdq_handle);
  5704. dprec_logger_done(DPREC_LOGGER_PRIMARY_CONFIG, input->src_x, input->src_y);
  5705. return ret;
  5706. }
  5707. #endif
  5708. static void update_debug_fps_meter(disp_ddp_path_config *data_config)
  5709. {
  5710. int i, dst_id = 0;
  5711. for (i = 0; i < HW_OVERLAY_COUNT; i++) {
  5712. if (data_config->ovl_config[i].layer_en && data_config->ovl_config[i].dst_x == 0 &&
  5713. data_config->ovl_config[i].dst_y == 0)
  5714. dst_id = i;
  5715. }
  5716. _debug_fps_meter(data_config->ovl_config[dst_id].addr,
  5717. data_config->ovl_config[dst_id].vaddr,
  5718. data_config->ovl_config[dst_id].dst_w,
  5719. data_config->ovl_config[dst_id].dst_h,
  5720. data_config->ovl_config[dst_id].src_pitch, 0x00000000, dst_id,
  5721. data_config->ovl_config[dst_id].buff_idx);
  5722. }
  5723. static int _config_ovl_input(disp_session_input_config *session_input,
  5724. disp_path_handle disp_handle, cmdqRecHandle cmdq_handle)
  5725. {
  5726. int ret = 0, i = 0, layer = 0;
  5727. disp_ddp_path_config *data_config = NULL;
  5728. int max_layer_id_configed = 0;
  5729. #ifndef MTK_FB_CMDQ_DISABLE
  5730. int force_disable_ovl1 = 0;
  5731. #endif
  5732. cmdqBackupSlotHandle *p_cur_config_fence;
  5733. cmdqBackupSlotHandle *p_subtractor_when_free;
  5734. LCM_PARAMS *lcm_param = NULL;
  5735. /* create new data_config for ovl input */
  5736. data_config = dpmgr_path_get_last_config(disp_handle);
  5737. if (DISP_SESSION_TYPE(session_input->session_id) == DISP_SESSION_MEMORY) {
  5738. p_cur_config_fence = &(pgc->cur_mem_config_fence);
  5739. p_subtractor_when_free = &(pgc->mem_subtractor_when_free);
  5740. data_config->is_memory = true;
  5741. } else {
  5742. lcm_param = disp_lcm_get_params(pgc->plcm);
  5743. p_cur_config_fence = &(pgc->cur_config_fence);
  5744. p_subtractor_when_free = &(pgc->subtractor_when_free);
  5745. data_config->dst_h = lcm_param->height;
  5746. data_config->dst_w = lcm_param->width;
  5747. data_config->is_memory = false;
  5748. }
  5749. for (i = 0; i < session_input->config_layer_num; i++) {
  5750. disp_input_config *input_cfg = &session_input->config[i];
  5751. OVL_CONFIG_STRUCT *ovl_cfg;
  5752. layer = input_cfg->layer_id;
  5753. /*security issue*/
  5754. if (layer >= OVL_LAYER_NUM)
  5755. continue;
  5756. ovl_cfg = &(data_config->ovl_config[layer]);
  5757. if (session_input->setter != SESSION_USER_AEE) {
  5758. if (isAEEEnabled && layer == primary_display_get_option("ASSERT_LAYER")) {
  5759. DISPMSG("skip AEE layer %d\n", layer);
  5760. continue;
  5761. }
  5762. } else {
  5763. DISPMSG("set AEE layer %d\n", layer);
  5764. }
  5765. _convert_disp_input_to_ovl(ovl_cfg, input_cfg);
  5766. if (ovl_cfg->layer_en)
  5767. _debug_pattern(ovl_cfg->addr, ovl_cfg->vaddr, ovl_cfg->dst_w,
  5768. ovl_cfg->dst_h, ovl_cfg->src_pitch, 0x00000000,
  5769. ovl_cfg->layer, ovl_cfg->buff_idx);
  5770. dprec_logger_start(DPREC_LOGGER_PRIMARY_CONFIG, ovl_cfg->layer | (ovl_cfg->layer_en << 16),
  5771. ovl_cfg->addr);
  5772. dprec_logger_done(DPREC_LOGGER_PRIMARY_CONFIG, ovl_cfg->src_x, ovl_cfg->src_y);
  5773. dprec_mmp_dump_ovl_layer(ovl_cfg, layer, 1);
  5774. if ((ovl_cfg->layer == 0) && (!_is_decouple_mode(pgc->session_mode)))
  5775. update_frm_seq_info(ovl_cfg->addr, ovl_cfg->src_x * 4 + ovl_cfg->src_y * ovl_cfg->src_pitch,
  5776. mtkfb_query_frm_seq_by_addr(pgc->session_id, 0, 0), FRM_CONFIG);
  5777. if (max_layer_id_configed < layer)
  5778. max_layer_id_configed = layer;
  5779. data_config->ovl_dirty = 1;
  5780. #if defined(CONFIG_FOR_SOURCE_PQ)
  5781. data_config->dst_dirty = 1;
  5782. #endif
  5783. #if defined(OVL_TIME_SHARING)
  5784. data_config->roi_dirty = 1;
  5785. #endif
  5786. }
  5787. #ifdef OVL_CASCADE_SUPPORT
  5788. if (ovl_get_status() == DDP_OVL1_STATUS_SUB_REQUESTING) {
  5789. /* disable ovl layer 4~8 to free ovl1 */
  5790. if (max_layer_id_configed < OVL_LAYER_NUM_PER_OVL - is_DAL_Enabled()) {
  5791. for (i = OVL_LAYER_NUM_PER_OVL; i < OVL_LAYER_NUM; i++)
  5792. data_config->ovl_config[i].layer_en = 0;
  5793. force_disable_ovl1 = 1;
  5794. DISPMSG("cascade: HWC set %d layers, force disable OVL1 layers\n",
  5795. max_layer_id_configed);
  5796. } else {
  5797. DISPMSG("cascade: try to split ovl1 fail: HWC set %d layers\n",
  5798. max_layer_id_configed);
  5799. }
  5800. }
  5801. #endif
  5802. if (_should_wait_path_idle())
  5803. dpmgr_wait_event_timeout(disp_handle, DISP_PATH_EVENT_FRAME_DONE, HZ * 1);
  5804. /* should we use cmdq_hand_config? need to check */
  5805. ret = dpmgr_path_config(disp_handle, data_config, cmdq_handle);
  5806. #ifndef MTK_FB_CMDQ_DISABLE
  5807. /* write fence_id/enable to DRAM using cmdq,
  5808. * it will be used when release fence (put these after config registers done)
  5809. */
  5810. for (i = 0; i < session_input->config_layer_num; i++) {
  5811. unsigned int last_fence, cur_fence;
  5812. disp_input_config *input_cfg = &session_input->config[i];
  5813. layer = input_cfg->layer_id;
  5814. cmdqBackupReadSlot(*p_cur_config_fence, layer, &last_fence);
  5815. cur_fence = input_cfg->next_buff_idx;
  5816. if (cur_fence != -1 && cur_fence > last_fence)
  5817. cmdqRecBackupUpdateSlot(cmdq_handle, *p_cur_config_fence, layer, cur_fence);
  5818. /* for dim_layer/disable_layer/no_fence_layer, just release all fences configured */
  5819. /* for other layers, release current_fence-1 */
  5820. if (input_cfg->buffer_source == DISP_BUFFER_ALPHA || input_cfg->layer_enable == 0 ||
  5821. cur_fence == -1 || DISP_SESSION_TYPE(session_input->session_id) == DISP_SESSION_MEMORY)
  5822. cmdqRecBackupUpdateSlot(cmdq_handle, *p_subtractor_when_free, layer, 0);
  5823. else
  5824. cmdqRecBackupUpdateSlot(cmdq_handle, *p_subtractor_when_free, layer, 1);
  5825. }
  5826. if (force_disable_ovl1) {
  5827. for (layer = OVL_LAYER_NUM_PER_OVL; layer < OVL_LAYER_NUM; layer++)
  5828. /* will release all fences */
  5829. cmdqRecBackupUpdateSlot(cmdq_handle, *p_subtractor_when_free, layer, 0);
  5830. }
  5831. #endif
  5832. update_debug_fps_meter(data_config);
  5833. if (DISP_SESSION_TYPE(session_input->session_id) == DISP_SESSION_PRIMARY) {
  5834. last_primary_config = *data_config;
  5835. is_hwc_update_frame = 1;
  5836. }
  5837. return ret;
  5838. }
  5839. #if 0
  5840. /**
  5841. * Defined but not used, avoid build warning. (2015.1.30 Rynn Wu)
  5842. */
  5843. static int _config_ovl_output(disp_mem_output_config *output)
  5844. {
  5845. int ret = 0;
  5846. disp_ddp_path_config *data_config = NULL;
  5847. disp_path_handle *handle = NULL;
  5848. data_config = dpmgr_path_get_last_config(pgc->ovl2mem_path_handle);
  5849. data_config->wdma_dirty = 1;
  5850. if (_should_wait_path_idle())
  5851. dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ*1);
  5852. handle = pgc->ovl2mem_path_handle;
  5853. ret = dpmgr_path_config(pgc->ovl2mem_path_handle, data_config, pgc->cmdq_handle_config);
  5854. return ret;
  5855. }
  5856. #endif
  5857. static int _config_rdma_input(disp_session_input_config *session_input, disp_path_handle *handle)
  5858. {
  5859. int ret;
  5860. disp_ddp_path_config *data_config = NULL;
  5861. /* all dirty should be cleared in dpmgr_path_get_last_config() */
  5862. data_config = dpmgr_path_get_last_config(handle);
  5863. data_config->dst_dirty = 0;
  5864. data_config->ovl_dirty = 0;
  5865. data_config->rdma_dirty = 0;
  5866. data_config->wdma_dirty = 0;
  5867. ret =
  5868. _convert_disp_input_to_rdma(&(data_config->rdma_config),
  5869. (disp_input_config *) session_input);
  5870. data_config->rdma_dirty = 1;
  5871. if (_should_wait_path_idle())
  5872. dpmgr_wait_event_timeout(handle, DISP_PATH_EVENT_FRAME_DONE, HZ * 1);
  5873. ret =
  5874. dpmgr_path_config(handle, data_config,
  5875. primary_display_cmdq_enabled() ? pgc->cmdq_handle_config : NULL);
  5876. return ret;
  5877. }
  5878. static int _primary_display_config_input_multiple(disp_session_input_config *session_input, int lock)
  5879. {
  5880. int ret = 0;
  5881. disp_path_handle disp_handle;
  5882. cmdqRecHandle cmdq_handle;
  5883. if (gTriggerDispMode > 0)
  5884. return 0;
  5885. if (lock)
  5886. _primary_path_lock(__func__);
  5887. if (primary_get_state() == DISP_SLEPT && DISP_SESSION_TYPE(session_input->session_id) != DISP_SESSION_MEMORY) {
  5888. DISPMSG("%s, skip because primary dipslay is sleep\n", __func__);
  5889. #ifdef CONFIG_SINGLE_PANEL_OUTPUT
  5890. primary_suspend_release_ovl_fence(session_input);
  5891. #endif
  5892. goto done;
  5893. }
  5894. #ifdef MTK_DISP_IDLE_LP
  5895. /* call this in trigger is enough, do not have to call this in config */
  5896. _disp_primary_path_exit_idle(__func__, 0);
  5897. #endif
  5898. if (_is_decouple_mode(pgc->session_mode)) {
  5899. disp_handle = pgc->ovl2mem_path_handle;
  5900. cmdq_handle = pgc->cmdq_handle_ovl1to2_config;
  5901. } else {
  5902. disp_handle = pgc->dpmgr_handle;
  5903. cmdq_handle = pgc->cmdq_handle_config;
  5904. }
  5905. if (_should_config_ovl_input())
  5906. _config_ovl_input(session_input, disp_handle, cmdq_handle);
  5907. else
  5908. _config_rdma_input(session_input, disp_handle);
  5909. done:
  5910. if (lock)
  5911. _primary_path_unlock(__func__);
  5912. return ret;
  5913. }
  5914. int primary_display_config_input_multiple(disp_session_input_config *session_input)
  5915. {
  5916. return _primary_display_config_input_multiple(session_input, 1);
  5917. }
  5918. static int primary_display_config_input_multiple_nolock(disp_session_input_config *session_input)
  5919. {
  5920. return _primary_display_config_input_multiple(session_input, 0);
  5921. }
  5922. int primary_display_config_interface_input(primary_disp_input_config *input)
  5923. {
  5924. int ret = 0;
  5925. void *cmdq_handle = NULL;
  5926. disp_ddp_path_config *data_config;
  5927. /* all dirty should be cleared in dpmgr_path_get_last_config() */
  5928. data_config = dpmgr_path_get_last_config(pgc->dpmgr_handle);
  5929. dprec_logger_start(DPREC_LOGGER_PRIMARY_CONFIG, input->layer | (input->layer_en << 16),
  5930. input->addr);
  5931. _primary_path_lock(__func__);
  5932. if (pgc->state == DISP_SLEPT) {
  5933. DISPMSG("%s, skip because primary dipslay is sleep\n", __func__);
  5934. goto done;
  5935. }
  5936. ret = _convert_disp_input_to_rdma(&(data_config->rdma_config), (disp_input_config *) input);
  5937. data_config->rdma_dirty = 1;
  5938. if (_should_wait_path_idle()) {
  5939. if (dpmgr_path_is_busy(pgc->dpmgr_handle))
  5940. dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE,
  5941. HZ * 1);
  5942. }
  5943. if (primary_display_cmdq_enabled())
  5944. cmdq_handle = pgc->cmdq_handle_config;
  5945. ret = dpmgr_path_config(pgc->dpmgr_handle, data_config, cmdq_handle);
  5946. /* this is used for decouple mode, to indicate whether we need to trigger ovl */
  5947. pgc->need_trigger_overlay = 1;
  5948. dprec_logger_done(DPREC_LOGGER_PRIMARY_CONFIG, input->src_x, input->src_y);
  5949. done:
  5950. _primary_path_unlock(__func__);
  5951. return ret;
  5952. }
  5953. static int Panel_Master_primary_display_config_dsi(const char *name, uint32_t config_value)
  5954. {
  5955. int ret = 0;
  5956. disp_ddp_path_config *data_config;
  5957. /* all dirty should be cleared in dpmgr_path_get_last_config() */
  5958. data_config = dpmgr_path_get_last_config(pgc->dpmgr_handle);
  5959. /* modify below for config dsi */
  5960. if (!strcmp(name, "PM_CLK")) {
  5961. pr_debug("Pmaster_config_dsi: PM_CLK:%d\n", config_value);
  5962. data_config->dispif_config.dsi.PLL_CLOCK = config_value;
  5963. } else if (!strcmp(name, "PM_SSC")) {
  5964. data_config->dispif_config.dsi.ssc_range = config_value;
  5965. }
  5966. pr_debug("Pmaster_config_dsi: will Run path_config()\n");
  5967. ret = dpmgr_path_config(pgc->dpmgr_handle, data_config, NULL);
  5968. return ret;
  5969. }
  5970. int primary_display_user_cmd(unsigned int cmd, unsigned long arg)
  5971. {
  5972. int ret = 0;
  5973. cmdqRecHandle handle = NULL;
  5974. int cmdqsize = 0;
  5975. MMProfileLogEx(ddp_mmp_get_events()->primary_display_cmd, MMProfileFlagStart,
  5976. (unsigned long)handle, 0);
  5977. #ifndef MTK_FB_CMDQ_DISABLE
  5978. #if 0 /* CONFIG_FOR_SOURCE_PQ */
  5979. if (primary_display_is_decouple_mode()) {
  5980. ret = cmdqRecCreate(CMDQ_SCENARIO_DISP_COLOR, &handle);
  5981. cmdqRecReset(handle);
  5982. cmdqRecWait(handle, CMDQ_EVENT_DISP_WDMA0_EOF);
  5983. } else {
  5984. ret = cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &handle);
  5985. cmdqRecReset(handle);
  5986. _cmdq_insert_wait_frame_done_token_mira(handle);
  5987. }
  5988. #else
  5989. ret = cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &handle);
  5990. cmdqRecReset(handle);
  5991. if (primary_display_is_video_mode())
  5992. cmdqRecWaitNoClear(handle, CMDQ_EVENT_DISP_RDMA0_EOF);
  5993. else
  5994. cmdqRecWaitNoClear(handle, CMDQ_SYNC_TOKEN_STREAM_EOF);
  5995. #endif
  5996. cmdqsize = cmdqRecGetInstructionCount(handle);
  5997. #ifdef MTK_DISP_IDLE_LP
  5998. /* will write register in dpmgr_path_user_cmd, need to exit idle */
  5999. last_primary_trigger_time = sched_clock();
  6000. _disp_primary_path_exit_idle(__func__, 1);
  6001. #endif
  6002. #ifdef CONFIG_FOR_SOURCE_PQ
  6003. if (primary_display_is_decouple_mode())
  6004. ret = dpmgr_path_user_cmd(pgc->ovl2mem_path_handle, cmd, arg, handle);
  6005. else
  6006. ret = dpmgr_path_user_cmd(pgc->dpmgr_handle, cmd, arg, handle);
  6007. #else
  6008. ret = dpmgr_path_user_cmd(pgc->dpmgr_handle, cmd, arg, handle);
  6009. #endif
  6010. if (handle) {
  6011. if (cmdqRecGetInstructionCount(handle) > cmdqsize) {
  6012. _primary_path_lock(__func__);
  6013. if (pgc->state == DISP_ALIVE) {
  6014. #if 0 /* CONFIG_FOR_SOURCE_PQ */
  6015. if (primary_display_is_decouple_mode()) {
  6016. dpmgr_path_trigger(pgc->ovl2mem_path_handle, handle,
  6017. CMDQ_ENABLE);
  6018. cmdqRecFlushAsync(handle);
  6019. } else {
  6020. _cmdq_set_config_handle_dirty_mira(handle);
  6021. /* use non-blocking flush here to avoid primary path is locked for too long */
  6022. _cmdq_flush_config_handle_mira(handle, 0);
  6023. }
  6024. #else
  6025. _cmdq_set_config_handle_dirty_mira(handle);
  6026. /* use non-blocking flush here to avoid primary path is locked for too long */
  6027. _cmdq_flush_config_handle_mira(handle, 0);
  6028. #endif
  6029. }
  6030. _primary_path_unlock(__func__);
  6031. }
  6032. cmdqRecDestroy(handle);
  6033. }
  6034. #endif
  6035. MMProfileLogEx(ddp_mmp_get_events()->primary_display_cmd, MMProfileFlagEnd,
  6036. (unsigned long)handle, cmdqsize);
  6037. return ret;
  6038. }
  6039. int init_ext_decouple_buffers(void)
  6040. {
  6041. int ret = 0;
  6042. #if defined(CONFIG_MTK_GMO_RAM_OPTIMIZE)
  6043. _primary_path_lock(__func__);
  6044. if (pgc->state == DISP_SLEPT) {
  6045. ret = -1;
  6046. } else {
  6047. if (decouple_buffer_info[0] == NULL)
  6048. ret = allocate_idle_lp_dc_buffer();
  6049. }
  6050. _primary_path_unlock(__func__);
  6051. #endif
  6052. return ret;
  6053. }
  6054. int deinit_ext_decouple_buffers(void)
  6055. {
  6056. int ret = 0;
  6057. #if defined(CONFIG_MTK_GMO_RAM_OPTIMIZE)
  6058. _primary_path_lock(__func__);
  6059. ret = release_idle_lp_dc_buffer(0);
  6060. _primary_path_unlock(__func__);
  6061. #endif
  6062. return ret;
  6063. }
  6064. int primary_display_switch_mode(int sess_mode, unsigned int session, int force)
  6065. {
  6066. DISPDBG("primary_display_switch_mode sess_mode %d, session 0x%x\n", sess_mode, session);
  6067. _primary_path_lock(__func__);
  6068. MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagStart,
  6069. pgc->session_mode, sess_mode);
  6070. if (primary_get_state() == DISP_BLANK)
  6071. sess_mode = DISP_SESSION_DECOUPLE_MODE;
  6072. if (pgc->session_mode == sess_mode)
  6073. goto done;
  6074. if (pgc->state == DISP_SLEPT) {
  6075. DISPMSG("primary display switch from %s to %s in suspend state!!!\n",
  6076. session_mode_spy(pgc->session_mode), session_mode_spy(sess_mode));
  6077. #ifdef OVL_TIME_SHARING
  6078. /*
  6079. Allow system to switch mode between Deouple and Decouple Mirror when time-sharing support.
  6080. Since system may use extension path to output data even when the primay path has suspended.
  6081. */
  6082. if (pgc->session_mode == DISP_SESSION_DECOUPLE_MODE
  6083. && sess_mode == DISP_SESSION_DECOUPLE_MIRROR_MODE) {
  6084. pgc->session_mode = sess_mode;
  6085. DISPMSG("primary display is %s mode now\n", session_mode_spy(pgc->session_mode));
  6086. } else if (pgc->session_mode == DISP_SESSION_DECOUPLE_MIRROR_MODE
  6087. && sess_mode == DISP_SESSION_DECOUPLE_MODE) {
  6088. pgc->session_mode = sess_mode;
  6089. DISPMSG("primary display is %s mode now\n", session_mode_spy(pgc->session_mode));
  6090. }
  6091. #endif
  6092. goto done;
  6093. }
  6094. DISPMSG("primary display will switch from %s to %s\n", session_mode_spy(pgc->session_mode),
  6095. session_mode_spy(sess_mode));
  6096. if (pgc->session_mode == DISP_SESSION_DIRECT_LINK_MODE
  6097. && sess_mode == DISP_SESSION_DECOUPLE_MODE) {
  6098. /* dl to dc */
  6099. _DL_switch_to_DC_fast();
  6100. pgc->session_mode = sess_mode;
  6101. DISPMSG("primary display is %s mode now\n", session_mode_spy(pgc->session_mode));
  6102. MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagPulse,
  6103. pgc->session_mode, sess_mode);
  6104. /* primary_display_diagnose(); */
  6105. } else if (pgc->session_mode == DISP_SESSION_DECOUPLE_MODE
  6106. && sess_mode == DISP_SESSION_DIRECT_LINK_MODE) {
  6107. /* dc to dl */
  6108. _DC_switch_to_DL_fast();
  6109. pgc->session_mode = sess_mode;
  6110. DISPMSG("primary display is %s mode now\n", session_mode_spy(pgc->session_mode));
  6111. MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagPulse,
  6112. pgc->session_mode, sess_mode);
  6113. /* primary_display_diagnose(); */
  6114. } else if (pgc->session_mode == DISP_SESSION_DIRECT_LINK_MODE
  6115. && sess_mode == DISP_SESSION_DIRECT_LINK_MIRROR_MODE) {
  6116. /* dl to dl mirror */
  6117. /* cmdqRecCreate(CMDQ_SCENARIO_DISP_SCREEN_CAPTURE, &pgc->cmdq_handle_dl_mirror); */
  6118. /* cmdqRecReset(pgc->cmdq_handle_dl_mirror); */
  6119. pgc->session_mode = sess_mode;
  6120. DISPMSG("primary display is %s mode now\n", session_mode_spy(pgc->session_mode));
  6121. MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagPulse,
  6122. pgc->session_mode, sess_mode);
  6123. } else if (pgc->session_mode == DISP_SESSION_DIRECT_LINK_MIRROR_MODE
  6124. && sess_mode == DISP_SESSION_DIRECT_LINK_MODE) {
  6125. /*dl mirror to dl */
  6126. /* cmdqRecDestroy(pgc->cmdq_handle_dl_mirror); */
  6127. /* pgc->cmdq_handle_dl_mirror = NULL; */
  6128. pgc->session_mode = sess_mode;
  6129. DISPMSG("primary display is %s mode now\n", session_mode_spy(pgc->session_mode));
  6130. MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagPulse,
  6131. pgc->session_mode, sess_mode);
  6132. } else if (pgc->session_mode == DISP_SESSION_DIRECT_LINK_MODE
  6133. && sess_mode == DISP_SESSION_DECOUPLE_MIRROR_MODE) {
  6134. /* dl to dc mirror mirror */
  6135. #ifdef CONFIG_MTK_GMO_RAM_OPTIMIZE
  6136. if (decouple_buffer_info[0] == NULL)
  6137. allocate_idle_lp_dc_buffer();
  6138. #endif
  6139. _DL_switch_to_DC_fast();
  6140. pgc->session_mode = sess_mode;
  6141. DISPMSG("primary display is %s mode now\n", session_mode_spy(pgc->session_mode));
  6142. MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagPulse,
  6143. pgc->session_mode, sess_mode);
  6144. /* primary_display_diagnose(); */
  6145. } else if (pgc->session_mode == DISP_SESSION_DECOUPLE_MIRROR_MODE
  6146. && sess_mode == DISP_SESSION_DIRECT_LINK_MODE) {
  6147. /*dc mirror to dl */
  6148. _DC_switch_to_DL_fast();
  6149. pgc->session_mode = sess_mode;
  6150. #ifdef CONFIG_MTK_GMO_RAM_OPTIMIZE
  6151. release_idle_lp_dc_buffer(0);
  6152. #endif
  6153. DISPMSG("primary display is %s mode now\n", session_mode_spy(pgc->session_mode));
  6154. MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagPulse,
  6155. pgc->session_mode, sess_mode);
  6156. /* primary_display_diagnose(); */
  6157. } else if (pgc->session_mode == DISP_SESSION_DECOUPLE_MODE
  6158. && sess_mode == DISP_SESSION_DECOUPLE_MIRROR_MODE) {
  6159. /*dc to dc mirror */
  6160. pgc->session_mode = sess_mode;
  6161. DISPMSG("primary display is %s mode now\n", session_mode_spy(pgc->session_mode));
  6162. MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagPulse,
  6163. pgc->session_mode, sess_mode);
  6164. } else if (pgc->session_mode == DISP_SESSION_DECOUPLE_MIRROR_MODE
  6165. && sess_mode == DISP_SESSION_DECOUPLE_MODE) {
  6166. /*dc mirror to dc */
  6167. pgc->session_mode = sess_mode;
  6168. DISPMSG("primary display is %s mode now\n", session_mode_spy(pgc->session_mode));
  6169. MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagPulse,
  6170. pgc->session_mode, sess_mode);
  6171. } else {
  6172. DISPERR("invalid mode switch from %s to %s\n", session_mode_spy(pgc->session_mode),
  6173. session_mode_spy(sess_mode));
  6174. }
  6175. done:
  6176. _primary_path_unlock(__func__);
  6177. pgc->session_id = session;
  6178. MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagEnd,
  6179. pgc->session_mode, sess_mode);
  6180. return 0; /* avoid build warning. */
  6181. }
  6182. #ifdef MTK_DISP_IDLE_LP
  6183. int primary_display_switch_mode_nolock(int sess_mode, unsigned int session, int force)
  6184. {
  6185. DISPCHECK("primary_display_switch_mode sess_mode %d, session 0x%x\n", sess_mode, session);
  6186. /* if(!force && _is_decouple_mode(pgc->session_mode)) */
  6187. /* return 0; */
  6188. /* _primary_path_lock(__func__); */
  6189. MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagStart,
  6190. pgc->session_mode, sess_mode);
  6191. if (pgc->session_mode == sess_mode)
  6192. goto done;
  6193. DISPMSG("primary display will switch from %s to %s\n", session_mode_spy(pgc->session_mode),
  6194. session_mode_spy(sess_mode));
  6195. if (pgc->session_mode == DISP_SESSION_DIRECT_LINK_MODE && sess_mode == DISP_SESSION_DECOUPLE_MODE) {
  6196. /* signal frame start event to switch logic in fence_release_worker_thread */
  6197. /* dpmgr_signal_event(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_START); */
  6198. _DL_switch_to_DC_fast();
  6199. pgc->session_mode = sess_mode;
  6200. DISPMSG("primary display is %s mode now\n", session_mode_spy(pgc->session_mode));
  6201. MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagPulse,
  6202. pgc->session_mode, sess_mode);
  6203. /* primary_display_diagnose(); */
  6204. } else if (pgc->session_mode == DISP_SESSION_DECOUPLE_MODE && sess_mode == DISP_SESSION_DIRECT_LINK_MODE) {
  6205. /* signal frame start event to switch logic in fence_release_worker_thread */
  6206. /* dpmgr_signal_event(pgc->ovl2mem_path_handle, DISP_PATH_EVENT_FRAME_START); */
  6207. _DC_switch_to_DL_fast();
  6208. pgc->session_mode = sess_mode;
  6209. DISPMSG("* primary display is %s mode now\n", session_mode_spy(pgc->session_mode));
  6210. MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagPulse,
  6211. pgc->session_mode, sess_mode);
  6212. /* primary_display_diagnose(); */
  6213. } else if (pgc->session_mode == DISP_SESSION_DIRECT_LINK_MODE &&
  6214. sess_mode == DISP_SESSION_DIRECT_LINK_MIRROR_MODE) {
  6215. /*need delay switch to output */
  6216. pgc->session_mode = sess_mode;
  6217. } else if (pgc->session_mode == DISP_SESSION_DIRECT_LINK_MIRROR_MODE
  6218. && sess_mode == DISP_SESSION_DIRECT_LINK_MODE) {
  6219. /* xxx */
  6220. pgc->session_mode = sess_mode;
  6221. } else if (pgc->session_mode == DISP_SESSION_DIRECT_LINK_MODE &&
  6222. sess_mode == DISP_SESSION_DECOUPLE_MIRROR_MODE) {
  6223. /*need delay switch to output */
  6224. _DL_switch_to_DC_fast();
  6225. pgc->session_mode = sess_mode;
  6226. DISPMSG("primary display is %s mode now\n", session_mode_spy(pgc->session_mode));
  6227. MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagPulse,
  6228. pgc->session_mode, sess_mode);
  6229. /* primary_display_diagnose(); */
  6230. /* pgc->session_delay_mode = sess_mode; */
  6231. } else if (pgc->session_mode == DISP_SESSION_DECOUPLE_MIRROR_MODE &&
  6232. sess_mode == DISP_SESSION_DIRECT_LINK_MODE) {
  6233. _DC_switch_to_DL_fast();
  6234. pgc->session_mode = sess_mode;
  6235. DISPMSG("primary display is %s mode now\n", session_mode_spy(pgc->session_mode));
  6236. MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagPulse,
  6237. pgc->session_mode, sess_mode);
  6238. /* primary_display_diagnose(); */
  6239. } else {
  6240. DISPERR("invalid mode switch from %s to %s\n", session_mode_spy(pgc->session_mode),
  6241. session_mode_spy(sess_mode));
  6242. }
  6243. done:
  6244. /* _primary_path_unlock(__func__); */
  6245. pgc->session_id = session;
  6246. MMProfileLogEx(ddp_mmp_get_events()->primary_switch_mode, MMProfileFlagEnd,
  6247. pgc->session_mode, sess_mode);
  6248. return 0; /* avoid build warning. */
  6249. }
  6250. #endif
  6251. int primary_display_is_alive(void)
  6252. {
  6253. unsigned int temp = 0;
  6254. /* DISPFUNC(); */
  6255. _primary_path_lock(__func__);
  6256. if (pgc->state == DISP_ALIVE)
  6257. temp = 1;
  6258. _primary_path_unlock(__func__);
  6259. return temp;
  6260. }
  6261. int primary_display_is_sleepd_nolock(void)
  6262. {
  6263. unsigned int temp = 0;
  6264. /* DISPFUNC(); */
  6265. if (pgc->state == DISP_SLEPT)
  6266. temp = 1;
  6267. return temp;
  6268. }
  6269. int primary_display_is_sleepd(void)
  6270. {
  6271. unsigned int temp = 0;
  6272. /* DISPFUNC(); */
  6273. _primary_path_lock(__func__);
  6274. if (pgc->state == DISP_SLEPT)
  6275. temp = 1;
  6276. _primary_path_unlock(__func__);
  6277. return temp;
  6278. }
  6279. int primary_display_get_width(void)
  6280. {
  6281. if (pgc->plcm == NULL) {
  6282. DISPERR("lcm handle is null\n");
  6283. return 0;
  6284. }
  6285. if (pgc->plcm->params)
  6286. return pgc->plcm->params->width;
  6287. DISPERR("lcm_params is null!\n");
  6288. return 0;
  6289. }
  6290. int primary_display_get_height(void)
  6291. {
  6292. if (pgc->plcm == NULL) {
  6293. DISPERR("lcm handle is null\n");
  6294. return 0;
  6295. }
  6296. if (pgc->plcm->params)
  6297. return pgc->plcm->params->height;
  6298. DISPERR("lcm_params is null!\n");
  6299. return 0;
  6300. }
  6301. int primary_display_get_original_width(void)
  6302. {
  6303. if (pgc->plcm == NULL) {
  6304. DISPERR("lcm handle is null\n");
  6305. return 0;
  6306. }
  6307. if (pgc->plcm->params)
  6308. return pgc->plcm->lcm_original_width;
  6309. DISPERR("lcm_params is null!\n");
  6310. return 0;
  6311. }
  6312. int primary_display_get_original_height(void)
  6313. {
  6314. if (pgc->plcm == NULL) {
  6315. DISPERR("lcm handle is null\n");
  6316. return 0;
  6317. }
  6318. if (pgc->plcm->params)
  6319. return pgc->plcm->lcm_original_height;
  6320. DISPERR("lcm_params is null!\n");
  6321. return 0;
  6322. }
  6323. int primary_display_get_bpp(void)
  6324. {
  6325. return 32;
  6326. }
  6327. int primary_display_get_dc_bpp(void)
  6328. {
  6329. return 24;
  6330. }
  6331. void primary_display_set_max_layer(int maxlayer)
  6332. {
  6333. pgc->max_layer = maxlayer;
  6334. }
  6335. int primary_display_get_info(void *info)
  6336. {
  6337. #if 1
  6338. /* DISPFUNC(); */
  6339. disp_session_info *dispif_info = (disp_session_info *) info;
  6340. LCM_PARAMS *lcm_param = disp_lcm_get_params(pgc->plcm);
  6341. if (lcm_param == NULL) {
  6342. DISPCHECK("lcm_param is null\n");
  6343. return -1;
  6344. }
  6345. memset((void *)dispif_info, 0, sizeof(disp_session_info));
  6346. #ifdef OVL_CASCADE_SUPPORT
  6347. if (is_DAL_Enabled() && pgc->max_layer == OVL_LAYER_NUM) {
  6348. /* OVL1 is used by mem session */
  6349. if (ovl_get_status() == DDP_OVL1_STATUS_PRIMARY || ovl_get_status() == DDP_OVL1_STATUS_IDLE)
  6350. dispif_info->maxLayerNum = pgc->max_layer - 1;
  6351. else
  6352. dispif_info->maxLayerNum = pgc->max_layer - 1 - 4;
  6353. } else {
  6354. /* OVL1 is used by mem session */
  6355. if (ovl_get_status() == DDP_OVL1_STATUS_PRIMARY || ovl_get_status() == DDP_OVL1_STATUS_IDLE)
  6356. dispif_info->maxLayerNum = pgc->max_layer;
  6357. else
  6358. dispif_info->maxLayerNum = pgc->max_layer - 4;
  6359. }
  6360. #else
  6361. if (is_DAL_Enabled() && pgc->max_layer == OVL_LAYER_NUM)
  6362. dispif_info->maxLayerNum = pgc->max_layer - 1;
  6363. else
  6364. dispif_info->maxLayerNum = pgc->max_layer;
  6365. #endif
  6366. /* DISPDBG("available layer num=%d\n", dispif_info->maxLayerNum); */
  6367. switch (lcm_param->type) {
  6368. case LCM_TYPE_DBI:
  6369. {
  6370. dispif_info->displayType = DISP_IF_TYPE_DBI;
  6371. dispif_info->displayMode = DISP_IF_MODE_COMMAND;
  6372. dispif_info->isHwVsyncAvailable = 1;
  6373. /* DISPMSG("DISP Info: DBI, CMD Mode, HW Vsync enable\n"); */
  6374. break;
  6375. }
  6376. case LCM_TYPE_DPI:
  6377. {
  6378. dispif_info->displayType = DISP_IF_TYPE_DPI;
  6379. dispif_info->displayMode = DISP_IF_MODE_VIDEO;
  6380. dispif_info->isHwVsyncAvailable = 1;
  6381. /* DISPMSG("DISP Info: DPI, VDO Mode, HW Vsync enable\n"); */
  6382. break;
  6383. }
  6384. case LCM_TYPE_DSI:
  6385. {
  6386. dispif_info->displayType = DISP_IF_TYPE_DSI0;
  6387. if (lcm_param->dsi.mode == CMD_MODE) {
  6388. dispif_info->displayMode = DISP_IF_MODE_COMMAND;
  6389. dispif_info->isHwVsyncAvailable = 1;
  6390. /* DISPMSG("DISP Info: DSI, CMD Mode, HW Vsync enable\n"); */
  6391. } else {
  6392. dispif_info->displayMode = DISP_IF_MODE_VIDEO;
  6393. dispif_info->isHwVsyncAvailable = 1;
  6394. /* DISPMSG("DISP Info: DSI, VDO Mode, HW Vsync enable\n"); */
  6395. }
  6396. break;
  6397. }
  6398. default:
  6399. break;
  6400. }
  6401. dispif_info->displayFormat = DISP_IF_FORMAT_RGB888;
  6402. dispif_info->displayWidth = primary_display_get_width();
  6403. dispif_info->displayHeight = primary_display_get_height();
  6404. dispif_info->physicalWidth = DISP_GetActiveWidth();
  6405. dispif_info->physicalHeight = DISP_GetActiveHeight();
  6406. dispif_info->vsyncFPS = pgc->lcm_fps;
  6407. dispif_info->isConnected = 1;
  6408. #ifdef ROME_TODO
  6409. #error
  6410. {
  6411. LCM_PARAMS lcm_params_temp;
  6412. memset((void *)&lcm_params_temp, 0, sizeof(lcm_params_temp));
  6413. if (lcm_drv) {
  6414. lcm_drv->get_params(&lcm_params_temp);
  6415. dispif_info->lcmOriginalWidth = lcm_params_temp.width;
  6416. dispif_info->lcmOriginalHeight = lcm_params_temp.height;
  6417. DISPMSG("DISP Info: LCM Panel Original Resolution(For DFO Only): %d x %d\n",
  6418. dispif_info->lcmOriginalWidth, dispif_info->lcmOriginalHeight);
  6419. } else {
  6420. DISPMSG("DISP Info: Fatal Error!!, lcm_drv is null\n");
  6421. }
  6422. }
  6423. #endif
  6424. #endif
  6425. return 0; /* avoid build warning. */
  6426. }
  6427. int primary_display_get_pages(void)
  6428. {
  6429. return 3;
  6430. }
  6431. int primary_display_is_video_mode(void)
  6432. {
  6433. /* TODO: we should store the video/cmd mode in runtime, because we will support cmd/vdo dynamic switch */
  6434. return disp_lcm_is_video_mode(pgc->plcm);
  6435. }
  6436. int primary_display_is_decouple_mode(void)
  6437. {
  6438. return _is_decouple_mode(pgc->session_mode);
  6439. }
  6440. int primary_display_is_mirror_mode(void)
  6441. {
  6442. return _is_mirror_mode(pgc->session_mode);
  6443. }
  6444. int primary_display_is_ovl1to2_handle(cmdqRecHandle *handle)
  6445. {
  6446. if (handle && (handle == (cmdqRecHandle *)pgc->cmdq_handle_ovl1to2_config))
  6447. return 1;
  6448. else
  6449. return 0;
  6450. }
  6451. int primary_display_diagnose(void)
  6452. {
  6453. int ret = 0;
  6454. if (pgc->dpmgr_handle != NULL)
  6455. dpmgr_check_status(pgc->dpmgr_handle);
  6456. if (_is_decouple_mode(pgc->session_mode) && (pgc->ovl2mem_path_handle != NULL))
  6457. dpmgr_check_status(pgc->ovl2mem_path_handle);
  6458. primary_display_check_path(NULL, 0);
  6459. return ret;
  6460. }
  6461. CMDQ_SWITCH primary_display_cmdq_enabled(void)
  6462. {
  6463. return primary_display_use_cmdq;
  6464. }
  6465. int primary_display_switch_cmdq_cpu(CMDQ_SWITCH use_cmdq)
  6466. {
  6467. _primary_path_lock(__func__);
  6468. primary_display_use_cmdq = use_cmdq;
  6469. DISPCHECK("display driver use %s to config register now\n",
  6470. (use_cmdq == CMDQ_ENABLE) ? "CMDQ" : "CPU");
  6471. _primary_path_unlock(__func__);
  6472. return primary_display_use_cmdq;
  6473. }
  6474. int primary_display_manual_lock(void)
  6475. {
  6476. _primary_path_lock(__func__);
  6477. return 0; /* avoid build warning */
  6478. }
  6479. int primary_display_manual_unlock(void)
  6480. {
  6481. _primary_path_unlock(__func__);
  6482. return 0;
  6483. }
  6484. void primary_display_reset(void)
  6485. {
  6486. dpmgr_path_reset(pgc->dpmgr_handle, CMDQ_DISABLE);
  6487. }
  6488. unsigned int primary_display_get_fps(void)
  6489. {
  6490. unsigned int fps = 0;
  6491. _primary_path_lock(__func__);
  6492. fps = pgc->lcm_fps;
  6493. _primary_path_unlock(__func__);
  6494. return fps;
  6495. }
  6496. int primary_display_force_set_vsync_fps(unsigned int fps)
  6497. {
  6498. int ret = 0;
  6499. DISPMSG("force set fps to %d\n", fps);
  6500. _primary_path_lock(__func__);
  6501. if (fps == pgc->lcm_fps) {
  6502. pgc->vsync_drop = 0;
  6503. ret = 0;
  6504. } else if (fps == 30) {
  6505. pgc->vsync_drop = 1;
  6506. ret = 0;
  6507. } else {
  6508. ret = -1;
  6509. }
  6510. _primary_path_unlock(__func__);
  6511. return ret;
  6512. }
  6513. int primary_display_insert_session_buf(disp_session_buf_info *session_buf_info)
  6514. {
  6515. int i = 0;
  6516. unsigned int *session_buf;
  6517. session_buf = pgc->session_buf;
  6518. pgc->session_buf_id = 0;
  6519. for (i = 0; i < DISP_INTERNAL_BUFFER_COUNT; i++) {
  6520. session_buf[i] = session_buf_info->buf_hnd[i];
  6521. DISPMSG("%s buf_hnd[%d] = 0x%x\n", __func__, i, session_buf_info->buf_hnd[i]);
  6522. }
  6523. return 0;
  6524. }
  6525. int primary_display_enable_path_cg(int enable)
  6526. {
  6527. int ret = 0;
  6528. #ifdef ENABLE_CLK_MGR
  6529. DISPMSG("%s primary display's path cg\n", enable ? "enable" : "disable");
  6530. _primary_path_lock(__func__);
  6531. if (enable) {
  6532. #ifdef CONFIG_MTK_CLKMGR
  6533. ret += disable_clock(MT_CG_DISP1_DSI_ENGINE, "DSI0");
  6534. ret += disable_clock(MT_CG_DISP1_DSI_DIGITAL, "DSI0");
  6535. ret += disable_clock(MT_CG_DISP0_DISP_OVL0, "DDP");
  6536. ret += disable_clock(MT_CG_DISP0_DISP_COLOR, "DDP");
  6537. ret += disable_clock(MT_CG_DISP0_DISP_CCORR, "DDP");
  6538. ret += disable_clock(MT_CG_DISP0_DISP_AAL, "DDP");
  6539. ret += disable_clock(MT_CG_DISP0_DISP_GAMMA, "DDP");
  6540. ret += disable_clock(MT_CG_DISP0_DISP_DITHER, "DDP");
  6541. ret += disable_clock(MT_CG_DISP0_DISP_RDMA0, "DDP");
  6542. ret += disable_clock(MT_CG_PERI_DISP_PWM, "PWM");
  6543. /* ret += disable_clock(MT_CG_DISP0_MUTEX_32K , "Debug"); */
  6544. ret += disable_clock(MT_CG_DISP0_SMI_LARB0, "Debug");
  6545. ret += disable_clock(MT_CG_DISP0_SMI_COMMON, "Debug");
  6546. /* ret += disable_clock(MT_CG_DISP0_MUTEX_32K , "Debug2"); */
  6547. ret += disable_clock(MT_CG_DISP0_SMI_LARB0, "Debug2");
  6548. ret += disable_clock(MT_CG_DISP0_SMI_COMMON, "Debug2");
  6549. #else
  6550. ddp_clk_disable(DISP1_DSI_ENGINE);
  6551. ddp_clk_disable(DISP1_DSI_DIGITAL);
  6552. ddp_clk_disable(DISP0_DISP_OVL0);
  6553. ddp_clk_disable(DISP0_DISP_COLOR);
  6554. ddp_clk_disable(DISP0_DISP_CCORR);
  6555. ddp_clk_disable(DISP0_DISP_AAL);
  6556. ddp_clk_disable(DISP0_DISP_GAMMA);
  6557. ddp_clk_disable(DISP0_DISP_DITHER);
  6558. ddp_clk_disable(DISP0_DISP_RDMA0);
  6559. ddp_clk_disable(DISP_PWM);
  6560. /*ddp_clk_disable(DISP0_MUTEX_32K); */
  6561. ddp_clk_disable(DISP0_SMI_LARB0);
  6562. ddp_clk_disable(DISP0_SMI_COMMON);
  6563. /*ddp_clk_disable(DISP0_MUTEX_32K); */
  6564. ddp_clk_disable(DISP0_SMI_LARB0);
  6565. ddp_clk_disable(DISP0_SMI_COMMON);
  6566. ddp_clk_disable(DISP_MTCMOS_CLK);
  6567. ddp_clk_unprepare(DISP_MTCMOS_CLK);
  6568. #endif
  6569. } else {
  6570. #ifdef CONFIG_MTK_CLKMGR
  6571. ret += enable_clock(MT_CG_DISP1_DSI_ENGINE, "DSI0");
  6572. ret += enable_clock(MT_CG_DISP1_DSI_DIGITAL, "DSI0");
  6573. ret += enable_clock(MT_CG_DISP0_DISP_OVL0, "DDP");
  6574. ret += enable_clock(MT_CG_DISP0_DISP_COLOR, "DDP");
  6575. ret += enable_clock(MT_CG_DISP0_DISP_CCORR, "DDP");
  6576. ret += enable_clock(MT_CG_DISP0_DISP_AAL, "DDP");
  6577. ret += enable_clock(MT_CG_DISP0_DISP_GAMMA, "DDP");
  6578. ret += enable_clock(MT_CG_DISP0_DISP_DITHER, "DDP");
  6579. ret += enable_clock(MT_CG_DISP0_DISP_RDMA0, "DDP");
  6580. ret += enable_clock(MT_CG_PERI_DISP_PWM, "PWM");
  6581. /* ret += enable_clock(MT_CG_DISP0_MUTEX_32K , "Debug"); */
  6582. ret += enable_clock(MT_CG_DISP0_SMI_LARB0, "Debug");
  6583. ret += enable_clock(MT_CG_DISP0_SMI_COMMON, "Debug");
  6584. /* ret += enable_clock(MT_CG_DISP0_MUTEX_32K , "Debug2"); */
  6585. ret += enable_clock(MT_CG_DISP0_SMI_LARB0, "Debug2");
  6586. ret += enable_clock(MT_CG_DISP0_SMI_COMMON, "Debug2");
  6587. #else
  6588. ddp_clk_prepare(DISP_MTCMOS_CLK);
  6589. ret += ddp_clk_enable(DISP_MTCMOS_CLK);
  6590. ret += ddp_clk_enable(DISP1_DSI_ENGINE);
  6591. ret += ddp_clk_enable(DISP1_DSI_DIGITAL);
  6592. ret += ddp_clk_enable(DISP0_DISP_OVL0);
  6593. ret += ddp_clk_enable(DISP0_DISP_COLOR);
  6594. ret += ddp_clk_enable(DISP0_DISP_CCORR);
  6595. ret += ddp_clk_enable(DISP0_DISP_AAL);
  6596. ret += ddp_clk_enable(DISP0_DISP_GAMMA);
  6597. ret += ddp_clk_enable(DISP0_DISP_DITHER);
  6598. ret += ddp_clk_enable(DISP0_DISP_RDMA0);
  6599. ret += ddp_clk_enable(DISP_PWM);
  6600. /*ret += ddp_clk_enable(DISP0_MUTEX_32K); */
  6601. ret += ddp_clk_enable(DISP0_SMI_LARB0);
  6602. ret += ddp_clk_enable(DISP0_SMI_COMMON);
  6603. /*ret += ddp_clk_enable(DISP0_MUTEX_32K); */
  6604. ret += ddp_clk_enable(DISP0_SMI_LARB0);
  6605. ret += ddp_clk_enable(DISP0_SMI_COMMON);
  6606. #endif
  6607. }
  6608. _primary_path_unlock(__func__);
  6609. #endif
  6610. return ret;
  6611. }
  6612. int _set_backlight_by_cmdq(unsigned int level)
  6613. {
  6614. int ret = 0;
  6615. cmdqRecHandle cmdq_handle_backlight = NULL;
  6616. MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl, MMProfileFlagPulse, 1, 1);
  6617. ret = cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &cmdq_handle_backlight);
  6618. DISPCHECK("primary backlight, handle=%p\n", cmdq_handle_backlight);
  6619. if (ret != 0) {
  6620. DISPCHECK("fail to create primary cmdq handle for backlight\n");
  6621. return -1;
  6622. }
  6623. if (primary_display_is_video_mode()) {
  6624. MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl, MMProfileFlagPulse, 1, 2);
  6625. cmdqRecReset(cmdq_handle_backlight);
  6626. dpmgr_path_ioctl(pgc->dpmgr_handle, cmdq_handle_backlight, DDP_BACK_LIGHT,
  6627. (unsigned long *)&level);
  6628. _cmdq_flush_config_handle_mira(cmdq_handle_backlight, 1);
  6629. DISPCHECK("[BL]_set_backlight_by_cmdq ret=%d\n", ret);
  6630. } else {
  6631. MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl, MMProfileFlagPulse, 1, 3);
  6632. cmdqRecReset(cmdq_handle_backlight);
  6633. _cmdq_insert_wait_frame_done_token_mira(cmdq_handle_backlight);
  6634. cmdqRecClearEventToken(cmdq_handle_backlight, CMDQ_SYNC_TOKEN_CABC_EOF);
  6635. dpmgr_path_ioctl(pgc->dpmgr_handle, cmdq_handle_backlight, DDP_BACK_LIGHT,
  6636. (unsigned long *)&level);
  6637. cmdqRecSetEventToken(cmdq_handle_backlight, CMDQ_SYNC_TOKEN_CABC_EOF);
  6638. MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl, MMProfileFlagPulse, 1, 4);
  6639. _cmdq_flush_config_handle_mira(cmdq_handle_backlight, 1);
  6640. MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl, MMProfileFlagPulse, 1, 6);
  6641. DISPCHECK("[BL]_set_backlight_by_cmdq ret=%d\n", ret);
  6642. }
  6643. cmdqRecDestroy(cmdq_handle_backlight);
  6644. cmdq_handle_backlight = NULL;
  6645. MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl, MMProfileFlagPulse, 1, 5);
  6646. return ret;
  6647. }
  6648. int _set_backlight_by_cpu(unsigned int level)
  6649. {
  6650. int ret = 0;
  6651. MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl, MMProfileFlagPulse, 0, 1);
  6652. if (primary_display_is_video_mode()) {
  6653. disp_lcm_set_backlight(pgc->plcm, level);
  6654. } else {
  6655. DISPCHECK("[BL]display cmdq trigger loop stop[begin]\n");
  6656. _cmdq_stop_trigger_loop();
  6657. DISPCHECK("[BL]display cmdq trigger loop stop[end]\n");
  6658. if (dpmgr_path_is_busy(pgc->dpmgr_handle)) {
  6659. DISPCHECK("[BL]primary display path is busy\n");
  6660. ret = dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ * 1);
  6661. DISPCHECK("[BL]wait frame done ret:%d\n", ret);
  6662. }
  6663. DISPCHECK("[BL]stop dpmgr path[begin]\n");
  6664. dpmgr_path_stop(pgc->dpmgr_handle, CMDQ_DISABLE);
  6665. DISPCHECK("[BL]stop dpmgr path[end]\n");
  6666. if (dpmgr_path_is_busy(pgc->dpmgr_handle)) {
  6667. DISPCHECK("[BL]primary display path is busy after stop\n");
  6668. dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE,
  6669. HZ * 1);
  6670. DISPCHECK("[BL]wait frame done ret:%d\n", ret);
  6671. }
  6672. DISPCHECK("[BL]reset display path[begin]\n");
  6673. dpmgr_path_reset(pgc->dpmgr_handle, CMDQ_DISABLE);
  6674. DISPCHECK("[BL]reset display path[end]\n");
  6675. MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl, MMProfileFlagPulse, 0, 2);
  6676. disp_lcm_set_backlight(pgc->plcm, level);
  6677. MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl, MMProfileFlagPulse, 0, 3);
  6678. DISPCHECK("[BL]start dpmgr path[begin]\n");
  6679. dpmgr_path_start(pgc->dpmgr_handle, CMDQ_DISABLE);
  6680. DISPCHECK("[BL]start dpmgr path[end]\n");
  6681. DISPCHECK("[BL]start cmdq trigger loop[begin]\n");
  6682. _cmdq_start_trigger_loop();
  6683. DISPCHECK("[BL]start cmdq trigger loop[end]\n");
  6684. }
  6685. MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl, MMProfileFlagPulse, 0, 7);
  6686. return ret;
  6687. }
  6688. int primary_display_setbacklight(unsigned int level)
  6689. {
  6690. int ret = 0;
  6691. static unsigned int last_level;
  6692. DISPFUNC();
  6693. if (last_level == level)
  6694. return 0;
  6695. MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl, MMProfileFlagStart, 0, 0);
  6696. #ifdef DISP_SWITCH_DST_MODE
  6697. _primary_path_switch_dst_lock();
  6698. #endif
  6699. _primary_path_cmd_lock();
  6700. _primary_path_lock(__func__);
  6701. if (pgc->state == DISP_SLEPT) {
  6702. DISPCHECK("Sleep State set backlight invald\n");
  6703. } else {
  6704. disp_update_trigger_time();
  6705. if (primary_display_cmdq_enabled()) {
  6706. if (primary_display_is_video_mode()) {
  6707. MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl,
  6708. MMProfileFlagPulse, 0, 7);
  6709. disp_lcm_set_backlight(pgc->plcm, level);
  6710. } else {
  6711. #ifdef MTK_DISP_IDLE_LP
  6712. /* CMD mode need to exit top clock off idle mode */
  6713. _disp_primary_path_exit_idle("primary_display_setbacklight", 0);
  6714. #endif
  6715. _set_backlight_by_cmdq(level);
  6716. }
  6717. } else {
  6718. #ifdef MTK_DISP_IDLE_LP
  6719. if (primary_display_is_video_mode() == 0)
  6720. _disp_primary_path_exit_idle("primary_display_setbacklight", 0);
  6721. #endif
  6722. _set_backlight_by_cpu(level);
  6723. }
  6724. last_level = level;
  6725. }
  6726. #ifndef CONFIG_FPGA_EARLY_PORTING
  6727. #ifdef GPIO_LCM_LED_EN
  6728. if (0 == level)
  6729. mt_set_gpio_out(GPIO_LCM_LED_EN, GPIO_OUT_ZERO);
  6730. else
  6731. mt_set_gpio_out(GPIO_LCM_LED_EN, GPIO_OUT_ONE);
  6732. #endif
  6733. #endif
  6734. #if 0 /* check writed success? for test after CABC */
  6735. {
  6736. /* extern uint32_t DSI_dcs_read_lcm_reg_v2(DISP_MODULE_ENUM module, cmdqRecHandle cmdq,
  6737. uint8_t cmd, uint8_t *buffer, uint8_t buffer_size);
  6738. */
  6739. uint8_t buffer[2];
  6740. if (primary_display_is_video_mode())
  6741. dpmgr_path_ioctl(pgc->dpmgr_handle, NULL, DDP_STOP_VIDEO_MODE, NULL);
  6742. DSI_dcs_read_lcm_reg_v2(DISP_MODULE_DSI0, NULL, 0x51, buffer, 1);
  6743. pr_debug("[CABC check result 0x51 = 0x%x,0x%x]\n", buffer[0], buffer[1]);
  6744. dpmgr_path_start(pgc->dpmgr_handle, CMDQ_DISABLE);
  6745. if (primary_display_is_video_mode()) {
  6746. /* for video mode, we need to force trigger here */
  6747. /* for cmd mode, just set DPREC_EVENT_CMDQ_SET_EVENT_ALLOW when trigger loop start */
  6748. dpmgr_path_trigger(pgc->dpmgr_handle, NULL, CMDQ_DISABLE);
  6749. }
  6750. }
  6751. #endif
  6752. _primary_path_unlock(__func__);
  6753. _primary_path_cmd_unlock();
  6754. #ifdef DISP_SWITCH_DST_MODE
  6755. _primary_path_switch_dst_unlock();
  6756. #endif
  6757. MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl, MMProfileFlagEnd, 0, 0);
  6758. return ret;
  6759. }
  6760. int primary_display_set_cmd(int *lcm_cmd, unsigned int cmd_num)
  6761. {
  6762. int ret = 0;
  6763. DISPFUNC();
  6764. _primary_path_cmd_lock();
  6765. _primary_path_lock(__func__);
  6766. if (pgc->state == DISP_SLEPT) {
  6767. DISPCHECK("Sleep State set cmd invald\n");
  6768. } else {
  6769. if (primary_display_cmdq_enabled()) { /* cmdq */
  6770. int ret = 0;
  6771. cmdqRecHandle cmdq_handle_cmd = NULL;
  6772. ret = cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &cmdq_handle_cmd);
  6773. DISPCHECK("primary set cmd, handle=%p\n", cmdq_handle_cmd);
  6774. if (ret != 0) {
  6775. DISPCHECK("fail to create primary cmdq handle for cmd\n");
  6776. return -1;
  6777. }
  6778. if (primary_display_is_video_mode()) {
  6779. /* video mode */
  6780. cmdqRecReset(cmdq_handle_cmd);
  6781. disp_lcm_set_cmd(pgc->plcm, (void *)cmdq_handle_cmd, lcm_cmd,
  6782. cmd_num);
  6783. _cmdq_flush_config_handle_mira(cmdq_handle_cmd, 1);
  6784. DISPCHECK("[Display]_set_cmd_by_cmdq ret=%d\n", ret);
  6785. } else {
  6786. /* cmd mode */
  6787. cmdqRecReset(cmdq_handle_cmd);
  6788. _cmdq_insert_wait_frame_done_token_mira(cmdq_handle_cmd);
  6789. cmdqRecClearEventToken(cmdq_handle_cmd, CMDQ_SYNC_TOKEN_CABC_EOF);
  6790. disp_lcm_set_cmd(pgc->plcm, (void *)cmdq_handle_cmd, lcm_cmd,
  6791. cmd_num);
  6792. cmdqRecSetEventToken(cmdq_handle_cmd, CMDQ_SYNC_TOKEN_CABC_EOF);
  6793. _cmdq_flush_config_handle_mira(cmdq_handle_cmd, 1);
  6794. DISPCHECK("[Display]_set_cmd_by_cmdq ret=%d\n", ret);
  6795. }
  6796. cmdqRecDestroy(cmdq_handle_cmd);
  6797. cmdq_handle_cmd = NULL;
  6798. }
  6799. }
  6800. _primary_path_unlock(__func__);
  6801. _primary_path_cmd_unlock();
  6802. return ret;
  6803. }
  6804. #define LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL
  6805. /***********************/
  6806. /*****Legacy DISP API*****/
  6807. /***********************/
  6808. uint32_t DISP_GetScreenWidth(void)
  6809. {
  6810. return primary_display_get_width();
  6811. }
  6812. uint32_t DISP_GetScreenHeight(void)
  6813. {
  6814. return primary_display_get_height();
  6815. }
  6816. uint32_t DISP_GetActiveHeight(void)
  6817. {
  6818. if (pgc->plcm == NULL) {
  6819. DISPERR("lcm handle is null\n");
  6820. return 0;
  6821. }
  6822. if (pgc->plcm->params)
  6823. return pgc->plcm->params->physical_height;
  6824. DISPERR("lcm_params is null!\n");
  6825. return 0;
  6826. }
  6827. uint32_t DISP_GetActiveWidth(void)
  6828. {
  6829. if (pgc->plcm == NULL) {
  6830. DISPERR("lcm handle is null\n");
  6831. return 0;
  6832. }
  6833. if (pgc->plcm->params)
  6834. return pgc->plcm->params->physical_width;
  6835. DISPERR("lcm_params is null!\n");
  6836. return 0;
  6837. }
  6838. LCM_PARAMS *DISP_GetLcmPara(void)
  6839. {
  6840. if (pgc->plcm == NULL) {
  6841. DISPERR("lcm handle is null\n");
  6842. return NULL;
  6843. }
  6844. if (pgc->plcm->params)
  6845. return pgc->plcm->params;
  6846. else
  6847. return NULL;
  6848. }
  6849. LCM_DRIVER *DISP_GetLcmDrv(void)
  6850. {
  6851. if (pgc->plcm == NULL) {
  6852. DISPERR("lcm handle is null\n");
  6853. return NULL;
  6854. }
  6855. if (pgc->plcm->drv)
  6856. return pgc->plcm->drv;
  6857. else
  6858. return NULL;
  6859. }
  6860. int primary_display_capture_framebuffer_decouple(unsigned long pbuf, unsigned int format)
  6861. {
  6862. unsigned int i = 0;
  6863. int ret = 0;
  6864. disp_ddp_path_config *pconfig = NULL;
  6865. m4u_client_t *m4uClient = NULL;
  6866. unsigned int mva = 0;
  6867. unsigned long va = 0;
  6868. unsigned int mapped_size = 0;
  6869. unsigned int w_xres = primary_display_get_width();
  6870. unsigned int h_yres = primary_display_get_height();
  6871. unsigned int pixel_byte = primary_display_get_dc_bpp() / 8;/* bpp is either 32 or 16, can not be other value */
  6872. unsigned int pitch = 0;
  6873. int buffer_size = h_yres * w_xres * pixel_byte;
  6874. m4uClient = m4u_create_client();
  6875. if (m4uClient == NULL) {
  6876. DISPCHECK("primary capture:Fail to alloc m4uClient=0x%p\n", m4uClient);
  6877. ret = -1;
  6878. goto out;
  6879. }
  6880. /* mva = pgc->dc_buf[pgc->dc_buf_id]; */
  6881. pconfig = dpmgr_path_get_last_config(pgc->dpmgr_handle);
  6882. if (_is_decouple_mode(pgc->session_mode) && !_is_mirror_mode(pgc->session_mode)) {
  6883. w_xres = decouple_wdma_config.srcWidth;
  6884. h_yres = decouple_wdma_config.srcHeight;
  6885. pitch = decouple_wdma_config.dstPitch;
  6886. mva = decouple_wdma_config.dstAddress;
  6887. } else {
  6888. w_xres = pconfig->wdma_config.srcWidth;
  6889. h_yres = pconfig->wdma_config.srcHeight;
  6890. pitch = pconfig->wdma_config.dstPitch;
  6891. mva = pconfig->wdma_config.dstAddress;
  6892. }
  6893. buffer_size = h_yres * pitch;
  6894. ASSERT((pitch / 4) >= w_xres);
  6895. /* dpmgr_get_input_address(pgc->dpmgr_handle,&mva); */
  6896. m4u_mva_map_kernel(mva, buffer_size, &va, &mapped_size);
  6897. if (!va) {
  6898. DISPERR("map mva 0x%08x failed\n", mva);
  6899. goto out;
  6900. }
  6901. DISPMSG("map 0x%08x with %d bytes to 0x%08lx with %d bytes\n", mva, buffer_size, va,
  6902. mapped_size);
  6903. ret =
  6904. m4u_cache_sync(m4uClient, M4U_PORT_DISP_WDMA0, va, buffer_size, mva,
  6905. M4U_CACHE_FLUSH_ALL);
  6906. #if 1
  6907. {
  6908. unsigned int j = 0;
  6909. unsigned char tem_va[4];
  6910. unsigned long src_va = va;
  6911. for (i = 0; i < h_yres; i++) {
  6912. for (j = 0; j < w_xres; j++) {
  6913. memcpy((void *)tem_va, (void *)src_va, 4);
  6914. *(unsigned long *)(pbuf + (i * w_xres + j) * 4) = 0xFF000000 | (tem_va[0] << 16) |
  6915. (tem_va[1] << 8) | (tem_va[2]);
  6916. src_va += 4;
  6917. }
  6918. src_va += (pitch - w_xres * 4);
  6919. }
  6920. }
  6921. #else
  6922. memcpy(pbuf, va, mapped_size);
  6923. #endif
  6924. out:
  6925. if (mapped_size)
  6926. m4u_mva_unmap_kernel(mva, mapped_size, va);
  6927. if (m4uClient != NULL)
  6928. m4u_destroy_client(m4uClient);
  6929. DISPMSG("primary capture: end\n");
  6930. return ret;
  6931. }
  6932. int primary_display_capture_framebuffer_ovl(unsigned long pbuf, unsigned int format)
  6933. {
  6934. int ret = 0;
  6935. cmdqRecHandle cmdq_handle = NULL;
  6936. cmdqRecHandle cmdq_wait_handle = NULL;
  6937. disp_ddp_path_config *pconfig = NULL;
  6938. m4u_client_t *m4uClient = NULL;
  6939. unsigned int mva = 0;
  6940. unsigned int w_xres = primary_display_get_width();
  6941. unsigned int h_yres = primary_display_get_height();
  6942. unsigned int pixel_byte = primary_display_get_dc_bpp() / 8; /* bpp is either 32 or 16, can not be other value */
  6943. int buffer_size = h_yres * w_xres * pixel_byte;
  6944. DISPMSG("primary capture: begin\n");
  6945. disp_sw_mutex_lock(&(pgc->capture_lock));
  6946. _primary_path_lock(__func__);
  6947. if (pgc->state == DISP_SLEPT) {
  6948. /*memset_io((void *)pbuf, 0, buffer_size);*/
  6949. DISPMSG("primary capture:fill black for sleep\n");
  6950. goto out;
  6951. }
  6952. if (!primary_display_cmdq_enabled()) {
  6953. /*memset_io((void *)pbuf, 0, buffer_size);*/
  6954. DISPMSG("primary capture:fill black to cmdq disable\n");
  6955. goto out;
  6956. }
  6957. if (_is_decouple_mode(pgc->session_mode) || _is_mirror_mode(pgc->session_mode)) {
  6958. primary_display_capture_framebuffer_decouple(pbuf, format);
  6959. /*memset_io((void *)pbuf, 0, buffer_size);*/
  6960. DISPMSG("primary capture: fill black for decouple & mirror mode End\n");
  6961. goto out;
  6962. }
  6963. m4uClient = m4u_create_client();
  6964. if (m4uClient == NULL) {
  6965. DISPCHECK("primary capture:Fail to alloc m4uClient=0x%p\n", m4uClient);
  6966. ret = -1;
  6967. goto out;
  6968. }
  6969. ret = m4u_alloc_mva(m4uClient, M4U_PORT_DISP_WDMA0, pbuf, NULL, buffer_size,
  6970. M4U_PROT_READ | M4U_PROT_WRITE, 0, (unsigned int *)&mva);
  6971. if (ret != 0) {
  6972. DISPCHECK("primary capture:Fail to allocate mva\n");
  6973. ret = -1;
  6974. goto out;
  6975. }
  6976. ret = m4u_cache_sync(m4uClient, M4U_PORT_DISP_WDMA0, pbuf, buffer_size, mva,
  6977. M4U_CACHE_FLUSH_BY_RANGE);
  6978. if (ret != 0) {
  6979. DISPCHECK("primary capture:Fail to cach sync\n");
  6980. ret = -1;
  6981. goto out;
  6982. }
  6983. if (primary_display_cmdq_enabled()) {
  6984. /* create config thread */
  6985. ret = cmdqRecCreate(CMDQ_SCENARIO_PRIMARY_DISP, &cmdq_handle);
  6986. if (ret != 0) {
  6987. DISPCHECK("primary capture:Fail to create primary cmdq handle for capture\n");
  6988. ret = -1;
  6989. goto out;
  6990. }
  6991. cmdqRecReset(cmdq_handle);
  6992. /* create wait thread */
  6993. ret = cmdqRecCreate(CMDQ_SCENARIO_DISP_SCREEN_CAPTURE, &cmdq_wait_handle);
  6994. if (ret != 0) {
  6995. DISPCHECK("primary capture:Fail to create primary cmdq wait handle for capture\n");
  6996. ret = -1;
  6997. goto out;
  6998. }
  6999. cmdqRecReset(cmdq_wait_handle);
  7000. /* configure config thread */
  7001. _cmdq_insert_wait_frame_done_token_mira(cmdq_handle);
  7002. dpmgr_path_memout_clock(pgc->dpmgr_handle, 1);
  7003. pconfig = dpmgr_path_get_last_config(pgc->dpmgr_handle);
  7004. pconfig->wdma_dirty = 1;
  7005. pconfig->wdma_config.dstAddress = mva;
  7006. pconfig->wdma_config.srcHeight = h_yres;
  7007. pconfig->wdma_config.srcWidth = w_xres;
  7008. pconfig->wdma_config.clipX = 0;
  7009. pconfig->wdma_config.clipY = 0;
  7010. pconfig->wdma_config.clipHeight = h_yres;
  7011. pconfig->wdma_config.clipWidth = w_xres;
  7012. pconfig->wdma_config.outputFormat = format;
  7013. pconfig->wdma_config.useSpecifiedAlpha = 1;
  7014. pconfig->wdma_config.alpha = 0xFF;
  7015. pconfig->wdma_config.dstPitch = w_xres * DP_COLOR_BITS_PER_PIXEL(format) / 8;
  7016. dpmgr_path_add_memout(pgc->dpmgr_handle, ENGINE_OVL0, cmdq_handle);
  7017. #if 0 /* do not have to call enable_cascade here, dpmgr_path_add_memout() will add ovl1 if necessary */
  7018. if (ovl_get_status() == DDP_OVL1_STATUS_IDLE || ovl_get_status() == DDP_OVL1_STATUS_PRIMARY) {
  7019. DISPMSG("dpmgr_path_enable_cascade called!\n");
  7020. dpmgr_path_enable_cascade(pgc->dpmgr_handle, cmdq_handle);
  7021. if (ovl_get_status() != DDP_OVL1_STATUS_PRIMARY)
  7022. pconfig->ovl_dirty = 1;
  7023. }
  7024. #endif
  7025. ret = dpmgr_path_config(pgc->dpmgr_handle, pconfig, cmdq_handle);
  7026. pconfig->wdma_dirty = 0;
  7027. _cmdq_set_config_handle_dirty_mira(cmdq_handle);
  7028. _cmdq_flush_config_handle_mira(cmdq_handle, 0);
  7029. DISPMSG("primary capture:Flush add memout mva(0x%x)\n", mva);
  7030. /* primary_display_diagnose(); */
  7031. /* wait wdma0 sof */
  7032. cmdqRecWait(cmdq_wait_handle, CMDQ_EVENT_DISP_WDMA0_SOF);
  7033. cmdqRecFlush(cmdq_wait_handle);
  7034. DISPMSG("primary capture:Flush wait wdma sof\n");
  7035. cmdqRecReset(cmdq_handle);
  7036. _cmdq_insert_wait_frame_done_token_mira(cmdq_handle);
  7037. dpmgr_path_remove_memout(pgc->dpmgr_handle, cmdq_handle);
  7038. cmdqRecClearEventToken(cmdq_handle, CMDQ_EVENT_DISP_WDMA0_SOF);
  7039. _cmdq_set_config_handle_dirty_mira(cmdq_handle);
  7040. /* flush remove memory to cmdq */
  7041. _cmdq_flush_config_handle_mira(cmdq_handle, 1);
  7042. DISPMSG("primary capture: Flush remove memout\n");
  7043. dpmgr_path_memout_clock(pgc->dpmgr_handle, 0);
  7044. }
  7045. out:
  7046. cmdqRecDestroy(cmdq_handle);
  7047. cmdqRecDestroy(cmdq_wait_handle);
  7048. if (mva > 0)
  7049. m4u_dealloc_mva(m4uClient, M4U_PORT_DISP_WDMA0, mva);
  7050. if (m4uClient != 0)
  7051. m4u_destroy_client(m4uClient);
  7052. _primary_path_unlock(__func__);
  7053. disp_sw_mutex_unlock(&(pgc->capture_lock));
  7054. DISPMSG("primary capture: end\n");
  7055. return ret;
  7056. }
  7057. int primary_display_capture_framebuffer(unsigned long pbuf)
  7058. {
  7059. #if 1
  7060. unsigned int fb_layer_id = primary_display_get_option("FB_LAYER");
  7061. unsigned int w_xres = primary_display_get_width();
  7062. unsigned int h_yres = primary_display_get_height();
  7063. /* bpp is either 32 or 16, can not be other value */
  7064. unsigned int pixel_bpp = primary_display_get_dc_bpp() / 8;
  7065. unsigned int w_fb = ALIGN_TO(w_xres, MTK_FB_ALIGNMENT);
  7066. unsigned int fbsize = w_fb * h_yres * pixel_bpp; /* frame buffer size */
  7067. unsigned long fbaddress = dpmgr_path_get_last_config(pgc->dpmgr_handle)->ovl_config[fb_layer_id].addr;
  7068. unsigned long fbv = 0;
  7069. unsigned int i = 0;
  7070. unsigned long ttt = 0;
  7071. DISPMSG("w_res=%d, h_yres=%d, pixel_bpp=%d, w_fb=%d, fbsize=%d, fbaddress=0x%lx\n",
  7072. w_xres, h_yres, pixel_bpp, w_fb, fbsize, fbaddress);
  7073. fbv = (unsigned long)ioremap(fbaddress, fbsize);
  7074. DISPMSG("w_xres = %d, h_yres = %d, w_fb = %d, pixel_bpp = %d, fbsize = %d, fbaddress = 0x%lx\n",
  7075. w_xres, h_yres, w_fb, pixel_bpp, fbsize, fbaddress);
  7076. if (!fbv) {
  7077. DISPMSG("[FB Driver], Unable to allocate memory for frame buffer: address=0x%lx, size=0x%08x\n",
  7078. fbaddress, fbsize);
  7079. return -1;
  7080. }
  7081. ttt = get_current_time_us();
  7082. for (i = 0; i < h_yres; i++) {
  7083. /* DISPMSG("i=%d, dst=0x%08x, src=%08x\n",
  7084. i, (pbuf + i * w_xres * pixel_bpp), (fbv + i * w_fb * pixel_bpp));
  7085. */
  7086. memcpy((void *)(pbuf + i * w_xres * pixel_bpp),
  7087. (void *)(fbv + i * w_fb * pixel_bpp), w_xres * pixel_bpp);
  7088. }
  7089. DISPMSG("capture framebuffer cost %ld us\n", get_current_time_us() - ttt);
  7090. iounmap((void *)fbv);
  7091. #endif
  7092. return -1;
  7093. }
  7094. uint32_t DISP_GetPanelBPP(void)
  7095. {
  7096. #if 0
  7097. PANEL_COLOR_FORMAT fmt;
  7098. disp_drv_init_context();
  7099. if (disp_if_drv->get_panel_color_format == NULL)
  7100. return DISP_STATUS_NOT_IMPLEMENTED;
  7101. fmt = disp_if_drv->get_panel_color_format();
  7102. switch (fmt) {
  7103. case PANEL_COLOR_FORMAT_RGB332:
  7104. return 8;
  7105. case PANEL_COLOR_FORMAT_RGB444:
  7106. return 12;
  7107. case PANEL_COLOR_FORMAT_RGB565:
  7108. return 16;
  7109. case PANEL_COLOR_FORMAT_RGB666:
  7110. return 18;
  7111. case PANEL_COLOR_FORMAT_RGB888:
  7112. return 24;
  7113. default:
  7114. return 0;
  7115. }
  7116. #else
  7117. return 0; /* avoid build warning */
  7118. #endif
  7119. }
  7120. static uint32_t disp_fb_bpp = 32;
  7121. static uint32_t disp_fb_pages = 3;
  7122. uint32_t DISP_GetScreenBpp(void)
  7123. {
  7124. return disp_fb_bpp;
  7125. }
  7126. uint32_t DISP_GetPages(void)
  7127. {
  7128. return disp_fb_pages;
  7129. }
  7130. uint32_t DISP_GetFBRamSize(void)
  7131. {
  7132. return ALIGN_TO(DISP_GetScreenWidth(), MTK_FB_ALIGNMENT) * DISP_GetScreenHeight() *
  7133. ((DISP_GetScreenBpp() + 7) >> 3) * DISP_GetPages();
  7134. }
  7135. uint32_t DISP_GetVRamSize(void)
  7136. {
  7137. #if 0
  7138. /* Use a local static variable to cache the calculated vram size */
  7139. /* */
  7140. static uint32_t vramSize;
  7141. if (0 == vramSize) {
  7142. disp_drv_init_context();
  7143. /* /get framebuffer size */
  7144. vramSize = DISP_GetFBRamSize();
  7145. /* /get DXI working buffer size */
  7146. vramSize += disp_if_drv->get_working_buffer_size();
  7147. /* get assertion layer buffer size */
  7148. vramSize += DAL_GetLayerSize();
  7149. /* Align vramSize to 1MB */
  7150. /* */
  7151. vramSize = ALIGN_TO_POW_OF_2(vramSize, 0x100000);
  7152. DISP_LOG("DISP_GetVRamSize: %u bytes\n", vramSize);
  7153. }
  7154. return vramSize;
  7155. #else
  7156. return 0; /* avoid build warning */
  7157. #endif
  7158. }
  7159. uint32_t DISP_GetVRamSizeBoot(char *cmdline)
  7160. {
  7161. #ifdef CONFIG_OF
  7162. /* extern unsigned int vramsize; */
  7163. /* extern int _parse_tag_videolfb(void); */
  7164. _parse_tag_videolfb();
  7165. if (vramsize == 0)
  7166. vramsize = 0x3000000;
  7167. /* not necessary */
  7168. /* DISPCHECK("[DT]display vram size = 0x%08x|%d\n", vramsize, vramsize); */
  7169. return vramsize;
  7170. #else
  7171. int ret = 0;
  7172. char *p = NULL;
  7173. uint32_t vramSize = 0;
  7174. DISPMSG("%s, cmdline=%s\n", __func__, cmdline);
  7175. p = strstr(cmdline, "vram=");
  7176. if (p == NULL) {
  7177. vramSize = 0x3000000;
  7178. DISPERR("[FB driver]can not get vram size from lk\n");
  7179. } else {
  7180. p += 5;
  7181. ret = kstrtol(p, 10, &vramSize);
  7182. if (ret)
  7183. pr_err("DISP/%s: errno %d\n", __func__, ret);
  7184. if (0 == vramSize)
  7185. vramSize = 0x3000000;
  7186. }
  7187. DISPCHECK("display vram size = 0x%08x|%d\n", vramSize, vramSize);
  7188. return vramSize;
  7189. #endif
  7190. }
  7191. struct sg_table table;
  7192. int disp_hal_allocate_framebuffer(phys_addr_t pa_start, phys_addr_t pa_end, unsigned long *va,
  7193. unsigned long *mva)
  7194. {
  7195. #ifndef MTKFB_NO_M4U
  7196. int ret = 0;
  7197. #endif
  7198. *va = (unsigned long)ioremap_nocache(pa_start, pa_end - pa_start + 1);
  7199. /* printk("disphal_allocate_fb, pa=%p, va=0x%lx\n", &pa_start, *va); */
  7200. /* if (_get_init_setting("M4U")) */
  7201. /* xuecheng, m4u not enabled now */
  7202. #ifndef MTKFB_NO_M4U
  7203. if (1) {
  7204. m4u_client_t *client;
  7205. struct sg_table *sg_table = &table;
  7206. sg_alloc_table(sg_table, 1, GFP_KERNEL);
  7207. sg_dma_address(sg_table->sgl) = pa_start;
  7208. sg_dma_len(sg_table->sgl) = (pa_end - pa_start + 1);
  7209. client = m4u_create_client();
  7210. if (IS_ERR_OR_NULL(client))
  7211. DISPMSG("create client fail!\n");
  7212. *mva = pa_start & 0xffffffffULL;
  7213. ret = m4u_alloc_mva(client, M4U_PORT_DISP_OVL0, 0, sg_table, (pa_end - pa_start + 1),
  7214. M4U_PROT_READ | M4U_PROT_WRITE, M4U_FLAGS_FIX_MVA,
  7215. (unsigned int *)mva);
  7216. /* m4u_alloc_mva(M4U_PORT_DISP_OVL0, pa_start, (pa_end - pa_start + 1), 0, 0, mva); */
  7217. if (ret)
  7218. DISPMSG("m4u_alloc_mva returns fail: %d\n", ret);
  7219. /* printk("[DISPHAL] FB MVA is 0x%lx PA is %p\n", *mva, &pa_start);*/
  7220. } else
  7221. #endif
  7222. {
  7223. *mva = pa_start & 0xffffffffULL;
  7224. }
  7225. return 0;
  7226. }
  7227. int primary_display_remap_irq_event_map(void)
  7228. {
  7229. return 0; /* avoid build warning. */
  7230. }
  7231. unsigned int primary_display_get_option(const char *option)
  7232. {
  7233. if (!strcmp(option, "FB_LAYER"))
  7234. return 0;
  7235. if (!strcmp(option, "ASSERT_LAYER")) {
  7236. #ifdef OVL_CASCADE_SUPPORT
  7237. if (ovl_get_status() == DDP_OVL1_STATUS_PRIMARY
  7238. || ovl_get_status() == DDP_OVL1_STATUS_IDLE)
  7239. return OVL_LAYER_NUM - 1;
  7240. else
  7241. return OVL_LAYER_NUM - 4 - 1;
  7242. #else
  7243. return OVL_LAYER_NUM - 1;
  7244. #endif
  7245. }
  7246. if (!strcmp(option, "M4U_ENABLE"))
  7247. return 1;
  7248. ASSERT(0);
  7249. return 0; /* avoid build warning */
  7250. }
  7251. int primary_display_get_debug_info(char *buf)
  7252. {
  7253. /* resolution */
  7254. /* cmd/video mode */
  7255. /* display path */
  7256. /* dsi data rate/lane number/state */
  7257. /* primary path trigger count */
  7258. /* frame done count */
  7259. /* suspend/resume count */
  7260. /* current fps 10s/5s/1s */
  7261. /* error count and message */
  7262. /* current state of each module on the path */
  7263. return 0; /* avoid build warning */
  7264. }
  7265. #include "ddp_reg.h"
  7266. #define IS_READY(x) ((x)?"READY\t":"Not READY")
  7267. #define IS_VALID(x) ((x)?"VALID\t":"Not VALID")
  7268. #define READY_BIT0(x) ((DISP_REG_GET(DISPSYS_CONFIG_BASE + 0x8a0) & (1 << x)))
  7269. #define VALID_BIT0(x) ((DISP_REG_GET(DISPSYS_CONFIG_BASE + 0x8a4) & (1 << x)))
  7270. #define READY_BIT1(x) ((DISP_REG_GET(DISPSYS_CONFIG_BASE + 0x8a8) & (1 << x)))
  7271. #define VALID_BIT1(x) ((DISP_REG_GET(DISPSYS_CONFIG_BASE + 0x8ac) & (1 << x)))
  7272. int primary_display_check_path(char *stringbuf, int buf_len)
  7273. {
  7274. return 0; /* status will print in config dump. */
  7275. #if 0
  7276. int len = 0;
  7277. DISPMSG("primary_display_check_path() check signal status:\n");
  7278. if (stringbuf) {
  7279. len +=
  7280. scnprintf(stringbuf + len, buf_len - len,
  7281. "|--------------------------------------------------------------------------------------|\n");
  7282. len +=
  7283. scnprintf(stringbuf + len, buf_len - len,
  7284. "READY0=0x%08x, READY1=0x%08x, VALID0=0x%08x, VALID1=0x%08x\n",
  7285. DISP_REG_GET(DISPSYS_CONFIG_BASE + 0x8a0),
  7286. DISP_REG_GET(DISPSYS_CONFIG_BASE + 0x8a4),
  7287. DISP_REG_GET(DISPSYS_CONFIG_BASE + 0x8a8),
  7288. DISP_REG_GET(DISPSYS_CONFIG_BASE + 0x8ac));
  7289. len +=
  7290. scnprintf(stringbuf + len, buf_len - len, "OVL0\t\t\t%s\t%s\n",
  7291. IS_READY(READY_BIT0(DDP_SIGNAL_OVL0__OVL0_MOUT)),
  7292. IS_VALID(READY_BIT0(DDP_SIGNAL_OVL0__OVL0_MOUT)));
  7293. len +=
  7294. scnprintf(stringbuf + len, buf_len - len, "OVL0_MOUT:\t\t%s\t%s\n",
  7295. IS_READY(READY_BIT1(DDP_SIGNAL_OVL0_MOUT0__COLOR_SIN1)),
  7296. IS_VALID(READY_BIT1(DDP_SIGNAL_OVL0_MOUT0__COLOR_SIN1)));
  7297. len +=
  7298. scnprintf(stringbuf + len, buf_len - len, "COLOR0_SEL:\t\t%s\t%s\n",
  7299. IS_READY(READY_BIT0(DDP_SIGNAL_COLOR_SEL__COLOR)),
  7300. IS_VALID(READY_BIT0(DDP_SIGNAL_COLOR_SEL__COLOR)));
  7301. len +=
  7302. scnprintf(stringbuf + len, buf_len - len, "COLOR0:\t\t\t%s\t%s\n",
  7303. IS_READY(READY_BIT0(DDP_SIGNAL_COLOR__CCORR)),
  7304. IS_VALID(READY_BIT0(DDP_SIGNAL_COLOR__CCORR)));
  7305. len +=
  7306. scnprintf(stringbuf + len, buf_len - len, "CCORR:\t\t%s\t%s\n",
  7307. IS_READY(READY_BIT0(DDP_SIGNAL_CCORR__AAL)),
  7308. IS_VALID(READY_BIT0(DDP_SIGNAL_CCORR__AAL)));
  7309. len +=
  7310. scnprintf(stringbuf + len, buf_len - len, "AAL0:\t\t\t%s\t%s\n",
  7311. IS_READY(READY_BIT0(DDP_SIGNAL_AAL__GAMMA)),
  7312. IS_VALID(READY_BIT0(DDP_SIGNAL_AAL__GAMMA)));
  7313. len +=
  7314. scnprintf(stringbuf + len, buf_len - len, "GAMMA:\t\t\t%s\t%s\n",
  7315. IS_READY(READY_BIT1(DDP_SIGNAL_GAMMA__DITHER)),
  7316. IS_VALID(READY_BIT1(DDP_SIGNAL_GAMMA__DITHER)));
  7317. len +=
  7318. scnprintf(stringbuf + len, buf_len - len, "DITHER:\t\t\t%s\t%s\n",
  7319. IS_READY(READY_BIT1(DDP_SIGNAL_DITHER__DITHER_MOUT)),
  7320. IS_VALID(READY_BIT1(DDP_SIGNAL_DITHER__DITHER_MOUT)));
  7321. len +=
  7322. scnprintf(stringbuf + len, buf_len - len, "DITHER_MOUT:\t\t%s\t%s\n",
  7323. IS_READY(READY_BIT1(DDP_SIGNAL_DITHER_MOUT0__RDMA0)),
  7324. IS_VALID(READY_BIT1(DDP_SIGNAL_DITHER_MOUT0__RDMA0)));
  7325. len +=
  7326. scnprintf(stringbuf + len, buf_len - len, "RDMA0:\t\t\t%s\t%s\n",
  7327. IS_READY(READY_BIT1(DDP_SIGNAL_RDMA0__RDMA0_SOUT)),
  7328. IS_VALID(READY_BIT1(DDP_SIGNAL_RDMA0__RDMA0_SOUT)));
  7329. len +=
  7330. scnprintf(stringbuf + len, buf_len - len, "RDMA0_SOUT:\t\t%s\t%s\n",
  7331. IS_READY(READY_BIT1(DDP_SIGNAL_RDMA0_SOUT0__UFOE_SIN0)),
  7332. IS_VALID(READY_BIT1(DDP_SIGNAL_RDMA0_SOUT0__UFOE_SIN0)));
  7333. len +=
  7334. scnprintf(stringbuf + len, buf_len - len, "UFOE_SEL:\t\t%s\t%s\n",
  7335. IS_READY(READY_BIT0(DDP_SIGNAL_UFOE_SEL__UFOE)),
  7336. IS_VALID(READY_BIT0(DDP_SIGNAL_UFOE_SEL__UFOE)));
  7337. len +=
  7338. scnprintf(stringbuf + len, buf_len - len, "UFOE:\t\t\t%s\t%s\n",
  7339. IS_READY(READY_BIT0(DDP_SIGNAL_UFOE__UFOE_MOUT)),
  7340. IS_VALID(READY_BIT0(DDP_SIGNAL_UFOE__UFOE_MOUT)));
  7341. len +=
  7342. scnprintf(stringbuf + len, buf_len - len, "UFOE_MOUT:\t\t%s\t%s\n",
  7343. IS_READY(READY_BIT0(DDP_SIGNAL_UFOE_MOUT0__DSI0_SIN0)),
  7344. IS_VALID(READY_BIT0(DDP_SIGNAL_UFOE_MOUT0__DSI0_SIN0)));
  7345. len +=
  7346. scnprintf(stringbuf + len, buf_len - len, "DSI0_SEL:\t\t%s\t%s\n",
  7347. IS_READY(READY_BIT1(DDP_SIGNAL_DIS0_SEL__DSI0)),
  7348. IS_VALID(READY_BIT1(DDP_SIGNAL_DIS0_SEL__DSI0)));
  7349. } else {
  7350. DISPMSG
  7351. ("|--------------------------------------------------------------------------------------|\n");
  7352. DISPMSG("READY0=0x%08x, READY1=0x%08x, VALID0=0x%08x, VALID1=0x%08x\n",
  7353. DISP_REG_GET(DISPSYS_CONFIG_BASE + 0x8a0),
  7354. DISP_REG_GET(DISPSYS_CONFIG_BASE + 0x8a4),
  7355. DISP_REG_GET(DISPSYS_CONFIG_BASE + 0x8a8),
  7356. DISP_REG_GET(DISPSYS_CONFIG_BASE + 0x8ac));
  7357. DISPMSG("OVL0\t\t\t%s\t%s\n", IS_READY(READY_BIT0(DDP_SIGNAL_OVL0__OVL0_MOUT)),
  7358. IS_VALID(READY_BIT0(DDP_SIGNAL_OVL0__OVL0_MOUT)));
  7359. DISPMSG("OVL0_MOUT:\t\t%s\t%s\n",
  7360. IS_READY(READY_BIT1(DDP_SIGNAL_OVL0_MOUT0__COLOR_SIN1)),
  7361. IS_VALID(READY_BIT1(DDP_SIGNAL_OVL0_MOUT0__COLOR_SIN1)));
  7362. DISPMSG("COLOR0_SEL:\t\t%s\t%s\n",
  7363. IS_READY(READY_BIT0(DDP_SIGNAL_COLOR_SEL__COLOR)),
  7364. IS_VALID(READY_BIT0(DDP_SIGNAL_COLOR_SEL__COLOR)));
  7365. DISPMSG("COLOR0:\t\t\t%s\t%s\n", IS_READY(READY_BIT0(DDP_SIGNAL_COLOR__CCORR)),
  7366. IS_VALID(READY_BIT0(DDP_SIGNAL_COLOR__CCORR)));
  7367. DISPMSG("CCORR:\t\t%s\t%s\n", IS_READY(READY_BIT0(DDP_SIGNAL_CCORR__AAL)),
  7368. IS_VALID(READY_BIT0(DDP_SIGNAL_CCORR__AAL)));
  7369. DISPMSG("AAL0:\t\t\t%s\t%s\n", IS_READY(READY_BIT0(DDP_SIGNAL_AAL__GAMMA)),
  7370. IS_VALID(READY_BIT0(DDP_SIGNAL_AAL__GAMMA)));
  7371. DISPMSG("GAMMA:\t\t\t%s\t%s\n", IS_READY(READY_BIT1(DDP_SIGNAL_GAMMA__DITHER)),
  7372. IS_VALID(READY_BIT1(DDP_SIGNAL_GAMMA__DITHER)));
  7373. DISPMSG("DITHER:\t\t\t%s\t%s\n",
  7374. IS_READY(READY_BIT1(DDP_SIGNAL_DITHER__DITHER_MOUT)),
  7375. IS_VALID(READY_BIT1(DDP_SIGNAL_DITHER__DITHER_MOUT)));
  7376. DISPMSG("DITHER_MOUT:\t\t%s\t%s\n",
  7377. IS_READY(READY_BIT1(DDP_SIGNAL_DITHER_MOUT0__RDMA0)),
  7378. IS_VALID(READY_BIT1(DDP_SIGNAL_DITHER_MOUT0__RDMA0)));
  7379. DISPMSG("RDMA0:\t\t\t%s\t%s\n", IS_READY(READY_BIT1(DDP_SIGNAL_RDMA0__RDMA0_SOUT)),
  7380. IS_VALID(READY_BIT1(DDP_SIGNAL_RDMA0__RDMA0_SOUT)));
  7381. DISPMSG("RDMA0_SOUT:\t\t%s\t%s\n",
  7382. IS_READY(READY_BIT1(DDP_SIGNAL_RDMA0_SOUT0__UFOE_SIN0)),
  7383. IS_VALID(READY_BIT1(DDP_SIGNAL_RDMA0_SOUT0__UFOE_SIN0)));
  7384. DISPMSG("UFOE_SEL:\t\t%s\t%s\n", IS_READY(READY_BIT0(DDP_SIGNAL_UFOE_SEL__UFOE)),
  7385. IS_VALID(READY_BIT0(DDP_SIGNAL_UFOE_SEL__UFOE)));
  7386. DISPMSG("UFOE:\t\t\t%s\t%s\n", IS_READY(READY_BIT0(DDP_SIGNAL_UFOE__UFOE_MOUT)),
  7387. IS_VALID(READY_BIT0(DDP_SIGNAL_UFOE__UFOE_MOUT)));
  7388. DISPMSG("UFOE_MOUT:\t\t%s\t%s\n",
  7389. IS_READY(READY_BIT0(DDP_SIGNAL_UFOE_MOUT0__DSI0_SIN0)),
  7390. IS_VALID(READY_BIT0(DDP_SIGNAL_UFOE_MOUT0__DSI0_SIN0)));
  7391. DISPMSG("DSI0_SEL:\t\t%s\t%s\n", IS_READY(READY_BIT1(DDP_SIGNAL_DIS0_SEL__DSI0)),
  7392. IS_VALID(READY_BIT1(DDP_SIGNAL_DIS0_SEL__DSI0)));
  7393. }
  7394. return len;
  7395. #endif
  7396. }
  7397. int primary_display_lcm_ATA(void)
  7398. {
  7399. DISP_STATUS ret = DISP_STATUS_OK;
  7400. DISPFUNC();
  7401. _primary_path_lock(__func__);
  7402. if (pgc->state == 0) {
  7403. DISPCHECK("ATA_LCM, primary display path is already sleep, skip\n");
  7404. goto done;
  7405. }
  7406. DISPCHECK("[ATA_LCM]primary display path stop[begin]\n");
  7407. if (primary_display_is_video_mode())
  7408. dpmgr_path_ioctl(pgc->dpmgr_handle, NULL, DDP_STOP_VIDEO_MODE, NULL);
  7409. DISPCHECK("[ATA_LCM]primary display path stop[end]\n");
  7410. ret = disp_lcm_ATA(pgc->plcm);
  7411. dpmgr_path_start(pgc->dpmgr_handle, CMDQ_DISABLE);
  7412. /* for video mode, we need to force trigger here
  7413. * for cmd mode, just set DPREC_EVENT_CMDQ_SET_EVENT_ALLOW when trigger loop start
  7414. */
  7415. if (primary_display_is_video_mode())
  7416. dpmgr_path_trigger(pgc->dpmgr_handle, NULL, CMDQ_DISABLE);
  7417. done:
  7418. _primary_path_unlock(__func__);
  7419. return ret;
  7420. }
  7421. int fbconfig_get_esd_check_test(uint32_t dsi_id, uint32_t cmd, uint8_t *buffer, uint32_t num)
  7422. {
  7423. int ret = 0;
  7424. /* extern int fbconfig_get_esd_check(DSI_INDEX dsi_id, uint32_t cmd, uint8_t *buffer, uint32_t num); */
  7425. _primary_path_lock(__func__);
  7426. if (pgc->state == DISP_SLEPT) {
  7427. DISPCHECK("[ESD]primary display path is slept?? -- skip esd check\n");
  7428. _primary_path_unlock(__func__);
  7429. goto done;
  7430. }
  7431. /* primary_display_esd_check_enable(0); */
  7432. /* / 1: stop path */
  7433. _cmdq_stop_trigger_loop();
  7434. if (dpmgr_path_is_busy(pgc->dpmgr_handle))
  7435. DISPCHECK("[ESD]wait frame done ret:%d\n", ret);
  7436. dpmgr_path_stop(pgc->dpmgr_handle, CMDQ_DISABLE);
  7437. DISPCHECK("[ESD]stop dpmgr path[end]\n");
  7438. if (dpmgr_path_is_busy(pgc->dpmgr_handle))
  7439. DISPCHECK("[ESD]wait frame done ret:%d\n", ret);
  7440. /* dpmgr_path_reset(pgc->dpmgr_handle, CMDQ_DISABLE); */
  7441. ret = fbconfig_get_esd_check(dsi_id, cmd, buffer, num);
  7442. dpmgr_path_start(pgc->dpmgr_handle, CMDQ_DISABLE);
  7443. DISPCHECK("[ESD]start dpmgr path[end]\n");
  7444. if (primary_display_is_video_mode()) {
  7445. /* for video mode, we need to force trigger here */
  7446. /* for cmd mode, just set DPREC_EVENT_CMDQ_SET_EVENT_ALLOW when trigger loop start */
  7447. dpmgr_path_trigger(pgc->dpmgr_handle, NULL, CMDQ_DISABLE);
  7448. }
  7449. _cmdq_start_trigger_loop();
  7450. DISPCHECK("[ESD]start cmdq trigger loop[end]\n");
  7451. _primary_path_unlock(__func__);
  7452. done:
  7453. return ret;
  7454. }
  7455. int Panel_Master_dsi_config_entry(const char *name, void *config_value)
  7456. {
  7457. int ret = 0;
  7458. int force_trigger_path = 0;
  7459. uint32_t *config_dsi = (uint32_t *)config_value;
  7460. LCM_PARAMS *lcm_param = NULL;
  7461. LCM_DRIVER *pLcm_drv = NULL;
  7462. int esd_check_backup = 0;
  7463. DISPFUNC();
  7464. pLcm_drv = DISP_GetLcmDrv();
  7465. esd_check_backup = atomic_read(&esd_check_task_wakeup);
  7466. if (!strcmp(name, "DRIVER_IC_RESET") || !strcmp(name, "PM_DDIC_CONFIG")) {
  7467. primary_display_esd_check_enable(0);
  7468. msleep(2500);
  7469. }
  7470. _primary_path_lock(__func__);
  7471. lcm_param = disp_lcm_get_params(pgc->plcm);
  7472. if (pgc->state == DISP_SLEPT) {
  7473. DISPERR("[Pmaster]Panel_Master: primary display path is slept??\n");
  7474. goto done;
  7475. }
  7476. /* / Esd Check : Read from lcm */
  7477. /* / the following code is to */
  7478. /* / 0: lock path */
  7479. /* / 1: stop path */
  7480. /* / 2: do esd check (!!!) */
  7481. /* / 3: start path */
  7482. /* / 4: unlock path */
  7483. /* / 1: stop path */
  7484. _cmdq_stop_trigger_loop();
  7485. if (dpmgr_path_is_busy(pgc->dpmgr_handle))
  7486. DISPCHECK("[ESD]wait frame done ret:%d\n", ret);
  7487. dpmgr_path_stop(pgc->dpmgr_handle, CMDQ_DISABLE);
  7488. DISPCHECK("[ESD]stop dpmgr path[end]\n");
  7489. if (dpmgr_path_is_busy(pgc->dpmgr_handle))
  7490. DISPCHECK("[ESD]wait frame done ret:%d\n", ret);
  7491. dpmgr_path_reset(pgc->dpmgr_handle, CMDQ_DISABLE);
  7492. if ((!strcmp(name, "PM_CLK")) || (!strcmp(name, "PM_SSC")))
  7493. Panel_Master_primary_display_config_dsi(name, *config_dsi);
  7494. else if (!strcmp(name, "PM_DDIC_CONFIG")) {
  7495. Panel_Master_DDIC_config();
  7496. force_trigger_path = 1;
  7497. } else if (!strcmp(name, "DRIVER_IC_RESET")) {
  7498. if (pLcm_drv && pLcm_drv->init_power)
  7499. pLcm_drv->init_power();
  7500. if (pLcm_drv)
  7501. pLcm_drv->init();
  7502. else
  7503. ret = -1;
  7504. force_trigger_path = 1;
  7505. }
  7506. dpmgr_path_start(pgc->dpmgr_handle, CMDQ_DISABLE);
  7507. if (primary_display_is_video_mode()) {
  7508. /* for video mode, we need to force trigger here */
  7509. /* for cmd mode, just set DPREC_EVENT_CMDQ_SET_EVENT_ALLOW when trigger loop start */
  7510. dpmgr_path_trigger(pgc->dpmgr_handle, NULL, CMDQ_DISABLE);
  7511. force_trigger_path = 0;
  7512. }
  7513. _cmdq_start_trigger_loop();
  7514. DISPCHECK("[Pmaster]start cmdq trigger loop\n");
  7515. done:
  7516. _primary_path_unlock(__func__);
  7517. if (force_trigger_path) {/* command mode only */
  7518. primary_display_trigger(0, NULL, 0);
  7519. DISPCHECK("[Pmaster]force trigger display path\r\n");
  7520. }
  7521. atomic_set(&esd_check_task_wakeup, esd_check_backup);
  7522. return ret;
  7523. }
  7524. /*
  7525. mode: 0, switch to cmd mode; 1, switch to vdo mode
  7526. */
  7527. int primary_display_switch_dst_mode(int mode)
  7528. {
  7529. DISP_STATUS ret = DISP_STATUS_ERROR;
  7530. #ifdef DISP_SWITCH_DST_MODE
  7531. void *lcm_cmd = NULL;
  7532. DISPFUNC();
  7533. _primary_path_switch_dst_lock();
  7534. disp_sw_mutex_lock(&(pgc->capture_lock));
  7535. if (pgc->plcm->params->type != LCM_TYPE_DSI) {
  7536. pr_debug("[primary_display_switch_dst_mode] Error, only support DSI IF\n");
  7537. goto done;
  7538. }
  7539. if (pgc->state == DISP_SLEPT) {
  7540. DISPCHECK
  7541. ("[primary_display_switch_dst_mode], primary display path is already sleep, skip\n");
  7542. goto done;
  7543. }
  7544. if (mode == primary_display_cur_dst_mode) {
  7545. DISPCHECK("[primary_display_switch_dst_mode]not need switch, cur_mode:%d, switch_mode:%d\n",
  7546. primary_display_cur_dst_mode, mode);
  7547. goto done;
  7548. }
  7549. /* DISPCHECK("[primary_display_switch_mode]need switch, cur_mode:%d, switch_mode:%d\n",
  7550. primary_display_cur_dst_mode, mode);
  7551. */
  7552. lcm_cmd = disp_lcm_switch_mode(pgc->plcm, mode);
  7553. if (lcm_cmd == NULL) {
  7554. DISPCHECK("[primary_display_switch_dst_mode]get lcm cmd fail %d, %d\n",
  7555. primary_display_cur_dst_mode, mode);
  7556. goto done;
  7557. } else {
  7558. int temp_mode = 0;
  7559. if (0 != dpmgr_path_ioctl(pgc->dpmgr_handle, pgc->cmdq_handle_config,
  7560. DDP_SWITCH_LCM_MODE, lcm_cmd)) {
  7561. pr_debug("switch lcm mode fail, return directly\n");
  7562. goto done;
  7563. }
  7564. _primary_path_lock(__func__);
  7565. temp_mode = (int)(pgc->plcm->params->dsi.mode);
  7566. pgc->plcm->params->dsi.mode = pgc->plcm->params->dsi.switch_mode;
  7567. pgc->plcm->params->dsi.switch_mode = temp_mode;
  7568. dpmgr_path_set_video_mode(pgc->dpmgr_handle, primary_display_is_video_mode());
  7569. if (0 != dpmgr_path_ioctl(pgc->dpmgr_handle, pgc->cmdq_handle_config,
  7570. DDP_SWITCH_DSI_MODE, lcm_cmd)) {
  7571. pr_debug("switch dsi mode fail, return directly\n");
  7572. _primary_path_unlock(__func__);
  7573. goto done;
  7574. }
  7575. }
  7576. primary_display_sodi_rule_init();
  7577. _cmdq_stop_trigger_loop();
  7578. _cmdq_build_trigger_loop();
  7579. _cmdq_start_trigger_loop();
  7580. _cmdq_reset_config_handle(); /* must do this */
  7581. _cmdq_insert_wait_frame_done_token();
  7582. primary_display_cur_dst_mode = mode;
  7583. if (primary_display_is_video_mode())
  7584. dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC,
  7585. DDP_IRQ_RDMA0_DONE);
  7586. else
  7587. dpmgr_map_event_to_irq(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC,
  7588. DDP_IRQ_DSI0_EXT_TE);
  7589. _primary_path_unlock(__func__);
  7590. ret = DISP_STATUS_OK;
  7591. done:
  7592. /* dprec_handle_option(0x0); */
  7593. disp_sw_mutex_unlock(&(pgc->capture_lock));
  7594. _primary_path_switch_dst_unlock();
  7595. #else
  7596. pr_debug("[ERROR: primary_display_switch_dst_mode]this function not enable in disp driver\n");
  7597. #endif
  7598. return ret;
  7599. }
  7600. /* warm reset ovl0 and ovl1 by CMDQ */
  7601. void primary_display_reset_ovl_by_cmdq(unsigned int force)
  7602. {
  7603. cmdqRecWaitNoClear(pgc->cmdq_handle_config, CMDQ_EVENT_MUTEX0_STREAM_EOF);
  7604. if (force == 0) { /* warm reset ovl */
  7605. DISPMSG("warm reset ovl\n");
  7606. /* reset ovl0 */
  7607. DISP_REG_SET(pgc->cmdq_handle_config, DISP_REG_OVL_RST, 0x1);
  7608. DISP_REG_SET(pgc->cmdq_handle_config, DISP_REG_OVL_RST, 0x0);
  7609. cmdqRecPoll(pgc->cmdq_handle_config, disp_addr_convert(DISP_REG_OVL_STA), 0, 0x1);
  7610. /* reset ovl1 */
  7611. if (ovl_get_status() == DDP_OVL1_STATUS_PRIMARY) {
  7612. DISP_REG_SET(pgc->cmdq_handle_config,
  7613. DISP_REG_OVL_RST + DISP_OVL_INDEX_OFFSET, 0x1);
  7614. DISP_REG_SET(pgc->cmdq_handle_config,
  7615. DISP_REG_OVL_RST + DISP_OVL_INDEX_OFFSET, 0x0);
  7616. cmdqRecPoll(pgc->cmdq_handle_config,
  7617. disp_addr_convert(DISP_REG_OVL_STA + DISP_OVL_INDEX_OFFSET), 0, 0x1);
  7618. }
  7619. } else if (force == 1) { /* force reset ovl */
  7620. DISPMSG("force reset ovl\n");
  7621. /* reset ovl0 */
  7622. DISP_REG_SET_FIELD(pgc->cmdq_handle_config, RST_FLD_FORCE_RST, DISP_REG_OVL_RST, 0x1);
  7623. DISP_REG_SET_FIELD(pgc->cmdq_handle_config, RST_FLD_FORCE_RST, DISP_REG_OVL_RST, 0x0);
  7624. cmdqRecPoll(pgc->cmdq_handle_config, disp_addr_convert(DISP_REG_OVL_STA), 0, 0x1);
  7625. /* reset ovl1 */
  7626. if (ovl_get_status() == DDP_OVL1_STATUS_PRIMARY) {
  7627. DISP_REG_SET_FIELD(pgc->cmdq_handle_config, RST_FLD_FORCE_RST,
  7628. DISP_REG_OVL_RST + DISP_OVL_INDEX_OFFSET, 0x1);
  7629. DISP_REG_SET_FIELD(pgc->cmdq_handle_config, RST_FLD_FORCE_RST,
  7630. DISP_REG_OVL_RST + DISP_OVL_INDEX_OFFSET, 0x0);
  7631. cmdqRecPoll(pgc->cmdq_handle_config,
  7632. disp_addr_convert(DISP_REG_OVL_STA + DISP_OVL_INDEX_OFFSET), 0,
  7633. 0x1);
  7634. }
  7635. }
  7636. }
  7637. /* extern void DSI_ForceConfig(int forceconfig); */
  7638. /* extern int DSI_set_roi(int x, int y); */
  7639. /* extern int DSI_check_roi(void); */
  7640. /* extern atomic_t ESDCheck_byCPU; */
  7641. static int width_array[] = { 2560, 1440, 1920, 1280, 1200, 800, 960, 640 };
  7642. static int heigh_array[] = { 1440, 2560, 1200, 800, 1920, 1280, 640, 960 };
  7643. static int array_id[] = { 6, 2, 7, 4, 3, 0, 5, 1 };
  7644. LCM_PARAMS *lcm_param2 = NULL;
  7645. disp_ddp_path_config data_config2;
  7646. int primary_display_te_test(void)
  7647. {
  7648. int ret = 0;
  7649. int try_cnt = 3;
  7650. int time_interval = 0;
  7651. int time_interval_max = 0;
  7652. long long time_te = 0;
  7653. long long time_framedone = 0;
  7654. pr_debug("display_test te begin\n");
  7655. if (primary_display_is_video_mode()) {
  7656. pr_debug("Video Mode No TE\n");
  7657. return ret;
  7658. }
  7659. while (try_cnt >= 0) {
  7660. try_cnt--;
  7661. ret = dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_IF_VSYNC, HZ * 1);
  7662. time_te = sched_clock();
  7663. dpmgr_path_trigger(pgc->dpmgr_handle, NULL, CMDQ_DISABLE);
  7664. ret = dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ * 1);
  7665. time_framedone = sched_clock();
  7666. time_interval = (int)(time_framedone - time_te);
  7667. time_interval = time_interval / 1000;
  7668. if (time_interval > time_interval_max)
  7669. time_interval_max = time_interval;
  7670. }
  7671. if (time_interval_max > 20000)
  7672. ret = 0;
  7673. else
  7674. ret = -1;
  7675. if (ret >= 0)
  7676. pr_debug("[display_test_result]==>Force On TE Open!(%d)\n", time_interval_max);
  7677. else
  7678. pr_debug("[display_test_result]==>Force On TE Closed!(%d)\n", time_interval_max);
  7679. pr_debug("display_test te end\n");
  7680. return ret;
  7681. }
  7682. #if 0
  7683. int primary_display_fps_test(void)
  7684. {
  7685. int ret = 0;
  7686. unsigned int w_backup = 0;
  7687. unsigned int h_backup = 0;
  7688. LCM_DSI_MODE_CON dsi_mode_backup = primary_display_is_video_mode();
  7689. memset((void *)&data_config2, 0, sizeof(data_config2));
  7690. lcm_param2 = NULL;
  7691. memcpy((void *)&data_config2, (void *)dpmgr_path_get_last_config(pgc->dpmgr_handle),
  7692. sizeof(disp_ddp_path_config));
  7693. w_backup = data_config2.dst_w;
  7694. h_backup = data_config2.dst_h;
  7695. DISPCHECK("[display_test]w_backup %d h_backup %d dsi_mode_backup %d\n", w_backup, h_backup,
  7696. dsi_mode_backup);
  7697. /* for dsi config */
  7698. DSI_ForceConfig(1);
  7699. DISPCHECK("[display_test]FPS config[begin]\n");
  7700. lcm_param2 = disp_lcm_get_params(pgc->plcm);
  7701. lcm_param2->dsi.mode = SYNC_PULSE_VDO_MODE;
  7702. lcm_param2->dsi.vertical_active_line = 1280;
  7703. lcm_param2->dsi.horizontal_active_pixel = 360;
  7704. data_config2.dst_w = 360;
  7705. data_config2.dst_h = 1280;
  7706. data_config2.dispif_config.dsi.vertical_active_line = 1280;
  7707. data_config2.dispif_config.dsi.horizontal_active_pixel = 360;
  7708. data_config2.dispif_config.dsi.mode = SYNC_PULSE_VDO_MODE;
  7709. data_config2.dst_dirty = 1;
  7710. dpmgr_path_set_video_mode(pgc->dpmgr_handle, primary_display_is_video_mode());
  7711. DISPCHECK("[display_test]==>FPS set vdo mode done, is_vdo_mode:%d\n",
  7712. primary_display_is_video_mode());
  7713. dpmgr_path_connect(pgc->dpmgr_handle, CMDQ_DISABLE);
  7714. dpmgr_path_config(pgc->dpmgr_handle, &data_config2, CMDQ_DISABLE);
  7715. data_config2.dst_dirty = 0;
  7716. DISPCHECK("[display_test]FPS config[end]\n");
  7717. DISPCHECK("[display_test]Start dpmgr path[begin]\n");
  7718. dpmgr_path_start(pgc->dpmgr_handle, CMDQ_DISABLE);
  7719. if (dpmgr_path_is_busy(pgc->dpmgr_handle))
  7720. DISPERR("[display_test]==>Fatal error, we didn't trigger display path but it's already busy\n");
  7721. DISPCHECK("[display_test]Start dpmgr path[end]\n");
  7722. DISPCHECK("[display_test]Trigger dpmgr path[begin]\n");
  7723. dpmgr_path_trigger(pgc->dpmgr_handle, NULL, CMDQ_DISABLE);
  7724. DISPCHECK("[display_test]Trigger dpmgr path[end]\n");
  7725. /* check fps bonding: rdma frame end interval < 12ms */
  7726. disp_record_rdma_end_interval(1);
  7727. /* loop 50 times to get max rdma end interval */
  7728. int i = 50;
  7729. while (i--)
  7730. dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ * 1);
  7731. unsigned long long min_interval = disp_get_rdma_min_interval();
  7732. unsigned long long max_interval = disp_get_rdma_max_interval();
  7733. disp_record_rdma_end_interval(0);
  7734. DISPCHECK("[display_test]Check RDMA frame end interval:%lld[end]\n", min_interval);
  7735. if (min_interval < 12 * 1000000) {
  7736. DISPCHECK("[display_test_result]=>0.No limit\n");
  7737. } else {
  7738. DISPCHECK("[display_test_result]=>1.limit max_interval %lld\n", max_interval);
  7739. if (max_interval < 13 * 1000000)
  7740. DISPCHECK("[display_test_result]=>2.naughty enable\n");
  7741. }
  7742. DISPCHECK("[display_test]Stop dpmgr path[begin]\n");
  7743. dpmgr_path_stop(pgc->dpmgr_handle, CMDQ_DISABLE);
  7744. DISPCHECK("[display_test]Stop dpmgr path[end]\n");
  7745. DISPCHECK("[display_test]Restore path config[begin]\n");
  7746. lcm_param2 = disp_lcm_get_params(pgc->plcm);
  7747. lcm_param2->dsi.mode = dsi_mode_backup;
  7748. lcm_param2->dsi.vertical_active_line = h_backup;
  7749. lcm_param2->dsi.horizontal_active_pixel = w_backup;
  7750. data_config2.dispif_config.dsi.vertical_active_line = h_backup;
  7751. data_config2.dispif_config.dsi.horizontal_active_pixel = w_backup;
  7752. data_config2.dispif_config.dsi.mode = dsi_mode_backup;
  7753. data_config2.dst_w = w_backup;
  7754. data_config2.dst_h = h_backup;
  7755. data_config2.dst_dirty = 1;
  7756. dpmgr_path_set_video_mode(pgc->dpmgr_handle, primary_display_is_video_mode());
  7757. DISPCHECK("[display_test]==>Restore mode done, is_vdo_mode:%d\n",
  7758. primary_display_is_video_mode());
  7759. DISPCHECK("[display_test]==>Restore resolution done, w=%d, h=%d\n", w_backup, h_backup);
  7760. dpmgr_path_connect(pgc->dpmgr_handle, CMDQ_DISABLE);
  7761. dpmgr_path_config(pgc->dpmgr_handle, &data_config2, CMDQ_DISABLE);
  7762. data_config2.dst_dirty = 0;
  7763. DSI_ForceConfig(0);
  7764. DISPCHECK("[display_test]Restore path config[end]\n");
  7765. return ret;
  7766. }
  7767. #endif
  7768. int primary_display_roi_test(int x, int y)
  7769. {
  7770. int ret = 0;
  7771. pr_debug("display_test roi begin\n");
  7772. pr_debug("display_test roi set roi %d, %d\n", x, y);
  7773. DSI_set_roi(x, y);
  7774. msleep(50);
  7775. dpmgr_path_trigger(pgc->dpmgr_handle, NULL, CMDQ_DISABLE);
  7776. msleep(50);
  7777. pr_debug("display_test DSI_check_roi\n");
  7778. ret = DSI_check_roi();
  7779. msleep(20);
  7780. if (ret == 0)
  7781. pr_debug("[display_test_result]==>DSI_ROI limit!\n");
  7782. else
  7783. pr_debug("[display_test_result]==>DSI_ROI Normal!\n");
  7784. pr_debug("display_test set roi %d, %d\n", 0, 0);
  7785. DSI_set_roi(0, 0);
  7786. msleep(20);
  7787. DISPCHECK("display_test end\n");
  7788. return ret;
  7789. }
  7790. int primary_display_resolution_test(void)
  7791. {
  7792. int ret = 0;
  7793. int i = 0;
  7794. unsigned int w_backup = 0;
  7795. unsigned int h_backup = 0;
  7796. int dst_width = 0;
  7797. int dst_heigh = 0;
  7798. LCM_DSI_MODE_CON dsi_mode_backup = primary_display_is_video_mode();
  7799. memset((void *)&data_config2, 0, sizeof(data_config2));
  7800. lcm_param2 = NULL;
  7801. memcpy((void *)&data_config2, (void *)dpmgr_path_get_last_config(pgc->dpmgr_handle),
  7802. sizeof(disp_ddp_path_config));
  7803. w_backup = data_config2.dst_w;
  7804. h_backup = data_config2.dst_h;
  7805. DISPCHECK("[display_test resolution]w_backup %d h_backup %d dsi_mode_backup %d\n",
  7806. w_backup, h_backup, dsi_mode_backup);
  7807. /* for dsi config */
  7808. DSI_ForceConfig(1);
  7809. for (i = 0; i < sizeof(width_array) / sizeof(int); i++) {
  7810. dst_width = width_array[i];
  7811. dst_heigh = heigh_array[i];
  7812. DISPCHECK("[display_test resolution] width %d, heigh %d\n", dst_width, dst_heigh);
  7813. lcm_param2 = disp_lcm_get_params(pgc->plcm);
  7814. lcm_param2->dsi.mode = CMD_MODE;
  7815. lcm_param2->dsi.horizontal_active_pixel = dst_width;
  7816. lcm_param2->dsi.vertical_active_line = dst_heigh;
  7817. data_config2.dispif_config.dsi.mode = CMD_MODE;
  7818. data_config2.dispif_config.dsi.horizontal_active_pixel = dst_width;
  7819. data_config2.dispif_config.dsi.vertical_active_line = dst_heigh;
  7820. data_config2.dst_w = dst_width;
  7821. data_config2.dst_h = dst_heigh;
  7822. data_config2.ovl_config[0].layer = 0;
  7823. data_config2.ovl_config[0].layer_en = 0;
  7824. data_config2.ovl_config[1].layer = 1;
  7825. data_config2.ovl_config[1].layer_en = 0;
  7826. data_config2.ovl_config[2].layer = 2;
  7827. data_config2.ovl_config[2].layer_en = 0;
  7828. data_config2.ovl_config[3].layer = 3;
  7829. data_config2.ovl_config[3].layer_en = 0;
  7830. data_config2.dst_dirty = 1;
  7831. data_config2.ovl_dirty = 1;
  7832. dpmgr_path_set_video_mode(pgc->dpmgr_handle, primary_display_is_video_mode());
  7833. dpmgr_path_config(pgc->dpmgr_handle, &data_config2, CMDQ_DISABLE);
  7834. data_config2.dst_dirty = 0;
  7835. data_config2.ovl_dirty = 0;
  7836. dpmgr_path_start(pgc->dpmgr_handle, CMDQ_DISABLE);
  7837. if (dpmgr_path_is_busy(pgc->dpmgr_handle))
  7838. DISPERR("[display_test]==>Fatal error, we didn't trigger display path but it's already busy\n");
  7839. dpmgr_path_trigger(pgc->dpmgr_handle, NULL, CMDQ_DISABLE);
  7840. ret = dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ * 1);
  7841. if (ret > 0) {
  7842. if (!dpmgr_path_is_busy(pgc->dpmgr_handle)) {
  7843. if (i == 0)
  7844. DISPCHECK("[display_test resolution] display_result 0x%x unlimited!\n",
  7845. array_id[i]);
  7846. else if (i == 1)
  7847. DISPCHECK("[display_test resolution] display_result 0x%x unlimited (W<H)\n",
  7848. array_id[i]);
  7849. else
  7850. DISPCHECK("[display_test resolution] display_result 0x%x(%d x %d)\n",
  7851. array_id[i], dst_width, dst_heigh);
  7852. break;
  7853. }
  7854. }
  7855. dpmgr_path_reset(pgc->dpmgr_handle, CMDQ_DISABLE);
  7856. }
  7857. dpmgr_path_stop(pgc->dpmgr_handle, CMDQ_DISABLE);
  7858. lcm_param2 = disp_lcm_get_params(pgc->plcm);
  7859. lcm_param2->dsi.mode = dsi_mode_backup;
  7860. lcm_param2->dsi.vertical_active_line = h_backup;
  7861. lcm_param2->dsi.horizontal_active_pixel = w_backup;
  7862. data_config2.dispif_config.dsi.vertical_active_line = h_backup;
  7863. data_config2.dispif_config.dsi.horizontal_active_pixel = w_backup;
  7864. data_config2.dispif_config.dsi.mode = dsi_mode_backup;
  7865. data_config2.dst_w = w_backup;
  7866. data_config2.dst_h = h_backup;
  7867. data_config2.dst_dirty = 1;
  7868. dpmgr_path_set_video_mode(pgc->dpmgr_handle, primary_display_is_video_mode());
  7869. dpmgr_path_connect(pgc->dpmgr_handle, CMDQ_DISABLE);
  7870. dpmgr_path_config(pgc->dpmgr_handle, &data_config2, CMDQ_DISABLE);
  7871. data_config2.dst_dirty = 0;
  7872. DSI_ForceConfig(0);
  7873. return ret;
  7874. }
  7875. int primary_display_check_test(void)
  7876. {
  7877. int ret = 0;
  7878. int esd_backup = 0;
  7879. DISPCHECK("[display_test]Display test[Start]\n");
  7880. _primary_path_lock(__func__);
  7881. /* disable esd check */
  7882. if (atomic_read(&esd_check_task_wakeup)) {
  7883. esd_backup = 1;
  7884. primary_display_esd_check_enable(0);
  7885. msleep(2000);
  7886. DISPCHECK("[display_test]Disable esd check end\n");
  7887. }
  7888. /* if suspend => return */
  7889. if (pgc->state == DISP_SLEPT) {
  7890. DISPCHECK("[display_test_result]======================================\n");
  7891. DISPCHECK("[display_test_result]==>Test Fail : primary display path is slept\n");
  7892. DISPCHECK("[display_test_result]======================================\n");
  7893. goto done;
  7894. }
  7895. /* stop trigger loop */
  7896. DISPCHECK("[display_test]Stop trigger loop[begin]\n");
  7897. _cmdq_stop_trigger_loop();
  7898. atomic_set(&ESDCheck_byCPU, 1);
  7899. if (dpmgr_path_is_busy(pgc->dpmgr_handle)) {
  7900. DISPCHECK("[display_test]==>primary display path is busy\n");
  7901. ret = dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ * 1);
  7902. if (ret <= 0)
  7903. dpmgr_path_reset(pgc->dpmgr_handle, CMDQ_DISABLE);
  7904. DISPCHECK("[display_test]==>wait frame done ret:%d\n", ret);
  7905. }
  7906. DISPCHECK("[display_test]Stop trigger loop[end]\n");
  7907. /* test rdma res after reset */
  7908. /* primary_display_rdma_res_test(); */
  7909. /* test force te */
  7910. primary_display_te_test();
  7911. /* test roi */
  7912. primary_display_roi_test(30, 30);
  7913. /* test resolution test */
  7914. primary_display_resolution_test();
  7915. /* mutex fps */
  7916. /* primary_display_fps_test(); */
  7917. DISPCHECK("[display_test]start dpmgr path[begin]\n");
  7918. dpmgr_path_start(pgc->dpmgr_handle, CMDQ_DISABLE);
  7919. if (dpmgr_path_is_busy(pgc->dpmgr_handle))
  7920. DISPERR("[display_test]==>Fatal error, we didn't trigger display path but it's already busy\n");
  7921. DISPCHECK("[display_test]start dpmgr path[end]\n");
  7922. DISPCHECK("[display_test]Start trigger loop[begin]\n");
  7923. _cmdq_start_trigger_loop();
  7924. DISPCHECK("[display_test]Start trigger loop[end]\n");
  7925. atomic_set(&ESDCheck_byCPU, 0);
  7926. done:
  7927. /* restore esd */
  7928. if (esd_backup == 1) {
  7929. primary_display_esd_check_enable(1);
  7930. DISPCHECK("[display_test]Restore esd check\n");
  7931. }
  7932. /* unlock path */
  7933. _primary_path_unlock(__func__);
  7934. DISPCHECK("[display_test]Display test[End]\n");
  7935. return ret;
  7936. }
  7937. static DISP_POWER_STATE tui_power_stat_backup;
  7938. static int tui_session_mode_backup;
  7939. int display_enter_tui(void)
  7940. {
  7941. msleep(500);
  7942. DISPMSG("TDDP: %s\n", __func__);
  7943. MMProfileLogEx(ddp_mmp_get_events()->tui, MMProfileFlagStart, 0, 0);
  7944. _primary_path_lock(__func__);
  7945. if (primary_get_state() != DISP_ALIVE) {
  7946. DISPERR("Can't enter tui: current_stat=%d is not alive\n", primary_get_state());
  7947. goto err0;
  7948. }
  7949. tui_power_stat_backup = primary_set_state(DISP_BLANK);
  7950. if (primary_display_is_mirror_mode()) {
  7951. DISPERR("Can't enter tui: current_mode=%s\n", session_mode_spy(pgc->session_mode));
  7952. goto err1;
  7953. }
  7954. #ifdef MTK_DISP_IDLE_LP
  7955. _disp_primary_path_exit_idle(__func__, 0);
  7956. #endif
  7957. tui_session_mode_backup = pgc->session_mode;
  7958. primary_display_switch_mode_nolock(DISP_SESSION_DECOUPLE_MODE, pgc->session_id, 0);
  7959. MMProfileLogEx(ddp_mmp_get_events()->tui, MMProfileFlagPulse, 0, 1);
  7960. _primary_path_unlock(__func__);
  7961. return 0;
  7962. err1:
  7963. primary_set_state(tui_power_stat_backup);
  7964. err0:
  7965. MMProfileLogEx(ddp_mmp_get_events()->tui, MMProfileFlagEnd, 0, 0);
  7966. _primary_path_unlock(__func__);
  7967. return -1;
  7968. }
  7969. int display_exit_tui(void)
  7970. {
  7971. MMProfileLogEx(ddp_mmp_get_events()->tui, MMProfileFlagPulse, 1, 1);
  7972. _primary_path_lock(__func__);
  7973. primary_set_state(tui_power_stat_backup);
  7974. /* trigger rdma to display last normal buffer
  7975. _decouple_update_rdma_config_nolock();*/
  7976. /* workaround: wait until this frame triggered to lcm */
  7977. msleep(32);
  7978. primary_display_switch_mode_nolock(tui_session_mode_backup, pgc->session_id, 0);
  7979. _primary_path_unlock(__func__);
  7980. MMProfileLogEx(ddp_mmp_get_events()->tui, MMProfileFlagEnd, 0, 0);
  7981. DISPMSG("TDDP: %s\n", __func__);
  7982. return 0;
  7983. }
  7984. #if defined(OVL_TIME_SHARING)
  7985. int primary_display_disable_ovl2mem(void)
  7986. {
  7987. DISPMSG("%s\n", __func__);
  7988. _primary_path_lock(__func__);
  7989. if (_is_decouple_mode(pgc->session_mode) &&
  7990. pgc->state == DISP_SLEPT &&
  7991. pgc->force_on_wdma_path == 1) {
  7992. /* msleep(16); */ /* wait last frame done */
  7993. usleep_range(16000, 17000);
  7994. if (dpmgr_path_is_busy(pgc->ovl2mem_path_handle))
  7995. dpmgr_wait_event_timeout(pgc->ovl2mem_path_handle, DISP_PATH_EVENT_FRAME_COMPLETE, HZ);
  7996. DISPCHECK("[POWER]stop cmdq[begin]\n");
  7997. _cmdq_stop_trigger_loop();
  7998. DISPCHECK("[POWER]stop cmdq[end]\n");
  7999. dpmgr_path_power_off(pgc->ovl2mem_path_handle, CMDQ_DISABLE);
  8000. #ifndef CONFIG_MTK_CLKMGR
  8001. ddp_clk_unprepare(DISP_MTCMOS_CLK);
  8002. #endif
  8003. DISPMSG("disable ovl power\n");
  8004. pgc->force_on_wdma_path = 0;
  8005. }
  8006. _primary_path_unlock(__func__);
  8007. return 1;
  8008. }
  8009. #endif