12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059 |
- /*
- * Copyright (c) 2015 MediaTek Inc.
- * Copyright (C) 2021 XiaoMi, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
- #include <drm/drmP.h>
- #include <drm/drm_atomic_helper.h>
- #include <drm/drm_crtc_helper.h>
- #include <drm/drm_mipi_dsi.h>
- #include <drm/drm_panel.h>
- #include <drm/drm_crtc_helper.h>
- #include <linux/clk.h>
- #include <linux/sched.h>
- #include <linux/sched/clock.h>
- #include <linux/component.h>
- #include <linux/irq.h>
- #include <linux/of.h>
- #include <linux/of_platform.h>
- #include <linux/of_graph.h>
- #include <linux/phy/phy.h>
- #include <linux/platform_device.h>
- #include <video/mipi_display.h>
- #include <video/videomode.h>
- #include <linux/soc/mediatek/mtk-cmdq.h>
- #if defined(CONFIG_MACH_MT6873) || defined(CONFIG_MACH_MT6853) \
- || defined(CONFIG_MACH_MT6833)
- #include <linux/ratelimit.h>
- #endif
- #include "mtk_drm_ddp_comp.h"
- #include "mtk_drm_crtc.h"
- #include "mtk_drm_drv.h"
- #include "mtk_drm_helper.h"
- #include "mtk_mipi_tx.h"
- #include "mtk_dump.h"
- #include "mtk_log.h"
- #include "mtk_drm_lowpower.h"
- #include "mtk_drm_mmp.h"
- #include "mtk_drm_arr.h"
- #include "mtk_panel_ext.h"
- /* ************ Panel Master ********** */
- #include "mtk_drm_fbdev.h"
- #include "mtk_fbconfig_kdebug.h"
- /* ********* end Panel Master *********** */
- #define DSI_START 0x00
- #define SLEEPOUT_START BIT(2)
- #define VM_CMD_START BIT(16)
- #define START_FLD_REG_START REG_FLD_MSB_LSB(0, 0)
- #define DSI_INTEN 0x08
- #define DSI_INTSTA 0x0c
- #define LPRX_RD_RDY_INT_FLAG BIT(0)
- #define CMD_DONE_INT_FLAG BIT(1)
- #define TE_RDY_INT_FLAG BIT(2)
- #define VM_DONE_INT_FLAG BIT(3)
- #define FRAME_DONE_INT_FLAG BIT(4)
- #define VM_CMD_DONE_INT_EN BIT(5)
- #define SLEEPOUT_DONE_INT_FLAG BIT(6)
- #define BUFFER_UNDERRUN_INT_FLAG BIT(12)
- #define INP_UNFINISH_INT_EN BIT(14)
- #define SLEEPIN_ULPS_DONE_INT_FLAG BIT(15)
- #define DSI_BUSY BIT(31)
- #define INTSTA_FLD_REG_RD_RDY REG_FLD_MSB_LSB(0, 0)
- #define INTSTA_FLD_REG_CMD_DONE REG_FLD_MSB_LSB(1, 1)
- #define INTSTA_FLD_REG_TE_RDY REG_FLD_MSB_LSB(2, 2)
- #define INTSTA_FLD_REG_VM_DONE REG_FLD_MSB_LSB(3, 3)
- #define INTSTA_FLD_REG_FRM_DONE REG_FLD_MSB_LSB(4, 4)
- #define INTSTA_FLD_REG_VM_CMD_DONE REG_FLD_MSB_LSB(5, 5)
- #define INTSTA_FLD_REG_SLEEPOUT_DONE REG_FLD_MSB_LSB(6, 6)
- #define INTSTA_FLD_REG_BUSY REG_FLD_MSB_LSB(31, 31)
- #define DSI_CON_CTRL 0x10
- #define DSI_RESET BIT(0)
- #define DSI_EN BIT(1)
- #define DSI_PHY_RESET BIT(2)
- #define CON_CTRL_FLD_REG_DUAL_EN REG_FLD_MSB_LSB(4, 4)
- #define DSI_CM_WAIT_FIFO_FULL_EN BIT(27)
- #define DSI_MODE_CTRL 0x14
- #define MODE (3)
- #define CMD_MODE 0
- #define SYNC_PULSE_MODE 1
- #define SYNC_EVENT_MODE 2
- #define BURST_MODE 3
- #define FRM_MODE BIT(16)
- #define MIX_MODE BIT(17)
- #define SLEEP_MODE BIT(20)
- #define MODE_FLD_REG_MODE_CON REG_FLD_MSB_LSB(1, 0)
- #define DSI_TXRX_CTRL 0x18
- #define VC_NUM BIT(1)
- #define LANE_NUM (0xf << 2)
- #define DIS_EOT BIT(6)
- #define NULL_EN BIT(7)
- #define TE_FREERUN BIT(8)
- #define EXT_TE_EN BIT(9)
- #define EXT_TE_EDGE BIT(10)
- #define MAX_RTN_SIZE (0xf << 12)
- #define HSTX_CKLP_EN BIT(16)
- #define TXRX_CTRL_FLD_REG_LANE_NUM REG_FLD_MSB_LSB(5, 2)
- #define TXRX_CTRL_FLD_REG_EXT_TE_EN REG_FLD_MSB_LSB(9, 9)
- #define TXRX_CTRL_FLD_REG_EXT_TE_EDGE REG_FLD_MSB_LSB(10, 10)
- #define TXRX_CTRL_FLD_REG_HSTX_CKLP_EN REG_FLD_MSB_LSB(16, 16)
- #define DSI_PSCTRL 0x1c
- #define DSI_PS_WC REG_FLD_MSB_LSB(14, 0)
- #define DSI_PS_SEL REG_FLD_MSB_LSB(18, 16)
- #define DSI_VSA_NL 0x20
- #define DSI_VBP_NL 0x24
- #define DSI_VFP_NL 0x28
- #define DSI_SIZE_CON 0x38
- #define DSI_VACT_NL 0x2C
- #define DSI_LFR_CON 0x30
- #define DSI_LFR_STA 0x34
- #define LFR_STA_FLD_REG_LFR_SKIP_STA REG_FLD_MSB_LSB(8, 8)
- #define LFR_STA_FLD_REG_LFR_SKIP_CNT REG_FLD_MSB_LSB(5, 0)
- #define LFR_CON_FLD_REG_LFR_MODE REG_FLD_MSB_LSB(1, 0)
- #define LFR_CON_FLD_REG_LFR_TYPE REG_FLD_MSB_LSB(3, 2)
- #define LFR_CON_FLD_REG_LFR_EN REG_FLD_MSB_LSB(4, 4)
- #define LFR_CON_FLD_REG_LFR_UPDATE REG_FLD_MSB_LSB(5, 5)
- #define LFR_CON_FLD_REG_LFR_VSE_DIS REG_FLD_MSB_LSB(6, 6)
- #define LFR_CON_FLD_REG_LFR_SKIP_NUM REG_FLD_MSB_LSB(13, 8)
- #define DSI_HSA_WC 0x50
- #define DSI_HBP_WC 0x54
- #define DSI_HFP_WC 0x58
- #define DSI_BLLP_WC 0x5C
- #define DSI_CMDQ_SIZE 0x60
- #define CMDQ_SIZE 0x3f
- #define DSI_HSTX_CKL_WC 0x64
- #define DSI_RX_DATA0 0x74
- #define DSI_RX_DATA1 0x78
- #define DSI_RX_DATA2 0x7c
- #define DSI_RX_DATA3 0x80
- #define DSI_RACK 0x84
- #define RACK BIT(0)
- #define DSI_MEM_CONTI 0x90
- #define DSI_WMEM_CONTI 0x3C
- #define DSI_TIME_CON0 0xA0
- #define DSI_PHY_LCCON 0x104
- #define LC_HS_TX_EN BIT(0)
- #define LC_ULPM_EN BIT(1)
- #define LC_WAKEUP_EN BIT(2)
- #define PHY_FLD_REG_LC_HSTX_EN REG_FLD_MSB_LSB(0, 0)
- #define DSI_PHY_LD0CON 0x108
- #define LD0_HS_TX_EN BIT(0)
- #define LD0_ULPM_EN BIT(1)
- #define LD0_WAKEUP_EN BIT(2)
- #define LDX_ULPM_AS_L0 BIT(3)
- #define DSI_PHY_TIMECON0 0x110
- #define LPX (0xff << 0)
- #define HS_PREP (0xff << 8)
- #define HS_ZERO (0xff << 16)
- #define HS_TRAIL (0xff << 24)
- #define FLD_LPX REG_FLD_MSB_LSB(7, 0)
- #define FLD_HS_PREP REG_FLD_MSB_LSB(15, 8)
- #define FLD_HS_ZERO REG_FLD_MSB_LSB(23, 16)
- #define FLD_HS_TRAIL REG_FLD_MSB_LSB(31, 24)
- #define DSI_PHY_TIMECON1 0x114
- #define TA_GO (0xff << 0)
- #define TA_SURE (0xff << 8)
- #define TA_GET (0xff << 16)
- #define DA_HS_EXIT (0xff << 24)
- #define FLD_TA_GO REG_FLD_MSB_LSB(7, 0)
- #define FLD_TA_SURE REG_FLD_MSB_LSB(15, 8)
- #define FLD_TA_GET REG_FLD_MSB_LSB(23, 16)
- #define FLD_DA_HS_EXIT REG_FLD_MSB_LSB(31, 24)
- #define DSI_PHY_TIMECON2 0x118
- #define CONT_DET (0xff << 0)
- #define CLK_ZERO (0xff << 16)
- #define CLK_TRAIL (0xff << 24)
- #define FLD_CONT_DET REG_FLD_MSB_LSB(7, 0)
- #define FLD_DA_HS_SYNC REG_FLD_MSB_LSB(15, 8)
- #define FLD_CLK_HS_ZERO REG_FLD_MSB_LSB(23, 16)
- #define FLD_CLK_HS_TRAIL REG_FLD_MSB_LSB(31, 24)
- #define DSI_PHY_TIMECON3 0x11c
- #define CLK_HS_PREP (0xff << 0)
- #define CLK_HS_POST (0xff << 8)
- #define CLK_HS_EXIT (0xff << 16)
- #define FLD_CLK_HS_PREP REG_FLD_MSB_LSB(7, 0)
- #define FLD_CLK_HS_POST REG_FLD_MSB_LSB(15, 8)
- #define FLD_CLK_HS_EXIT REG_FLD_MSB_LSB(23, 16)
- #define DSI_CPHY_CON0 0x120
- #define DSI_VM_CMD_CON 0x130
- #define VM_CMD_EN BIT(0)
- #define TS_VFP_EN BIT(5)
- #define DSI_VM_CMD_DATA0 0x134
- #define DSI_VM_CMD_DATA10 0x180
- #define DSI_VM_CMD_DATA20 0x1A0
- #define DSI_VM_CMD_DATA30 0x1B0
- #define DSI_VM_CMD_DATA0 0x134
- #define DSI_STATE_DBG6 0x160
- #define STATE_DBG6_FLD_REG_CMCTL_STATE REG_FLD_MSB_LSB(14, 0)
- #define DSI_SHADOW_DEBUG 0x190
- #define DSI_BYPASS_SHADOW BIT(1)
- #define DSI_READ_WORKING BIT(2)
- #define DSI_CMDQ0 0x200
- #define DSI_CMDQ1 0x204
- #define CONFIG (0xff << 0)
- #define SHORT_PACKET 0
- #define LONG_PACKET 2
- #define VM_LONG_PACKET BIT(1)
- #define BTA BIT(2)
- #define HSTX BIT(3)
- #define DATA_ID (0xff << 8)
- #define DATA_0 (0xff << 16)
- #define DATA_1 (0xff << 24)
- #define MMSYS_SW_RST_DSI_B BIT(2)
- #define MMSYS_SW_RST_DSI1_B BIT(3)
- #define DSI_START_FLD_DSI_START REG_FLD_MSB_LSB(0, 0)
- #define DSI_INSTA_FLD_DSI_BUSY REG_FLD_MSB_LSB(31, 31)
- #define DSI_COM_CON_FLD_DUAL_EN REG_FLD_MSB_LSB(4, 4)
- #define DSI_MODE_CON_FLD_MODE_CON REG_FLD_MSB_LSB(1, 0)
- #define T_LPX (8)
- #define T_HS_PREP (7)
- #define T_HS_TRAIL (8)
- #define T_HS_EXIT (16)
- #define T_HS_ZERO (15)
- #define DA_HS_SYNC (1)
- #define NS_TO_CYCLE(n, c) ((n) / (c))
- #define MTK_DSI_HOST_IS_READ(type) \
- ((type == MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM) || \
- (type == MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM) || \
- (type == MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM) || \
- (type == MIPI_DSI_DCS_READ))
- struct phy;
- struct mtk_dsi;
- #define DSI_DCS_SHORT_PACKET_ID_0 0x05
- #define DSI_DCS_SHORT_PACKET_ID_1 0x15
- #define DSI_DCS_LONG_PACKET_ID 0x39
- #define DSI_DCS_READ_PACKET_ID 0x06
- #define DSI_GERNERIC_SHORT_PACKET_ID_1 0x13
- #define DSI_GERNERIC_SHORT_PACKET_ID_2 0x23
- #define DSI_GERNERIC_LONG_PACKET_ID 0x29
- #define DSI_GERNERIC_READ_LONG_PACKET_ID 0x14
- struct DSI_T0_INS {
- unsigned CONFG : 8;
- unsigned Data_ID : 8;
- unsigned Data0 : 8;
- unsigned Data1 : 8;
- };
- #define DECLARE_DSI_PORCH(EXPR) \
- EXPR(DSI_VFP) \
- EXPR(DSI_VSA) \
- EXPR(DSI_VBP) \
- EXPR(DSI_VACT) \
- EXPR(DSI_HFP) \
- EXPR(DSI_HSA) \
- EXPR(DSI_HBP) \
- EXPR(DSI_BLLP) \
- EXPR(DSI_PORCH_NUM)
- enum dsi_porch_type { DECLARE_DSI_PORCH(DECLARE_NUM) };
- static const char * const mtk_dsi_porch_str[] = {
- DECLARE_DSI_PORCH(DECLARE_STR)};
- #define AS_UINT32(x) (*(u32 *)((void *)x))
- struct mtk_dsi_driver_data {
- const u32 reg_cmdq_ofs;
- s32 (*poll_for_idle)(struct mtk_dsi *dsi, struct cmdq_pkt *handle);
- irqreturn_t (*irq_handler)(int irq, void *dev_id);
- char *esd_eint_compat;
- bool support_shadow;
- };
- struct t_condition_wq {
- wait_queue_head_t wq;
- atomic_t condition;
- };
- struct mtk_dsi {
- struct mtk_ddp_comp ddp_comp;
- struct device *dev;
- struct mipi_dsi_host host;
- struct drm_encoder encoder;
- struct drm_connector conn;
- struct drm_panel *panel;
- struct mtk_panel_ext *ext;
- struct cmdq_pkt_buffer cmdq_buf;
- struct drm_bridge *bridge;
- struct phy *phy;
- void __iomem *regs;
- struct clk *engine_clk;
- struct clk *digital_clk;
- struct clk *hs_clk;
- u32 data_rate;
- unsigned long mode_flags;
- enum mipi_dsi_pixel_format format;
- unsigned int lanes;
- struct videomode vm;
- int clk_refcnt;
- bool output_en;
- bool doze_enabled;
- u32 irq_data;
- wait_queue_head_t irq_wait_queue;
- struct mtk_dsi_driver_data *driver_data;
- struct t_condition_wq enter_ulps_done;
- struct t_condition_wq exit_ulps_done;
- struct t_condition_wq te_rdy;
- struct t_condition_wq frame_done;
- unsigned int hs_trail;
- unsigned int hs_prpr;
- unsigned int hs_zero;
- unsigned int lpx;
- unsigned int ta_get;
- unsigned int ta_sure;
- unsigned int ta_go;
- unsigned int da_hs_exit;
- unsigned int cont_det;
- unsigned int clk_zero;
- unsigned int clk_hs_prpr;
- unsigned int clk_hs_exit;
- unsigned int clk_hs_post;
- unsigned int vsa;
- unsigned int vbp;
- unsigned int vfp;
- unsigned int hsa_byte;
- unsigned int hbp_byte;
- unsigned int hfp_byte;
- bool mipi_hopping_sta;
- bool panel_osc_hopping_sta;
- unsigned int data_phy_cycle;
- /* for Panel Master dcs read/write */
- struct mipi_dsi_device *dev_for_PM;
- };
- enum DSI_MODE_CON {
- MODE_CON_CMD = 0,
- MODE_CON_SYNC_PULSE_VDO,
- MODE_CON_SYNC_EVENT_VDO,
- MODE_CON_BURST_VDO,
- };
- struct mtk_panel_ext *mtk_dsi_get_panel_ext(struct mtk_ddp_comp *comp);
- static inline struct mtk_dsi *encoder_to_dsi(struct drm_encoder *e)
- {
- return container_of(e, struct mtk_dsi, encoder);
- }
- static inline struct mtk_dsi *connector_to_dsi(struct drm_connector *c)
- {
- return container_of(c, struct mtk_dsi, conn);
- }
- static inline struct mtk_dsi *host_to_dsi(struct mipi_dsi_host *h)
- {
- return container_of(h, struct mtk_dsi, host);
- }
- static void mtk_dsi_mask(struct mtk_dsi *dsi, u32 offset, u32 mask, u32 data)
- {
- u32 temp = readl(dsi->regs + offset);
- writel((temp & ~mask) | (data & mask), dsi->regs + offset);
- }
- #define CHK_SWITCH(a, b) ((a == 0) ? b : a)
- static bool mtk_dsi_doze_state(struct mtk_dsi *dsi)
- {
- struct drm_crtc *crtc = dsi->encoder.crtc;
- struct mtk_crtc_state *state = to_mtk_crtc_state(crtc->state);
- return state->prop_val[CRTC_PROP_DOZE_ACTIVE];
- }
- static bool mtk_dsi_doze_status_change(struct mtk_dsi *dsi)
- {
- bool doze_enabled = mtk_dsi_doze_state(dsi);
- if (dsi->doze_enabled == doze_enabled)
- return false;
- return true;
- }
- static void mtk_dsi_dphy_timconfig(struct mtk_dsi *dsi, void *handle)
- {
- struct mtk_dsi_phy_timcon *phy_timcon = NULL;
- u32 lpx = 0, hs_prpr = 0, hs_zero = 0, hs_trail = 0;
- u32 ta_get = 0, ta_sure = 0, ta_go = 0, da_hs_exit = 0;
- u32 clk_zero = 0, clk_trail = 0, da_hs_sync = 0;
- u32 clk_hs_prpr = 0, clk_hs_exit = 0, clk_hs_post = 0;
- u32 cont_det = 0;
- u32 ui = 0, cycle_time = 0;
- u32 value = 0;
- struct mtk_ddp_comp *comp = &dsi->ddp_comp;
- ui = 1000 / dsi->data_rate + 0x01;
- cycle_time = 8000 / dsi->data_rate + 0x01;
- lpx = NS_TO_CYCLE(dsi->data_rate * 0x4B, 0x1F40) + 0x1;
- hs_prpr = NS_TO_CYCLE((0x40 + 0x5 * ui), cycle_time) + 0x1;
- hs_zero = NS_TO_CYCLE((0xC8 + 0x0A * ui), cycle_time);
- hs_zero = hs_zero > hs_prpr ? hs_zero - hs_prpr : hs_zero;
- hs_trail = NS_TO_CYCLE((0x4 * ui + 0x50) *
- dsi->data_rate, 0x1F40) + 0x1;
- ta_get = 5 * lpx;
- ta_sure = 3 * lpx / 2;
- ta_go = 4 * lpx;
- da_hs_exit = 2 * lpx;
- clk_zero = NS_TO_CYCLE(0x190, cycle_time);
- clk_trail = NS_TO_CYCLE(0x64 * dsi->data_rate, 0x1F40) + 0x1;
- da_hs_sync = 0x1;
- cont_det = 0x3;
- clk_hs_prpr = NS_TO_CYCLE(0x50 * dsi->data_rate, 0x1F40);
- clk_hs_exit = 2 * lpx;
- clk_hs_post = NS_TO_CYCLE(0x60 + 0x34 * ui, cycle_time);
- if (!(dsi->ext && dsi->ext->params))
- goto CONFIG_REG;
- phy_timcon = &dsi->ext->params->phy_timcon;
- lpx = CHK_SWITCH(phy_timcon->lpx, lpx);
- hs_prpr = CHK_SWITCH(phy_timcon->hs_prpr, hs_prpr);
- hs_zero = CHK_SWITCH(phy_timcon->hs_zero, hs_zero);
- hs_trail = CHK_SWITCH(phy_timcon->hs_trail, hs_trail);
- ta_get = CHK_SWITCH(phy_timcon->ta_get, ta_get);
- ta_sure = CHK_SWITCH(phy_timcon->ta_sure, ta_sure);
- ta_go = CHK_SWITCH(phy_timcon->ta_go, ta_go);
- da_hs_exit = CHK_SWITCH(phy_timcon->da_hs_exit, da_hs_exit);
- clk_zero = CHK_SWITCH(phy_timcon->clk_zero, clk_zero);
- clk_trail = CHK_SWITCH(phy_timcon->clk_trail, clk_trail);
- da_hs_sync = CHK_SWITCH(phy_timcon->da_hs_sync, da_hs_sync);
- clk_hs_prpr = CHK_SWITCH(phy_timcon->clk_hs_prpr, clk_hs_prpr);
- clk_hs_exit = CHK_SWITCH(phy_timcon->clk_hs_exit, clk_hs_exit);
- clk_hs_post = CHK_SWITCH(phy_timcon->clk_hs_post, clk_hs_post);
- CONFIG_REG:
- value = REG_FLD_VAL(FLD_LPX, lpx)
- | REG_FLD_VAL(FLD_HS_PREP, hs_prpr)
- | REG_FLD_VAL(FLD_HS_ZERO, hs_zero)
- | REG_FLD_VAL(FLD_HS_TRAIL, hs_trail);
- if (handle)
- cmdq_pkt_write((struct cmdq_pkt *)handle, comp->cmdq_base,
- comp->regs_pa+DSI_PHY_TIMECON0, value, ~0);
- else
- writel(value, dsi->regs + DSI_PHY_TIMECON0);
- value = REG_FLD_VAL(FLD_TA_GO, ta_go)
- | REG_FLD_VAL(FLD_TA_SURE, ta_sure)
- | REG_FLD_VAL(FLD_TA_GET, ta_get)
- | REG_FLD_VAL(FLD_DA_HS_EXIT, da_hs_exit);
- if (handle)
- cmdq_pkt_write((struct cmdq_pkt *)handle, comp->cmdq_base,
- comp->regs_pa+DSI_PHY_TIMECON1, value, ~0);
- else
- writel(value, dsi->regs + DSI_PHY_TIMECON1);
- value = REG_FLD_VAL(FLD_CONT_DET, cont_det)
- | REG_FLD_VAL(FLD_DA_HS_SYNC, da_hs_sync)
- | REG_FLD_VAL(FLD_CLK_HS_ZERO, clk_zero)
- | REG_FLD_VAL(FLD_CLK_HS_TRAIL, clk_trail);
- if (handle)
- cmdq_pkt_write((struct cmdq_pkt *)handle, comp->cmdq_base,
- comp->regs_pa+DSI_PHY_TIMECON2, value, ~0);
- else
- writel(value, dsi->regs + DSI_PHY_TIMECON2);
- value = REG_FLD_VAL(FLD_CLK_HS_PREP, clk_hs_prpr)
- | REG_FLD_VAL(FLD_CLK_HS_POST, clk_hs_post)
- | REG_FLD_VAL(FLD_CLK_HS_EXIT, clk_hs_exit);
- if (handle)
- cmdq_pkt_write((struct cmdq_pkt *)handle, comp->cmdq_base,
- comp->regs_pa+DSI_PHY_TIMECON3, value, ~0);
- else
- writel(value, dsi->regs + DSI_PHY_TIMECON3);
- }
- static void mtk_dsi_cphy_timconfig(struct mtk_dsi *dsi, void *handle)
- {
- struct mtk_dsi_phy_timcon *phy_timcon = NULL;
- u32 lpx = 0, hs_prpr = 0, hs_zero = 0, hs_trail = 0;
- u32 ta_get = 0, ta_sure = 0, ta_go = 0, da_hs_exit = 0;
- u32 clk_zero = 0, clk_trail = 0, da_hs_sync = 0;
- u32 clk_hs_prpr = 0, clk_hs_exit = 0, clk_hs_post = 0;
- u32 ui = 0, cycle_time = 0;
- u32 value = 0;
- struct mtk_ddp_comp *comp = &dsi->ddp_comp;
- DDPINFO("%s+\n", __func__);
- ui = 1000 / dsi->data_rate + 0x01;
- cycle_time = 8000 / dsi->data_rate + 0x01;
- lpx = NS_TO_CYCLE(dsi->data_rate * 0x4B, 0x1B58) + 0x1;
- hs_prpr = NS_TO_CYCLE(NS_TO_CYCLE(dsi->data_rate, 2) * 101,
- 0x1B58) + 0x1;
- hs_zero = 0x30;
- hs_trail = 0x20;
- ta_get = 5 * NS_TO_CYCLE(0x55, cycle_time);
- ta_sure = 3 * NS_TO_CYCLE(0x55, cycle_time) / 2;
- ta_go = 4 * NS_TO_CYCLE(0x55, cycle_time);
- da_hs_exit = NS_TO_CYCLE(NS_TO_CYCLE(dsi->data_rate, 2) * 225,
- 0x1B58) + 0x1;
- clk_zero = NS_TO_CYCLE(0x190, cycle_time);
- clk_trail = NS_TO_CYCLE(0x60, cycle_time) + 0x1;
- da_hs_sync = 0x1;
- clk_hs_prpr = NS_TO_CYCLE(0x40, cycle_time);
- clk_hs_exit = 2 * lpx;
- clk_hs_post = NS_TO_CYCLE(0x60 + 0x34 * ui, cycle_time);
- if (!(dsi->ext && dsi->ext->params))
- goto CONFIG_REG;
- phy_timcon = &dsi->ext->params->phy_timcon;
- lpx = CHK_SWITCH(phy_timcon->lpx, lpx);
- hs_prpr = CHK_SWITCH(phy_timcon->hs_prpr, hs_prpr);
- hs_zero = CHK_SWITCH(phy_timcon->hs_zero, hs_zero);
- hs_trail = CHK_SWITCH(phy_timcon->hs_trail, hs_trail);
- ta_get = CHK_SWITCH(phy_timcon->ta_get, ta_get);
- ta_sure = CHK_SWITCH(phy_timcon->ta_sure, ta_sure);
- ta_go = CHK_SWITCH(phy_timcon->ta_go, ta_go);
- da_hs_exit = CHK_SWITCH(phy_timcon->da_hs_exit, da_hs_exit);
- clk_zero = CHK_SWITCH(phy_timcon->clk_zero, clk_zero);
- clk_trail = CHK_SWITCH(phy_timcon->clk_trail, clk_trail);
- da_hs_sync = CHK_SWITCH(phy_timcon->da_hs_sync, da_hs_sync);
- clk_hs_prpr = CHK_SWITCH(phy_timcon->clk_hs_prpr, clk_hs_prpr);
- clk_hs_exit = CHK_SWITCH(phy_timcon->clk_hs_exit, clk_hs_exit);
- clk_hs_post = CHK_SWITCH(phy_timcon->clk_hs_post, clk_hs_post);
- CONFIG_REG:
- dsi->data_phy_cycle = hs_prpr + hs_zero + da_hs_exit + lpx + 5;
- value = REG_FLD_VAL(FLD_LPX, lpx)
- | REG_FLD_VAL(FLD_HS_PREP, hs_prpr)
- | REG_FLD_VAL(FLD_HS_ZERO, hs_zero)
- | REG_FLD_VAL(FLD_HS_TRAIL, hs_trail);
- if (handle)
- cmdq_pkt_write((struct cmdq_pkt *)handle, comp->cmdq_base,
- comp->regs_pa+DSI_PHY_TIMECON0, value, ~0);
- else
- writel(value, dsi->regs + DSI_PHY_TIMECON0);
- value = REG_FLD_VAL(FLD_TA_GO, ta_go)
- | REG_FLD_VAL(FLD_TA_SURE, ta_sure)
- | REG_FLD_VAL(FLD_TA_GET, ta_get)
- | REG_FLD_VAL(FLD_DA_HS_EXIT, da_hs_exit);
- if (handle)
- cmdq_pkt_write((struct cmdq_pkt *)handle, comp->cmdq_base,
- comp->regs_pa+DSI_PHY_TIMECON1, value, ~0);
- else
- writel(value, dsi->regs + DSI_PHY_TIMECON1);
- value = REG_FLD_VAL(FLD_DA_HS_SYNC, da_hs_sync)
- | REG_FLD_VAL(FLD_CLK_HS_ZERO, clk_zero)
- | REG_FLD_VAL(FLD_CLK_HS_TRAIL, clk_trail);
- if (handle)
- cmdq_pkt_write((struct cmdq_pkt *)handle, comp->cmdq_base,
- comp->regs_pa+DSI_PHY_TIMECON2, value, ~0);
- else
- writel(value, dsi->regs + DSI_PHY_TIMECON2);
- value = REG_FLD_VAL(FLD_CLK_HS_PREP, clk_hs_prpr)
- | REG_FLD_VAL(FLD_CLK_HS_POST, clk_hs_post)
- | REG_FLD_VAL(FLD_CLK_HS_EXIT, clk_hs_exit);
- if (handle)
- cmdq_pkt_write((struct cmdq_pkt *)handle, comp->cmdq_base,
- comp->regs_pa+DSI_PHY_TIMECON3, value, ~0);
- else
- writel(value, dsi->regs + DSI_PHY_TIMECON3);
- if (handle)
- cmdq_pkt_write((struct cmdq_pkt *)handle, comp->cmdq_base,
- comp->regs_pa+DSI_PHY_TIMECON0, 0x012c003, ~0);
- else
- writel(0x012c0003, dsi->regs + DSI_CPHY_CON0);
- }
- static void mtk_dsi_phy_timconfig(struct mtk_dsi *dsi,
- struct cmdq_pkt *handle)
- {
- dsi->ext = find_panel_ext(dsi->panel);
- if (!dsi->ext)
- return;
- if (dsi->ext->params->is_cphy)
- mtk_dsi_cphy_timconfig(dsi, handle);
- else
- mtk_dsi_dphy_timconfig(dsi, handle);
- }
- static void mtk_dsi_enable(struct mtk_dsi *dsi)
- {
- mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_EN, DSI_EN);
- #if !defined(CONFIG_MACH_MT6885)
- mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_CM_WAIT_FIFO_FULL_EN,
- DSI_CM_WAIT_FIFO_FULL_EN);
- #endif
- }
- static void mtk_dsi_disable(struct mtk_dsi *dsi)
- {
- mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_EN, 0);
- }
- static void mtk_dsi_reset_engine(struct mtk_dsi *dsi)
- {
- mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_RESET, DSI_RESET);
- mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_RESET, 0);
- }
- static void mtk_dsi_phy_reset(struct mtk_dsi *dsi)
- {
- mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_PHY_RESET, DSI_PHY_RESET);
- mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_PHY_RESET, 0);
- }
- static void mtk_dsi_clear_rxrd_irq(struct mtk_dsi *dsi)
- {
- mtk_dsi_mask(dsi, DSI_INTSTA, LPRX_RD_RDY_INT_FLAG, 0);
- }
- static unsigned int mtk_dsi_default_rate(struct mtk_dsi *dsi)
- {
- u32 data_rate;
- /**
- * vm.pixelclock is in kHz, pixel_clock unit is Hz, so multiply by 1000
- * htotal_time = htotal * byte_per_pixel / num_lanes
- * overhead_time = lpx + hs_prepare + hs_zero + hs_trail + hs_exit
- * mipi_ratio = (htotal_time + overhead_time) / htotal_time
- * data_rate = pixel_clock * bit_per_pixel * mipi_ratio / num_lanes;
- */
- if (dsi->ext && dsi->ext->params->data_rate) {
- data_rate = dsi->ext->params->data_rate;
- } else if (dsi->ext && dsi->ext->params->pll_clk) {
- data_rate = dsi->ext->params->pll_clk * 2;
- } else {
- u64 pixel_clock, total_bits;
- u32 htotal, htotal_bits, bit_per_pixel;
- u32 overhead_cycles, overhead_bits;
- switch (dsi->format) {
- case MIPI_DSI_FMT_RGB565:
- bit_per_pixel = 16;
- break;
- case MIPI_DSI_FMT_RGB666_PACKED:
- bit_per_pixel = 18;
- break;
- case MIPI_DSI_FMT_RGB666:
- case MIPI_DSI_FMT_RGB888:
- default:
- bit_per_pixel = 24;
- break;
- }
- pixel_clock = dsi->vm.pixelclock * 1000;
- htotal = dsi->vm.hactive + dsi->vm.hback_porch +
- dsi->vm.hfront_porch + dsi->vm.hsync_len;
- htotal_bits = htotal * bit_per_pixel;
- overhead_cycles = T_LPX + T_HS_PREP + T_HS_ZERO + T_HS_TRAIL +
- T_HS_EXIT;
- overhead_bits = overhead_cycles * dsi->lanes * 8;
- total_bits = htotal_bits + overhead_bits;
- data_rate = DIV_ROUND_UP_ULL(pixel_clock * total_bits,
- htotal * dsi->lanes);
- data_rate /= 1000000;
- }
- return data_rate;
- }
- static int mtk_dsi_set_LFR(struct mtk_dsi *dsi, struct mtk_ddp_comp *comp,
- void *handle)
- {
- u32 val = 0, mask = 0;
- //lfr_dbg: setting value form debug mode
- unsigned int lfr_dbg = mtk_dbg_get_lfr_dbg_value();
- unsigned int lfr_mode = LFR_MODE_BOTH_MODE;
- unsigned int lfr_type = 0;
- unsigned int lfr_enable = 1;
- unsigned int lfr_skip_num = 0;
- if (mtk_dsi_is_cmd_mode(&dsi->ddp_comp))
- return -1;
- //Settings lfr settings to LFR_CON_REG
- if (dsi->ext && dsi->ext->params &&
- dsi->ext->params->dyn_fps.lfr_minimum_fps != 0 &&
- dsi->ext->params->dyn_fps.lfr_enable == 1) {
- lfr_skip_num =
- (dsi->ext->params->dyn_fps.vact_timing_fps /
- dsi->ext->params->dyn_fps.lfr_minimum_fps) - 1;
- }
- if (lfr_dbg) {
- lfr_mode = mtk_dbg_get_lfr_mode_value();
- lfr_type = mtk_dbg_get_lfr_type_value();
- lfr_enable = mtk_dbg_get_lfr_enable_value();
- lfr_skip_num = mtk_dbg_get_lfr_skip_num_value();
- }
- SET_VAL_MASK(val, mask, lfr_mode, LFR_CON_FLD_REG_LFR_MODE);
- SET_VAL_MASK(val, mask, lfr_type, LFR_CON_FLD_REG_LFR_TYPE);
- SET_VAL_MASK(val, mask, lfr_enable, LFR_CON_FLD_REG_LFR_EN);
- SET_VAL_MASK(val, mask, 0, LFR_CON_FLD_REG_LFR_UPDATE);
- SET_VAL_MASK(val, mask, 1, LFR_CON_FLD_REG_LFR_VSE_DIS);
- SET_VAL_MASK(val, mask, lfr_skip_num, LFR_CON_FLD_REG_LFR_SKIP_NUM);
- if (handle == NULL)
- mtk_dsi_mask(dsi, DSI_LFR_CON, mask, val);
- else
- cmdq_pkt_write(handle, comp->cmdq_base,
- comp->regs_pa + DSI_LFR_CON, val, mask);
- return 0;
- }
- static int mtk_dsi_LFR_update(struct mtk_dsi *dsi, struct mtk_ddp_comp *comp,
- void *handle)
- {
- u32 val = 0, mask = 0;
- if (mtk_dsi_is_cmd_mode(&dsi->ddp_comp))
- return -1;
- if (comp == NULL) {
- DDPPR_ERR("%s mtk_ddp_comp is null\n", __func__);
- return -1;
- }
- if (handle == NULL) {
- DDPPR_ERR("%s cmdq handle is null\n", __func__);
- return -1;
- }
- SET_VAL_MASK(val, mask, 0, LFR_CON_FLD_REG_LFR_UPDATE);
- cmdq_pkt_write(handle, comp->cmdq_base,
- comp->regs_pa + DSI_LFR_CON, val, mask);
- SET_VAL_MASK(val, mask, 1, LFR_CON_FLD_REG_LFR_UPDATE);
- cmdq_pkt_write(handle, comp->cmdq_base,
- comp->regs_pa + DSI_LFR_CON, val, mask);
- return 0;
- }
- static int mtk_dsi_LFR_status_check(struct mtk_dsi *dsi)
- {
- u32 dsi_LFR_sta;
- u32 dsi_LFR_skip_cnt;
- u32 data;
- data = readl(dsi->regs + DSI_LFR_STA);
- dsi_LFR_sta = REG_FLD_VAL_GET(LFR_STA_FLD_REG_LFR_SKIP_STA, data);
- dsi_LFR_skip_cnt = REG_FLD_VAL_GET(LFR_STA_FLD_REG_LFR_SKIP_CNT, data);
- DDPINFO("%s dsi_LFR_sta=%d, dsi_LFR_skip_cnt=%d\n",
- __func__, dsi_LFR_sta, dsi_LFR_skip_cnt);
- return 0;
- }
- static int mtk_dsi_poweron(struct mtk_dsi *dsi)
- {
- struct device *dev = dsi->dev;
- int ret;
- unsigned int data_rate;
- unsigned long mipi_tx_rate;
- DDPDBG("%s+\n", __func__);
- if (++dsi->clk_refcnt != 1)
- return 0;
- data_rate = mtk_dsi_default_rate(dsi);
- mipi_tx_rate = data_rate * 1000000;
- /* Store DSI data rate in MHz */
- dsi->data_rate = data_rate;
- DDPDBG("set mipitx's data rate: %lu Hz\n", mipi_tx_rate);
- ret = clk_set_rate(dsi->hs_clk, mipi_tx_rate);
- if (ret < 0) {
- dev_err(dev, "Failed to set data rate: %d\n", ret);
- goto err_refcount;
- }
- if (dsi->ext) {
- if (dsi->ext->params->is_cphy)
- mtk_mipi_tx_cphy_lane_config(dsi->phy, dsi->ext);
- else
- mtk_mipi_tx_dphy_lane_config(dsi->phy, dsi->ext);
- }
- phy_power_on(dsi->phy);
- ret = clk_prepare_enable(dsi->engine_clk);
- if (ret < 0) {
- dev_err(dev, "Failed to enable engine clock: %d\n", ret);
- goto err_phy_power_off;
- }
- ret = clk_prepare_enable(dsi->digital_clk);
- if (ret < 0) {
- dev_err(dev, "Failed to enable digital clock: %d\n", ret);
- goto err_disable_engine_clk;
- }
- mtk_dsi_set_LFR(dsi, NULL, NULL);
- #if defined(CONFIG_DRM_MTK_SHADOW_REGISTER_SUPPORT)
- if (dsi->driver_data->support_shadow) {
- /* Enable shadow register and read shadow register */
- mtk_dsi_mask(dsi, DSI_SHADOW_DEBUG,
- DSI_BYPASS_SHADOW, 0x0);
- } else {
- /* Bypass shadow register and read shadow register */
- mtk_dsi_mask(dsi, DSI_SHADOW_DEBUG,
- DSI_BYPASS_SHADOW, DSI_BYPASS_SHADOW);
- }
- #else
- #if defined(CONFIG_MACH_MT6873) || defined(CONFIG_MACH_MT6853) \
- || defined(CONFIG_MACH_MT6833)
- /* Bypass shadow register and read shadow register */
- mtk_dsi_mask(dsi, DSI_SHADOW_DEBUG,
- DSI_BYPASS_SHADOW, DSI_BYPASS_SHADOW);
- #endif
- #endif
- DDPDBG("%s-\n", __func__);
- return 0;
- err_disable_engine_clk:
- clk_disable_unprepare(dsi->engine_clk);
- err_phy_power_off:
- phy_power_off(dsi->phy);
- err_refcount:
- dsi->clk_refcnt--;
- return ret;
- }
- static bool mtk_dsi_clk_hs_state(struct mtk_dsi *dsi)
- {
- u32 tmp_reg1;
- tmp_reg1 = readl(dsi->regs + DSI_PHY_LCCON);
- return ((tmp_reg1 & LC_HS_TX_EN) == 1) ? true : false;
- }
- static void mtk_dsi_clk_hs_mode(struct mtk_dsi *dsi, bool enter)
- {
- if (enter && !mtk_dsi_clk_hs_state(dsi))
- mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, LC_HS_TX_EN);
- else if (!enter && mtk_dsi_clk_hs_state(dsi))
- mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, 0);
- }
- static void mtk_dsi_set_mode(struct mtk_dsi *dsi)
- {
- u32 vid_mode = CMD_MODE;
- if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
- if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
- vid_mode = BURST_MODE;
- else if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
- vid_mode = SYNC_PULSE_MODE;
- else
- vid_mode = SYNC_EVENT_MODE;
- }
- writel(vid_mode, dsi->regs + DSI_MODE_CTRL);
- }
- static void mtk_dsi_set_vm_cmd(struct mtk_dsi *dsi)
- {
- mtk_dsi_mask(dsi, DSI_VM_CMD_CON, VM_CMD_EN, VM_CMD_EN);
- mtk_dsi_mask(dsi, DSI_VM_CMD_CON, TS_VFP_EN, TS_VFP_EN);
- }
- static int mtk_dsi_get_virtual_heigh(struct mtk_dsi *dsi,
- struct drm_crtc *crtc)
- {
- struct mtk_panel_ext *panel_ext = NULL;
- struct mtk_crtc_state *state =
- to_mtk_crtc_state(crtc->state);
- struct drm_display_mode adjusted_mode = state->base.adjusted_mode;
- unsigned int virtual_heigh = adjusted_mode.vdisplay;
- panel_ext = dsi->ext;
- if (panel_ext && panel_ext->funcs
- && panel_ext->funcs->get_virtual_heigh)
- virtual_heigh = panel_ext->funcs->get_virtual_heigh();
- if (!virtual_heigh)
- virtual_heigh = crtc->mode.vdisplay;
- DDPINFO("%s,virtual_heigh %d\n", __func__, virtual_heigh);
- return virtual_heigh;
- }
- static int mtk_dsi_get_virtual_width(struct mtk_dsi *dsi,
- struct drm_crtc *crtc)
- {
- struct mtk_panel_ext *panel_ext = NULL;
- struct mtk_crtc_state *state =
- to_mtk_crtc_state(crtc->state);
- struct drm_display_mode adjusted_mode = state->base.adjusted_mode;
- unsigned int virtual_width = adjusted_mode.hdisplay;
- panel_ext = dsi->ext;
- if (panel_ext && panel_ext->funcs
- && panel_ext->funcs->get_virtual_width)
- virtual_width = panel_ext->funcs->get_virtual_width();
- if (!virtual_width)
- virtual_width = crtc->mode.hdisplay;
- DDPINFO("%s,virtual_width %d\n", __func__, virtual_width);
- return virtual_width;
- }
- static void mtk_dsi_ps_control_vact(struct mtk_dsi *dsi)
- {
- u32 ps_wc, size;
- u32 dsi_buf_bpp, val;
- u32 value = 0, mask = 0;
- u32 width = mtk_dsi_get_virtual_width(dsi, dsi->encoder.crtc);
- u32 height = mtk_dsi_get_virtual_heigh(dsi, dsi->encoder.crtc);
- struct mtk_panel_ext *ext = mtk_dsi_get_panel_ext(&dsi->ddp_comp);
- struct mtk_panel_dsc_params *dsc_params = &ext->params->dsc_params;
- if (dsi->format == MIPI_DSI_FMT_RGB565)
- dsi_buf_bpp = 2;
- else
- dsi_buf_bpp = 3;
- if (dsc_params->enable == 0) {
- ps_wc = width * dsi_buf_bpp;
- SET_VAL_MASK(value, mask, ps_wc, DSI_PS_WC);
- switch (dsi->format) {
- case MIPI_DSI_FMT_RGB888:
- SET_VAL_MASK(value, mask, 3, DSI_PS_SEL);
- break;
- case MIPI_DSI_FMT_RGB666:
- SET_VAL_MASK(value, mask, 2, DSI_PS_SEL);
- break;
- case MIPI_DSI_FMT_RGB666_PACKED:
- SET_VAL_MASK(value, mask, 1, DSI_PS_SEL);
- break;
- case MIPI_DSI_FMT_RGB565:
- SET_VAL_MASK(value, mask, 0, DSI_PS_SEL);
- break;
- }
- size = (height << 16) + width;
- } else {
- ps_wc = (((dsc_params->chunk_size + 2) / 3) * 3);
- if (dsc_params->slice_mode == 1)
- ps_wc *= 2;
- SET_VAL_MASK(value, mask, ps_wc, DSI_PS_WC);
- SET_VAL_MASK(value, mask, 5, DSI_PS_SEL);
- size = (height << 16) + (ps_wc / 3);
- }
- writel(height, dsi->regs + DSI_VACT_NL);
- val = readl(dsi->regs + DSI_PSCTRL);
- val = (val & ~mask) | (value & mask);
- writel(val, dsi->regs + DSI_PSCTRL);
- #if !defined(CONFIG_MACH_MT6885) && !defined(CONFIG_MACH_MT6873) \
- && !defined(CONFIG_MACH_MT6893) && !defined(CONFIG_MACH_MT6853) \
- && !defined(CONFIG_MACH_MT6833)
- val = vm->hactive * dsi_buf_bpp;
- writel(val, dsi->regs + DSI_HSTX_CKL_WC);
- #endif
- writel(size, dsi->regs + DSI_SIZE_CON);
- }
- static void mtk_dsi_rxtx_control(struct mtk_dsi *dsi)
- {
- u32 tmp_reg;
- switch (dsi->lanes) {
- case 1:
- tmp_reg = 1 << 2;
- break;
- case 2:
- tmp_reg = 3 << 2;
- break;
- case 3:
- tmp_reg = 7 << 2;
- break;
- case 4:
- tmp_reg = 0xf << 2;
- break;
- default:
- tmp_reg = 0xf << 2;
- break;
- }
- tmp_reg |= (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) << 6;
- #if !defined(CONFIG_MACH_MT6885) && !defined(CONFIG_MACH_MT6873) \
- && !defined(CONFIG_MACH_MT6893) && !defined(CONFIG_MACH_MT6853) \
- && !defined(CONFIG_MACH_MT6833)
- tmp_reg |= (dsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET) >> 3;
- #endif
- writel(tmp_reg, dsi->regs + DSI_TXRX_CTRL);
- /* need to config for cmd mode to transmit frame data to DDIC */
- writel(DSI_WMEM_CONTI, dsi->regs + DSI_MEM_CONTI);
- }
- static void mtk_dsi_calc_vdo_timing(struct mtk_dsi *dsi)
- {
- u32 horizontal_sync_active_byte;
- u32 horizontal_backporch_byte;
- u32 horizontal_frontporch_byte;
- u32 dsi_tmp_buf_bpp;
- u32 t_vfp, t_vbp, t_vsa;
- u32 t_hfp, t_hbp, t_hsa;
- struct mtk_panel_ext *ext = dsi->ext;
- struct videomode *vm = &dsi->vm;
- struct dynamic_mipi_params *dyn = NULL;
- if (ext && ext->params)
- dyn = &ext->params->dyn;
- t_vfp = (dsi->mipi_hopping_sta) ?
- ((dyn && !!dyn->vfp) ?
- dyn->vfp : vm->vfront_porch) :
- vm->vfront_porch;
- t_vbp = (dsi->mipi_hopping_sta) ?
- ((dyn && !!dyn->vbp) ?
- dyn->vbp : vm->vback_porch) :
- vm->vback_porch;
- t_vsa = (dsi->mipi_hopping_sta) ?
- ((dyn && !!dyn->vsa) ?
- dyn->vsa : vm->vsync_len) :
- vm->vsync_len;
- t_hfp = (dsi->mipi_hopping_sta) ?
- ((dyn && !!dyn->hfp) ?
- dyn->hfp : vm->hfront_porch) :
- vm->hfront_porch;
- t_hbp = (dsi->mipi_hopping_sta) ?
- ((dyn && !!dyn->hbp) ?
- dyn->hbp : vm->hback_porch) :
- vm->hback_porch;
- t_hsa = (dsi->mipi_hopping_sta) ?
- ((dyn && !!dyn->hsa) ?
- dyn->hsa : vm->hsync_len) :
- vm->hsync_len;
- if (dsi->format == MIPI_DSI_FMT_RGB565)
- dsi_tmp_buf_bpp = 2;
- else
- dsi_tmp_buf_bpp = 3;
- dsi->ext = find_panel_ext(dsi->panel);
- if (!dsi->ext)
- return;
- if (dsi->ext->params->is_cphy) {
- if (t_hsa * dsi_tmp_buf_bpp < 10 * dsi->lanes + 26 + 5)
- horizontal_sync_active_byte = 4;
- else
- horizontal_sync_active_byte = ALIGN_TO(
- t_hsa * dsi_tmp_buf_bpp -
- 10 * dsi->lanes - 26, 2);
- if (t_hbp * dsi_tmp_buf_bpp < 12 * dsi->lanes + 26 + 5)
- horizontal_backporch_byte = 4;
- else
- horizontal_backporch_byte = ALIGN_TO(
- t_hbp * dsi_tmp_buf_bpp -
- 12 * dsi->lanes - 26, 2);
- if (t_hfp * dsi_tmp_buf_bpp < 8 * dsi->lanes + 28 +
- 2 * dsi->data_phy_cycle * dsi->lanes + 9)
- horizontal_frontporch_byte = 8;
- else if ((t_hfp * dsi_tmp_buf_bpp > 8 * dsi->lanes + 28 +
- 2 * dsi->data_phy_cycle * dsi->lanes + 8) &&
- (t_hfp * dsi_tmp_buf_bpp < 8 * dsi->lanes + 28 +
- 2 * dsi->data_phy_cycle * dsi->lanes +
- 2 * (32 + 1) * dsi->lanes - 6 * dsi->lanes - 12))
- horizontal_frontporch_byte = 2*(32 + 1)*dsi->lanes -
- 6*dsi->lanes - 12;
- else
- horizontal_frontporch_byte = t_hfp * dsi_tmp_buf_bpp -
- 8 * dsi->lanes - 28 -
- 2 * dsi->data_phy_cycle * dsi->lanes;
- } else {
- if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) {
- horizontal_sync_active_byte =
- ALIGN_TO((t_hsa * dsi_tmp_buf_bpp - 10), 4);
- horizontal_backporch_byte =
- ALIGN_TO((t_hbp * dsi_tmp_buf_bpp - 10), 4);
- } else {
- horizontal_sync_active_byte =
- ALIGN_TO((t_hsa * dsi_tmp_buf_bpp - 4), 4);
- horizontal_backporch_byte =
- ALIGN_TO(((t_hbp + t_hsa) * dsi_tmp_buf_bpp -
- 10), 4);
- }
- horizontal_frontporch_byte =
- ALIGN_TO((t_hfp * dsi_tmp_buf_bpp - 12), 4);
- }
- dsi->vfp = t_vfp;
- dsi->vbp = t_vbp;
- dsi->vsa = t_vsa;
- dsi->hfp_byte = horizontal_frontporch_byte;
- dsi->hbp_byte = horizontal_backporch_byte;
- dsi->hsa_byte = horizontal_sync_active_byte;
- }
- static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi)
- {
- struct videomode *vm = &dsi->vm;
- unsigned int vact = vm->vactive;
- writel(dsi->vsa, dsi->regs + DSI_VSA_NL);
- writel(dsi->vbp, dsi->regs + DSI_VBP_NL);
- writel(dsi->vfp, dsi->regs + DSI_VFP_NL);
- vact = mtk_dsi_get_virtual_heigh(dsi, dsi->encoder.crtc);
- writel(vact, dsi->regs + DSI_VACT_NL);
- writel(dsi->hsa_byte, dsi->regs + DSI_HSA_WC);
- writel(dsi->hbp_byte, dsi->regs + DSI_HBP_WC);
- writel(dsi->hfp_byte, dsi->regs + DSI_HFP_WC);
- }
- static void mtk_dsi_start(struct mtk_dsi *dsi)
- {
- writel(0, dsi->regs + DSI_START);
- writel(1, dsi->regs + DSI_START);
- }
- static void mtk_dsi_vm_start(struct mtk_dsi *dsi)
- {
- mtk_dsi_mask(dsi, DSI_START, VM_CMD_START, 0);
- mtk_dsi_mask(dsi, DSI_START, VM_CMD_START, VM_CMD_START);
- }
- static void mtk_dsi_stop(struct mtk_dsi *dsi)
- {
- writel(0, dsi->regs + DSI_START);
- writel(0, dsi->regs + DSI_INTEN);
- writel(0, dsi->regs + DSI_INTSTA);
- }
- static void mtk_dsi_set_interrupt_enable(struct mtk_dsi *dsi)
- {
- u32 inten;
- inten = BUFFER_UNDERRUN_INT_FLAG | INP_UNFINISH_INT_EN;
- if (!mtk_dsi_is_cmd_mode(&dsi->ddp_comp))
- inten |= FRAME_DONE_INT_FLAG;
- else
- inten |= TE_RDY_INT_FLAG;
- writel(inten, dsi->regs + DSI_INTEN);
- }
- static void mtk_dsi_irq_data_set(struct mtk_dsi *dsi, u32 irq_bit)
- {
- dsi->irq_data |= irq_bit;
- }
- static void mtk_dsi_irq_data_clear(struct mtk_dsi *dsi, u32 irq_bit)
- {
- dsi->irq_data &= ~irq_bit;
- }
- static s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi *dsi, u32 irq_flag,
- unsigned int timeout)
- {
- s32 ret = 0;
- unsigned long jiffies = msecs_to_jiffies(timeout);
- ret = wait_event_interruptible_timeout(
- dsi->irq_wait_queue, dsi->irq_data & irq_flag, jiffies);
- if (ret == 0) {
- DRM_WARN("Wait DSI IRQ(0x%08x) Timeout\n", irq_flag);
- mtk_dsi_enable(dsi);
- mtk_dsi_reset_engine(dsi);
- }
- return ret;
- }
- static void mtk_dsi_cmdq_poll(struct mtk_ddp_comp *comp,
- struct cmdq_pkt *handle, unsigned int reg,
- unsigned int val, unsigned int mask)
- {
- struct mtk_drm_crtc *mtk_crtc = comp->mtk_crtc;
- struct cmdq_client *client = mtk_crtc->gce_obj.client[CLIENT_DSI_CFG];
- if (handle == NULL)
- DDPPR_ERR("%s no cmdq handle\n", __func__);
- #if 0
- cmdq_pkt_poll_reg(handle, val, comp->cmdq_subsys, reg & 0xFFFF, mask);
- #else
- if (handle->cl == (void *)client) {
- cmdq_pkt_poll_timeout(handle, val, SUBSYS_NO_SUPPORT,
- reg, mask, 0xFFFF,
- CMDQ_GPR_R14);
- } else {
- cmdq_pkt_poll_timeout(handle, val, SUBSYS_NO_SUPPORT,
- reg, mask, 0xFFFF,
- CMDQ_GPR_R07);
- }
- #endif
- }
- static s32 mtk_dsi_poll_for_idle(struct mtk_dsi *dsi, struct cmdq_pkt *handle)
- {
- unsigned int loop_cnt = 0;
- s32 tmp;
- if (handle) {
- mtk_dsi_cmdq_poll(&dsi->ddp_comp, handle,
- dsi->ddp_comp.regs_pa + DSI_INTSTA, 0,
- 0x80000000);
- return 1;
- }
- while (loop_cnt < 100 * 1000) {
- tmp = readl(dsi->regs + DSI_INTSTA);
- if (!(tmp & DSI_BUSY))
- return 1;
- loop_cnt++;
- udelay(1);
- }
- DDPPR_ERR("%s timeout\n", __func__);
- return 0;
- }
- static s32 mtk_dsi_wait_idle(struct mtk_dsi *dsi, u32 irq_flag,
- unsigned int timeout, struct cmdq_pkt *handle)
- {
- if (dsi->driver_data->poll_for_idle)
- return dsi->driver_data->poll_for_idle(dsi, handle);
- return mtk_dsi_wait_for_irq_done(dsi, irq_flag, timeout);
- }
- static void init_dsi_wq(struct mtk_dsi *dsi)
- {
- init_waitqueue_head(&dsi->enter_ulps_done.wq);
- init_waitqueue_head(&dsi->exit_ulps_done.wq);
- init_waitqueue_head(&dsi->te_rdy.wq);
- init_waitqueue_head(&dsi->frame_done.wq);
- atomic_set(&dsi->enter_ulps_done.condition, 0);
- atomic_set(&dsi->exit_ulps_done.condition, 0);
- atomic_set(&dsi->te_rdy.condition, 0);
- atomic_set(&dsi->frame_done.condition, 0);
- }
- static void reset_dsi_wq(struct t_condition_wq *wq)
- {
- atomic_set(&wq->condition, 0);
- }
- static void wakeup_dsi_wq(struct t_condition_wq *wq)
- {
- atomic_set(&wq->condition, 1);
- wake_up(&wq->wq);
- }
- static int wait_dsi_wq(struct t_condition_wq *wq, int timeout)
- {
- int ret;
- ret = wait_event_timeout(wq->wq, atomic_read(&wq->condition), timeout);
- atomic_set(&wq->condition, 0);
- return ret;
- }
- static irqreturn_t mtk_dsi_irq_status(int irq, void *dev_id)
- {
- struct mtk_dsi *dsi = dev_id;
- struct mtk_drm_crtc *mtk_crtc;
- struct mtk_panel_ext *panel_ext;
- u32 status;
- static unsigned int dsi_underrun_trigger = 1;
- unsigned int ret = 0;
- #if defined(CONFIG_MACH_MT6873) || defined(CONFIG_MACH_MT6853) \
- || defined(CONFIG_MACH_MT6833)
- static DEFINE_RATELIMIT_STATE(ioctl_ratelimit, 1 * HZ, 20);
- #endif
- bool doze_enabled = 0;
- unsigned int doze_wait = 0;
- static unsigned int cnt;
- if (mtk_drm_top_clk_isr_get("dsi_irq") == false) {
- DDPIRQ("%s, top clk off\n", __func__);
- return IRQ_NONE;
- }
- status = readl(dsi->regs + DSI_INTSTA);
- if (!status) {
- ret = IRQ_NONE;
- goto out;
- }
- DRM_MMP_MARK(IRQ, irq, status);
- if (dsi->ddp_comp.id == DDP_COMPONENT_DSI0)
- DRM_MMP_MARK(dsi0, status, 0);
- else if (dsi->ddp_comp.id == DDP_COMPONENT_DSI1)
- DRM_MMP_MARK(dsi1, status, 0);
- DDPIRQ("%s irq, val:0x%x\n", mtk_dump_comp_str(&dsi->ddp_comp), status);
- /*
- * rd_rdy don't clear and wait for ESD &
- * Read LCM will clear the bit.
- */
- /* do not clear vm command done */
- status &= 0xffde;
- if (status) {
- writel(~status, dsi->regs + DSI_INTSTA);
- if (status & BUFFER_UNDERRUN_INT_FLAG) {
- struct mtk_drm_private *priv = NULL;
- mtk_crtc = dsi->ddp_comp.mtk_crtc;
- if (mtk_crtc && mtk_crtc->base.dev)
- priv = mtk_crtc->base.dev->dev_private;
- if (priv && mtk_drm_helper_get_opt(priv->helper_opt,
- MTK_DRM_OPT_DSI_UNDERRUN_AEE)) {
- if (dsi_underrun_trigger == 1) {
- DDPAEE(
- "[IRQ] %s:buffer underrun,sys_time=%u\n",
- mtk_dump_comp_str(
- &dsi->ddp_comp),
- (u32)arch_counter_get_cntvct());
- if (dsi->encoder.crtc) {
- mtk_drm_crtc_analysis(
- dsi->encoder.crtc);
- mtk_drm_crtc_dump(
- dsi->encoder.crtc);
- }
- dsi_underrun_trigger = 0;
- }
- }
- #if defined(CONFIG_MACH_MT6873) || defined(CONFIG_MACH_MT6853) \
- || defined(CONFIG_MACH_MT6833)
- mtk_dprec_logger_pr(DPREC_LOGGER_ERROR,
- "[IRQ] %s: buffer underrun\n",
- mtk_dump_comp_str(&dsi->ddp_comp));
- if (__ratelimit(&ioctl_ratelimit))
- pr_err(pr_fmt("[IRQ] %s: buffer underrun\n"),
- mtk_dump_comp_str(&dsi->ddp_comp));
- #else
- DDPPR_ERR("[IRQ] %s: buffer underrun\n",
- mtk_dump_comp_str(&dsi->ddp_comp));
- #endif
- if (dsi_underrun_trigger == 1 && dsi->encoder.crtc) {
- mtk_drm_crtc_analysis(dsi->encoder.crtc);
- mtk_drm_crtc_dump(dsi->encoder.crtc);
- dsi_underrun_trigger = 0;
- }
- }
- if (status & INP_UNFINISH_INT_EN)
- DDPPR_ERR("[IRQ] %s: input relay unfinish\n",
- mtk_dump_comp_str(&dsi->ddp_comp));
- if (status & SLEEPOUT_DONE_INT_FLAG)
- wakeup_dsi_wq(&dsi->exit_ulps_done);
- if (status & SLEEPIN_ULPS_DONE_INT_FLAG)
- wakeup_dsi_wq(&dsi->enter_ulps_done);
- if (status & TE_RDY_INT_FLAG) {
- struct mtk_drm_private *priv = NULL;
- if (dsi->ddp_comp.id == DDP_COMPONENT_DSI0) {
- unsigned long long ext_te_time = sched_clock();
- lcm_fps_ctx_update(ext_te_time, 0, 0);
- }
- mtk_crtc = dsi->ddp_comp.mtk_crtc;
- if (mtk_crtc && mtk_crtc->base.dev)
- priv = mtk_crtc->base.dev->dev_private;
- if (priv && mtk_drm_helper_get_opt(priv->helper_opt,
- MTK_DRM_OPT_HBM))
- wakeup_dsi_wq(&dsi->te_rdy);
- if (mtk_dsi_is_cmd_mode(&dsi->ddp_comp) &&
- mtk_crtc && mtk_crtc->vblank_en) {
- panel_ext = dsi->ext;
- if (dsi->encoder.crtc)
- doze_enabled = mtk_dsi_doze_state(dsi);
- if (panel_ext->params->doze_delay &&
- doze_enabled) {
- doze_wait =
- panel_ext->params->doze_delay;
- if (cnt % doze_wait == 0) {
- mtk_crtc_vblank_irq(
- &mtk_crtc->base);
- cnt = 0;
- }
- cnt++;
- } else
- mtk_crtc_vblank_irq(&mtk_crtc->base);
- }
- }
- if (status & FRAME_DONE_INT_FLAG) {
- struct mtk_drm_private *priv = NULL;
- mtk_crtc = dsi->ddp_comp.mtk_crtc;
- if (mtk_crtc && mtk_crtc->base.dev)
- priv = mtk_crtc->base.dev->dev_private;
- if (priv && mtk_drm_helper_get_opt(priv->helper_opt,
- MTK_DRM_OPT_HBM))
- wakeup_dsi_wq(&dsi->frame_done);
- if (!mtk_dsi_is_cmd_mode(&dsi->ddp_comp) &&
- mtk_crtc && mtk_crtc->vblank_en)
- mtk_crtc_vblank_irq(&mtk_crtc->base);
- }
- }
- ret = IRQ_HANDLED;
- out:
- mtk_drm_top_clk_isr_put("dsi_irq");
- return ret;
- }
- static irqreturn_t mtk_dsi_irq(int irq, void *dev_id)
- {
- struct mtk_dsi *dsi = dev_id;
- u32 status, tmp;
- u32 flag = LPRX_RD_RDY_INT_FLAG | CMD_DONE_INT_FLAG | VM_DONE_INT_FLAG;
- status = readl(dsi->regs + DSI_INTSTA) & flag;
- if (status) {
- do {
- mtk_dsi_mask(dsi, DSI_RACK, RACK, RACK);
- tmp = readl(dsi->regs + DSI_INTSTA);
- } while (tmp & DSI_BUSY);
- mtk_dsi_mask(dsi, DSI_INTSTA, status, 0);
- mtk_dsi_irq_data_set(dsi, status);
- wake_up_interruptible(&dsi->irq_wait_queue);
- }
- return IRQ_HANDLED;
- }
- static void mtk_dsi_poweroff(struct mtk_dsi *dsi)
- {
- DDPDBG("%s +\n", __func__);
- if (dsi->clk_refcnt == 0) {
- DDPAEE("%s:%d, invalid cnt:%d\n",
- __func__, __LINE__,
- dsi->clk_refcnt);
- return;
- }
- if (--dsi->clk_refcnt != 0)
- return;
- clk_disable_unprepare(dsi->engine_clk);
- clk_disable_unprepare(dsi->digital_clk);
- phy_power_off(dsi->phy);
- DDPDBG("%s -\n", __func__);
- }
- static void mtk_dsi_enter_ulps(struct mtk_dsi *dsi)
- {
- unsigned int ret = 0;
- /* reset enter_ulps_done before waiting */
- reset_dsi_wq(&dsi->enter_ulps_done);
- /* config and trigger enter ulps mode */
- mtk_dsi_mask(dsi, DSI_INTEN, SLEEPIN_ULPS_DONE_INT_FLAG,
- SLEEPIN_ULPS_DONE_INT_FLAG);
- mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, 0);
- mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LDX_ULPM_AS_L0, LDX_ULPM_AS_L0);
- mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_ULPM_EN, LD0_ULPM_EN);
- mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_ULPM_EN, LC_ULPM_EN);
- /* wait enter_ulps_done */
- ret = wait_dsi_wq(&dsi->enter_ulps_done, 2 * HZ);
- if (ret)
- DDPDBG("%s success\n", __func__);
- else {
- /* IRQ maybe be un-expectedly disabled for long time,
- * which makes false alarm timeout...
- */
- u32 status = readl(dsi->regs + DSI_INTSTA);
- if (status & SLEEPIN_ULPS_DONE_INT_FLAG)
- DDPPR_ERR("%s success but IRQ is blocked\n",
- __func__);
- else {
- mtk_dsi_dump(&dsi->ddp_comp);
- DDPAEE("%s fail\n", __func__);
- }
- }
- /* reset related setting */
- mtk_dsi_mask(dsi, DSI_INTEN, SLEEPIN_ULPS_DONE_INT_FLAG, 0);
- mtk_mipi_tx_pre_oe_config(dsi->phy, 0);
- mtk_mipi_tx_sw_control_en(dsi->phy, 1);
- /* set lane num = 0 */
- mtk_dsi_mask(dsi, DSI_TXRX_CTRL, LANE_NUM, 0);
- }
- static void mtk_dsi_exit_ulps(struct mtk_dsi *dsi)
- {
- int wake_up_prd = (dsi->data_rate * 1000) / (1024 * 8) + 1;
- unsigned int ret = 0;
- mtk_dsi_phy_reset(dsi);
- /* set pre oe */
- mtk_mipi_tx_pre_oe_config(dsi->phy, 1);
- /* reset exit_ulps_done before waiting */
- reset_dsi_wq(&dsi->exit_ulps_done);
- mtk_dsi_mask(dsi, DSI_INTEN, SLEEPOUT_DONE_INT_FLAG,
- SLEEPOUT_DONE_INT_FLAG);
- mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LDX_ULPM_AS_L0, LDX_ULPM_AS_L0);
- mtk_dsi_mask(dsi, DSI_MODE_CTRL, SLEEP_MODE, SLEEP_MODE);
- mtk_dsi_mask(dsi, DSI_TIME_CON0, 0xffff, wake_up_prd);
- /* free sw control */
- mtk_mipi_tx_sw_control_en(dsi->phy, 0);
- mtk_dsi_mask(dsi, DSI_START, SLEEPOUT_START, 0);
- mtk_dsi_mask(dsi, DSI_START, SLEEPOUT_START, SLEEPOUT_START);
- /* wait exit_ulps_done */
- ret = wait_dsi_wq(&dsi->exit_ulps_done, 2 * HZ);
- if (ret)
- DDPDBG("%s success\n", __func__);
- else {
- /* IRQ maybe be un-expectedly disabled for long time,
- * which makes false alarm timeout...
- */
- u32 status = readl(dsi->regs + DSI_INTSTA);
- if (status & SLEEPOUT_DONE_INT_FLAG)
- DDPPR_ERR("%s success but IRQ is blocked\n",
- __func__);
- else {
- mtk_dsi_dump(&dsi->ddp_comp);
- DDPAEE("%s fail\n", __func__);
- }
- }
- /* reset related setting */
- mtk_dsi_mask(dsi, DSI_INTEN, SLEEPOUT_DONE_INT_FLAG, 0);
- mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LDX_ULPM_AS_L0, 0);
- mtk_dsi_mask(dsi, DSI_MODE_CTRL, SLEEP_MODE, 0);
- mtk_dsi_mask(dsi, DSI_START, SLEEPOUT_START, 0);
- /* do DSI reset after exit ULPS */
- mtk_dsi_reset_engine(dsi);
- }
- static int mtk_dsi_stop_vdo_mode(struct mtk_dsi *dsi, void *handle);
- static void mipi_dsi_dcs_write_gce2(struct mtk_dsi *dsi, struct cmdq_pkt *dummy,
- const void *data, size_t len);
- static void mtk_output_en_doze_switch(struct mtk_dsi *dsi)
- {
- bool doze_enabled = mtk_dsi_doze_state(dsi);
- struct mtk_panel_funcs *panel_funcs;
- if (!dsi->output_en)
- return;
- DDPINFO("%s doze_enabled state change %d->%d\n", __func__,
- dsi->doze_enabled, doze_enabled);
- if (dsi->ext && dsi->ext->funcs) {
- panel_funcs = dsi->ext->funcs;
- } else {
- DDPINFO("%s, AOD should have use panel extension function\n",
- __func__);
- return;
- }
- /* Change LCM Doze mode */
- if (doze_enabled && panel_funcs->doze_enable_start)
- panel_funcs->doze_enable_start(dsi->panel, dsi,
- mipi_dsi_dcs_write_gce2, NULL);
- else if (!doze_enabled && panel_funcs->doze_disable)
- panel_funcs->doze_disable(dsi->panel, dsi,
- mipi_dsi_dcs_write_gce2, NULL);
- /* Display mode switch */
- if (panel_funcs->doze_get_mode_flags) {
- if (!mtk_dsi_is_cmd_mode(&dsi->ddp_comp))
- mtk_dsi_stop_vdo_mode(dsi, NULL);
- /* set DSI into ULPS mode */
- mtk_dsi_reset_engine(dsi);
- dsi->mode_flags =
- panel_funcs->doze_get_mode_flags(
- dsi->panel, doze_enabled);
- if (mtk_dsi_is_cmd_mode(&dsi->ddp_comp))
- writel(0x0001023c, dsi->regs + DSI_TXRX_CTRL);
- mtk_dsi_set_mode(dsi);
- mtk_dsi_clk_hs_mode(dsi, 1);
- /* Update RDMA golden setting after switch */
- {
- struct drm_crtc *crtc = dsi->encoder.crtc;
- struct mtk_drm_crtc *mtk_crtc =
- to_mtk_crtc(dsi->encoder.crtc);
- unsigned int i, j;
- struct cmdq_pkt *handle;
- struct mtk_ddp_comp *comp;
- struct mtk_ddp_config cfg;
- mtk_crtc_pkt_create(&handle, &mtk_crtc->base,
- mtk_crtc->gce_obj.client[CLIENT_CFG]);
- cfg.w = crtc->state->adjusted_mode.hdisplay;
- cfg.h = crtc->state->adjusted_mode.vdisplay;
- cfg.vrefresh = crtc->state->adjusted_mode.vrefresh;
- cfg.bpc = mtk_crtc->bpc;
- cfg.p_golden_setting_context =
- __get_golden_setting_context(mtk_crtc);
- for_each_comp_in_cur_crtc_path(comp, mtk_crtc, i, j)
- mtk_ddp_comp_io_cmd(comp, handle,
- MTK_IO_CMD_RDMA_GOLDEN_SETTING, &cfg);
- cmdq_pkt_flush(handle);
- cmdq_pkt_destroy(handle);
- }
- if (!mtk_dsi_is_cmd_mode(&dsi->ddp_comp)) {
- mtk_dsi_set_vm_cmd(dsi);
- mtk_dsi_calc_vdo_timing(dsi);
- mtk_dsi_config_vdo_timing(dsi);
- mtk_dsi_start(dsi);
- }
- }
- if (doze_enabled && panel_funcs->doze_enable)
- panel_funcs->doze_enable(dsi->panel, dsi,
- mipi_dsi_dcs_write_gce2, NULL);
- if (doze_enabled && panel_funcs->doze_area)
- panel_funcs->doze_area(dsi->panel, dsi,
- mipi_dsi_dcs_write_gce2, NULL);
- if (panel_funcs->doze_post_disp_on)
- panel_funcs->doze_post_disp_on(dsi->panel,
- dsi, mipi_dsi_dcs_write_gce2, NULL);
- dsi->doze_enabled = doze_enabled;
- }
- static void mtk_output_dsi_enable(struct mtk_dsi *dsi,
- int force_lcm_update)
- {
- int ret;
- struct mtk_panel_ext *ext = dsi->ext;
- bool new_doze_state = mtk_dsi_doze_state(dsi);
- struct drm_crtc *crtc = dsi->encoder.crtc;
- struct mtk_crtc_state *mtk_state = to_mtk_crtc_state(crtc->state);
- unsigned int mode_id = mtk_state->prop_val[CRTC_PROP_DISP_MODE_IDX];
- DDPINFO("%s +\n", __func__);
- if (dsi->output_en) {
- if (mtk_dsi_doze_status_change(dsi))
- mtk_output_en_doze_switch(dsi);
- else
- DDPINFO("dsi is initialized\n");
- return;
- }
- ret = mtk_dsi_poweron(dsi);
- if (ret < 0) {
- DDPPR_ERR("failed to power on dsi\n");
- return;
- }
- mtk_dsi_enable(dsi);
- mtk_dsi_phy_timconfig(dsi, NULL);
- mtk_dsi_rxtx_control(dsi);
- mtk_dsi_ps_control_vact(dsi);
- if (!mtk_dsi_is_cmd_mode(&dsi->ddp_comp)) {
- mtk_dsi_set_vm_cmd(dsi);
- mtk_dsi_calc_vdo_timing(dsi);
- mtk_dsi_config_vdo_timing(dsi);
- }
- mtk_dsi_set_interrupt_enable(dsi);
- mtk_dsi_exit_ulps(dsi);
- mtk_dsi_clk_hs_mode(dsi, 0);
- if (dsi->panel) {
- if ((!dsi->doze_enabled || force_lcm_update)
- && drm_panel_prepare(dsi->panel)) {
- DDPPR_ERR("failed to prepare the panel\n");
- return;
- }
- /* add for ESD recovery */
- if (mtk_dsi_is_cmd_mode(&dsi->ddp_comp) && mode_id != 0) {
- if (dsi->ext && dsi->ext->funcs &&
- dsi->ext->funcs->mode_switch) {
- DDPMSG("%s do lcm mode_switch to %u\n",
- __func__, mode_id);
- dsi->ext->funcs->mode_switch(dsi->panel, 0,
- mode_id, AFTER_DSI_POWERON);
- }
- }
- if (new_doze_state && !dsi->doze_enabled) {
- if (ext && ext->funcs &&
- ext->funcs->doze_enable_start)
- ext->funcs->doze_enable_start(dsi->panel, dsi,
- mipi_dsi_dcs_write_gce2, NULL);
- if (ext && ext->funcs
- && ext->funcs->doze_enable)
- ext->funcs->doze_enable(dsi->panel, dsi,
- mipi_dsi_dcs_write_gce2, NULL);
- if (ext && ext->funcs
- && ext->funcs->doze_area)
- ext->funcs->doze_area(dsi->panel, dsi,
- mipi_dsi_dcs_write_gce2, NULL);
- }
- if (!new_doze_state && dsi->doze_enabled) {
- if (ext && ext->funcs
- && ext->funcs->doze_disable)
- ext->funcs->doze_disable(dsi->panel, dsi,
- mipi_dsi_dcs_write_gce2, NULL);
- }
- }
- /*
- * TODO: It's a temp workaround for cmd mode. When set the EXT_TE_EN bit
- * before sending DSI cmd. System would hang. So move the bit control
- * after
- * lcm initialize.
- */
- if (mtk_dsi_is_cmd_mode(&dsi->ddp_comp))
- writel(0x0001023c, dsi->regs + DSI_TXRX_CTRL);
- mtk_dsi_set_mode(dsi);
- mtk_dsi_clk_hs_mode(dsi, 1);
- if (!mtk_dsi_is_cmd_mode(&dsi->ddp_comp))
- mtk_dsi_start(dsi);
- if (dsi->panel) {
- if (drm_panel_enable(dsi->panel)) {
- DDPPR_ERR("failed to enable the panel\n");
- goto err_dsi_power_off;
- }
- /* Suspend to Doze */
- if (mtk_dsi_doze_status_change(dsi)) {
- /* We use doze_get_mode_flags to determine if
- * there has CV switch in Doze mode.
- */
- if (ext && ext->funcs
- && ext->funcs->doze_post_disp_on
- && ext->funcs->doze_get_mode_flags)
- ext->funcs->doze_post_disp_on(dsi->panel,
- dsi, mipi_dsi_dcs_write_gce2, NULL);
- }
- }
- DDPINFO("%s -\n", __func__);
- dsi->output_en = true;
- dsi->doze_enabled = new_doze_state;
- return;
- err_dsi_power_off:
- mtk_dsi_stop(dsi);
- mtk_dsi_poweroff(dsi);
- }
- static int mtk_dsi_stop_vdo_mode(struct mtk_dsi *dsi, void *handle);
- static int mtk_dsi_wait_cmd_frame_done(struct mtk_dsi *dsi,
- int force_lcm_update)
- {
- struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(dsi->encoder.crtc);
- struct cmdq_pkt *handle;
- bool new_doze_state = mtk_dsi_doze_state(dsi);
- mtk_crtc_pkt_create(&handle,
- &mtk_crtc->base,
- mtk_crtc->gce_obj.client[CLIENT_CFG]);
- /* wait frame done */
- cmdq_pkt_wait_no_clear(handle,
- mtk_crtc->gce_obj.event[EVENT_STREAM_EOF]);
- /* When system ready to go to Doze suspend stage, it has to
- * update the latest image before entering it to make sure display
- * correctly. Since it's hard to know how many frame config GCE
- * commands are there in the waiting queue, so here we force
- * frame updating and wait for the latest frame done.
- */
- if (new_doze_state && !force_lcm_update) {
- cmdq_pkt_set_event(handle,
- mtk_crtc->gce_obj.event[EVENT_STREAM_DIRTY]);
- cmdq_pkt_wait_no_clear(handle,
- mtk_crtc->gce_obj.event[EVENT_CMD_EOF]);
- }
- cmdq_pkt_clear_event(
- handle,
- mtk_crtc->gce_obj.event[EVENT_STREAM_BLOCK]);
- cmdq_pkt_flush(handle);
- cmdq_pkt_destroy(handle);
- return 0;
- }
- static void mtk_output_dsi_disable(struct mtk_dsi *dsi,
- int force_lcm_update)
- {
- bool new_doze_state = mtk_dsi_doze_state(dsi);
- struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(dsi->encoder.crtc);
- DDPINFO("%s+ doze_enabled:%d\n", __func__, new_doze_state);
- if (!dsi->output_en)
- return;
- mtk_drm_crtc_wait_blank(mtk_crtc);
- /* 1. If not doze mode, turn off backlight */
- if (dsi->panel && (!new_doze_state || force_lcm_update)) {
- if (drm_panel_disable(dsi->panel)) {
- DRM_ERROR("failed to disable the panel\n");
- return;
- }
- }
- /* 2. If VDO mode, stop it and set to CMD mode */
- if (!mtk_dsi_is_cmd_mode(&dsi->ddp_comp))
- mtk_dsi_stop_vdo_mode(dsi, NULL);
- else
- mtk_dsi_wait_cmd_frame_done(dsi, force_lcm_update);
- /* 3. turn off panel or set to doze mode */
- if (dsi->panel) {
- if (!new_doze_state || force_lcm_update) {
- if (drm_panel_unprepare(dsi->panel))
- DRM_ERROR("failed to unprepare the panel\n");
- } else if (new_doze_state && !dsi->doze_enabled) {
- mtk_output_en_doze_switch(dsi);
- }
- }
- /* set DSI into ULPS mode */
- mtk_dsi_reset_engine(dsi);
- mtk_dsi_enter_ulps(dsi);
- mtk_dsi_disable(dsi);
- mtk_dsi_stop(dsi);
- mtk_dsi_poweroff(dsi);
- dsi->output_en = false;
- dsi->doze_enabled = new_doze_state;
- DDPINFO("%s-\n", __func__);
- }
- static void mtk_dsi_encoder_destroy(struct drm_encoder *encoder)
- {
- drm_encoder_cleanup(encoder);
- }
- static const struct drm_encoder_funcs mtk_dsi_encoder_funcs = {
- .destroy = mtk_dsi_encoder_destroy,
- };
- static bool mtk_dsi_encoder_mode_fixup(struct drm_encoder *encoder,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
- {
- return true;
- }
- static void mtk_dsi_encoder_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted)
- {
- struct mtk_dsi *dsi = encoder_to_dsi(encoder);
- dsi->vm.pixelclock = adjusted->clock;
- dsi->vm.hactive = adjusted->hdisplay;
- dsi->vm.hback_porch = adjusted->htotal - adjusted->hsync_end;
- dsi->vm.hfront_porch = adjusted->hsync_start - adjusted->hdisplay;
- dsi->vm.hsync_len = adjusted->hsync_end - adjusted->hsync_start;
- dsi->vm.vactive = adjusted->vdisplay;
- dsi->vm.vback_porch = adjusted->vtotal - adjusted->vsync_end;
- dsi->vm.vfront_porch = adjusted->vsync_start - adjusted->vdisplay;
- dsi->vm.vsync_len = adjusted->vsync_end - adjusted->vsync_start;
- }
- static void mtk_dsi_encoder_disable(struct drm_encoder *encoder)
- {
- struct mtk_dsi *dsi = encoder_to_dsi(encoder);
- struct drm_crtc *crtc = encoder->crtc;
- int index = drm_crtc_index(crtc);
- CRTC_MMP_EVENT_START(index, dsi_suspend,
- (unsigned long)crtc, index);
- DDPINFO("%s\n", __func__);
- mtk_drm_idlemgr_kick(__func__, crtc, 0);
- mtk_output_dsi_disable(dsi, false);
- CRTC_MMP_EVENT_END(index, dsi_suspend,
- (unsigned long)dsi->output_en, 0);
- }
- static void mtk_dsi_encoder_enable(struct drm_encoder *encoder)
- {
- struct mtk_dsi *dsi = encoder_to_dsi(encoder);
- struct drm_crtc *crtc = encoder->crtc;
- int index = drm_crtc_index(crtc);
- CRTC_MMP_EVENT_START(index, dsi_resume,
- (unsigned long)crtc, index);
- DDPINFO("%s\n", __func__);
- mtk_output_dsi_enable(dsi, false);
- CRTC_MMP_EVENT_END(index, dsi_resume,
- (unsigned long)dsi->output_en, 0);
- }
- static enum drm_connector_status
- mtk_dsi_connector_detect(struct drm_connector *connector, bool force)
- {
- return connector_status_connected;
- }
- static int mtk_dsi_connector_get_modes(struct drm_connector *connector)
- {
- struct mtk_dsi *dsi = connector_to_dsi(connector);
- return drm_panel_get_modes(dsi->panel);
- }
- static int mtk_dsi_atomic_check(struct drm_encoder *encoder,
- struct drm_crtc_state *crtc_state,
- struct drm_connector_state *conn_state)
- {
- struct mtk_drm_crtc *mtk_crtc =
- container_of(conn_state->crtc, struct mtk_drm_crtc, base);
- struct mtk_dsi *dsi = encoder_to_dsi(encoder);
- switch (dsi->format) {
- case MIPI_DSI_FMT_RGB565:
- mtk_crtc->bpc = 5;
- break;
- case MIPI_DSI_FMT_RGB666_PACKED:
- mtk_crtc->bpc = 6;
- break;
- case MIPI_DSI_FMT_RGB666:
- case MIPI_DSI_FMT_RGB888:
- default:
- mtk_crtc->bpc = 8;
- break;
- }
- return 0;
- }
- static const struct drm_encoder_helper_funcs mtk_dsi_encoder_helper_funcs = {
- .mode_fixup = mtk_dsi_encoder_mode_fixup,
- .mode_set = mtk_dsi_encoder_mode_set,
- .disable = mtk_dsi_encoder_disable,
- .enable = mtk_dsi_encoder_enable,
- .atomic_check = mtk_dsi_atomic_check,
- };
- static const struct drm_connector_funcs mtk_dsi_connector_funcs = {
- /* .dpms = drm_atomic_helper_connector_dpms, */
- .detect = mtk_dsi_connector_detect,
- .fill_modes = drm_helper_probe_single_connector_modes,
- .destroy = drm_connector_cleanup,
- .reset = drm_atomic_helper_connector_reset,
- .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
- .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
- };
- static const struct drm_connector_helper_funcs mtk_dsi_conn_helper_funcs = {
- .get_modes = mtk_dsi_connector_get_modes,
- };
- static int mtk_drm_attach_bridge(struct drm_bridge *bridge,
- struct drm_encoder *encoder)
- {
- int ret;
- if (!bridge)
- return -ENOENT;
- encoder->bridge = bridge;
- bridge->encoder = encoder;
- ret = drm_bridge_attach(encoder, bridge, NULL);
- if (ret) {
- DRM_ERROR("Failed to attach bridge to drm\n");
- encoder->bridge = NULL;
- bridge->encoder = NULL;
- }
- return ret;
- }
- static int mtk_dsi_create_connector(struct drm_device *drm, struct mtk_dsi *dsi)
- {
- int ret;
- ret = drm_connector_init(drm, &dsi->conn, &mtk_dsi_connector_funcs,
- DRM_MODE_CONNECTOR_DSI);
- if (ret) {
- DRM_ERROR("Failed to connector init to drm\n");
- return ret;
- }
- drm_connector_helper_add(&dsi->conn, &mtk_dsi_conn_helper_funcs);
- dsi->conn.dpms = DRM_MODE_DPMS_OFF;
- drm_mode_connector_attach_encoder(&dsi->conn, &dsi->encoder);
- if (dsi->panel) {
- ret = drm_panel_attach(dsi->panel, &dsi->conn);
- if (ret) {
- DRM_ERROR("Failed to attach panel to drm\n");
- goto err_connector_cleanup;
- }
- }
- return 0;
- err_connector_cleanup:
- drm_connector_cleanup(&dsi->conn);
- return ret;
- }
- static int mtk_dsi_create_conn_enc(struct drm_device *drm, struct mtk_dsi *dsi)
- {
- int ret;
- ret = drm_encoder_init(drm, &dsi->encoder, &mtk_dsi_encoder_funcs,
- DRM_MODE_ENCODER_DSI, NULL);
- if (ret) {
- DRM_ERROR("Failed to encoder init to drm\n");
- return ret;
- }
- drm_encoder_helper_add(&dsi->encoder, &mtk_dsi_encoder_helper_funcs);
- /*
- * Currently display data paths are statically assigned to a crtc each.
- * crtc 0 is OVL0 -> COLOR0 -> AAL -> OD -> RDMA0 -> UFOE -> DSI0
- */
- dsi->encoder.possible_crtcs = 1;
- /* If there's a bridge, attach to it and let it create the connector */
- ret = mtk_drm_attach_bridge(dsi->bridge, &dsi->encoder);
- if (ret) {
- /* Otherwise create our own connector and attach to a panel */
- ret = mtk_dsi_create_connector(drm, dsi);
- if (ret)
- goto err_encoder_cleanup;
- }
- return 0;
- err_encoder_cleanup:
- drm_encoder_cleanup(&dsi->encoder);
- return ret;
- }
- static void mtk_dsi_destroy_conn_enc(struct mtk_dsi *dsi)
- {
- drm_encoder_cleanup(&dsi->encoder);
- /* Skip connector cleanup if creation was delegated to the bridge */
- if (dsi->conn.dev)
- drm_connector_cleanup(&dsi->conn);
- }
- struct mtk_panel_ext *mtk_dsi_get_panel_ext(struct mtk_ddp_comp *comp)
- {
- struct mtk_dsi *dsi = container_of(comp, struct mtk_dsi, ddp_comp);
- return dsi->ext;
- }
- /* SET MODE */
- static void _mtk_dsi_set_mode(struct mtk_ddp_comp *comp, void *handle,
- unsigned int mode)
- {
- cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DSI_MODE_CTRL,
- mode, ~0);
- }
- /* STOP VDO MODE */
- static int mtk_dsi_stop_vdo_mode(struct mtk_dsi *dsi, void *handle)
- {
- struct mtk_ddp_comp *comp = &dsi->ddp_comp;
- struct mtk_drm_crtc *mtk_crtc = comp->mtk_crtc;
- int need_create_hnd = 0;
- struct cmdq_pkt *cmdq_handle;
- if (!mtk_crtc) {
- DDPPR_ERR("%s, mtk_crtc is NULL\n", __func__);
- return 1;
- }
- /* Add blocking flush for waiting dsi idle in other gce client */
- if (handle) {
- struct cmdq_pkt *cmdq_handle1 = (struct cmdq_pkt *)handle;
- if (cmdq_handle1->cl !=
- mtk_crtc->gce_obj.client[CLIENT_DSI_CFG]) {
- mtk_crtc_pkt_create(&cmdq_handle,
- &mtk_crtc->base,
- mtk_crtc->gce_obj.client[CLIENT_DSI_CFG]);
- cmdq_pkt_flush(cmdq_handle);
- cmdq_pkt_destroy(cmdq_handle);
- }
- } else {
- mtk_crtc_pkt_create(&cmdq_handle,
- &mtk_crtc->base,
- mtk_crtc->gce_obj.client[CLIENT_DSI_CFG]);
- cmdq_pkt_flush(cmdq_handle);
- cmdq_pkt_destroy(cmdq_handle);
- }
- if (!handle)
- need_create_hnd = 1;
- if (need_create_hnd) {
- mtk_crtc_pkt_create((struct cmdq_pkt **)&handle,
- &mtk_crtc->base,
- mtk_crtc->gce_obj.client[CLIENT_CFG]);
- /* wait frame done */
- cmdq_pkt_wait_no_clear(handle,
- mtk_crtc->gce_obj.event[EVENT_VDO_EOF]);
- }
- /* stop vdo mode */
- _mtk_dsi_set_mode(&dsi->ddp_comp, handle, CMD_MODE);
- cmdq_pkt_write(handle, dsi->ddp_comp.cmdq_base,
- dsi->ddp_comp.regs_pa + DSI_START, 0, ~0);
- mtk_dsi_poll_for_idle(dsi, handle);
- if (need_create_hnd) {
- cmdq_pkt_flush(handle);
- cmdq_pkt_destroy(handle);
- }
- return 0;
- }
- static int mtk_dsi_start_vdo_mode(struct mtk_ddp_comp *comp, void *handle)
- {
- struct mtk_dsi *dsi = container_of(comp, struct mtk_dsi, ddp_comp);
- u32 vid_mode = CMD_MODE;
- if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
- if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
- vid_mode = BURST_MODE;
- else if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
- vid_mode = SYNC_PULSE_MODE;
- else
- vid_mode = SYNC_EVENT_MODE;
- }
- cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DSI_START, 0,
- ~0);
- _mtk_dsi_set_mode(comp, handle, vid_mode);
- return 0;
- }
- static int mtk_dsi_trigger(struct mtk_ddp_comp *comp, void *handle)
- {
- cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DSI_START, 1,
- ~0);
- return 0;
- }
- int mtk_dsi_read_gce(struct mtk_ddp_comp *comp, void *handle,
- struct DSI_T0_INS *t0, int i, uintptr_t slot)
- {
- struct mtk_dsi *dsi = container_of(comp, struct mtk_dsi, ddp_comp);
- dma_addr_t read_slot = (dma_addr_t)slot;
- cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DSI_CMDQ0,
- 0x00013700, ~0);
- cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DSI_CMDQ1,
- AS_UINT32(t0), ~0);
- cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DSI_CMDQ_SIZE,
- 0x2, ~0);
- cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DSI_START,
- 0x0, ~0);
- cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DSI_START,
- 0x1, ~0);
- mtk_dsi_cmdq_poll(comp, handle, comp->regs_pa + DSI_INTSTA, 0x1, 0x1);
- cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DSI_INTSTA,
- 0x0, 0x1);
- cmdq_pkt_mem_move(handle, comp->cmdq_base,
- comp->regs_pa + DSI_RX_DATA0, read_slot + (i * 2) * 0x4,
- CMDQ_THR_SPR_IDX3);
- cmdq_pkt_mem_move(handle, comp->cmdq_base,
- comp->regs_pa + DSI_RX_DATA1, read_slot + (i * 2 + 1) * 0x4,
- CMDQ_THR_SPR_IDX3);
- cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DSI_RACK,
- 0x1, 0x1);
- cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DSI_INTSTA,
- 0x0, 0x1);
- mtk_dsi_poll_for_idle(dsi, handle);
- return 0;
- }
- int mtk_dsi_esd_read(struct mtk_ddp_comp *comp, void *handle, uintptr_t slot)
- {
- int i;
- struct DSI_T0_INS t0;
- struct mtk_dsi *dsi = container_of(comp, struct mtk_dsi, ddp_comp);
- struct mtk_panel_params *params;
- if (dsi->ext && dsi->ext->params)
- params = dsi->ext->params;
- else /* can't find panel ext information, stop esd read */
- return 0;
- for (i = 0 ; i < ESD_CHECK_NUM ; i++) {
- if (params->lcm_esd_check_table[i].cmd == 0)
- break;
- t0.CONFG = 0x04;
- t0.Data0 = params->lcm_esd_check_table[i].cmd;
- t0.Data_ID = (t0.Data0 < 0xB0)
- ? DSI_DCS_READ_PACKET_ID
- : DSI_GERNERIC_READ_LONG_PACKET_ID;
- t0.Data1 = 0;
- mtk_dsi_read_gce(comp, handle, &t0, i, slot);
- }
- return 0;
- }
- int mtk_dsi_esd_cmp(struct mtk_ddp_comp *comp, void *handle, void *slot)
- {
- int i, ret = 0;
- u32 tmp0, tmp1, chk_val;
- struct mtk_dsi *dsi = container_of(comp, struct mtk_dsi, ddp_comp);
- struct esd_check_item *lcm_esd_tb;
- struct mtk_panel_params *params;
- if (dsi->ext && dsi->ext->params)
- params = dsi->ext->params;
- else /* can't find panel ext information, stop esd read */
- return 0;
- for (i = 0; i < ESD_CHECK_NUM; i++) {
- if (dsi->ext->params->lcm_esd_check_table[i].cmd == 0)
- break;
- if (slot) {
- tmp0 = AS_UINT32(slot + (i * 2) * 0x4);
- tmp1 = AS_UINT32(slot + (i * 2 + 1) * 0x4);
- } else if (i == 0) {
- tmp0 = readl(dsi->regs + DSI_RX_DATA0);
- tmp1 = readl(dsi->regs + DSI_RX_DATA1);
- }
- lcm_esd_tb = ¶ms->lcm_esd_check_table[i];
- if ((tmp0 & 0xff) == 0x1C)
- chk_val = tmp1 & 0xff;
- else
- chk_val = (tmp0 >> 8) & 0xff;
- if (lcm_esd_tb->mask_list[0])
- chk_val = chk_val & lcm_esd_tb->mask_list[0];
- if (chk_val == lcm_esd_tb->para_list[0]) {
- ret = 0;
- } else {
- DDPPR_ERR("[DSI]cmp fail:read(0x%x)!=expect(0x%x)\n",
- chk_val, lcm_esd_tb->para_list[0]);
- ret = -1;
- break;
- }
- }
- return ret;
- }
- static const char *mtk_dsi_cmd_mode_parse_state(unsigned int state)
- {
- switch (state) {
- case 0x0001:
- return "idle";
- case 0x0002:
- return "Reading command queue for header";
- case 0x0004:
- return "Sending type-0 command";
- case 0x0008:
- return "Waiting frame data from RDMA for type-1 command";
- case 0x0010:
- return "Sending type-1 command";
- case 0x0020:
- return "Sending type-2 command";
- case 0x0040:
- return "Reading command queue for type-2 data";
- case 0x0080:
- return "Sending type-3 command";
- case 0x0100:
- return "Sending BTA";
- case 0x0200:
- return "Waiting RX-read data";
- case 0x0400:
- return "Waiting SW RACK for RX-read data";
- case 0x0800:
- return "Waiting TE";
- case 0x1000:
- return "Get TE";
- case 0x2000:
- return "Waiting SW RACK for TE";
- case 0x4000:
- return "Waiting external TE";
- case 0x8000:
- return "Get external TE";
- default:
- return "unknown";
- }
- }
- static const char *mtk_dsi_vdo_mode_parse_state(unsigned int state)
- {
- switch (state) {
- case 0x0001:
- return "Video mode idle";
- case 0x0002:
- return "Sync start packet";
- case 0x0004:
- return "Hsync active";
- case 0x0008:
- return "Sync end packet";
- case 0x0010:
- return "Hsync back porch";
- case 0x0020:
- return "Video data period";
- case 0x0040:
- return "Hsync front porch";
- case 0x0080:
- return "BLLP";
- case 0x0100:
- return "--";
- case 0x0200:
- return "Mix mode using command mode transmission";
- case 0x0400:
- return "Command transmission in BLLP";
- default:
- return "unknown";
- }
- }
- int mtk_dsi_dump(struct mtk_ddp_comp *comp)
- {
- int k;
- struct mtk_dsi *dsi = container_of(comp, struct mtk_dsi, ddp_comp);
- void __iomem *baddr = comp->regs;
- unsigned int reg_val;
- if (DISP_REG_GET_FIELD(MODE_FLD_REG_MODE_CON,
- baddr + DSI_MODE_CTRL)) {
- /* VDO mode */
- reg_val = (readl(dsi->regs + 0x164)) & 0xff;
- DDPDUMP("state7(vdo mode):%s\n",
- mtk_dsi_vdo_mode_parse_state(reg_val));
- } else {
- reg_val = (readl(dsi->regs + 0x160)) & 0xffff;
- DDPDUMP("state6(cmd mode):%s\n",
- mtk_dsi_cmd_mode_parse_state(reg_val));
- }
- reg_val = (readl(dsi->regs + 0x168)) & 0x3fff;
- DDPDUMP("state8 WORD_COUNTER(cmd mode):%u\n", reg_val);
- reg_val = (readl(dsi->regs + 0x16C)) & 0x3fffff;
- DDPDUMP("state9 LINE_COUNTER(cmd mode):%u\n", reg_val);
- DDPDUMP("== %s REGS ==\n", mtk_dump_comp_str(comp));
- for (k = 0; k < 0x200; k += 16) {
- DDPDUMP("0x%04x: 0x%08x 0x%08x 0x%08x 0x%08x\n", k,
- readl(dsi->regs + k),
- readl(dsi->regs + k + 0x4),
- readl(dsi->regs + k + 0x8),
- readl(dsi->regs + k + 0xc));
- }
- DDPDUMP("- DSI CMD REGS -\n");
- for (k = 0; k < 32; k += 16) {
- DDPDUMP("0x%04x: 0x%08x 0x%08x 0x%08x 0x%08x\n", k,
- readl(dsi->regs + 0x200 + k),
- readl(dsi->regs + 0x200 + k + 0x4),
- readl(dsi->regs + 0x200 + k + 0x8),
- readl(dsi->regs + 0x200 + k + 0xc));
- }
- mtk_mipi_tx_dump(dsi->phy);
- return 0;
- }
- unsigned int mtk_dsi_fps_change_index(struct mtk_dsi *dsi,
- struct mtk_drm_crtc *mtk_crtc, struct drm_crtc_state *old_state)
- {
- struct mtk_panel_ext *panel_ext = mtk_crtc->panel_ext;
- struct mtk_panel_ext *get_panel_ext = find_panel_ext(dsi->panel);
- struct drm_display_mode *old_mode;
- struct drm_display_mode *adjust_mode;
- struct mtk_panel_params *cur_panel_params = panel_ext->params;
- struct mtk_panel_params *adjust_panel_params = NULL;
- unsigned int fps_chg_index = 0;
- unsigned int old_get_sta = 0, new_get_sta = 0;
- struct mtk_crtc_state *state =
- to_mtk_crtc_state(mtk_crtc->base.state);
- struct mtk_crtc_state *old_mtk_state =
- to_mtk_crtc_state(old_state);
- unsigned int src_mode_idx =
- old_mtk_state->prop_val[CRTC_PROP_DISP_MODE_IDX];
- unsigned int dst_mode_idx =
- state->prop_val[CRTC_PROP_DISP_MODE_IDX];
- old_mode = &(mtk_crtc->avail_modes[src_mode_idx]);
- adjust_mode = &(mtk_crtc->avail_modes[dst_mode_idx]);
- if (panel_ext && panel_ext->funcs &&
- panel_ext->funcs->ext_param_set) {
- DDPINFO("old ext_param_set\n");
- old_get_sta = panel_ext->funcs->ext_param_set(
- dsi->panel, src_mode_idx);
- }
- if (old_get_sta)
- DDPINFO("%s,error:not support src MODE:(%d)\n", __func__,
- src_mode_idx);
- if (get_panel_ext) {
- cur_panel_params = get_panel_ext->params;
- adjust_panel_params = get_panel_ext->params;
- }
- if (panel_ext && panel_ext->funcs &&
- panel_ext->funcs->ext_param_set) {
- DDPINFO("new ext_param_set\n");
- new_get_sta = panel_ext->funcs->ext_param_set(
- dsi->panel, dst_mode_idx);
- }
- if (new_get_sta)
- DDPINFO("%s,error:not support dst MODE:(%d)\n", __func__,
- dst_mode_idx);
- if (!(dsi->mipi_hopping_sta && adjust_panel_params &&
- cur_panel_params && cur_panel_params->dyn.switch_en &&
- adjust_panel_params->dyn.switch_en == 1)) {
- if (adjust_mode->vtotal !=
- old_mode->vtotal) {
- fps_chg_index |= DYNFPS_DSI_VFP;
- }
- if (adjust_mode->htotal !=
- old_mode->htotal) {
- fps_chg_index |= DYNFPS_DSI_HFP;
- }
- if (panel_ext && adjust_panel_params &&
- panel_ext->params->data_rate !=
- adjust_panel_params->data_rate) {
- fps_chg_index |= DYNFPS_DSI_MIPI_CLK;
- }
- if (!fps_chg_index && cur_panel_params &&
- adjust_panel_params && cur_panel_params->pll_clk !=
- adjust_panel_params->pll_clk) {
- fps_chg_index |= DYNFPS_DSI_MIPI_CLK;
- }
- if (!fps_chg_index &&
- adjust_mode->clock != old_mode->clock) {
- fps_chg_index |= DYNFPS_DSI_MIPI_CLK;
- }
- } else if (cur_panel_params && adjust_panel_params) {
- if (cur_panel_params->dyn.vfp !=
- adjust_panel_params->dyn.vfp) {
- fps_chg_index |= DYNFPS_DSI_VFP;
- }
- if (cur_panel_params->dyn.hfp !=
- adjust_panel_params->dyn.hfp) {
- fps_chg_index |= DYNFPS_DSI_HFP;
- }
- if (cur_panel_params->dyn.pll_clk !=
- adjust_panel_params->dyn.pll_clk) {
- fps_chg_index |= DYNFPS_DSI_MIPI_CLK;
- }
- if (cur_panel_params->dyn.data_rate !=
- adjust_panel_params->dyn.data_rate) {
- fps_chg_index |= DYNFPS_DSI_MIPI_CLK;
- }
- }
- mtk_crtc->fps_change_index = fps_chg_index;
- DDPINFO("%s,chg %d->%d\n", __func__, old_mode->vrefresh,
- adjust_mode->vrefresh);
- DDPINFO("%s,mipi_hopping_sta %d,chg solution:0x%x\n", __func__,
- dsi->mipi_hopping_sta, fps_chg_index);
- return 0;
- }
- static const char *mtk_dsi_mode_spy(enum DSI_MODE_CON mode)
- {
- switch (mode) {
- case MODE_CON_CMD:
- return "CMD_MODE";
- case MODE_CON_SYNC_PULSE_VDO:
- return "SYNC_PULSE_VDO_MODE";
- case MODE_CON_SYNC_EVENT_VDO:
- return "SYNC_EVENT_VDO_MODE";
- case MODE_CON_BURST_VDO:
- return "BURST_VDO_MODE";
- default:
- break;
- }
- return "unknown-mode";
- }
- int mtk_dsi_analysis(struct mtk_ddp_comp *comp)
- {
- #ifndef CONFIG_FPGA_EARLY_PORTING
- struct mtk_dsi *dsi = container_of(comp, struct mtk_dsi, ddp_comp);
- #endif
- void __iomem *baddr = comp->regs;
- unsigned int reg_val;
- DDPDUMP("== %s ANALYSIS ==\n", mtk_dump_comp_str(comp));
- #ifndef CONFIG_FPGA_EARLY_PORTING
- DDPDUMP("MIPITX Clock:%d\n", mtk_mipi_tx_pll_get_rate(dsi->phy));
- #endif
- DDPDUMP("start:%x,busy:%d,DSI_DUAL_EN:%d\n",
- DISP_REG_GET_FIELD(START_FLD_REG_START, baddr + DSI_START),
- DISP_REG_GET_FIELD(INTSTA_FLD_REG_BUSY, baddr + DSI_INTSTA),
- DISP_REG_GET_FIELD(CON_CTRL_FLD_REG_DUAL_EN,
- baddr + DSI_CON_CTRL));
- DDPDUMP("mode:%s,high_speed:%d,FSM_State:%s\n",
- mtk_dsi_mode_spy(DISP_REG_GET_FIELD(MODE_FLD_REG_MODE_CON,
- baddr + DSI_MODE_CTRL)),
- DISP_REG_GET_FIELD(PHY_FLD_REG_LC_HSTX_EN,
- baddr + DSI_PHY_LCCON),
- mtk_dsi_cmd_mode_parse_state(
- DISP_REG_GET_FIELD(STATE_DBG6_FLD_REG_CMCTL_STATE,
- baddr + DSI_STATE_DBG6)));
- reg_val = readl(DSI_INTEN + baddr);
- DDPDUMP("IRQ_EN,RD_RDY:%d,CMD_DONE:%d,SLEEPOUT_DONE:%d\n",
- REG_FLD_VAL_GET(INTSTA_FLD_REG_RD_RDY, reg_val),
- REG_FLD_VAL_GET(INTSTA_FLD_REG_CMD_DONE, reg_val),
- REG_FLD_VAL_GET(INTSTA_FLD_REG_SLEEPOUT_DONE, reg_val));
- DDPDUMP("TE_RDY:%d,VM_CMD_DONE:%d,VM_DONE:%d\n",
- REG_FLD_VAL_GET(INTSTA_FLD_REG_TE_RDY, reg_val),
- REG_FLD_VAL_GET(INTSTA_FLD_REG_VM_CMD_DONE, reg_val),
- REG_FLD_VAL_GET(INTSTA_FLD_REG_VM_DONE, reg_val));
- reg_val = readl(DSI_INTSTA + baddr);
- DDPDUMP("IRQ,RD_RDY:%d,CMD_DONE:%d,SLEEPOUT_DONE:%d\n",
- REG_FLD_VAL_GET(INTSTA_FLD_REG_RD_RDY, reg_val),
- REG_FLD_VAL_GET(INTSTA_FLD_REG_CMD_DONE, reg_val),
- REG_FLD_VAL_GET(INTSTA_FLD_REG_SLEEPOUT_DONE, reg_val));
- DDPDUMP("TE_RDY:%d,VM_CMD_DONE:%d,VM_DONE:%d\n",
- REG_FLD_VAL_GET(INTSTA_FLD_REG_TE_RDY, reg_val),
- REG_FLD_VAL_GET(INTSTA_FLD_REG_VM_CMD_DONE, reg_val),
- REG_FLD_VAL_GET(INTSTA_FLD_REG_VM_DONE, reg_val));
- reg_val = readl(DSI_TXRX_CTRL + baddr);
- DDPDUMP("lane_num:%d,Ext_TE_EN:%d,Ext_TE_Edge:%d,HSTX_CKLP_EN:%d\n",
- REG_FLD_VAL_GET(TXRX_CTRL_FLD_REG_LANE_NUM, reg_val),
- REG_FLD_VAL_GET(TXRX_CTRL_FLD_REG_EXT_TE_EN, reg_val),
- REG_FLD_VAL_GET(TXRX_CTRL_FLD_REG_EXT_TE_EDGE, reg_val),
- REG_FLD_VAL_GET(TXRX_CTRL_FLD_REG_HSTX_CKLP_EN, reg_val));
- reg_val = readl(DSI_LFR_CON + baddr);
- DDPDUMP("LFR_en:%d, LFR_VSE_DIS:%d, LFR_UPDATE:%d, LFR_MODE:%d, LFR_TYPE:%d, LFR_SKIP_NUMBER:%d\n",
- REG_FLD_VAL_GET(LFR_CON_FLD_REG_LFR_EN, reg_val),
- REG_FLD_VAL_GET(LFR_CON_FLD_REG_LFR_VSE_DIS, reg_val),
- REG_FLD_VAL_GET(LFR_CON_FLD_REG_LFR_UPDATE, reg_val),
- REG_FLD_VAL_GET(LFR_CON_FLD_REG_LFR_MODE, reg_val),
- REG_FLD_VAL_GET(LFR_CON_FLD_REG_LFR_TYPE, reg_val),
- REG_FLD_VAL_GET(LFR_CON_FLD_REG_LFR_SKIP_NUM, reg_val));
- return 0;
- }
- static void mtk_dsi_ddp_prepare(struct mtk_ddp_comp *comp)
- {
- struct mtk_dsi *dsi = container_of(comp, struct mtk_dsi, ddp_comp);
- mtk_dsi_poweron(dsi);
- }
- static void mtk_dsi_ddp_unprepare(struct mtk_ddp_comp *comp)
- {
- struct mtk_dsi *dsi = container_of(comp, struct mtk_dsi, ddp_comp);
- mtk_dsi_poweroff(dsi);
- }
- static void mtk_dsi_config_trigger(struct mtk_ddp_comp *comp,
- struct cmdq_pkt *handle,
- enum mtk_ddp_comp_trigger_flag flag)
- {
- struct mtk_dsi *dsi = container_of(comp, struct mtk_dsi, ddp_comp);
- switch (flag) {
- case MTK_TRIG_FLAG_TRIGGER:
- /* TODO: avoid hardcode: 0xF0 register offset */
- cmdq_pkt_write(handle, comp->cmdq_base,
- comp->mtk_crtc->config_regs_pa + 0xF0, 0x1, 0x1);
- cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + 0x200,
- 0x002c3909, ~0);
- cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + 0x60, 1,
- ~0);
- cmdq_pkt_write(handle, comp->cmdq_base,
- comp->regs_pa + DSI_START, 0, ~0);
- cmdq_pkt_write(handle, comp->cmdq_base,
- comp->regs_pa + DSI_START, 1, ~0);
- break;
- case MTK_TRIG_FLAG_EOF:
- mtk_dsi_poll_for_idle(dsi, handle);
- break;
- default:
- break;
- }
- }
- static int mtk_dsi_is_busy(struct mtk_ddp_comp *comp)
- {
- int ret, tmp;
- struct mtk_dsi *dsi = container_of(comp, struct mtk_dsi, ddp_comp);
- tmp = readl(dsi->regs + DSI_INTSTA);
- ret = (tmp & DSI_BUSY) ? 1 : 0;
- DDPINFO("%s:%d is:%d regs:0x%x\n", __func__, __LINE__, ret, tmp);
- return ret;
- }
- bool mtk_dsi_is_cmd_mode(struct mtk_ddp_comp *comp)
- {
- struct mtk_dsi *dsi;
- if (mtk_ddp_comp_get_type(comp->id) == MTK_DISP_WDMA)
- return true;
- dsi = container_of(comp, struct mtk_dsi, ddp_comp);
- if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO)
- return false;
- else
- return true;
- }
- static const char *mtk_dsi_get_porch_str(enum dsi_porch_type type)
- {
- if (type < 0) {
- DDPPR_ERR("%s: Invalid dsi porch type:%d\n", __func__, type);
- type = 0;
- }
- return mtk_dsi_porch_str[type];
- }
- int mtk_dsi_porch_setting(struct mtk_ddp_comp *comp, struct cmdq_pkt *handle,
- enum dsi_porch_type type, unsigned int value)
- {
- int ret = 0;
- DDPINFO("%s set %s: %s to %d\n", __func__, mtk_dump_comp_str(comp),
- mtk_dsi_get_porch_str(type), value);
- switch (type) {
- case DSI_VFP:
- mtk_ddp_write_relaxed(comp, value, DSI_VFP_NL, handle);
- break;
- case DSI_VSA:
- mtk_ddp_write_relaxed(comp, value, DSI_VSA_NL, handle);
- break;
- case DSI_VBP:
- mtk_ddp_write_relaxed(comp, value, DSI_VBP_NL, handle);
- break;
- case DSI_VACT:
- mtk_ddp_write_relaxed(comp, value, DSI_VACT_NL, handle);
- break;
- case DSI_HFP:
- mtk_ddp_write_relaxed(comp, value, DSI_HFP_WC, handle);
- break;
- case DSI_HSA:
- mtk_ddp_write_relaxed(comp, value, DSI_HSA_WC, handle);
- break;
- case DSI_HBP:
- mtk_ddp_write_relaxed(comp, value, DSI_HBP_WC, handle);
- break;
- case DSI_BLLP:
- mtk_ddp_write_relaxed(comp, value, DSI_BLLP_WC, handle);
- break;
- default:
- break;
- }
- return ret;
- }
- /* TODO: refactor to remove duplicate code */
- static void mtk_dsi_enter_idle(struct mtk_dsi *dsi)
- {
- mtk_dsi_mask(dsi, DSI_INTEN, ~0, 0);
- mtk_dsi_reset_engine(dsi);
- mtk_dsi_enter_ulps(dsi);
- mtk_dsi_poweroff(dsi);
- }
- static void mtk_dsi_leave_idle(struct mtk_dsi *dsi)
- {
- int ret;
- ret = mtk_dsi_poweron(dsi);
- if (ret < 0) {
- DDPPR_ERR("failed to power on dsi\n");
- return;
- }
- mtk_dsi_enable(dsi);
- mtk_dsi_phy_timconfig(dsi, NULL);
- mtk_dsi_rxtx_control(dsi);
- mtk_dsi_ps_control_vact(dsi);
- mtk_dsi_set_interrupt_enable(dsi);
- mtk_dsi_exit_ulps(dsi);
- /*
- * TODO: It's a temp workaround for cmd mode. When set the EXT_TE_EN bit
- * before sending DSI cmd. System would hang. So move the bit control
- * after
- * lcm initialize.
- */
- if (mtk_dsi_is_cmd_mode(&dsi->ddp_comp))
- writel(0x0001023c, dsi->regs + DSI_TXRX_CTRL);
- mtk_dsi_set_mode(dsi);
- mtk_dsi_clk_hs_mode(dsi, 1);
- }
- static void mtk_dsi_clk_change(struct mtk_dsi *dsi, int en)
- {
- struct mtk_panel_ext *ext = dsi->ext;
- struct mtk_ddp_comp *comp = &dsi->ddp_comp;
- struct mtk_drm_crtc *mtk_crtc = comp->mtk_crtc;
- struct drm_crtc *crtc = &mtk_crtc->base;
- bool mod_vfp, mod_vbp, mod_vsa;
- bool mod_hfp, mod_hbp, mod_hsa;
- unsigned int data_rate;
- struct cmdq_pkt *cmdq_handle;
- int index = 0;
- if (!crtc) {
- DDPPR_ERR("%s, crtc is NULL\n", __func__);
- return;
- }
- index = drm_crtc_index(crtc);
- dsi->mipi_hopping_sta = en;
- if (!(ext && ext->params &&
- ext->params->dyn.switch_en == 1))
- return;
- CRTC_MMP_EVENT_START(index, clk_change,
- en, (ext->params->data_rate << 16)
- | ext->params->pll_clk);
- mod_vfp = !!ext->params->dyn.vfp;
- mod_vbp = !!ext->params->dyn.vbp;
- mod_vsa = !!ext->params->dyn.vsa;
- mod_hfp = !!ext->params->dyn.hfp;
- mod_hbp = !!ext->params->dyn.hbp;
- mod_hsa = !!ext->params->dyn.hsa;
- if (en) {
- data_rate = !!ext->params->dyn.data_rate ?
- ext->params->dyn.data_rate :
- ext->params->dyn.pll_clk * 2;
- } else {
- data_rate = mtk_dsi_default_rate(dsi);
- }
- dsi->data_rate = data_rate;
- mtk_mipi_tx_pll_rate_set_adpt(dsi->phy, data_rate);
- /* implicit way for display power state */
- if (dsi->clk_refcnt == 0) {
- CRTC_MMP_MARK(index, clk_change, 0, 1);
- goto done;
- }
- if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO)
- mtk_crtc_pkt_create(&cmdq_handle, &mtk_crtc->base,
- mtk_crtc->gce_obj.client[CLIENT_DSI_CFG]);
- else
- mtk_crtc_pkt_create(&cmdq_handle, &mtk_crtc->base,
- mtk_crtc->gce_obj.client[CLIENT_CFG]);
- if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
- mtk_dsi_calc_vdo_timing(dsi);
- cmdq_pkt_wait_no_clear(cmdq_handle,
- mtk_crtc->gce_obj.event[EVENT_VDO_EOF]);
- mtk_dsi_phy_timconfig(dsi, cmdq_handle);
- if (mod_hfp)
- mtk_dsi_porch_setting(comp, cmdq_handle, DSI_HFP,
- dsi->hfp_byte);
- if (mod_hbp)
- mtk_dsi_porch_setting(comp, cmdq_handle, DSI_HBP,
- dsi->hbp_byte);
- if (mod_hsa)
- mtk_dsi_porch_setting(comp, cmdq_handle, DSI_HSA,
- dsi->hsa_byte);
- if (mod_vbp)
- mtk_dsi_porch_setting(comp, cmdq_handle,
- DSI_VBP, dsi->vbp);
- if (mod_vsa)
- mtk_dsi_porch_setting(comp, cmdq_handle,
- DSI_VSA, dsi->vsa);
- }
- mtk_mipi_tx_pll_rate_switch_gce(dsi->phy, cmdq_handle, data_rate);
- if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
- cmdq_pkt_clear_event(cmdq_handle,
- mtk_crtc->gce_obj.event[EVENT_DSI0_SOF]);
- cmdq_pkt_wait_no_clear(cmdq_handle,
- mtk_crtc->gce_obj.event[EVENT_DSI0_SOF]);
- if (mod_vfp)
- mtk_dsi_porch_setting(comp, cmdq_handle,
- DSI_VFP, dsi->vfp);
- }
- cmdq_pkt_flush(cmdq_handle);
- cmdq_pkt_destroy(cmdq_handle);
- done:
- CRTC_MMP_EVENT_END(index, clk_change,
- dsi->mode_flags,
- (ext->params->dyn.data_rate << 16) |
- ext->params->dyn.pll_clk);
- }
- static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
- struct mipi_dsi_device *device)
- {
- struct mtk_dsi *dsi = host_to_dsi(host);
- dsi->lanes = device->lanes;
- dsi->format = device->format;
- dsi->mode_flags = device->mode_flags;
- /* ********Panel Master********** */
- dsi->dev_for_PM = device;
- /* ******end Panel Master**** */
- if (dsi->conn.dev)
- drm_helper_hpd_irq_event(dsi->conn.dev);
- return 0;
- }
- static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
- struct mipi_dsi_device *device)
- {
- struct mtk_dsi *dsi = host_to_dsi(host);
- if (dsi->conn.dev)
- drm_helper_hpd_irq_event(dsi->conn.dev);
- return 0;
- }
- static u32 mtk_dsi_recv_cnt(u8 type, u8 *read_data)
- {
- switch (type) {
- case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE:
- case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
- return 1;
- case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE:
- case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE:
- return 2;
- case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE:
- case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE:
- return read_data[1] + read_data[2] * 16;
- case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
- DDPINFO("type is 0x02, try again\n");
- break;
- default:
- DDPINFO("type(0x%x) cannot be non-recognite\n", type);
- break;
- }
- return 0;
- }
- static void mtk_dsi_cmdq(struct mtk_dsi *dsi, const struct mipi_dsi_msg *msg)
- {
- const char *tx_buf = msg->tx_buf;
- u8 config, cmdq_size, cmdq_off, type = msg->type;
- u32 reg_val, cmdq_mask, i;
- unsigned long goto_addr;
- if (MTK_DSI_HOST_IS_READ(type))
- config = BTA;
- else
- config = (msg->tx_len > 2) ? LONG_PACKET : SHORT_PACKET;
- if (msg->tx_len > 2) {
- cmdq_size = 1 + (msg->tx_len + 3) / 4;
- cmdq_off = 4;
- cmdq_mask = CONFIG | DATA_ID | DATA_0 | DATA_1;
- reg_val = (msg->tx_len << 16) | (type << 8) | config;
- } else {
- cmdq_size = 1;
- cmdq_off = 2;
- cmdq_mask = CONFIG | DATA_ID;
- reg_val = (type << 8) | config;
- }
- for (i = 0; i < msg->tx_len; i++) {
- goto_addr = dsi->driver_data->reg_cmdq_ofs + cmdq_off + i;
- cmdq_mask = (0xFFu << ((goto_addr & 0x3u) * 8));
- mtk_dsi_mask(dsi, goto_addr & (~(0x3UL)),
- (0xFFu << ((goto_addr & 0x3u) * 8)),
- tx_buf[i] << ((goto_addr & 0x3u) * 8));
- }
- if (msg->tx_len > 2)
- cmdq_mask = CONFIG | DATA_ID | DATA_0 | DATA_1;
- else
- cmdq_mask = CONFIG | DATA_ID;
- mtk_dsi_mask(dsi, dsi->driver_data->reg_cmdq_ofs, cmdq_mask, reg_val);
- mtk_dsi_mask(dsi, DSI_CMDQ_SIZE, CMDQ_SIZE, cmdq_size);
- }
- static void build_vm_cmdq(struct mtk_dsi *dsi,
- const struct mipi_dsi_msg *msg, struct cmdq_pkt *handle)
- {
- unsigned int i = 0, j = 0, k;
- const char *tx_buf = msg->tx_buf;
- while (i < msg->tx_len) {
- unsigned int vm_cmd_val = 0;
- unsigned int vm_cmd_addr = 0;
- k = (((j + 4) > msg->tx_len) ? (msg->tx_len) : (j + 4));
- for (j = i; j < k; j++)
- vm_cmd_val += (tx_buf[j] << ((j - i) * 8));
- if (i / 16 == 0)
- vm_cmd_addr = DSI_VM_CMD_DATA0 + (i%16);
- if (i / 16 == 1)
- vm_cmd_addr = DSI_VM_CMD_DATA10 + (i%16);
- if (i / 16 == 2)
- vm_cmd_addr = DSI_VM_CMD_DATA20 + (i%16);
- if (i / 16 == 3)
- vm_cmd_addr = DSI_VM_CMD_DATA30 + (i%16);
- if (handle)
- cmdq_pkt_write(handle, dsi->ddp_comp.cmdq_base,
- dsi->ddp_comp.regs_pa + vm_cmd_addr,
- vm_cmd_val, ~0);
- else
- writel(vm_cmd_val, dsi->regs + vm_cmd_addr);
- i += 4;
- }
- }
- static void mtk_dsi_vm_cmdq(struct mtk_dsi *dsi,
- const struct mipi_dsi_msg *msg, struct cmdq_pkt *handle)
- {
- const char *tx_buf = msg->tx_buf;
- u8 config, type = msg->type;
- u32 reg_val;
- config = (msg->tx_len > 2) ? VM_LONG_PACKET : 0;
- if (msg->tx_len > 2) {
- build_vm_cmdq(dsi, msg, handle);
- reg_val = (msg->tx_len << 16) | (type << 8) | config;
- } else if (msg->tx_len == 2) {
- reg_val = (tx_buf[1] << 24) | (tx_buf[0] << 16) |
- (type << 8) | config;
- } else {
- reg_val = (tx_buf[0] << 16) | (type << 8) | config;
- }
- reg_val |= (VM_CMD_EN + TS_VFP_EN);
- if (handle == NULL)
- writel(reg_val, dsi->regs + DSI_VM_CMD_CON);
- else
- cmdq_pkt_write(handle, dsi->ddp_comp.cmdq_base,
- dsi->ddp_comp.regs_pa + DSI_VM_CMD_CON, reg_val, ~0);
- }
- static void mtk_dsi_cmdq_gce(struct mtk_dsi *dsi, struct cmdq_pkt *handle,
- const struct mipi_dsi_msg *msg)
- {
- const char *tx_buf = msg->tx_buf;
- u8 config, cmdq_size, cmdq_off, type = msg->type;
- u32 reg_val, cmdq_mask, i;
- unsigned long goto_addr;
- if (MTK_DSI_HOST_IS_READ(type))
- config = BTA;
- else
- config = (msg->tx_len > 2) ? LONG_PACKET : SHORT_PACKET;
- if (msg->tx_len > 2) {
- cmdq_size = 1 + (msg->tx_len + 3) / 4;
- cmdq_off = 4;
- cmdq_mask = CONFIG | DATA_ID | DATA_0 | DATA_1;
- reg_val = (msg->tx_len << 16) | (type << 8) | config;
- } else {
- cmdq_size = 1;
- cmdq_off = 2;
- cmdq_mask = CONFIG | DATA_ID;
- reg_val = (type << 8) | config;
- }
- for (i = 0; i < msg->tx_len; i++) {
- goto_addr = dsi->driver_data->reg_cmdq_ofs + cmdq_off + i;
- cmdq_mask = (0xFFu << ((goto_addr & 0x3u) * 8));
- mtk_ddp_write_mask(&dsi->ddp_comp,
- tx_buf[i] << ((goto_addr & 0x3u) * 8),
- goto_addr, (0xFFu << ((goto_addr & 0x3u) * 8)),
- handle);
- DDPINFO("set cmdqaddr %lx, val:%x, mask %x\n", goto_addr,
- tx_buf[i] << ((goto_addr & 0x3u) * 8),
- (0xFFu << ((goto_addr & 0x3u) * 8)));
- }
- if (msg->tx_len > 2)
- cmdq_mask = CONFIG | DATA_ID | DATA_0 | DATA_1;
- else
- cmdq_mask = CONFIG | DATA_ID;
- mtk_ddp_write_mask(&dsi->ddp_comp, reg_val,
- dsi->driver_data->reg_cmdq_ofs,
- cmdq_mask, handle);
- DDPINFO("set cmdqaddr %u, val:%x, mask %x\n",
- dsi->driver_data->reg_cmdq_ofs,
- reg_val,
- cmdq_mask);
- mtk_ddp_write_mask(&dsi->ddp_comp, cmdq_size,
- DSI_CMDQ_SIZE, CMDQ_SIZE, handle);
- DDPINFO("set cmdqaddr %u, val:%x, mask %x\n", DSI_CMDQ_SIZE, cmdq_size,
- CMDQ_SIZE);
- }
- static void mtk_dsi_cmdq_grp_gce(struct mtk_dsi *dsi, struct cmdq_pkt *handle,
- struct mtk_panel_para_table *para_table,
- unsigned int para_size)
- {
- struct mipi_dsi_msg msg;
- const char *tx_buf;
- u8 config, cmdq_off, type;
- u8 cmdq_size, total_cmdq_size = 0;
- u8 start_off = 0;
- u32 reg_val, cmdq_val;
- u32 cmdq_mask, i, j;
- unsigned int base_addr;
- struct mtk_ddp_comp *comp = &dsi->ddp_comp;
- const u32 reg_cmdq_ofs = dsi->driver_data->reg_cmdq_ofs;
- for (j = 0; j < para_size; j++) {
- msg.tx_buf = para_table[j].para_list,
- msg.tx_len = para_table[j].count;
- switch (msg.tx_len) {
- case 0:
- continue;
- case 1:
- msg.type = MIPI_DSI_DCS_SHORT_WRITE;
- break;
- case 2:
- msg.type = MIPI_DSI_DCS_SHORT_WRITE_PARAM;
- break;
- default:
- msg.type = MIPI_DSI_DCS_LONG_WRITE;
- break;
- }
- tx_buf = msg.tx_buf;
- type = msg.type;
- if (MTK_DSI_HOST_IS_READ(type))
- config = BTA;
- else
- config = (msg.tx_len > 2) ? LONG_PACKET : SHORT_PACKET;
- if (msg.tx_len > 2) {
- cmdq_off = 4;
- cmdq_mask = CONFIG | DATA_ID | DATA_0 | DATA_1;
- reg_val = (msg.tx_len << 16) | (type << 8) | config;
- mtk_ddp_write_relaxed(comp, reg_val,
- reg_cmdq_ofs + start_off,
- handle);
- DDPINFO("set cmdq addr %x, val:%x\n",
- reg_cmdq_ofs + start_off,
- reg_val);
- reg_val = 0;
- for (i = 0; i < msg.tx_len; i++) {
- cmdq_val = tx_buf[i] << ((i & 0x3u) * 8);
- cmdq_mask = (0xFFu << ((i & 0x3u) * 8));
- reg_val = reg_val | (cmdq_val & cmdq_mask);
- if (((i & 0x3) == 0x3) ||
- (i == (msg.tx_len - 1))) {
- base_addr = reg_cmdq_ofs + start_off +
- cmdq_off + ((i / 4) * 4);
- mtk_ddp_write_relaxed(comp,
- reg_val,
- base_addr,
- handle);
- DDPINFO("set cmdq addr %x, val:%x\n",
- base_addr,
- reg_val);
- reg_val = 0;
- }
- }
- } else {
- cmdq_off = 2;
- cmdq_mask = CONFIG | DATA_ID;
- reg_val = (type << 8) | config;
- for (i = 0; i < msg.tx_len; i++) {
- cmdq_val = tx_buf[i] << ((i & 0x3u) * 8);
- cmdq_mask = (0xFFu << ((i & 0x3u) * 8));
- reg_val = reg_val | (cmdq_val & cmdq_mask);
- if (i == (msg.tx_len - 1)) {
- base_addr = reg_cmdq_ofs + start_off +
- cmdq_off + (i / 4) * 4;
- mtk_ddp_write_relaxed(comp,
- reg_val,
- base_addr,
- handle);
- DDPINFO("set cmdq addr %x, val:%x\n",
- base_addr,
- reg_val);
- reg_val = 0;
- }
- }
- }
- if (msg.tx_len > 2)
- cmdq_size = 1 + ((msg.tx_len + 3) / 4);
- else
- cmdq_size = 1;
- start_off += (cmdq_size * 4);
- total_cmdq_size += cmdq_size;
- DDPINFO("offset:%d, size:%d\n", start_off, cmdq_size);
- }
- mtk_ddp_write_mask(comp, total_cmdq_size,
- DSI_CMDQ_SIZE, CMDQ_SIZE, handle);
- mtk_ddp_write_relaxed(comp, 0x0, DSI_START, handle);
- mtk_ddp_write_relaxed(comp, 0x1, DSI_START, handle);
- mtk_dsi_cmdq_poll(comp, handle, comp->regs_pa + DSI_INTSTA,
- CMD_DONE_INT_FLAG, CMD_DONE_INT_FLAG);
- mtk_ddp_write_mask(comp, 0x0, DSI_INTSTA, CMD_DONE_INT_FLAG,
- handle);
- DDPINFO("set cmdqaddr %x, val:%d, mask %x\n", DSI_CMDQ_SIZE,
- total_cmdq_size,
- CMDQ_SIZE);
- }
- void mipi_dsi_dcs_write_gce(struct mtk_dsi *dsi, struct cmdq_pkt *handle,
- const void *data, size_t len)
- {
- struct mipi_dsi_msg msg = {
- .tx_buf = data,
- .tx_len = len
- };
- switch (len) {
- case 0:
- return;
- case 1:
- msg.type = MIPI_DSI_DCS_SHORT_WRITE;
- break;
- case 2:
- msg.type = MIPI_DSI_DCS_SHORT_WRITE_PARAM;
- break;
- default:
- msg.type = MIPI_DSI_DCS_LONG_WRITE;
- break;
- }
- if (mtk_dsi_is_cmd_mode(&dsi->ddp_comp)) {
- mtk_dsi_poll_for_idle(dsi, handle);
- mtk_dsi_cmdq_gce(dsi, handle, &msg);
- cmdq_pkt_write(handle, dsi->ddp_comp.cmdq_base,
- dsi->ddp_comp.regs_pa + DSI_START, 0x0, ~0);
- cmdq_pkt_write(handle, dsi->ddp_comp.cmdq_base,
- dsi->ddp_comp.regs_pa + DSI_START, 0x1, ~0);
- mtk_dsi_poll_for_idle(dsi, handle);
- } else {
- /* set BL cmd */
- mtk_dsi_vm_cmdq(dsi, &msg, handle);
- /* clear VM_CMD_DONE */
- cmdq_pkt_write(handle, dsi->ddp_comp.cmdq_base,
- dsi->ddp_comp.regs_pa + DSI_INTSTA, 0,
- VM_CMD_DONE_INT_EN);
- /* start to send VM cmd */
- cmdq_pkt_write(handle, dsi->ddp_comp.cmdq_base,
- dsi->ddp_comp.regs_pa + DSI_START, 0,
- VM_CMD_START);
- cmdq_pkt_write(handle, dsi->ddp_comp.cmdq_base,
- dsi->ddp_comp.regs_pa + DSI_START, VM_CMD_START,
- VM_CMD_START);
- /* poll VM cmd done */
- mtk_dsi_cmdq_poll(&dsi->ddp_comp, handle,
- dsi->ddp_comp.regs_pa + DSI_INTSTA,
- VM_CMD_DONE_INT_EN, VM_CMD_DONE_INT_EN);
- }
- }
- void mipi_dsi_dcs_write_gce_dyn(struct mtk_dsi *dsi, struct cmdq_pkt *handle,
- const void *data, size_t len)
- {
- struct mipi_dsi_msg msg = {
- .tx_buf = data,
- .tx_len = len
- };
- switch (len) {
- case 0:
- return;
- case 1:
- msg.type = MIPI_DSI_DCS_SHORT_WRITE;
- break;
- case 2:
- msg.type = MIPI_DSI_DCS_SHORT_WRITE_PARAM;
- break;
- default:
- msg.type = MIPI_DSI_DCS_LONG_WRITE;
- break;
- }
- mtk_dsi_poll_for_idle(dsi, handle);
- mtk_dsi_cmdq_gce(dsi, handle, &msg);
- cmdq_pkt_write(handle, dsi->ddp_comp.cmdq_base,
- dsi->ddp_comp.regs_pa + DSI_START, 0x0, ~0);
- cmdq_pkt_write(handle, dsi->ddp_comp.cmdq_base,
- dsi->ddp_comp.regs_pa + DSI_START, 0x1, ~0);
- mtk_dsi_poll_for_idle(dsi, handle);
- }
- void mipi_dsi_dcs_write_gce2(struct mtk_dsi *dsi, struct cmdq_pkt *dummy,
- const void *data, size_t len)
- {
- struct cmdq_pkt *handle;
- struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(dsi->encoder.crtc);
- int dsi_mode = readl(dsi->regs + DSI_MODE_CTRL);
- struct mipi_dsi_msg msg = {
- .tx_buf = data,
- .tx_len = len
- };
- switch (len) {
- case 0:
- return;
- case 1:
- msg.type = MIPI_DSI_DCS_SHORT_WRITE;
- break;
- case 2:
- msg.type = MIPI_DSI_DCS_SHORT_WRITE_PARAM;
- break;
- default:
- msg.type = MIPI_DSI_DCS_LONG_WRITE;
- break;
- }
- if (dsi_mode == 0) {
- mtk_crtc_pkt_create(&handle, &mtk_crtc->base,
- mtk_crtc->gce_obj.client[CLIENT_CFG]);
- mtk_dsi_poll_for_idle(dsi, handle);
- mtk_dsi_cmdq_gce(dsi, handle, &msg);
- cmdq_pkt_write(handle, dsi->ddp_comp.cmdq_base,
- dsi->ddp_comp.regs_pa + DSI_START, 0x0, ~0);
- cmdq_pkt_write(handle, dsi->ddp_comp.cmdq_base,
- dsi->ddp_comp.regs_pa + DSI_START, 0x1, ~0);
- mtk_dsi_poll_for_idle(dsi, handle);
- } else {
- mtk_crtc_pkt_create(&handle, &mtk_crtc->base,
- mtk_crtc->gce_obj.client[CLIENT_DSI_CFG]);
- /* build VM cmd */
- mtk_dsi_vm_cmdq(dsi, &msg, handle);
- /* clear VM_CMD_DONE */
- cmdq_pkt_write(handle, dsi->ddp_comp.cmdq_base,
- dsi->ddp_comp.regs_pa + DSI_INTSTA, 0,
- VM_CMD_DONE_INT_EN);
- /* start to send VM cmd */
- cmdq_pkt_write(handle, dsi->ddp_comp.cmdq_base,
- dsi->ddp_comp.regs_pa + DSI_START, 0,
- VM_CMD_START);
- cmdq_pkt_write(handle, dsi->ddp_comp.cmdq_base,
- dsi->ddp_comp.regs_pa + DSI_START, VM_CMD_START,
- VM_CMD_START);
- /* poll VM cmd done */
- mtk_dsi_cmdq_poll(&dsi->ddp_comp, handle,
- dsi->ddp_comp.regs_pa + DSI_INTSTA,
- VM_CMD_DONE_INT_EN, VM_CMD_DONE_INT_EN);
- cmdq_pkt_write(handle, dsi->ddp_comp.cmdq_base,
- dsi->ddp_comp.regs_pa + DSI_START, 0,
- VM_CMD_START);
- /* clear VM_CMD_DONE */
- cmdq_pkt_write(handle, dsi->ddp_comp.cmdq_base,
- dsi->ddp_comp.regs_pa + DSI_INTSTA, 0,
- VM_CMD_DONE_INT_EN);
- }
- cmdq_pkt_flush(handle);
- cmdq_pkt_destroy(handle);
- }
- void mipi_dsi_dcs_grp_write_gce(struct mtk_dsi *dsi, struct cmdq_pkt *handle,
- struct mtk_panel_para_table *para_table,
- unsigned int para_size)
- {
- struct mtk_ddp_comp *comp = &dsi->ddp_comp;
- /* wait DSI idle */
- if (!mtk_dsi_is_cmd_mode(comp)) {
- _mtk_dsi_set_mode(comp, handle, CMD_MODE);
- cmdq_pkt_write(handle, comp->cmdq_base,
- comp->regs_pa + DSI_START, 0, ~0);
- mtk_dsi_cmdq_poll(comp, handle,
- comp->regs_pa + DSI_INTSTA, 0,
- DSI_BUSY);
- }
- mtk_dsi_cmdq_grp_gce(dsi, handle, para_table, para_size);
- /* trigger */
- if (!mtk_dsi_is_cmd_mode(comp)) {
- mtk_dsi_start_vdo_mode(comp, handle);
- mtk_disp_mutex_trigger(comp->mtk_crtc->mutex[0], handle);
- mtk_dsi_trigger(comp, handle);
- }
- }
- static void _mtk_mipi_dsi_write_gce(struct mtk_dsi *dsi,
- struct cmdq_pkt *handle,
- const struct mipi_dsi_msg *msg)
- {
- const char *tx_buf = msg->tx_buf;
- u8 config, cmdq_size, cmdq_off, type = msg->type;
- u32 reg_val, cmdq_mask, i;
- unsigned long goto_addr;
- DDPMSG("%s +\n", __func__);
- if (MTK_DSI_HOST_IS_READ(type))
- config = BTA;
- else
- config = (msg->tx_len > 2) ? LONG_PACKET : SHORT_PACKET;
- if (!(msg->flags & MIPI_DSI_MSG_USE_LPM))
- config |= HSTX;
- if (msg->tx_len > 2) {
- cmdq_size = 1 + (msg->tx_len + 3) / 4;
- cmdq_off = 4;
- cmdq_mask = CONFIG | DATA_ID | DATA_0 | DATA_1;
- reg_val = (msg->tx_len << 16) | (type << 8) | config;
- } else {
- cmdq_size = 1;
- cmdq_off = 2;
- cmdq_mask = CONFIG | DATA_ID;
- reg_val = (type << 8) | config;
- }
- for (i = 0; i < msg->tx_len; i++) {
- goto_addr = dsi->driver_data->reg_cmdq_ofs + cmdq_off + i;
- cmdq_mask = (0xFFu << ((goto_addr & 0x3u) * 8));
- mtk_ddp_write_mask(&dsi->ddp_comp,
- tx_buf[i] << ((goto_addr & 0x3u) * 8),
- goto_addr, (0xFFu << ((goto_addr & 0x3u) * 8)),
- handle);
- DDPINFO("set cmdqaddr %lx, val:%x, mask %x\n", goto_addr,
- tx_buf[i] << ((goto_addr & 0x3u) * 8),
- (0xFFu << ((goto_addr & 0x3u) * 8)));
- }
- if (msg->tx_len > 2)
- cmdq_mask = CONFIG | DATA_ID | DATA_0 | DATA_1;
- else
- cmdq_mask = CONFIG | DATA_ID;
- mtk_ddp_write_mask(&dsi->ddp_comp, reg_val,
- dsi->driver_data->reg_cmdq_ofs,
- cmdq_mask, handle);
- DDPINFO("set cmdqaddr %u, val:%x, mask %x\n",
- dsi->driver_data->reg_cmdq_ofs,
- reg_val,
- cmdq_mask);
- mtk_ddp_write_mask(&dsi->ddp_comp, cmdq_size,
- DSI_CMDQ_SIZE, CMDQ_SIZE, handle);
- DDPINFO("set cmdqaddr %u, val:%x, mask %x\n", DSI_CMDQ_SIZE, cmdq_size,
- CMDQ_SIZE);
- DDPMSG("%s -\n", __func__);
- }
- int mtk_mipi_dsi_write_gce(struct mtk_dsi *dsi,
- struct cmdq_pkt *handle,
- struct mtk_drm_crtc *mtk_crtc,
- struct mtk_ddic_dsi_msg *cmd_msg)
- {
- unsigned int i = 0, j = 0;
- int dsi_mode = readl(dsi->regs + DSI_MODE_CTRL) & MODE;
- struct mipi_dsi_msg msg;
- unsigned int use_lpm = cmd_msg->flags & MIPI_DSI_MSG_USE_LPM;
- struct mtk_ddp_comp *comp = &dsi->ddp_comp;
- DDPMSG("%s +\n", __func__);
- /* Check cmd_msg param */
- if (cmd_msg->type == 0 ||
- cmd_msg->tx_cmd_num == 0 ||
- cmd_msg->tx_cmd_num > MAX_TX_CMD_NUM) {
- DDPPR_ERR("%s: type is %s, tx_cmd_num is %d\n",
- __func__, cmd_msg->type, (int)cmd_msg->tx_cmd_num);
- return -EINVAL;
- }
- for (i = 0; i < cmd_msg->tx_cmd_num; i++) {
- if (cmd_msg->tx_buf[i] == 0 || cmd_msg->tx_len[i] == 0) {
- DDPPR_ERR("%s: tx_buf[%d] is %s, tx_len[%d] is %d\n",
- __func__, i, (char *)cmd_msg->tx_buf[i], i,
- (int)cmd_msg->tx_len[i]);
- return -EINVAL;
- }
- }
- /* Debug info */
- DDPINFO("%s: channel=%d, flags=0x%x, tx_cmd_num=%d\n",
- __func__, cmd_msg->channel,
- cmd_msg->flags, (int)cmd_msg->tx_cmd_num);
- for (i = 0; i < cmd_msg->tx_cmd_num; i++) {
- DDPINFO("type[%d]=0x%x, tx_len[%d]=%d\n",
- i, cmd_msg->type[i], i, (int)cmd_msg->tx_len[i]);
- for (j = 0; j < cmd_msg->tx_len[i]; j++) {
- DDPINFO("tx_buf[%d]--byte:%d,val:0x%x\n",
- i, j, *(char *)(cmd_msg->tx_buf[i] + j));
- }
- }
- msg.channel = cmd_msg->channel;
- msg.flags = cmd_msg->flags;
- if (dsi_mode == 0) { /* CMD mode HS/LP */
- for (i = 0; i < cmd_msg->tx_cmd_num; i++) {
- msg.type = cmd_msg->type[i];
- msg.tx_len = cmd_msg->tx_len[i];
- msg.tx_buf = cmd_msg->tx_buf[i];
- mtk_dsi_poll_for_idle(dsi, handle);
- _mtk_mipi_dsi_write_gce(dsi, handle, &msg);
- cmdq_pkt_write(handle, dsi->ddp_comp.cmdq_base,
- dsi->ddp_comp.regs_pa + DSI_START, 0x0, ~0);
- cmdq_pkt_write(handle, dsi->ddp_comp.cmdq_base,
- dsi->ddp_comp.regs_pa + DSI_START, 0x1, ~0);
- mtk_dsi_poll_for_idle(dsi, handle);
- }
- } else if (dsi_mode != 0 && !use_lpm) { /* VDO with VM_CMD */
- for (i = 0; i < cmd_msg->tx_cmd_num; i++) {
- msg.type = cmd_msg->type[i];
- msg.tx_len = cmd_msg->tx_len[i];
- msg.tx_buf = cmd_msg->tx_buf[i];
- /* build VM cmd */
- mtk_dsi_vm_cmdq(dsi, &msg, handle);
- /* clear VM_CMD_DONE */
- cmdq_pkt_write(handle, dsi->ddp_comp.cmdq_base,
- dsi->ddp_comp.regs_pa + DSI_INTSTA, 0,
- VM_CMD_DONE_INT_EN);
- /* start to send VM cmd */
- cmdq_pkt_write(handle, dsi->ddp_comp.cmdq_base,
- dsi->ddp_comp.regs_pa + DSI_START, 0,
- VM_CMD_START);
- cmdq_pkt_write(handle, dsi->ddp_comp.cmdq_base,
- dsi->ddp_comp.regs_pa + DSI_START, VM_CMD_START,
- VM_CMD_START);
- /* poll VM cmd done */
- mtk_dsi_cmdq_poll(&dsi->ddp_comp, handle,
- dsi->ddp_comp.regs_pa + DSI_INTSTA,
- VM_CMD_DONE_INT_EN, VM_CMD_DONE_INT_EN);
- cmdq_pkt_write(handle, dsi->ddp_comp.cmdq_base,
- dsi->ddp_comp.regs_pa + DSI_START, 0,
- VM_CMD_START);
- /* clear VM_CMD_DONE */
- cmdq_pkt_write(handle, dsi->ddp_comp.cmdq_base,
- dsi->ddp_comp.regs_pa + DSI_INTSTA, 0,
- VM_CMD_DONE_INT_EN);
- }
- } else if (dsi_mode != 0 && use_lpm) { /* VDO to CMD with LP */
- mtk_dsi_stop_vdo_mode(dsi, handle);
- for (i = 0; i < cmd_msg->tx_cmd_num; i++) {
- msg.type = cmd_msg->type[i];
- msg.tx_len = cmd_msg->tx_len[i];
- msg.tx_buf = cmd_msg->tx_buf[i];
- mtk_dsi_poll_for_idle(dsi, handle);
- _mtk_mipi_dsi_write_gce(dsi, handle, &msg);
- cmdq_pkt_write(handle, dsi->ddp_comp.cmdq_base,
- dsi->ddp_comp.regs_pa + DSI_START, 0x0, ~0);
- cmdq_pkt_write(handle, dsi->ddp_comp.cmdq_base,
- dsi->ddp_comp.regs_pa + DSI_START, 0x1, ~0);
- mtk_dsi_poll_for_idle(dsi, handle);
- }
- mtk_dsi_start_vdo_mode(comp, handle);
- mtk_disp_mutex_trigger(comp->mtk_crtc->mutex[0], handle);
- mtk_dsi_trigger(comp, handle);
- }
- DDPMSG("%s -\n", __func__);
- return 0;
- }
- static void _mtk_mipi_dsi_read_gce(struct mtk_dsi *dsi,
- struct cmdq_pkt *handle,
- struct mipi_dsi_msg *msg)
- {
- struct mtk_ddp_comp *comp = &dsi->ddp_comp;
- struct mtk_drm_crtc *mtk_crtc = dsi->ddp_comp.mtk_crtc;
- struct DSI_T0_INS t0, t1;
- dma_addr_t read_slot = mtk_crtc->gce_obj.buf.pa_base +
- DISP_SLOT_READ_DDIC_BASE;
- const char *tx_buf = msg->tx_buf;
- DDPMSG("%s +\n", __func__);
- DDPINFO("%s type=0x%x, tx_len=%d, tx_buf[0]=0x%x, rx_len=%d\n",
- __func__, msg->type, (int)msg->tx_len,
- tx_buf[0], (int)msg->rx_len);
- if (msg->tx_len > 2) {
- DDPPR_ERR("%s: msg->tx_len is more than 2\n", __func__);
- goto done;
- }
- t0.CONFG = 0x00;
- t0.Data_ID = 0x37;
- t0.Data0 = msg->rx_len;
- t0.Data1 = 0;
- t1.CONFG = BTA;
- t1.Data_ID = msg->type;
- t1.Data0 = tx_buf[0];
- if (msg->tx_len == 2)
- t1.Data1 = tx_buf[1];
- else
- t1.Data1 = 0;
- cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DSI_CMDQ0,
- AS_UINT32(&t0), ~0);
- cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DSI_CMDQ1,
- AS_UINT32(&t1), ~0);
- cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DSI_CMDQ_SIZE,
- 0x2, ~0);
- cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DSI_START,
- 0x0, ~0);
- cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DSI_START,
- 0x1, ~0);
- mtk_dsi_cmdq_poll(comp, handle, comp->regs_pa + DSI_INTSTA, 0x1, 0x1);
- cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DSI_INTSTA,
- 0x0, 0x1);
- cmdq_pkt_mem_move(handle, comp->cmdq_base,
- comp->regs_pa + DSI_RX_DATA0, read_slot,
- CMDQ_THR_SPR_IDX3);
- cmdq_pkt_mem_move(handle, comp->cmdq_base,
- comp->regs_pa + DSI_RX_DATA1, read_slot + 1 * 0x4,
- CMDQ_THR_SPR_IDX3);
- cmdq_pkt_mem_move(handle, comp->cmdq_base,
- comp->regs_pa + DSI_RX_DATA2, read_slot + 2 * 0x4,
- CMDQ_THR_SPR_IDX3);
- cmdq_pkt_mem_move(handle, comp->cmdq_base,
- comp->regs_pa + DSI_RX_DATA3, read_slot + 3 * 0x4,
- CMDQ_THR_SPR_IDX3);
- cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DSI_RACK,
- 0x1, 0x1);
- cmdq_pkt_write(handle, comp->cmdq_base, comp->regs_pa + DSI_INTSTA,
- 0x0, 0x1);
- mtk_dsi_poll_for_idle(dsi, handle);
- done:
- DDPMSG("%s -\n", __func__);
- }
- static unsigned int read_ddic_chk_sta;
- static void ddic_read_timeout_cb(struct cmdq_cb_data data)
- {
- struct drm_crtc *crtc = data.data;
- if (!crtc) {
- DDPPR_ERR("%s find crtc fail\n", __func__);
- return;
- }
- DDPPR_ERR("%s flush fail\n", __func__);
- read_ddic_chk_sta = 0xff;
- mtk_drm_crtc_analysis(crtc);
- mtk_drm_crtc_dump(crtc);
- }
- int mtk_mipi_dsi_read_gce(struct mtk_dsi *dsi,
- struct cmdq_pkt *handle,
- struct mtk_drm_crtc *mtk_crtc,
- struct mtk_ddic_dsi_msg *cmd_msg)
- {
- unsigned int i = 0, j = 0;
- int dsi_mode = readl(dsi->regs + DSI_MODE_CTRL) & MODE;
- struct drm_crtc *crtc = &mtk_crtc->base;
- struct mipi_dsi_msg msg;
- struct mtk_ddp_comp *comp = &dsi->ddp_comp;
- struct cmdq_pkt *cmdq_handle, *cmdq_handle2;
- int ret = 0;
- struct DSI_RX_DATA_REG read_data0 = {0, 0, 0, 0};
- struct DSI_RX_DATA_REG read_data1 = {0, 0, 0, 0};
- struct DSI_RX_DATA_REG read_data2 = {0, 0, 0, 0};
- struct DSI_RX_DATA_REG read_data3 = {0, 0, 0, 0};
- unsigned char packet_type;
- unsigned int recv_data_cnt = 0;
- DDPMSG("%s +\n", __func__);
- /* Check cmd_msg param */
- if (cmd_msg->type == 0 ||
- cmd_msg->tx_cmd_num == 0 ||
- cmd_msg->rx_cmd_num == 0 ||
- cmd_msg->tx_cmd_num > MAX_TX_CMD_NUM ||
- cmd_msg->rx_cmd_num > MAX_RX_CMD_NUM) {
- DDPPR_ERR(
- "%s: type is %s, tx_cmd_num is %d, rx_cmd_num is %d\n",
- __func__, cmd_msg->type,
- (int)cmd_msg->tx_cmd_num, (int)cmd_msg->rx_cmd_num);
- return -EINVAL;
- }
- if (cmd_msg->tx_cmd_num != cmd_msg->rx_cmd_num) {
- DDPPR_ERR("%s: tx_cmd_num is %d, rx_cmd_num is %d\n",
- __func__, (int)cmd_msg->tx_cmd_num,
- (int)cmd_msg->rx_cmd_num);
- return -EINVAL;
- }
- for (i = 0; i < cmd_msg->tx_cmd_num; i++) {
- if (cmd_msg->tx_buf[i] == 0 || cmd_msg->tx_len[i] == 0) {
- DDPPR_ERR("%s: tx_buf[%d] is %s, tx_len[%d] is %d\n",
- __func__, i, (char *)cmd_msg->tx_buf[i], i,
- (int)cmd_msg->tx_len[i]);
- return -EINVAL;
- }
- }
- for (i = 0; i < cmd_msg->rx_cmd_num; i++) {
- if (cmd_msg->rx_buf[i] == 0 || cmd_msg->rx_len[i] == 0) {
- DDPPR_ERR("%s: rx_buf[%d] is %s, rx_len[%d] is %d\n",
- __func__, i, (char *)cmd_msg->rx_buf[i], i,
- (int)cmd_msg->rx_len[i]);
- return -EINVAL;
- }
- if (cmd_msg->rx_len[i] > RT_MAX_NUM) {
- DDPPR_ERR("%s: only supprt read 10 bytes params\n",
- __func__);
- cmd_msg->rx_len[i] = RT_MAX_NUM;
- }
- }
- /* Debug info */
- DDPINFO("%s: channel=%d, flags=0x%x, tx_cmd_num=%d, rx_cmd_num=%d\n",
- __func__, cmd_msg->channel,
- cmd_msg->flags, (int)cmd_msg->tx_cmd_num,
- (int)cmd_msg->rx_cmd_num);
- for (i = 0; i < cmd_msg->tx_cmd_num; i++) {
- DDPINFO("type[%d]=0x%x, tx_len[%d]=%d\n",
- i, cmd_msg->type[i], i, (int)cmd_msg->tx_len[i]);
- for (j = 0; j < (int)cmd_msg->tx_len[i]; j++) {
- DDPINFO("tx_buf[%d]--byte:%d,val:0x%x\n",
- i, j, *(char *)(cmd_msg->tx_buf[i] + j));
- }
- }
- msg.channel = cmd_msg->channel;
- msg.flags = cmd_msg->flags;
- cmdq_handle = cmdq_pkt_create(mtk_crtc->gce_obj.client[CLIENT_DSI_CFG]);
- cmdq_handle->err_cb.cb = ddic_read_timeout_cb;
- cmdq_handle->err_cb.data = crtc;
- /* Reset DISP_SLOT_READ_DDIC_BASE to 0xff00ff00 */
- for (i = 0; i < READ_DDIC_SLOT_NUM; i++) {
- cmdq_pkt_write(cmdq_handle,
- mtk_crtc->gce_obj.base,
- (mtk_crtc->gce_obj.buf.pa_base +
- DISP_SLOT_READ_DDIC_BASE + i * 0x4),
- 0xff00ff00, ~0);
- }
- /* Todo: Support read multiple registers */
- msg.type = cmd_msg->type[0];
- msg.tx_len = cmd_msg->tx_len[0];
- msg.tx_buf = cmd_msg->tx_buf[0];
- msg.rx_len = cmd_msg->rx_len[0];
- msg.rx_buf = cmd_msg->rx_buf[0];
- if (dsi_mode == 0) { /* CMD mode LP */
- cmdq_pkt_wait_no_clear(cmdq_handle,
- mtk_crtc->gce_obj.event[EVENT_STREAM_EOF]);
- cmdq_pkt_clear_event(cmdq_handle,
- mtk_crtc->gce_obj.event[EVENT_ESD_EOF]);
- _mtk_mipi_dsi_read_gce(dsi, cmdq_handle, &msg);
- cmdq_pkt_set_event(cmdq_handle,
- mtk_crtc->gce_obj.event[EVENT_ESD_EOF]);
- } else { /* VDO to CMD mode LP */
- cmdq_pkt_wfe(cmdq_handle,
- mtk_crtc->gce_obj.event[EVENT_VDO_EOF]);
- mtk_dsi_stop_vdo_mode(dsi, cmdq_handle);
- _mtk_mipi_dsi_read_gce(dsi, cmdq_handle, &msg);
- mtk_dsi_start_vdo_mode(comp, cmdq_handle);
- mtk_disp_mutex_trigger(comp->mtk_crtc->mutex[0], cmdq_handle);
- mtk_dsi_trigger(comp, cmdq_handle);
- }
- read_ddic_chk_sta = 0;
- cmdq_pkt_flush(cmdq_handle);
- mtk_dsi_clear_rxrd_irq(dsi);
- if (read_ddic_chk_sta == 0xff) {
- ret = -EINVAL;
- /* CMD mode error handle */
- if (dsi_mode == 0) {
- /* TODO: set ESD_EOF event through CPU is better */
- mtk_crtc_pkt_create(&cmdq_handle2, crtc,
- mtk_crtc->gce_obj.client[CLIENT_DSI_CFG]);
- cmdq_pkt_set_event(
- cmdq_handle2,
- mtk_crtc->gce_obj.event[EVENT_ESD_EOF]);
- cmdq_pkt_flush(cmdq_handle2);
- cmdq_pkt_destroy(cmdq_handle2);
- }
- goto done;
- }
- /* Copy slot data to data array */
- memcpy((void *)&read_data0,
- (mtk_crtc->gce_obj.buf.va_base +
- DISP_SLOT_READ_DDIC_BASE + 0 * 0x4),
- sizeof(unsigned int));
- memcpy((void *)&read_data1,
- (mtk_crtc->gce_obj.buf.va_base +
- DISP_SLOT_READ_DDIC_BASE + 1 * 0x4),
- sizeof(unsigned int));
- memcpy((void *)&read_data2,
- (mtk_crtc->gce_obj.buf.va_base +
- DISP_SLOT_READ_DDIC_BASE + 2 * 0x4),
- sizeof(unsigned int));
- memcpy((void *)&read_data3,
- (mtk_crtc->gce_obj.buf.va_base +
- DISP_SLOT_READ_DDIC_BASE + 3 * 0x4),
- sizeof(unsigned int));
- DDPINFO("%s: read_data0 byte0~3=0x%x~0x%x~0x%x~0x%x\n",
- __func__, read_data0.byte0, read_data0.byte1
- , read_data0.byte2, read_data0.byte3);
- DDPINFO("%s: read_data1 byte0~3=0x%x~0x%x~0x%x~0x%x\n",
- __func__, read_data1.byte0, read_data1.byte1
- , read_data1.byte2, read_data1.byte3);
- DDPINFO("%s: read_data2 byte0~3=0x%x~0x%x~0x%x~0x%x\n",
- __func__, read_data2.byte0, read_data2.byte1
- , read_data2.byte2, read_data2.byte3);
- DDPINFO("%s: read_data3 byte0~3=0x%x~0x%x~0x%x~0x%x\n",
- __func__, read_data3.byte0, read_data3.byte1
- , read_data3.byte2, read_data3.byte3);
- /*parse packet*/
- packet_type = read_data0.byte0;
- /* 0x02: acknowledge & error report */
- /* 0x11: generic short read response(1 byte return) */
- /* 0x12: generic short read response(2 byte return) */
- /* 0x1a: generic long read response */
- /* 0x1c: dcs long read response */
- /* 0x21: dcs short read response(1 byte return) */
- /* 0x22: dcs short read response(2 byte return) */
- if (packet_type == 0x1A || packet_type == 0x1C) {
- recv_data_cnt = read_data0.byte1
- + read_data0.byte2 * 16;
- if (recv_data_cnt > RT_MAX_NUM) {
- DDPMSG("DSI read long packet data exceeds 10 bytes\n");
- recv_data_cnt = RT_MAX_NUM;
- }
- if (recv_data_cnt > msg.rx_len)
- recv_data_cnt = msg.rx_len;
- DDPINFO("DSI read long packet size: %d\n",
- recv_data_cnt);
- if (recv_data_cnt <= 4) {
- memcpy((void *)msg.rx_buf,
- (void *)&read_data1, recv_data_cnt);
- } else if (recv_data_cnt <= 8) {
- memcpy((void *)msg.rx_buf,
- (void *)&read_data1, 4);
- memcpy((void *)(msg.rx_buf + 4),
- (void *)&read_data2, recv_data_cnt - 4);
- } else {
- memcpy((void *)msg.rx_buf,
- (void *)&read_data1, 4);
- memcpy((void *)(msg.rx_buf + 4),
- (void *)&read_data2, 4);
- memcpy((void *)(msg.rx_buf + 8),
- (void *)&read_data3, recv_data_cnt - 8);
- }
- } else if (packet_type == 0x11 || packet_type == 0x21) {
- recv_data_cnt = 1;
- memcpy((void *)msg.rx_buf,
- (void *)&read_data0.byte1, recv_data_cnt);
- } else if (packet_type == 0x12 || packet_type == 0x22) {
- recv_data_cnt = 2;
- if (recv_data_cnt > msg.rx_len)
- recv_data_cnt = msg.rx_len;
- memcpy((void *)msg.rx_buf,
- (void *)&read_data0.byte1, recv_data_cnt);
- } else if (packet_type == 0x02) {
- DDPPR_ERR("read return type is 0x02, re-read\n");
- } else {
- DDPPR_ERR("read return type is non-recognite, type = 0x%x\n",
- packet_type);
- }
- msg.rx_len = recv_data_cnt;
- DDPINFO("[DSI]packet_type~recv_data_cnt = 0x%x~0x%x\n",
- packet_type, recv_data_cnt);
- /* Todo: Support read multiple registers */
- cmd_msg->rx_len[0] = msg.rx_len;
- cmd_msg->rx_buf[0] = msg.rx_buf;
- /* Debug info */
- for (i = 0; i < cmd_msg->rx_cmd_num; i++) {
- DDPINFO("rx_len[%d]=%d\n", i, (int)cmd_msg->rx_len[i]);
- for (j = 0; j < cmd_msg->rx_len[i]; j++) {
- DDPINFO("rx_buf[%d]--byte:%d,val:0x%x\n",
- i, j, *(char *)(cmd_msg->rx_buf[i] + j));
- }
- }
- done:
- cmdq_pkt_destroy(cmdq_handle);
- DDPMSG("%s -\n", __func__);
- return 0;
- }
- static ssize_t mtk_dsi_host_send_cmd(struct mtk_dsi *dsi,
- const struct mipi_dsi_msg *msg, u8 flag)
- {
- mtk_dsi_wait_idle(dsi, flag, 2000, NULL);
- mtk_dsi_irq_data_clear(dsi, flag);
- mtk_dsi_cmdq(dsi, msg);
- mtk_dsi_start(dsi);
- if (MTK_DSI_HOST_IS_READ(msg->type)) {
- unsigned int loop_cnt = 0;
- s32 tmp;
- udelay(1);
- while (loop_cnt < 100 * 1000) {
- tmp = readl(dsi->regs + DSI_INTSTA);
- if ((tmp & LPRX_RD_RDY_INT_FLAG))
- break;
- loop_cnt++;
- usleep_range(100, 200);
- }
- DDPINFO("%s wait RXDY done\n", __func__);
- mtk_dsi_mask(dsi, DSI_INTSTA, LPRX_RD_RDY_INT_FLAG, 0);
- mtk_dsi_mask(dsi, DSI_RACK, RACK, RACK);
- }
- if (!mtk_dsi_wait_idle(dsi, flag, 2000, NULL))
- return -ETIME;
- else
- return 0;
- }
- static void mtk_dsi_dy_fps_cmdq_cb(struct cmdq_cb_data data)
- {
- struct mtk_cmdq_cb_data *cb_data = data.data;
- DDPINFO("%s vdo mode fps change done\n", __func__);
- cmdq_pkt_destroy(cb_data->cmdq_handle);
- kfree(cb_data);
- }
- static ssize_t mtk_dsi_host_send_vm_cmd(struct mtk_dsi *dsi,
- const struct mipi_dsi_msg *msg, u8 flag)
- {
- unsigned int loop_cnt = 0;
- s32 tmp;
- mtk_dsi_vm_cmdq(dsi, msg, NULL);
- /* clear status */
- mtk_dsi_mask(dsi, DSI_INTSTA, VM_CMD_DONE_INT_EN, 0);
- mtk_dsi_vm_start(dsi);
- while (loop_cnt < 100 * 1000) {
- tmp = readl(dsi->regs + DSI_INTSTA);
- if (!(tmp & VM_CMD_DONE_INT_EN))
- return 0;
- loop_cnt++;
- udelay(1);
- }
- DDPMSG("%s timeout\n", __func__);
- return -ETIME;
- }
- static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
- const struct mipi_dsi_msg *msg)
- {
- struct mtk_dsi *dsi = host_to_dsi(host);
- u32 recv_cnt, i;
- u8 read_data[16];
- void *src_addr;
- u8 irq_flag;
- if (readl(dsi->regs + DSI_MODE_CTRL) & MODE)
- irq_flag = VM_CMD_DONE_INT_EN;
- else
- irq_flag = CMD_DONE_INT_FLAG;
- if (MTK_DSI_HOST_IS_READ(msg->type)) {
- struct mipi_dsi_msg set_rd_msg = {
- .tx_buf = (u8 [1]) { msg->rx_len},
- .tx_len = 0x1,
- .type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE,
- };
- if (mtk_dsi_host_send_cmd(dsi, &set_rd_msg, irq_flag) < 0)
- DDPPR_ERR("RX mtk_dsi_host_send_cmd fail\n");
- irq_flag |= LPRX_RD_RDY_INT_FLAG;
- }
- if (readl(dsi->regs + DSI_MODE_CTRL) & MODE) {
- if (mtk_dsi_host_send_vm_cmd(dsi, msg, irq_flag) < 0)
- return -ETIME;
- } else {
- if (mtk_dsi_host_send_cmd(dsi, msg, irq_flag) < 0)
- return -ETIME;
- }
- if (!MTK_DSI_HOST_IS_READ(msg->type))
- return 0;
- if (!msg->rx_buf) {
- DRM_ERROR("dsi receive buffer size may be NULL\n");
- return -EINVAL;
- }
- for (i = 0; i < 16; i++)
- *(read_data + i) = readb(dsi->regs + DSI_RX_DATA0 + i);
- recv_cnt = mtk_dsi_recv_cnt(read_data[0], read_data);
- if (recv_cnt > 2)
- src_addr = &read_data[4];
- else
- src_addr = &read_data[1];
- if (recv_cnt > 10)
- recv_cnt = 10;
- if (recv_cnt > msg->rx_len)
- recv_cnt = msg->rx_len;
- if (recv_cnt)
- memcpy(msg->rx_buf, src_addr, recv_cnt);
- DDPINFO("dsi get %d byte data from the panel address(0x%x)\n", recv_cnt,
- *((u8 *)(msg->tx_buf)));
- return recv_cnt;
- }
- static const struct mipi_dsi_host_ops mtk_dsi_ops = {
- .attach = mtk_dsi_host_attach,
- .detach = mtk_dsi_host_detach,
- .transfer = mtk_dsi_host_transfer,
- };
- void mtk_dsi_send_switch_cmd(struct mtk_dsi *dsi,
- struct cmdq_pkt *handle,
- struct mtk_drm_crtc *mtk_crtc, unsigned int cur_mode, unsigned int dst_mode)
- {
- unsigned int i;
- struct dfps_switch_cmd *dfps_cmd = NULL;
- struct mtk_panel_params *params = NULL;
- struct drm_display_mode *old_mode = NULL;
- old_mode = &(mtk_crtc->avail_modes[cur_mode]);
- if (dsi->ext && dsi->ext->params)
- params = mtk_crtc->panel_ext->params;
- else /* can't find panel ext information,stop */
- return;
- for (i = 0; i < MAX_DYN_CMD_NUM; i++) {
- dfps_cmd = ¶ms->dyn_fps.dfps_cmd_table[i];
- if (dfps_cmd->cmd_num == 0)
- break;
- if (dfps_cmd->src_fps == 0 || old_mode->vrefresh == dfps_cmd->src_fps)
- mipi_dsi_dcs_write_gce_dyn(dsi, handle, dfps_cmd->para_list,
- dfps_cmd->cmd_num);
- }
- }
- static void mtk_dsi_cmd_timing_change(struct mtk_dsi *dsi,
- struct mtk_drm_crtc *mtk_crtc, struct drm_crtc_state *old_state)
- {
- struct cmdq_pkt *cmdq_handle;
- struct cmdq_pkt *cmdq_handle2;
- int clk_refcnt = 0;
- struct mtk_crtc_state *state =
- to_mtk_crtc_state(mtk_crtc->base.state);
- struct mtk_crtc_state *old_mtk_state =
- to_mtk_crtc_state(old_state);
- unsigned int src_mode =
- old_mtk_state->prop_val[CRTC_PROP_DISP_MODE_IDX];
- unsigned int dst_mode =
- state->prop_val[CRTC_PROP_DISP_MODE_IDX];
- bool need_mipi_change = 1;
- /* use no mipi clk change solution */
- if (dsi->ext && dsi->ext->params &&
- dsi->ext->params->dyn_fps.switch_en > 0)
- need_mipi_change = 0;
- mtk_crtc_pkt_create(&cmdq_handle, &mtk_crtc->base,
- mtk_crtc->gce_obj.client[CLIENT_CFG]);
- /* 1. wait frame done & wait DSI not busy */
- cmdq_pkt_wfe(cmdq_handle,
- mtk_crtc->gce_obj.event[EVENT_STREAM_EOF]);
- /* Clear stream block to prevent trigger loop start */
- cmdq_pkt_clear_event(cmdq_handle,
- mtk_crtc->gce_obj.event[EVENT_STREAM_BLOCK]);
- mtk_dsi_poll_for_idle(dsi, cmdq_handle);
- cmdq_pkt_flush(cmdq_handle);
- cmdq_pkt_destroy(cmdq_handle);
- if (need_mipi_change == 0)
- goto skip_change_mipi;
- /* send lcm cmd before DSI power down if needed */
- if (dsi->ext && dsi->ext->funcs &&
- dsi->ext->funcs->mode_switch)
- dsi->ext->funcs->mode_switch(dsi->panel, src_mode,
- dst_mode, BEFORE_DSI_POWERDOWN);
- /* Power off DSI */
- clk_refcnt = dsi->clk_refcnt;
- while (dsi->clk_refcnt != 1)
- mtk_dsi_ddp_unprepare(&dsi->ddp_comp);
- mtk_dsi_enter_idle(dsi);
- if (dsi->ext && dsi->ext->funcs &&
- dsi->ext->funcs->ext_param_set)
- dsi->ext->funcs->ext_param_set(dsi->panel,
- state->prop_val[CRTC_PROP_DISP_MODE_IDX]);
- /* Power on & re-config DSI*/
- mtk_dsi_leave_idle(dsi);
- while (dsi->clk_refcnt != clk_refcnt)
- mtk_dsi_ddp_prepare(&dsi->ddp_comp);
- skip_change_mipi:
- /* send lcm cmd after DSI power on if needed */
- if (dsi->ext && dsi->ext->funcs &&
- dsi->ext->funcs->mode_switch)
- dsi->ext->funcs->mode_switch(dsi->panel, src_mode,
- dst_mode, AFTER_DSI_POWERON);
- /* set frame done */
- mtk_crtc_pkt_create(&cmdq_handle2, &mtk_crtc->base,
- mtk_crtc->gce_obj.client[CLIENT_CFG]);
- cmdq_pkt_set_event(cmdq_handle2,
- mtk_crtc->gce_obj.event[EVENT_STREAM_EOF]);
- cmdq_pkt_set_event(cmdq_handle2,
- mtk_crtc->gce_obj.event[EVENT_STREAM_BLOCK]);
- cmdq_pkt_flush(cmdq_handle2);
- cmdq_pkt_destroy(cmdq_handle2);
- }
- static void mtk_dsi_vdo_timing_change(struct mtk_dsi *dsi,
- struct mtk_drm_crtc *mtk_crtc, struct drm_crtc_state *old_state)
- {
- unsigned int vfp = 0;
- unsigned int hfp = 0;
- unsigned int fps_chg_index = 0;
- struct cmdq_pkt *handle;
- struct cmdq_client *client = mtk_crtc->gce_obj.client[CLIENT_DSI_CFG];
- struct mtk_ddp_comp *comp = &dsi->ddp_comp;
- struct mtk_crtc_state *state =
- to_mtk_crtc_state(mtk_crtc->base.state);
- struct mtk_cmdq_cb_data *cb_data;
- struct drm_display_mode adjusted_mode = state->base.adjusted_mode;
- struct mtk_crtc_state *old_mtk_state =
- to_mtk_crtc_state(old_state);
- unsigned int src_mode =
- old_mtk_state->prop_val[CRTC_PROP_DISP_MODE_IDX];
- DDPINFO("%s+\n", __func__);
- if (dsi->ext && dsi->ext->funcs &&
- dsi->ext->funcs->ext_param_set)
- dsi->ext->funcs->ext_param_set(dsi->panel,
- state->prop_val[CRTC_PROP_DISP_MODE_IDX]);
- //1.fps change index
- fps_chg_index = mtk_crtc->fps_change_index;
- mtk_drm_idlemgr_kick(__func__, &(mtk_crtc->base), 0);
- cb_data = kmalloc(sizeof(*cb_data), GFP_KERNEL);
- if (!cb_data) {
- DDPINFO("%s:%d, cb data creation failed\n",
- __func__, __LINE__);
- return;
- }
- mtk_crtc_pkt_create(&handle, &(mtk_crtc->base), client);
- if (fps_chg_index & DYNFPS_DSI_MIPI_CLK) {
- DDPINFO("%s, change MIPI Clock\n", __func__);
- } else if (fps_chg_index & DYNFPS_DSI_HFP) {
- DDPINFO("%s, change HFP\n", __func__);
- /*wait and clear EOF
- * avoid other display related task break fps change task
- * because fps change need stop & re-start vdo mode
- */
- cmdq_pkt_wfe(handle,
- mtk_crtc->gce_obj.event[EVENT_VDO_EOF]);
- /*1.1 send cmd: stop vdo mode*/
- mtk_dsi_stop_vdo_mode(dsi, handle);
- /* for crtc first enable,dyn fps fail*/
- if (dsi->data_rate == 0) {
- dsi->data_rate = mtk_dsi_default_rate(dsi);
- mtk_mipi_tx_pll_rate_set_adpt(dsi->phy, dsi->data_rate);
- mtk_dsi_phy_timconfig(dsi, NULL);
- }
- if (dsi->mipi_hopping_sta) {
- DDPINFO("%s,mipi_clk_change_sta\n", __func__);
- hfp = dsi->ext->params->dyn.hfp;
- } else
- hfp = adjusted_mode.hsync_start -
- adjusted_mode.hdisplay;
- dsi->vm.hfront_porch = hfp;
- mtk_dsi_calc_vdo_timing(dsi);
- mtk_dsi_porch_setting(comp, handle, DSI_HFP, dsi->hfp_byte);
- /*1.2 send cmd: send cmd*/
- mtk_dsi_send_switch_cmd(dsi, handle, mtk_crtc, src_mode, adjusted_mode.vrefresh);
- /*1.3 send cmd: start vdo mode*/
- mtk_dsi_start_vdo_mode(comp, handle);
- /*clear EOF
- * avoid config continue after we trigger vdo mode
- */
- cmdq_pkt_clear_event(handle,
- mtk_crtc->gce_obj.event[EVENT_VDO_EOF]);
- /*1.3 send cmd: trigger*/
- mtk_disp_mutex_trigger(comp->mtk_crtc->mutex[0], handle);
- mtk_dsi_trigger(comp, handle);
- } else if (fps_chg_index & DYNFPS_DSI_VFP) {
- DDPINFO("%s, change VFP\n", __func__);
- cmdq_pkt_clear_event(handle,
- mtk_crtc->gce_obj.event[EVENT_DSI0_SOF]);
- cmdq_pkt_wait_no_clear(handle,
- mtk_crtc->gce_obj.event[EVENT_DSI0_SOF]);
- comp = mtk_ddp_comp_request_output(mtk_crtc);
- if (!comp) {
- DDPPR_ERR("ddp comp is NULL\n");
- return;
- }
- if (dsi->mipi_hopping_sta) {
- DDPINFO("%s,mipi_clk_change_sta\n", __func__);
- vfp = dsi->ext->params->dyn.vfp;
- } else
- vfp = adjusted_mode.vsync_start -
- adjusted_mode.vdisplay;
- dsi->vm.vfront_porch = vfp;
- if (dsi->mipi_hopping_sta) {
- DDPINFO("%s,mipi_clk_change_sta\n", __func__);
- vfp = dsi->ext->params->dyn.vfp;
- } else
- vfp = adjusted_mode.vsync_start -
- adjusted_mode.vdisplay;
- dsi->vm.vfront_porch = vfp;
- mtk_dsi_porch_setting(comp, handle, DSI_VFP, vfp);
- }
- cb_data->cmdq_handle = handle;
- if (cmdq_pkt_flush_threaded(handle,
- mtk_dsi_dy_fps_cmdq_cb, cb_data) < 0)
- DDPPR_ERR("failed to flush dsi_dy_fps\n");
- }
- static void mtk_dsi_timing_change(struct mtk_dsi *dsi,
- struct mtk_drm_crtc *mtk_crtc, struct drm_crtc_state *old_state)
- {
- if (mtk_dsi_is_cmd_mode(&dsi->ddp_comp))
- mtk_dsi_cmd_timing_change(dsi, mtk_crtc, old_state);
- else
- mtk_dsi_vdo_timing_change(dsi, mtk_crtc, old_state);
- }
- unsigned int mtk_dsi_get_dsc_compress_rate(struct mtk_dsi *dsi)
- {
- unsigned int compress_rate, bpp, bpc;
- struct mtk_panel_ext *ext = dsi->ext;
- if (ext->params->dsc_params.enable) {
- bpp = ext->params->dsc_params.bit_per_pixel / 16;
- bpc = ext->params->dsc_params.bit_per_channel;
- //compress_rate*100 for 3.75 or 2.5 case
- compress_rate = bpc * 3 * 100 / bpp;
- } else
- compress_rate = 100;
- return compress_rate;
- }
- /******************************************************************************
- * HRT BW = Overlap x vact x hact x vrefresh x 4 x (vtotal/vact)
- * In Video Mode , Using the Formula below:
- * MM Clock
- * DSC on: vact x hact x vrefresh x (vtotal / vact)
- * DSC off: vact x hact x vrefresh x (vtotal x htotal) / (vact x hact)
- * In Command Mode Using the Formula below:
- * Type | MM Clock (unit: Pixel)
- * CPHY | data_rate x (16/7) x lane_num x compress_ratio / bpp
- * DPHY | data_rate x lane_num x compress_ratio / bpp
- ******************************************************************************/
- void mtk_dsi_set_mmclk_by_datarate(struct mtk_dsi *dsi,
- struct mtk_drm_crtc *mtk_crtc, unsigned int en)
- {
- struct mtk_panel_ext *ext = dsi->ext;
- unsigned int compress_rate;
- unsigned int data_rate;
- unsigned int pixclk = 0;
- u32 bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
- unsigned int pixclk_min = 0;
- unsigned int hact = mtk_crtc->base.state->adjusted_mode.hdisplay;
- unsigned int htotal = mtk_crtc->base.state->adjusted_mode.htotal;
- unsigned int vtotal = mtk_crtc->base.state->adjusted_mode.vtotal;
- unsigned int vact = mtk_crtc->base.state->adjusted_mode.vdisplay;
- unsigned int vrefresh = mtk_crtc->base.state->adjusted_mode.vrefresh;
- if (!en) {
- mtk_drm_set_mmclk_by_pixclk(&mtk_crtc->base, pixclk,
- __func__);
- return;
- }
- //for FPS change,update dsi->ext
- dsi->ext = find_panel_ext(dsi->panel);
- data_rate = mtk_dsi_default_rate(dsi);
- if (!dsi->ext) {
- DDPPR_ERR("DSI panel ext is NULL\n");
- return;
- }
- compress_rate = mtk_dsi_get_dsc_compress_rate(dsi);
- if (!data_rate) {
- DDPPR_ERR("DSI data_rate is NULL\n");
- return;
- }
- //If DSI mode is vdo mode
- if (!mtk_dsi_is_cmd_mode(&dsi->ddp_comp)) {
- if (ext->params->is_cphy)
- pixclk_min = data_rate * dsi->lanes * 2 / 7 / 3;
- else
- pixclk_min = data_rate * dsi->lanes / 8 / 3;
- pixclk = vact * hact * vrefresh / 1000;
- if (ext->params->dsc_params.enable)
- pixclk = pixclk * vtotal / vact;
- else
- pixclk = pixclk * (vtotal * htotal * 100 /
- (vact * hact)) / 100;
- pixclk = (unsigned int)(pixclk / 1000);
- pixclk = (pixclk_min > pixclk) ? pixclk_min : pixclk;
- }
- else {
- pixclk = data_rate * dsi->lanes * compress_rate;
- if (data_rate && ext->params->is_cphy)
- pixclk = pixclk * 16 / 7;
- pixclk = pixclk / bpp / 100;
- }
- DDPINFO("%s,data_rate =%d,clk=%u pixclk_min=%d\n", __func__,
- data_rate, pixclk, pixclk_min);
- mtk_drm_set_mmclk_by_pixclk(&mtk_crtc->base, pixclk, __func__);
- }
- /******************************************************************************
- * DSI Type | PHY TYPE | HRT_BW (unit: Bytes) one frame ( Overlap * )
- * VDO MODE | CPHY/DPHY| Overlap x vact x hact x vrefresh x 4 x (vtotal/vact)
- * CMD MODE | CPHY | (16/7) x data_rate x lane_num x compress_ratio/ bpp x4
- * CMD MODE | DPHY | data_rate x lane_num x compress_ratio / bpp x 4
- ******************************************************************************/
- unsigned long long mtk_dsi_get_frame_hrt_bw_base_by_datarate(
- struct mtk_drm_crtc *mtk_crtc,
- struct mtk_dsi *dsi)
- {
- static unsigned long long bw_base;
- int hact = mtk_crtc->base.state->adjusted_mode.hdisplay;
- int vtotal = mtk_crtc->base.state->adjusted_mode.vtotal;
- int vact = mtk_crtc->base.state->adjusted_mode.vdisplay;
- int vrefresh = mtk_crtc->base.state->adjusted_mode.vrefresh;
- //For CMD mode to calculate HRT BW
- unsigned int compress_rate = mtk_dsi_get_dsc_compress_rate(dsi);
- unsigned int data_rate = mtk_dsi_default_rate(dsi);
- u32 bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
- bw_base = vact * hact * vrefresh * 4 / 1000;
- if (!mtk_dsi_is_cmd_mode(&dsi->ddp_comp)) {
- bw_base = bw_base * vtotal / vact;
- bw_base = bw_base / 1000;
- } else {
- bw_base = data_rate * dsi->lanes * compress_rate * 4;
- bw_base = bw_base / bpp / 100;
- }
- DDPDBG("Frame Bw:%llu", bw_base);
- return bw_base;
- }
- static int mtk_dsi_io_cmd(struct mtk_ddp_comp *comp, struct cmdq_pkt *handle,
- enum mtk_ddp_io_cmd cmd, void *params)
- {
- struct mtk_panel_ext **ext;
- struct mtk_dsi *dsi = container_of(comp, struct mtk_dsi, ddp_comp);
- void **out_params;
- struct mtk_panel_ext *panel_ext = NULL;
- struct drm_display_mode **mode;
- bool *enable;
- unsigned int vfp_low_power = 0;
- switch (cmd) {
- case REQ_PANEL_EXT:
- ext = (struct mtk_panel_ext **)params;
- *ext = mtk_dsi_get_panel_ext(comp);
- break;
- case DSI_START_VDO_MODE:
- mtk_dsi_start_vdo_mode(comp, handle);
- break;
- case DSI_STOP_VDO_MODE:
- mtk_dsi_stop_vdo_mode(dsi, handle);
- break;
- case ESD_CHECK_READ:
- mtk_dsi_esd_read(comp, handle, (uintptr_t)params);
- break;
- case ESD_CHECK_CMP:
- return mtk_dsi_esd_cmp(comp, handle, params);
- case CONNECTOR_READ_EPILOG:
- mtk_dsi_clear_rxrd_irq(dsi);
- break;
- case REQ_ESD_EINT_COMPAT:
- out_params = (void **)params;
- *out_params = (void *)dsi->driver_data->esd_eint_compat;
- break;
- case COMP_REG_START:
- mtk_dsi_trigger(comp, handle);
- break;
- case CONNECTOR_PANEL_ENABLE:
- mtk_output_dsi_enable(dsi, true);
- break;
- case CONNECTOR_PANEL_DISABLE:
- {
- mtk_output_dsi_disable(dsi, true);
- dsi->doze_enabled = false;
- }
- break;
- case CONNECTOR_ENABLE:
- mtk_dsi_leave_idle(dsi);
- break;
- case CONNECTOR_DISABLE:
- mtk_dsi_enter_idle(dsi);
- break;
- case CONNECTOR_RESET:
- mtk_dsi_reset_engine(dsi);
- break;
- case CONNECTOR_IS_ENABLE:
- enable = (bool *)params;
- *enable = dsi->output_en;
- break;
- case DSI_VFP_IDLE_MODE:
- {
- panel_ext = mtk_dsi_get_panel_ext(comp);
- if (dsi->mipi_hopping_sta && panel_ext && panel_ext->params
- && panel_ext->params->dyn.vfp_lp_dyn)
- vfp_low_power = panel_ext->params->dyn.vfp_lp_dyn;
- else if (panel_ext && panel_ext->params
- && panel_ext->params->vfp_low_power)
- vfp_low_power = panel_ext->params->vfp_low_power;
- if (vfp_low_power) {
- DDPINFO("vfp_low_power=%d\n", vfp_low_power);
- mtk_dsi_porch_setting(comp, handle, DSI_VFP,
- vfp_low_power);
- }
- }
- break;
- case DSI_VFP_DEFAULT_MODE:
- {
- unsigned int vfront_porch = 0;
- struct mtk_drm_crtc *crtc = comp->mtk_crtc;
- panel_ext = mtk_dsi_get_panel_ext(comp);
- if (dsi->mipi_hopping_sta && panel_ext && panel_ext->params
- && panel_ext->params->dyn.vfp)
- vfront_porch = panel_ext->params->dyn.vfp;
- else
- vfront_porch = dsi->vm.vfront_porch;
- DDPINFO("vfront_porch=%d\n", vfront_porch);
- if (panel_ext->params->wait_sof_before_dec_vfp) {
- cmdq_pkt_clear_event(handle,
- crtc->gce_obj.event[EVENT_DSI0_SOF]);
- cmdq_pkt_wait_no_clear(handle,
- crtc->gce_obj.event[EVENT_DSI0_SOF]);
- }
- mtk_dsi_porch_setting(comp, handle, DSI_VFP,
- vfront_porch);
- }
- break;
- case DSI_GET_TIMING:
- mode = (struct drm_display_mode **)params;
- *mode = list_first_entry(&dsi->conn.modes,
- struct drm_display_mode, head);
- break;
- case DSI_GET_MODE_BY_MAX_VREFRESH:
- {
- struct drm_display_mode *tmp = NULL;
- unsigned int vrefresh = 0;
- mode = (struct drm_display_mode **)params;
- list_for_each_entry(tmp, &dsi->conn.modes, head) {
- if (tmp && tmp->vrefresh > vrefresh) {
- vrefresh = tmp->vrefresh;
- *mode = tmp;
- }
- }
- }
- break;
- case IRQ_LEVEL_IDLE:
- {
- unsigned int inten;
- if (!mtk_dsi_is_cmd_mode(&dsi->ddp_comp) && handle) {
- inten = FRAME_DONE_INT_FLAG;
- cmdq_pkt_write(handle, comp->cmdq_base,
- comp->regs_pa + DSI_INTEN, 0, inten);
- }
- }
- break;
- case IRQ_LEVEL_ALL:
- {
- unsigned int inten;
- if (!handle) {
- DDPPR_ERR("GCE handle is NULL\n");
- return 0;
- }
- inten = BUFFER_UNDERRUN_INT_FLAG | INP_UNFINISH_INT_EN;
- if (!mtk_dsi_is_cmd_mode(&dsi->ddp_comp)) {
- inten |= FRAME_DONE_INT_FLAG;
- cmdq_pkt_write(handle, comp->cmdq_base,
- comp->regs_pa + DSI_INTEN, inten, inten);
- } else {
- inten |= TE_RDY_INT_FLAG;
- cmdq_pkt_write(handle, comp->cmdq_base,
- comp->regs_pa + DSI_INTEN, inten, inten);
- }
- }
- break;
- case LCM_RESET:
- {
- struct mtk_dsi *dsi =
- container_of(comp, struct mtk_dsi, ddp_comp);
- panel_ext = mtk_dsi_get_panel_ext(comp);
- if (panel_ext && panel_ext->funcs
- && panel_ext->funcs->reset)
- panel_ext->funcs->reset(dsi->panel, *(int *)params);
- }
- break;
- case DSI_SET_BL:
- {
- struct mtk_dsi *dsi =
- container_of(comp, struct mtk_dsi, ddp_comp);
- panel_ext = mtk_dsi_get_panel_ext(comp);
- if (panel_ext && panel_ext->funcs
- && panel_ext->funcs->set_backlight_cmdq)
- panel_ext->funcs->set_backlight_cmdq(dsi,
- mipi_dsi_dcs_write_gce,
- handle, *(int *)params);
- }
- break;
- case DSI_SET_BL_AOD:
- {
- struct mtk_dsi *dsi =
- container_of(comp, struct mtk_dsi, ddp_comp);
- panel_ext = mtk_dsi_get_panel_ext(comp);
- if (panel_ext && panel_ext->funcs
- && panel_ext->funcs->set_aod_light_mode)
- panel_ext->funcs->set_aod_light_mode(dsi,
- mipi_dsi_dcs_write_gce,
- handle, *(unsigned int *)params);
- }
- break;
- case DSI_SET_BL_GRP:
- {
- struct mtk_dsi *dsi =
- container_of(comp, struct mtk_dsi, ddp_comp);
- panel_ext = mtk_dsi_get_panel_ext(comp);
- if (panel_ext && panel_ext->funcs
- && panel_ext->funcs->set_backlight_grp_cmdq)
- panel_ext->funcs->set_backlight_grp_cmdq(dsi,
- mipi_dsi_dcs_grp_write_gce,
- handle, *(int *)params);
- }
- break;
- case DSI_HBM_SET:
- {
- panel_ext = mtk_dsi_get_panel_ext(comp);
- if (!(panel_ext && panel_ext->funcs &&
- panel_ext->funcs->hbm_set_cmdq))
- break;
- panel_ext->funcs->hbm_set_cmdq(dsi->panel, dsi,
- mipi_dsi_dcs_write_gce, handle,
- *(bool *)params);
- break;
- }
- case DSI_HBM_GET_STATE:
- {
- panel_ext = mtk_dsi_get_panel_ext(comp);
- if (!(panel_ext && panel_ext->funcs &&
- panel_ext->funcs->hbm_get_state))
- break;
- panel_ext->funcs->hbm_get_state(dsi->panel, (bool *)params);
- break;
- }
- case DSI_HBM_GET_WAIT_STATE:
- {
- panel_ext = mtk_dsi_get_panel_ext(comp);
- if (!(panel_ext && panel_ext->funcs &&
- panel_ext->funcs->hbm_get_wait_state))
- break;
- panel_ext->funcs->hbm_get_wait_state(dsi->panel,
- (bool *)params);
- break;
- }
- case DSI_HBM_SET_WAIT_STATE:
- {
- panel_ext = mtk_dsi_get_panel_ext(comp);
- if (!(panel_ext && panel_ext->funcs &&
- panel_ext->funcs->hbm_set_wait_state))
- break;
- panel_ext->funcs->hbm_set_wait_state(dsi->panel,
- *(bool *)params);
- break;
- }
- case DSI_HBM_WAIT:
- {
- int ret = 0;
- if (mtk_dsi_is_cmd_mode(&dsi->ddp_comp)) {
- reset_dsi_wq(&dsi->te_rdy);
- ret = wait_dsi_wq(&dsi->te_rdy, HZ);
- } else {
- reset_dsi_wq(&dsi->frame_done);
- ret = wait_dsi_wq(&dsi->frame_done, HZ);
- }
- if (!ret)
- DDPINFO("%s: DSI_HBM_WAIT failed\n", __func__);
- break;
- }
- case LCM_ATA_CHECK:
- {
- struct mtk_dsi *dsi =
- container_of(comp, struct mtk_dsi, ddp_comp);
- int *val = (int *)params;
- panel_ext = mtk_dsi_get_panel_ext(comp);
- if (panel_ext && panel_ext->funcs
- && panel_ext->funcs->ata_check)
- *val = panel_ext->funcs->ata_check(dsi->panel);
- }
- break;
- case DSI_SET_CRTC_AVAIL_MODES:
- {
- struct mtk_drm_crtc *crtc = (struct mtk_drm_crtc *)params;
- struct drm_display_mode *m;
- unsigned int i = 0;
- crtc->avail_modes_num = 0;
- list_for_each_entry(m, &dsi->conn.modes, head)
- crtc->avail_modes_num++;
- crtc->avail_modes =
- vzalloc(sizeof(struct drm_display_mode) *
- crtc->avail_modes_num);
- list_for_each_entry(m, &dsi->conn.modes, head) {
- drm_mode_copy(&crtc->avail_modes[i], m);
- i++;
- }
- }
- break;
- case DSI_TIMING_CHANGE:
- {
- struct mtk_drm_crtc *crtc = comp->mtk_crtc;
- struct drm_crtc_state *old_state =
- (struct drm_crtc_state *)params;
- mtk_dsi_timing_change(dsi, crtc, old_state);
- }
- break;
- case GET_PANEL_NAME:
- {
- struct mtk_dsi *dsi =
- container_of(comp, struct mtk_dsi, ddp_comp);
- out_params = (void **)params;
- *out_params = (void *)dsi->panel->dev->driver->name;
- }
- break;
- case DSI_CHANGE_MODE:
- {
- struct mtk_dsi *dsi =
- container_of(comp, struct mtk_dsi, ddp_comp);
- int *aod_en = params;
- panel_ext = mtk_dsi_get_panel_ext(comp);
- if (dsi->ext && dsi->ext->funcs
- && dsi->ext->funcs->doze_get_mode_flags) {
- dsi->mode_flags =
- dsi->ext->funcs->doze_get_mode_flags(
- dsi->panel, *aod_en);
- }
- }
- break;
- case MIPI_HOPPING:
- {
- struct mtk_dsi *dsi =
- container_of(comp, struct mtk_dsi, ddp_comp);
- int *en = (int *)params;
- mtk_dsi_clk_change(dsi, *en);
- }
- break;
- case DYN_FPS_INDEX:
- {
- struct mtk_drm_crtc *crtc = comp->mtk_crtc;
- struct drm_crtc_state *old_state =
- (struct drm_crtc_state *)params;
- mtk_dsi_fps_change_index(dsi, crtc, old_state);
- }
- break;
- case SET_MMCLK_BY_DATARATE:
- {
- #ifndef CONFIG_FPGA_EARLY_PORTING
- struct mtk_drm_crtc *crtc = comp->mtk_crtc;
- unsigned int *pixclk = (unsigned int *)params;
- mtk_dsi_set_mmclk_by_datarate(dsi, crtc, *pixclk);
- #endif
- }
- break;
- case GET_FRAME_HRT_BW_BY_DATARATE:
- {
- struct mtk_drm_crtc *crtc = comp->mtk_crtc;
- unsigned long long *base_bw =
- (unsigned long long *)params;
- *base_bw = mtk_dsi_get_frame_hrt_bw_base_by_datarate(crtc, dsi);
- }
- break;
- case DSI_SEND_DDIC_CMD:
- {
- struct mtk_drm_crtc *crtc = comp->mtk_crtc;
- struct mtk_ddic_dsi_msg *cmd_msg =
- (struct mtk_ddic_dsi_msg *)params;
- return mtk_mipi_dsi_write_gce(dsi, handle, crtc, cmd_msg);
- }
- break;
- case DSI_READ_DDIC_CMD:
- {
- struct mtk_drm_crtc *crtc = comp->mtk_crtc;
- struct mtk_ddic_dsi_msg *cmd_msg =
- (struct mtk_ddic_dsi_msg *)params;
- return mtk_mipi_dsi_read_gce(dsi, handle, crtc, cmd_msg);
- }
- break;
- case DSI_GET_VIRTUAL_HEIGH:
- {
- struct mtk_drm_crtc *crtc = comp->mtk_crtc;
- return mtk_dsi_get_virtual_heigh(dsi, &crtc->base);
- }
- break;
- case DSI_GET_VIRTUAL_WIDTH:
- {
- struct mtk_drm_crtc *crtc = comp->mtk_crtc;
- return mtk_dsi_get_virtual_width(dsi, &crtc->base);
- }
- break;
- case DSI_LFR_SET:
- {
- mtk_dsi_set_LFR(dsi, comp, handle);
- }
- break;
- case DSI_LFR_UPDATE:
- {
- mtk_dsi_LFR_update(dsi, comp, handle);
- }
- break;
- case DSI_LFR_STATUS_CHECK:
- {
- mtk_dsi_LFR_status_check(dsi);
- }
- break;
- default:
- break;
- }
- return 0;
- }
- static const struct mtk_ddp_comp_funcs mtk_dsi_funcs = {
- .prepare = mtk_dsi_ddp_prepare,
- .unprepare = mtk_dsi_ddp_unprepare,
- .config_trigger = mtk_dsi_config_trigger,
- .io_cmd = mtk_dsi_io_cmd,
- .is_busy = mtk_dsi_is_busy,
- };
- static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
- {
- int ret;
- struct drm_device *drm = data;
- struct mtk_dsi *dsi = dev_get_drvdata(dev);
- DDPINFO("%s+\n", __func__);
- ret = mtk_ddp_comp_register(drm, &dsi->ddp_comp);
- if (ret < 0) {
- dev_err(dev, "Failed to register component %s: %d\n",
- dev->of_node->full_name, ret);
- return ret;
- }
- ret = mtk_dsi_create_conn_enc(drm, dsi);
- if (ret) {
- DRM_ERROR("Encoder create failed with %d\n", ret);
- goto err_unregister;
- }
- DDPINFO("%s-\n", __func__);
- return 0;
- err_unregister:
- mipi_dsi_host_unregister(&dsi->host);
- mtk_ddp_comp_unregister(drm, &dsi->ddp_comp);
- return ret;
- }
- static void mtk_dsi_unbind(struct device *dev, struct device *master,
- void *data)
- {
- struct drm_device *drm = data;
- struct mtk_dsi *dsi = dev_get_drvdata(dev);
- mtk_dsi_destroy_conn_enc(dsi);
- mipi_dsi_host_unregister(&dsi->host);
- mtk_ddp_comp_unregister(drm, &dsi->ddp_comp);
- }
- static const struct component_ops mtk_dsi_component_ops = {
- .bind = mtk_dsi_bind, .unbind = mtk_dsi_unbind,
- };
- static const struct mtk_dsi_driver_data mt8173_dsi_driver_data = {
- .reg_cmdq_ofs = 0x200, .irq_handler = mtk_dsi_irq,
- .support_shadow = false,
- };
- static const struct mtk_dsi_driver_data mt6779_dsi_driver_data = {
- .reg_cmdq_ofs = 0x200,
- .poll_for_idle = mtk_dsi_poll_for_idle,
- .irq_handler = mtk_dsi_irq_status,
- .esd_eint_compat = "mediatek, DSI_TE-eint",
- .support_shadow = false,
- };
- static const struct mtk_dsi_driver_data mt6885_dsi_driver_data = {
- .reg_cmdq_ofs = 0x200,
- .poll_for_idle = mtk_dsi_poll_for_idle,
- .irq_handler = mtk_dsi_irq_status,
- .esd_eint_compat = "mediatek, DSI_TE-eint",
- .support_shadow = false,
- };
- static const struct mtk_dsi_driver_data mt6873_dsi_driver_data = {
- .reg_cmdq_ofs = 0x200,
- .poll_for_idle = mtk_dsi_poll_for_idle,
- .irq_handler = mtk_dsi_irq_status,
- .esd_eint_compat = "mediatek, DSI_TE-eint",
- .support_shadow = false,
- };
- static const struct mtk_dsi_driver_data mt6853_dsi_driver_data = {
- .reg_cmdq_ofs = 0x200,
- .poll_for_idle = mtk_dsi_poll_for_idle,
- .irq_handler = mtk_dsi_irq_status,
- .esd_eint_compat = "mediatek, DSI_TE-eint",
- .support_shadow = false,
- };
- static const struct mtk_dsi_driver_data mt6833_dsi_driver_data = {
- .reg_cmdq_ofs = 0x200,
- .poll_for_idle = mtk_dsi_poll_for_idle,
- .irq_handler = mtk_dsi_irq_status,
- .esd_eint_compat = "mediatek, DSI_TE-eint",
- .support_shadow = false,
- };
- static const struct mtk_dsi_driver_data mt2701_dsi_driver_data = {
- .reg_cmdq_ofs = 0x180, .irq_handler = mtk_dsi_irq,
- .support_shadow = false,
- };
- static const struct of_device_id mtk_dsi_of_match[] = {
- {.compatible = "mediatek,mt2701-dsi", .data = &mt2701_dsi_driver_data},
- {.compatible = "mediatek,mt6779-dsi", .data = &mt6779_dsi_driver_data},
- {.compatible = "mediatek,mt8173-dsi", .data = &mt8173_dsi_driver_data},
- {.compatible = "mediatek,mt6885-dsi", .data = &mt6885_dsi_driver_data},
- {.compatible = "mediatek,mt6873-dsi", .data = &mt6873_dsi_driver_data},
- {.compatible = "mediatek,mt6853-dsi", .data = &mt6853_dsi_driver_data},
- {.compatible = "mediatek,mt6833-dsi", .data = &mt6833_dsi_driver_data},
- {},
- };
- static int mtk_dsi_probe(struct platform_device *pdev)
- {
- struct mtk_dsi *dsi;
- struct device *dev = &pdev->dev;
- const struct of_device_id *of_id;
- struct device_node *remote_node, *endpoint;
- struct resource *regs;
- int irq_num;
- int comp_id;
- int ret;
- DDPINFO("%s+\n", __func__);
- dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
- if (!dsi)
- return -ENOMEM;
- dsi->host.ops = &mtk_dsi_ops;
- dsi->host.dev = dev;
- ret = mipi_dsi_host_register(&dsi->host);
- if (ret < 0) {
- dev_err(dev, "failed to register DSI host: %d\n", ret);
- return -EPROBE_DEFER;
- }
- of_id = of_match_device(mtk_dsi_of_match, &pdev->dev);
- if (!of_id) {
- dev_err(dev, "DSI device match failed\n");
- return -EPROBE_DEFER;
- }
- dsi->driver_data = (struct mtk_dsi_driver_data *)of_id->data;
- endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
- if (endpoint) {
- remote_node = of_graph_get_remote_port_parent(endpoint);
- if (!remote_node) {
- dev_err(dev, "No panel connected\n");
- ret = -ENODEV;
- goto error;
- }
- dsi->bridge = of_drm_find_bridge(remote_node);
- dsi->panel = of_drm_find_panel(remote_node);
- of_node_put(remote_node);
- if (!dsi->bridge && !dsi->panel) {
- dev_info(dev, "Waiting for bridge or panel driver\n");
- ret = -EPROBE_DEFER;
- goto error;
- }
- }
- dsi->ext = find_panel_ext(dsi->panel);
- dsi->engine_clk = devm_clk_get(dev, "engine");
- if (IS_ERR(dsi->engine_clk)) {
- ret = PTR_ERR(dsi->engine_clk);
- dev_err(dev, "Failed to get engine clock: %d\n", ret);
- #ifndef CONFIG_FPGA_EARLY_PORTING
- goto error;
- #endif
- }
- dsi->digital_clk = devm_clk_get(dev, "digital");
- if (IS_ERR(dsi->digital_clk)) {
- ret = PTR_ERR(dsi->digital_clk);
- dev_err(dev, "Failed to get digital clock: %d\n", ret);
- #ifndef CONFIG_FPGA_EARLY_PORTING
- goto error;
- #endif
- }
- dsi->hs_clk = devm_clk_get(dev, "hs");
- if (IS_ERR(dsi->hs_clk)) {
- ret = PTR_ERR(dsi->hs_clk);
- dev_err(dev, "Failed to get hs clock: %d\n", ret);
- #ifndef CONFIG_FPGA_EARLY_PORTING
- goto error;
- #endif
- }
- regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- dsi->regs = devm_ioremap_resource(dev, regs);
- if (IS_ERR(dsi->regs)) {
- ret = PTR_ERR(dsi->regs);
- dev_err(dev, "Failed to ioremap memory: %d\n", ret);
- #ifndef CONFIG_FPGA_EARLY_PORTING
- goto error;
- #endif
- }
- dsi->phy = devm_phy_get(dev, "dphy");
- if (IS_ERR(dsi->phy)) {
- ret = PTR_ERR(dsi->phy);
- dev_err(dev, "Failed to get MIPI-DPHY: %d\n", ret);
- goto error;
- }
- comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DSI);
- if (comp_id < 0) {
- dev_err(dev, "Failed to identify by alias: %d\n", comp_id);
- ret = comp_id;
- goto error;
- }
- ret = mtk_ddp_comp_init(dev, dev->of_node, &dsi->ddp_comp, comp_id,
- &mtk_dsi_funcs);
- if (ret) {
- dev_err(dev, "Failed to initialize component: %d\n", ret);
- goto error;
- }
- /* init wq */
- init_dsi_wq(dsi);
- irq_num = platform_get_irq(pdev, 0);
- if (irq_num < 0) {
- dev_err(&pdev->dev, "failed to request dsi irq resource\n");
- ret = -EPROBE_DEFER;
- goto error;
- }
- irq_set_status_flags(irq_num, IRQ_TYPE_LEVEL_HIGH);
- ret = devm_request_irq(
- &pdev->dev, irq_num, dsi->driver_data->irq_handler,
- IRQF_TRIGGER_NONE | IRQF_SHARED, dev_name(&pdev->dev), dsi);
- if (ret) {
- DDPAEE("%s:%d, failed to request irq:%d ret:%d\n",
- __func__, __LINE__,
- irq_num, ret);
- ret = -EPROBE_DEFER;
- goto error;
- }
- init_waitqueue_head(&dsi->irq_wait_queue);
- #ifndef CONFIG_FPGA_EARLY_PORTING
- /* set ccf reference cnt = 1 */
- phy_power_on(dsi->phy);
- ret = clk_prepare_enable(dsi->engine_clk);
- if (ret < 0)
- pr_info("%s Failed to enable engine clock: %d\n",
- __func__, ret);
- ret = clk_prepare_enable(dsi->digital_clk);
- if (ret < 0)
- pr_info("%s Failed to enable digital clock: %d\n",
- __func__, ret);
- #endif
- dsi->output_en = true;
- dsi->clk_refcnt = 1;
- platform_set_drvdata(pdev, dsi);
- DDPINFO("%s-\n", __func__);
- return component_add(&pdev->dev, &mtk_dsi_component_ops);
- error:
- mipi_dsi_host_unregister(&dsi->host);
- return -EPROBE_DEFER;
- }
- static int mtk_dsi_remove(struct platform_device *pdev)
- {
- struct mtk_dsi *dsi = platform_get_drvdata(pdev);
- mtk_output_dsi_disable(dsi, false);
- component_del(&pdev->dev, &mtk_dsi_component_ops);
- return 0;
- }
- struct platform_driver mtk_dsi_driver = {
- .probe = mtk_dsi_probe,
- .remove = mtk_dsi_remove,
- .driver = {
- .name = "mtk-dsi", .of_match_table = mtk_dsi_of_match,
- },
- };
- /* ***************** PanelMaster ******************* */
- u32 fbconfig_mtk_dsi_get_lanes_num(struct mtk_ddp_comp *comp)
- {
- struct mtk_dsi *dsi = container_of(comp, struct mtk_dsi, ddp_comp);
- return dsi->lanes;
- }
- int pm_mtk_dsi_get_mode_type(struct mtk_dsi *dsi)
- {
- u32 vid_mode = CMD_MODE;
- if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
- if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
- vid_mode = BURST_MODE;
- else if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
- vid_mode = SYNC_PULSE_MODE;
- else
- vid_mode = SYNC_EVENT_MODE;
- }
- return vid_mode;
- }
- int fbconfig_mtk_dsi_get_mode_type(struct mtk_ddp_comp *comp)
- {
- struct mtk_dsi *dsi = container_of(comp, struct mtk_dsi, ddp_comp);
- u32 vid_mode = pm_mtk_dsi_get_mode_type(dsi);
- return vid_mode;
- }
- u32 PanelMaster_get_dsi_timing(struct mtk_dsi *dsi, enum MIPI_SETTING_TYPE type)
- {
- u32 dsi_val = 0;
- u32 vid_mode;
- u32 t_hsa;
- int fbconfig_dsiTmpBufBpp = 0;
- struct mtk_panel_ext *ext = dsi->ext;
- struct videomode *vm = &dsi->vm;
- struct dynamic_mipi_params *dyn = NULL;
- if (ext && ext->params)
- dyn = &ext->params->dyn;
- if (dsi->format == MIPI_DSI_FMT_RGB565)
- fbconfig_dsiTmpBufBpp = 2;
- else
- fbconfig_dsiTmpBufBpp = 3;
- vid_mode = pm_mtk_dsi_get_mode_type(dsi);
- t_hsa = (dsi->mipi_hopping_sta) ?
- ((dyn && !!dyn->hsa) ?
- dyn->hsa : vm->hsync_len) :
- vm->hsync_len;
- switch (type) {
- case MIPI_LPX:
- {
- dsi_val = readl(dsi->regs + DSI_PHY_TIMECON0);
- dsi_val &= LPX;
- return dsi_val >> 0;
- }
- case MIPI_HS_PRPR:
- {
- dsi_val = readl(dsi->regs + DSI_PHY_TIMECON0);
- dsi_val &= HS_PREP;
- return dsi_val >> 8;
- }
- case MIPI_HS_ZERO:
- {
- dsi_val = readl(dsi->regs + DSI_PHY_TIMECON0);
- dsi_val &= HS_ZERO;
- return dsi_val >> 16;
- }
- case MIPI_HS_TRAIL:
- {
- dsi_val = readl(dsi->regs + DSI_PHY_TIMECON0);
- dsi_val &= HS_TRAIL;
- return dsi_val >> 24;
- }
- case MIPI_TA_GO:
- {
- dsi_val = readl(dsi->regs + DSI_PHY_TIMECON1);
- dsi_val &= TA_GO;
- return dsi_val >> 0;
- }
- case MIPI_TA_SURE:
- {
- dsi_val = readl(dsi->regs + DSI_PHY_TIMECON1);
- dsi_val &= TA_SURE;
- return dsi_val >> 8;
- }
- case MIPI_TA_GET:
- {
- dsi_val = readl(dsi->regs + DSI_PHY_TIMECON1);
- dsi_val &= TA_GET;
- return dsi_val >> 16;
- }
- case MIPI_DA_HS_EXIT:
- {
- dsi_val = readl(dsi->regs + DSI_PHY_TIMECON1);
- dsi_val &= DA_HS_EXIT;
- return dsi_val >> 24;
- }
- case MIPI_CONT_DET:
- {
- dsi_val = readl(dsi->regs + DSI_PHY_TIMECON2);
- dsi_val &= CONT_DET;
- return dsi_val >> 0;
- }
- case MIPI_CLK_ZERO:
- {
- dsi_val = readl(dsi->regs + DSI_PHY_TIMECON2);
- dsi_val &= CLK_ZERO;
- return dsi_val >> 16;
- }
- case MIPI_CLK_TRAIL:
- {
- dsi_val = readl(dsi->regs + DSI_PHY_TIMECON2);
- dsi_val &= CLK_TRAIL;
- return dsi_val >> 24;
- }
- case MIPI_CLK_HS_PRPR:
- {
- dsi_val = readl(dsi->regs + DSI_PHY_TIMECON3);
- dsi_val &= CLK_HS_PREP;
- return dsi_val >> 0;
- }
- case MIPI_CLK_HS_POST:
- {
- dsi_val = readl(dsi->regs + DSI_PHY_TIMECON3);
- dsi_val &= CLK_HS_POST;
- return dsi_val >> 8;
- }
- case MIPI_CLK_HS_EXIT:
- {
- dsi_val = readl(dsi->regs + DSI_PHY_TIMECON3);
- dsi_val &= CLK_HS_EXIT;
- return dsi_val >> 16;
- }
- case MIPI_HPW:
- {
- u32 tmp_hpw;
- tmp_hpw = readl(dsi->regs + DSI_HSA_WC);
- dsi_val = (tmp_hpw + 10) / fbconfig_dsiTmpBufBpp;
- return dsi_val;
- }
- case MIPI_HFP:
- {
- u32 tmp_hfp;
- tmp_hfp = readl(dsi->regs + DSI_HFP_WC);
- dsi_val = (tmp_hfp + 12) / fbconfig_dsiTmpBufBpp;
- return dsi_val;
- }
- case MIPI_HBP:
- {
- u32 tmp_hbp;
- tmp_hbp = readl(dsi->regs + DSI_HBP_WC);
- if (vid_mode == SYNC_EVENT_MODE || vid_mode == BURST_MODE)
- return (tmp_hbp + 10) / fbconfig_dsiTmpBufBpp - t_hsa;
- else
- return (tmp_hbp + 10) / fbconfig_dsiTmpBufBpp;
- }
- case MIPI_VPW:
- {
- u32 tmp_vpw;
- tmp_vpw = readl(dsi->regs + DSI_VACT_NL);
- return tmp_vpw;
- }
- case MIPI_VFP:
- {
- u32 tmp_vfp;
- tmp_vfp = readl(dsi->regs + DSI_VFP_NL);
- return tmp_vfp;
- }
- case MIPI_VBP:
- {
- u32 tmp_vbp;
- tmp_vbp = readl(dsi->regs + DSI_VBP_NL);
- return tmp_vbp;
- }
- case MIPI_SSC_EN:
- {
- if (dsi->ext->params->ssc_disable)
- dsi_val = 0;
- else
- dsi_val = 1;
- return dsi_val;
- }
- default:
- DDPMSG("fbconfig dsi set timing :no such type!!\n");
- break;
- }
- dsi_val = 0;
- return dsi_val;
- }
- u32 DSI_ssc_enable(struct mtk_dsi *dsi, u32 en)
- {
- u32 disable = en ? 0 : 1;
- dsi->ext->params->ssc_disable = disable;
- return 0;
- }
- int PanelMaster_DSI_set_timing(struct mtk_dsi *dsi, struct MIPI_TIMING timing)
- {
- u32 value;
- int ret = 0;
- u32 vid_mode;
- u32 t_hsa;
- int fbconfig_dsiTmpBufBpp = 0;
- struct mtk_panel_ext *ext = dsi->ext;
- struct videomode *vm = &dsi->vm;
- struct dynamic_mipi_params *dyn = NULL;
- if (ext && ext->params)
- dyn = &ext->params->dyn;
- if (dsi->format == MIPI_DSI_FMT_RGB565)
- fbconfig_dsiTmpBufBpp = 2;
- else
- fbconfig_dsiTmpBufBpp = 3;
- vid_mode = pm_mtk_dsi_get_mode_type(dsi);
- t_hsa = (dsi->mipi_hopping_sta) ?
- ((dyn && !!dyn->hsa) ?
- dyn->hsa : vm->hsync_len) :
- vm->hsync_len;
- switch (timing.type) {
- case MIPI_LPX:
- {
- value = readl(dsi->regs + DSI_PHY_TIMECON0);
- value &= 0xffffff00;
- value |= (timing.value << 0);
- writel(value, dsi->regs + DSI_PHY_TIMECON0);
- break;
- }
- case MIPI_HS_PRPR:
- {
- value = readl(dsi->regs + DSI_PHY_TIMECON0);
- value &= 0xffff00ff;
- value |= (timing.value << 8);
- writel(value, dsi->regs + DSI_PHY_TIMECON0);
- break;
- }
- case MIPI_HS_ZERO:
- {
- value = readl(dsi->regs + DSI_PHY_TIMECON0);
- value &= 0xff00ffff;
- value |= (timing.value << 16);
- writel(value, dsi->regs + DSI_PHY_TIMECON0);
- break;
- }
- case MIPI_HS_TRAIL:
- {
- value = readl(dsi->regs + DSI_PHY_TIMECON0);
- value &= 0x00ffffff;
- value |= (timing.value << 24);
- writel(value, dsi->regs + DSI_PHY_TIMECON0);
- break;
- }
- case MIPI_TA_GO:
- {
- value = readl(dsi->regs + DSI_PHY_TIMECON1);
- value &= 0xffffff00;
- value |= (timing.value << 0);
- writel(value, dsi->regs + DSI_PHY_TIMECON1);
- break;
- }
- case MIPI_TA_SURE:
- {
- value = readl(dsi->regs + DSI_PHY_TIMECON1);
- value &= 0xffff00ff;
- value |= (timing.value << 8);
- writel(value, dsi->regs + DSI_PHY_TIMECON1);
- break;
- }
- case MIPI_TA_GET:
- {
- value = readl(dsi->regs + DSI_PHY_TIMECON1);
- value &= 0xff00ffff;
- value |= (timing.value << 16);
- writel(value, dsi->regs + DSI_PHY_TIMECON1);
- break;
- }
- case MIPI_DA_HS_EXIT:
- {
- value = readl(dsi->regs + DSI_PHY_TIMECON1);
- value &= 0x00ffffff;
- value |= (timing.value << 24);
- writel(value, dsi->regs + DSI_PHY_TIMECON1);
- break;
- }
- case MIPI_CONT_DET:
- {
- value = readl(dsi->regs + DSI_PHY_TIMECON2);
- value &= 0xffffff00;
- value |= (timing.value << 0);
- writel(value, dsi->regs + DSI_PHY_TIMECON2);
- break;
- }
- case MIPI_CLK_ZERO:
- {
- value = readl(dsi->regs + DSI_PHY_TIMECON2);
- value &= 0xff00ffff;
- value |= (timing.value << 16);
- writel(value, dsi->regs + DSI_PHY_TIMECON2);
- break;
- }
- case MIPI_CLK_TRAIL:
- {
- value = readl(dsi->regs + DSI_PHY_TIMECON2);
- value &= 0x00ffffff;
- value |= (timing.value << 24);
- writel(value, dsi->regs + DSI_PHY_TIMECON2);
- break;
- }
- case MIPI_CLK_HS_PRPR:
- {
- value = readl(dsi->regs + DSI_PHY_TIMECON3);
- value &= 0xffffff00;
- value |= (timing.value << 0);
- writel(value, dsi->regs + DSI_PHY_TIMECON3);
- break;
- }
- case MIPI_CLK_HS_POST:
- {
- value = readl(dsi->regs + DSI_PHY_TIMECON3);
- value &= 0xffff00ff;
- value |= (timing.value << 8);
- writel(value, dsi->regs + DSI_PHY_TIMECON3);
- break;
- }
- case MIPI_CLK_HS_EXIT:
- {
- value = readl(dsi->regs + DSI_PHY_TIMECON3);
- value &= 0xff00ffff;
- value |= (timing.value << 16);
- writel(value, dsi->regs + DSI_PHY_TIMECON3);
- break;
- }
- case MIPI_HPW:
- {
- timing.value = timing.value * fbconfig_dsiTmpBufBpp - 10;
- timing.value = ALIGN_TO((timing.value), 4);
- writel(timing.value, dsi->regs + DSI_HSA_WC);
- break;
- }
- case MIPI_HFP:
- {
- timing.value = timing.value * fbconfig_dsiTmpBufBpp - 12;
- timing.value = ALIGN_TO(timing.value, 4);
- writel(timing.value, dsi->regs + DSI_HFP_WC);
- break;
- }
- case MIPI_HBP:
- {
- u32 hbp_byte;
- if (vid_mode == SYNC_EVENT_MODE ||
- vid_mode == BURST_MODE) {
- hbp_byte = timing.value + t_hsa;
- hbp_byte = hbp_byte * fbconfig_dsiTmpBufBpp - 10;
- } else {
- hbp_byte = timing.value * fbconfig_dsiTmpBufBpp - 10;
- }
- hbp_byte = ALIGN_TO(hbp_byte, 4);
- writel(hbp_byte, dsi->regs + DSI_HBP_WC);
- break;
- }
- case MIPI_VPW:
- {
- writel(timing.value, dsi->regs + DSI_VACT_NL);
- break;
- }
- case MIPI_VFP:
- {
- writel(timing.value, dsi->regs + DSI_VFP_NL);
- break;
- }
- case MIPI_VBP:
- {
- writel(timing.value, dsi->regs + DSI_VBP_NL);
- break;
- }
- case MIPI_SSC_EN:
- {
- DSI_ssc_enable(dsi, timing.value);
- break;
- }
- default:
- DDPMSG("fbconfig dsi set timing :no such type!!\n");
- break;
- }
- return ret;
- }
- static int dsi_dcs_write(struct mtk_dsi *dsi, void *data, size_t len)
- {
- struct mipi_dsi_device *dsi_device = dsi->dev_for_PM;
- ssize_t ret;
- char *addr;
- addr = (char *)data;
- if ((int)*addr < 0xB0)
- ret = mipi_dsi_dcs_write_buffer(dsi_device, data, len);
- else
- ret = mipi_dsi_generic_write(dsi_device, data, len);
- return ret;
- }
- static int dsi_dcs_read(struct mtk_dsi *dsi,
- uint8_t cmd, void *data, size_t len)
- {
- struct mipi_dsi_device *dsi_device = dsi->dev_for_PM;
- ssize_t ret;
- ret = mipi_dsi_dcs_read(dsi_device, cmd, data, len);
- return ret;
- }
- int fbconfig_get_esd_check(struct mtk_dsi *dsi, uint32_t cmd,
- uint8_t *buffer, uint32_t num)
- {
- int array[4];
- int ret = 0;
- /* set max returen packet size */
- /* array[0] = 0x00013700 */
- array[0] = 0x3700 + (num << 16);
- ret = dsi_dcs_write(dsi, array, 1);
- if (ret < 0) {
- DDPPR_ERR("fail to writing seq\n");
- return -1;
- }
- ret = dsi_dcs_read(dsi, cmd, buffer, num);
- if (ret < 0) {
- DDPPR_ERR("fail to read seq\n");
- return -1;
- }
- return 0;
- }
- int fbconfig_get_esd_check_test(struct drm_crtc *crtc,
- uint32_t cmd, uint8_t *buffer, uint32_t num)
- {
- int ret = 0;
- struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
- struct mtk_ddp_comp *output_comp;
- struct mtk_dsi *dsi;
- struct mtk_panel_params *dsi_params;
- int cmd_matched = 0;
- uint32_t i = 0;
- DDP_MUTEX_LOCK(&mtk_crtc->lock, __func__, __LINE__);
- if (crtc->state && !(crtc->state->active)) {
- DDPMSG("%s:crtc is inactive -- skip\n", __func__);
- DDP_MUTEX_UNLOCK(&mtk_crtc->lock, __func__, __LINE__);
- goto done;
- }
- output_comp = mtk_ddp_comp_request_output(mtk_crtc);
- if (unlikely(!output_comp)) {
- DDPPR_ERR("%s: invalid output comp\n", __func__);
- ret = -EINVAL;
- DDP_MUTEX_UNLOCK(&mtk_crtc->lock, __func__, __LINE__);
- goto done;
- }
- dsi = container_of(output_comp, struct mtk_dsi, ddp_comp);
- if (dsi && dsi->ext && dsi->ext->params)
- dsi_params = dsi->ext->params;//get_dsi_params_handle((uint32_t)(PM_DSI0));
- if (dsi && dsi_params) {
- for (i = 0; i < ESD_CHECK_NUM; i++) {
- if (dsi_params->lcm_esd_check_table[i].cmd == 0)
- break;
- if ((uint32_t)(dsi_params->lcm_esd_check_table[i].cmd) == cmd) {
- cmd_matched = 1;
- break;
- }
- }
- } else {
- DDPPR_ERR("%s: dsi or panel is invalid -- skip\n", __func__);
- DDP_MUTEX_UNLOCK(&mtk_crtc->lock, __func__, __LINE__);
- goto done;
- }
- if (!cmd_matched) {
- DDPPR_ERR("%s: cmd not matched support cmd=%d, test cmd =%d -- skip\n", __func__,
- dsi_params->lcm_esd_check_table[0].cmd, cmd);
- DDP_MUTEX_UNLOCK(&mtk_crtc->lock, __func__, __LINE__);
- goto done;
- }
- mtk_drm_idlemgr_kick(__func__, &mtk_crtc->base, 0);
- /* 0 disable esd check */
- if (mtk_drm_lcm_is_connect())
- mtk_disp_esd_check_switch(crtc, false);
- /* 1 stop crtc */
- mtk_crtc_stop_for_pm(mtk_crtc, true);
- /* 2 stop dsi */
- mtk_dsi_stop(dsi);
- mtk_dsi_clk_hs_mode(dsi, 0);
- mtk_dsi_set_interrupt_enable(dsi);
- /* 3 read lcm esd check */
- ret = fbconfig_get_esd_check(dsi, cmd, buffer, num);
- /* 4 start crtc */
- mtk_crtc_start_for_pm(crtc);
- /* 5 start dsi */
- mtk_dsi_clk_hs_mode(dsi, 1);
- mtk_dsi_start(dsi);
- /* 6 enable esd check */
- if (mtk_drm_lcm_is_connect())
- mtk_disp_esd_check_switch(crtc, true);
- mtk_crtc_hw_block_ready(crtc);
- if (mtk_crtc_is_frame_trigger_mode(crtc)) {
- struct cmdq_pkt *cmdq_handle;
- mtk_crtc_pkt_create(&cmdq_handle, &mtk_crtc->base,
- mtk_crtc->gce_obj.client[CLIENT_CFG]);
- cmdq_pkt_set_event(cmdq_handle,
- mtk_crtc->gce_obj.event[EVENT_STREAM_DIRTY]);
- cmdq_pkt_set_event(cmdq_handle,
- mtk_crtc->gce_obj.event[EVENT_CABC_EOF]);
- cmdq_pkt_set_event(cmdq_handle,
- mtk_crtc->gce_obj.event[EVENT_ESD_EOF]);
- cmdq_pkt_flush(cmdq_handle);
- cmdq_pkt_destroy(cmdq_handle);
- }
- mtk_drm_idlemgr_kick(__func__, &mtk_crtc->base, 0);
- DDP_MUTEX_UNLOCK(&mtk_crtc->lock, __func__, __LINE__);
- done:
- return ret;
- }
- void Panel_Master_primary_display_config_dsi(struct mtk_dsi *dsi,
- const char *name, uint32_t config_value)
- {
- unsigned long mipi_tx_rate;
- if (!strcmp(name, "PM_CLK")) {
- pr_debug("Pmaster_config_dsi: PM_CLK:%d\n", config_value);
- dsi->ext->params->pll_clk = config_value;
- } else if (!strcmp(name, "PM_SSC")) {
- pr_debug("Pmaster_config_dsi: PM_SSC:%d\n", config_value);
- dsi->ext->params->ssc_range = config_value;
- return;
- }
- dsi->data_rate = dsi->ext->params->pll_clk * 2;
- mipi_tx_rate = dsi->data_rate * 1000000;
- mtk_dsi_set_interrupt_enable(dsi);
- /* config dsi clk */
- clk_set_rate(dsi->hs_clk, mipi_tx_rate);
- mtk_mipi_tx_pll_rate_set_adpt(dsi->phy, dsi->data_rate);
- mtk_dsi_phy_timconfig(dsi, NULL);
- if (!mtk_dsi_is_cmd_mode(&dsi->ddp_comp)) {
- mtk_dsi_set_vm_cmd(dsi);
- mtk_dsi_calc_vdo_timing(dsi);
- mtk_dsi_config_vdo_timing(dsi);
- }
- }
- u32 PanelMaster_get_CC(struct mtk_dsi *dsi)
- {
- u32 tmp_reg;
- tmp_reg = readl(dsi->regs + DSI_TXRX_CTRL);
- tmp_reg &= HSTX_CKLP_EN;
- return (tmp_reg >> 16);
- }
- void PanelMaster_set_CC(struct mtk_dsi *dsi, u32 enable)
- {
- u32 tmp_reg;
- DDPMSG("set_cc :%d\n", enable);
- tmp_reg = readl(dsi->regs + DSI_TXRX_CTRL);
- tmp_reg &= (~HSTX_CKLP_EN);
- tmp_reg |= (enable << 16);
- writel(tmp_reg, dsi->regs + DSI_TXRX_CTRL);
- }
- struct mtk_dsi *pm_get_mtk_dsi(struct drm_crtc *crtc)
- {
- struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
- struct mtk_ddp_comp *output_comp = NULL;
- struct mtk_dsi *dsi = NULL;
- if (crtc->state && !(crtc->state->active)) {
- DDPMSG("%s: crtc is inactive -- skip\n", __func__);
- return dsi;
- }
- output_comp = mtk_ddp_comp_request_output(mtk_crtc);
- if (unlikely(!output_comp)) {
- DDPPR_ERR("%s: invalid output comp\n", __func__);
- return dsi;
- }
- dsi = container_of(output_comp, struct mtk_dsi, ddp_comp);
- return dsi;
- }
- int Panel_Master_dsi_config_entry(struct drm_crtc *crtc,
- const char *name, int config_value)
- {
- int ret = 0;
- struct mtk_dsi *dsi = NULL;
- struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
- dsi = pm_get_mtk_dsi(crtc);
- if (!dsi) {
- ret = -EINVAL;
- goto done;
- }
- mtk_drm_idlemgr_kick(__func__, &mtk_crtc->base, 0);
- /* disable esd check */
- if (mtk_drm_lcm_is_connect())
- mtk_disp_esd_check_switch(crtc, false);
- if ((!strcmp(name, "PM_CLK")) || (!strcmp(name, "PM_SSC"))) {
- Panel_Master_primary_display_config_dsi(dsi,
- name, config_value);
- } else if (!strcmp(name, "PM_DRIVER_IC_RESET") && (!config_value)) {
- if (dsi->panel) {
- if (drm_panel_prepare(dsi->panel))
- DDPPR_ERR("failed to enable the panel\n");
- }
- }
- /* enable esd check */
- if (mtk_drm_lcm_is_connect())
- mtk_disp_esd_check_switch(crtc, true);
- done:
- return ret;
- }
- int Panel_Master_lcm_get_dsi_timing_entry(struct drm_crtc *crtc,
- int type)
- {
- int ret = 0;
- struct mtk_dsi *dsi = NULL;
- struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
- DDP_MUTEX_LOCK(&mtk_crtc->lock, __func__, __LINE__);
- dsi = pm_get_mtk_dsi(crtc);
- if (!dsi) {
- ret = -EINVAL;
- goto done;
- }
- mtk_drm_idlemgr_kick(__func__, &mtk_crtc->base, 0);
- ret = PanelMaster_get_dsi_timing(dsi, type);
- done:
- DDP_MUTEX_UNLOCK(&mtk_crtc->lock, __func__, __LINE__);
- return ret;
- }
- int Panel_Master_mipi_set_timing_entry(struct drm_crtc *crtc,
- struct MIPI_TIMING timing)
- {
- int ret = 0;
- struct mtk_dsi *dsi = NULL;
- struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
- DDP_MUTEX_LOCK(&mtk_crtc->lock, __func__, __LINE__);
- dsi = pm_get_mtk_dsi(crtc);
- if (!dsi) {
- ret = -EINVAL;
- goto done;
- }
- mtk_drm_idlemgr_kick(__func__, &mtk_crtc->base, 0);
- ret = PanelMaster_DSI_set_timing(dsi, timing);
- done:
- DDP_MUTEX_UNLOCK(&mtk_crtc->lock, __func__, __LINE__);
- return ret;
- }
- int Panel_Master_mipi_set_cc_entry(struct drm_crtc *crtc,
- int enable)
- {
- int ret = 0;
- struct mtk_dsi *dsi = NULL;
- struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
- DDP_MUTEX_LOCK(&mtk_crtc->lock, __func__, __LINE__);
- dsi = pm_get_mtk_dsi(crtc);
- if (!dsi) {
- ret = -EINVAL;
- goto done;
- }
- mtk_drm_idlemgr_kick(__func__, &mtk_crtc->base, 0);
- PanelMaster_set_CC(dsi, enable);
- done:
- DDP_MUTEX_UNLOCK(&mtk_crtc->lock, __func__, __LINE__);
- return ret;
- }
- int Panel_Master_mipi_get_cc_entry(struct drm_crtc *crtc)
- {
- int ret = 0;
- struct mtk_dsi *dsi = NULL;
- struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
- DDP_MUTEX_LOCK(&mtk_crtc->lock, __func__, __LINE__);
- dsi = pm_get_mtk_dsi(crtc);
- if (!dsi) {
- ret = -EINVAL;
- goto done;
- }
- mtk_drm_idlemgr_kick(__func__, &mtk_crtc->base, 0);
- ret = PanelMaster_get_CC(dsi);
- done:
- DDP_MUTEX_UNLOCK(&mtk_crtc->lock, __func__, __LINE__);
- return ret;
- }
- /* ******************* end PanelMaster ***************** */
|