123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894 |
- /*
- * SiS 300/540/630[S]/730[S],
- * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX],
- * XGI V3XT/V5/V8, Z7
- * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
- *
- * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the named License,
- * or any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
- *
- * Author: Thomas Winischhofer <thomas@winischhofer.net>
- *
- * Author of (practically wiped) code base:
- * SiS (www.sis.com)
- * Copyright (C) 1999 Silicon Integrated Systems, Inc.
- *
- * See http://www.winischhofer.net/ for more information and updates
- *
- * Originally based on the VBE 2.0 compliant graphic boards framebuffer driver,
- * which is (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
- *
- */
- #include <linux/module.h>
- #include <linux/moduleparam.h>
- #include <linux/kernel.h>
- #include <linux/spinlock.h>
- #include <linux/errno.h>
- #include <linux/string.h>
- #include <linux/mm.h>
- #include <linux/screen_info.h>
- #include <linux/slab.h>
- #include <linux/fb.h>
- #include <linux/selection.h>
- #include <linux/ioport.h>
- #include <linux/init.h>
- #include <linux/pci.h>
- #include <linux/vmalloc.h>
- #include <linux/capability.h>
- #include <linux/fs.h>
- #include <linux/types.h>
- #include <linux/uaccess.h>
- #include <asm/io.h>
- #ifdef CONFIG_MTRR
- #include <asm/mtrr.h>
- #endif
- #include "sis.h"
- #include "sis_main.h"
- #if !defined(CONFIG_FB_SIS_300) && !defined(CONFIG_FB_SIS_315)
- #warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
- #warning sisfb will not work!
- #endif
- static void sisfb_handle_command(struct sis_video_info *ivideo,
- struct sisfb_cmd *sisfb_command);
- /* ------------------ Internal helper routines ----------------- */
- static void __init
- sisfb_setdefaultparms(void)
- {
- sisfb_off = 0;
- sisfb_parm_mem = 0;
- sisfb_accel = -1;
- sisfb_ypan = -1;
- sisfb_max = -1;
- sisfb_userom = -1;
- sisfb_useoem = -1;
- sisfb_mode_idx = -1;
- sisfb_parm_rate = -1;
- sisfb_crt1off = 0;
- sisfb_forcecrt1 = -1;
- sisfb_crt2type = -1;
- sisfb_crt2flags = 0;
- sisfb_pdc = 0xff;
- sisfb_pdca = 0xff;
- sisfb_scalelcd = -1;
- sisfb_specialtiming = CUT_NONE;
- sisfb_lvdshl = -1;
- sisfb_dstn = 0;
- sisfb_fstn = 0;
- sisfb_tvplug = -1;
- sisfb_tvstd = -1;
- sisfb_tvxposoffset = 0;
- sisfb_tvyposoffset = 0;
- sisfb_nocrt2rate = 0;
- #if !defined(__i386__) && !defined(__x86_64__)
- sisfb_resetcard = 0;
- sisfb_videoram = 0;
- #endif
- }
- /* ------------- Parameter parsing -------------- */
- static void __devinit
- sisfb_search_vesamode(unsigned int vesamode, bool quiet)
- {
- int i = 0, j = 0;
- /* We don't know the hardware specs yet and there is no ivideo */
- if(vesamode == 0) {
- if(!quiet)
- printk(KERN_ERR "sisfb: Invalid mode. Using default.\n");
- sisfb_mode_idx = DEFAULT_MODE;
- return;
- }
- vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
- while(sisbios_mode[i++].mode_no[0] != 0) {
- if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) ||
- (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) {
- if(sisfb_fstn) {
- if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
- sisbios_mode[i-1].mode_no[1] == 0x56 ||
- sisbios_mode[i-1].mode_no[1] == 0x53)
- continue;
- } else {
- if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
- sisbios_mode[i-1].mode_no[1] == 0x5b)
- continue;
- }
- sisfb_mode_idx = i - 1;
- j = 1;
- break;
- }
- }
- if((!j) && !quiet)
- printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
- }
- static void __devinit
- sisfb_search_mode(char *name, bool quiet)
- {
- unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
- int i = 0;
- char strbuf[16], strbuf1[20];
- char *nameptr = name;
- /* We don't know the hardware specs yet and there is no ivideo */
- if(name == NULL) {
- if(!quiet)
- printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
- sisfb_mode_idx = DEFAULT_MODE;
- return;
- }
- if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
- if(!quiet)
- printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
- sisfb_mode_idx = DEFAULT_MODE;
- return;
- }
- if(strlen(name) <= 19) {
- strcpy(strbuf1, name);
- for(i = 0; i < strlen(strbuf1); i++) {
- if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
- }
- /* This does some fuzzy mode naming detection */
- if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
- if((rate <= 32) || (depth > 32)) {
- j = rate; rate = depth; depth = j;
- }
- sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
- nameptr = strbuf;
- sisfb_parm_rate = rate;
- } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
- sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
- nameptr = strbuf;
- } else {
- xres = 0;
- if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
- sprintf(strbuf, "%ux%ux8", xres, yres);
- nameptr = strbuf;
- } else {
- sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
- return;
- }
- }
- }
- i = 0; j = 0;
- while(sisbios_mode[i].mode_no[0] != 0) {
- if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
- if(sisfb_fstn) {
- if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
- sisbios_mode[i-1].mode_no[1] == 0x56 ||
- sisbios_mode[i-1].mode_no[1] == 0x53)
- continue;
- } else {
- if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
- sisbios_mode[i-1].mode_no[1] == 0x5b)
- continue;
- }
- sisfb_mode_idx = i - 1;
- j = 1;
- break;
- }
- }
- if((!j) && !quiet)
- printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
- }
- #ifndef MODULE
- static void __devinit
- sisfb_get_vga_mode_from_kernel(void)
- {
- #ifdef CONFIG_X86
- char mymode[32];
- int mydepth = screen_info.lfb_depth;
- if(screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return;
- if( (screen_info.lfb_width >= 320) && (screen_info.lfb_width <= 2048) &&
- (screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) &&
- (mydepth >= 8) && (mydepth <= 32) ) {
- if(mydepth == 24) mydepth = 32;
- sprintf(mymode, "%ux%ux%u", screen_info.lfb_width,
- screen_info.lfb_height,
- mydepth);
- printk(KERN_DEBUG
- "sisfb: Using vga mode %s pre-set by kernel as default\n",
- mymode);
- sisfb_search_mode(mymode, true);
- }
- #endif
- return;
- }
- #endif
- static void __init
- sisfb_search_crt2type(const char *name)
- {
- int i = 0;
- /* We don't know the hardware specs yet and there is no ivideo */
- if(name == NULL) return;
- while(sis_crt2type[i].type_no != -1) {
- if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
- sisfb_crt2type = sis_crt2type[i].type_no;
- sisfb_tvplug = sis_crt2type[i].tvplug_no;
- sisfb_crt2flags = sis_crt2type[i].flags;
- break;
- }
- i++;
- }
- sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0;
- sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0;
- if(sisfb_crt2type < 0)
- printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
- }
- static void __init
- sisfb_search_tvstd(const char *name)
- {
- int i = 0;
- /* We don't know the hardware specs yet and there is no ivideo */
- if(name == NULL)
- return;
- while(sis_tvtype[i].type_no != -1) {
- if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
- sisfb_tvstd = sis_tvtype[i].type_no;
- break;
- }
- i++;
- }
- }
- static void __init
- sisfb_search_specialtiming(const char *name)
- {
- int i = 0;
- bool found = false;
- /* We don't know the hardware specs yet and there is no ivideo */
- if(name == NULL)
- return;
- if(!strnicmp(name, "none", 4)) {
- sisfb_specialtiming = CUT_FORCENONE;
- printk(KERN_DEBUG "sisfb: Special timing disabled\n");
- } else {
- while(mycustomttable[i].chipID != 0) {
- if(!strnicmp(name,mycustomttable[i].optionName,
- strlen(mycustomttable[i].optionName))) {
- sisfb_specialtiming = mycustomttable[i].SpecialID;
- found = true;
- printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
- mycustomttable[i].vendorName,
- mycustomttable[i].cardName,
- mycustomttable[i].optionName);
- break;
- }
- i++;
- }
- if(!found) {
- printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
- printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
- i = 0;
- while(mycustomttable[i].chipID != 0) {
- printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
- mycustomttable[i].optionName,
- mycustomttable[i].vendorName,
- mycustomttable[i].cardName);
- i++;
- }
- }
- }
- }
- /* ----------- Various detection routines ----------- */
- static void __devinit
- sisfb_detect_custom_timing(struct sis_video_info *ivideo)
- {
- unsigned char *biosver = NULL;
- unsigned char *biosdate = NULL;
- bool footprint;
- u32 chksum = 0;
- int i, j;
- if(ivideo->SiS_Pr.UseROM) {
- biosver = ivideo->SiS_Pr.VirtualRomBase + 0x06;
- biosdate = ivideo->SiS_Pr.VirtualRomBase + 0x2c;
- for(i = 0; i < 32768; i++)
- chksum += ivideo->SiS_Pr.VirtualRomBase[i];
- }
- i = 0;
- do {
- if( (mycustomttable[i].chipID == ivideo->chip) &&
- ((!strlen(mycustomttable[i].biosversion)) ||
- (ivideo->SiS_Pr.UseROM &&
- (!strncmp(mycustomttable[i].biosversion, biosver,
- strlen(mycustomttable[i].biosversion))))) &&
- ((!strlen(mycustomttable[i].biosdate)) ||
- (ivideo->SiS_Pr.UseROM &&
- (!strncmp(mycustomttable[i].biosdate, biosdate,
- strlen(mycustomttable[i].biosdate))))) &&
- ((!mycustomttable[i].bioschksum) ||
- (ivideo->SiS_Pr.UseROM &&
- (mycustomttable[i].bioschksum == chksum))) &&
- (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
- (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
- footprint = true;
- for(j = 0; j < 5; j++) {
- if(mycustomttable[i].biosFootprintAddr[j]) {
- if(ivideo->SiS_Pr.UseROM) {
- if(ivideo->SiS_Pr.VirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
- mycustomttable[i].biosFootprintData[j]) {
- footprint = false;
- }
- } else
- footprint = false;
- }
- }
- if(footprint) {
- ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
- printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
- mycustomttable[i].vendorName,
- mycustomttable[i].cardName);
- printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n",
- mycustomttable[i].optionName);
- break;
- }
- }
- i++;
- } while(mycustomttable[i].chipID);
- }
- static bool __devinit
- sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
- {
- int i, j, xres, yres, refresh, index;
- u32 emodes;
- if(buffer[0] != 0x00 || buffer[1] != 0xff ||
- buffer[2] != 0xff || buffer[3] != 0xff ||
- buffer[4] != 0xff || buffer[5] != 0xff ||
- buffer[6] != 0xff || buffer[7] != 0x00) {
- printk(KERN_DEBUG "sisfb: Bad EDID header\n");
- return false;
- }
- if(buffer[0x12] != 0x01) {
- printk(KERN_INFO "sisfb: EDID version %d not supported\n",
- buffer[0x12]);
- return false;
- }
- monitor->feature = buffer[0x18];
- if(!(buffer[0x14] & 0x80)) {
- if(!(buffer[0x14] & 0x08)) {
- printk(KERN_INFO
- "sisfb: WARNING: Monitor does not support separate syncs\n");
- }
- }
- if(buffer[0x13] >= 0x01) {
- /* EDID V1 rev 1 and 2: Search for monitor descriptor
- * to extract ranges
- */
- j = 0x36;
- for(i=0; i<4; i++) {
- if(buffer[j] == 0x00 && buffer[j + 1] == 0x00 &&
- buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd &&
- buffer[j + 4] == 0x00) {
- monitor->hmin = buffer[j + 7];
- monitor->hmax = buffer[j + 8];
- monitor->vmin = buffer[j + 5];
- monitor->vmax = buffer[j + 6];
- monitor->dclockmax = buffer[j + 9] * 10 * 1000;
- monitor->datavalid = true;
- break;
- }
- j += 18;
- }
- }
- if(!monitor->datavalid) {
- /* Otherwise: Get a range from the list of supported
- * Estabished Timings. This is not entirely accurate,
- * because fixed frequency monitors are not supported
- * that way.
- */
- monitor->hmin = 65535; monitor->hmax = 0;
- monitor->vmin = 65535; monitor->vmax = 0;
- monitor->dclockmax = 0;
- emodes = buffer[0x23] | (buffer[0x24] << 8) | (buffer[0x25] << 16);
- for(i = 0; i < 13; i++) {
- if(emodes & sisfb_ddcsmodes[i].mask) {
- if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h;
- if(monitor->hmax < sisfb_ddcsmodes[i].h) monitor->hmax = sisfb_ddcsmodes[i].h + 1;
- if(monitor->vmin > sisfb_ddcsmodes[i].v) monitor->vmin = sisfb_ddcsmodes[i].v;
- if(monitor->vmax < sisfb_ddcsmodes[i].v) monitor->vmax = sisfb_ddcsmodes[i].v;
- if(monitor->dclockmax < sisfb_ddcsmodes[i].d) monitor->dclockmax = sisfb_ddcsmodes[i].d;
- }
- }
- index = 0x26;
- for(i = 0; i < 8; i++) {
- xres = (buffer[index] + 31) * 8;
- switch(buffer[index + 1] & 0xc0) {
- case 0xc0: yres = (xres * 9) / 16; break;
- case 0x80: yres = (xres * 4) / 5; break;
- case 0x40: yres = (xres * 3) / 4; break;
- default: yres = xres; break;
- }
- refresh = (buffer[index + 1] & 0x3f) + 60;
- if((xres >= 640) && (yres >= 480)) {
- for(j = 0; j < 8; j++) {
- if((xres == sisfb_ddcfmodes[j].x) &&
- (yres == sisfb_ddcfmodes[j].y) &&
- (refresh == sisfb_ddcfmodes[j].v)) {
- if(monitor->hmin > sisfb_ddcfmodes[j].h) monitor->hmin = sisfb_ddcfmodes[j].h;
- if(monitor->hmax < sisfb_ddcfmodes[j].h) monitor->hmax = sisfb_ddcfmodes[j].h + 1;
- if(monitor->vmin > sisfb_ddcsmodes[j].v) monitor->vmin = sisfb_ddcsmodes[j].v;
- if(monitor->vmax < sisfb_ddcsmodes[j].v) monitor->vmax = sisfb_ddcsmodes[j].v;
- if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[j].d;
- }
- }
- }
- index += 2;
- }
- if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) {
- monitor->datavalid = true;
- }
- }
- return monitor->datavalid;
- }
- static void __devinit
- sisfb_handle_ddc(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, int crtno)
- {
- unsigned short temp, i, realcrtno = crtno;
- unsigned char buffer[256];
- monitor->datavalid = false;
- if(crtno) {
- if(ivideo->vbflags & CRT2_LCD) realcrtno = 1;
- else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2;
- else return;
- }
- if((ivideo->sisfb_crt1off) && (!crtno))
- return;
- temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
- realcrtno, 0, &buffer[0], ivideo->vbflags2);
- if((!temp) || (temp == 0xffff)) {
- printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
- return;
- } else {
- printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1);
- printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n",
- crtno + 1,
- (temp & 0x1a) ? "" : "[none of the supported]",
- (temp & 0x02) ? "2 " : "",
- (temp & 0x08) ? "D&P" : "",
- (temp & 0x10) ? "FPDI-2" : "");
- if(temp & 0x02) {
- i = 3; /* Number of retrys */
- do {
- temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
- realcrtno, 1, &buffer[0], ivideo->vbflags2);
- } while((temp) && i--);
- if(!temp) {
- if(sisfb_interpret_edid(monitor, &buffer[0])) {
- printk(KERN_INFO "sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
- monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax,
- monitor->dclockmax / 1000);
- } else {
- printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1);
- }
- } else {
- printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1);
- }
- } else {
- printk(KERN_INFO "sisfb: VESA D&P and FPDI-2 not supported yet\n");
- }
- }
- }
- /* -------------- Mode validation --------------- */
- static bool
- sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
- int mode_idx, int rate_idx, int rate)
- {
- int htotal, vtotal;
- unsigned int dclock, hsync;
- if(!monitor->datavalid)
- return true;
- if(mode_idx < 0)
- return false;
- /* Skip for 320x200, 320x240, 640x400 */
- switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) {
- case 0x59:
- case 0x41:
- case 0x4f:
- case 0x50:
- case 0x56:
- case 0x53:
- case 0x2f:
- case 0x5d:
- case 0x5e:
- return true;
- #ifdef CONFIG_FB_SIS_315
- case 0x5a:
- case 0x5b:
- if(ivideo->sisvga_engine == SIS_315_VGA) return true;
- #endif
- }
- if(rate < (monitor->vmin - 1))
- return false;
- if(rate > (monitor->vmax + 1))
- return false;
- if(sisfb_gettotalfrommode(&ivideo->SiS_Pr,
- sisbios_mode[mode_idx].mode_no[ivideo->mni],
- &htotal, &vtotal, rate_idx)) {
- dclock = (htotal * vtotal * rate) / 1000;
- if(dclock > (monitor->dclockmax + 1000))
- return false;
- hsync = dclock / htotal;
- if(hsync < (monitor->hmin - 1))
- return false;
- if(hsync > (monitor->hmax + 1))
- return false;
- } else {
- return false;
- }
- return true;
- }
- static int
- sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
- {
- u16 xres=0, yres, myres;
- #ifdef CONFIG_FB_SIS_300
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- if(!(sisbios_mode[myindex].chipset & MD_SIS300))
- return -1 ;
- }
- #endif
- #ifdef CONFIG_FB_SIS_315
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- if(!(sisbios_mode[myindex].chipset & MD_SIS315))
- return -1;
- }
- #endif
- myres = sisbios_mode[myindex].yres;
- switch(vbflags & VB_DISPTYPE_DISP2) {
- case CRT2_LCD:
- xres = ivideo->lcdxres; yres = ivideo->lcdyres;
- if((ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) &&
- (ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL856)) {
- if(sisbios_mode[myindex].xres > xres)
- return -1;
- if(myres > yres)
- return -1;
- }
- if(ivideo->sisfb_fstn) {
- if(sisbios_mode[myindex].xres == 320) {
- if(myres == 240) {
- switch(sisbios_mode[myindex].mode_no[1]) {
- case 0x50: myindex = MODE_FSTN_8; break;
- case 0x56: myindex = MODE_FSTN_16; break;
- case 0x53: return -1;
- }
- }
- }
- }
- if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
- sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn,
- ivideo->SiS_Pr.SiS_CustomT, xres, yres, ivideo->vbflags2) < 0x14) {
- return -1;
- }
- break;
- case CRT2_TV:
- if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
- sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
- return -1;
- }
- break;
- case CRT2_VGA:
- if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
- sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
- return -1;
- }
- break;
- }
- return myindex;
- }
- static u8
- sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx)
- {
- int i = 0;
- u16 xres = sisbios_mode[mode_idx].xres;
- u16 yres = sisbios_mode[mode_idx].yres;
- ivideo->rate_idx = 0;
- while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
- if((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) {
- if(sisfb_vrate[i].refresh == rate) {
- ivideo->rate_idx = sisfb_vrate[i].idx;
- break;
- } else if(sisfb_vrate[i].refresh > rate) {
- if((sisfb_vrate[i].refresh - rate) <= 3) {
- DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
- rate, sisfb_vrate[i].refresh);
- ivideo->rate_idx = sisfb_vrate[i].idx;
- ivideo->refresh_rate = sisfb_vrate[i].refresh;
- } else if((sisfb_vrate[i].idx != 1) &&
- ((rate - sisfb_vrate[i-1].refresh) <= 2)) {
- DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
- rate, sisfb_vrate[i-1].refresh);
- ivideo->rate_idx = sisfb_vrate[i-1].idx;
- ivideo->refresh_rate = sisfb_vrate[i-1].refresh;
- }
- break;
- } else if((rate - sisfb_vrate[i].refresh) <= 2) {
- DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
- rate, sisfb_vrate[i].refresh);
- ivideo->rate_idx = sisfb_vrate[i].idx;
- break;
- }
- }
- i++;
- }
- if(ivideo->rate_idx > 0) {
- return ivideo->rate_idx;
- } else {
- printk(KERN_INFO "sisfb: Unsupported rate %d for %dx%d\n",
- rate, xres, yres);
- return 0;
- }
- }
- static bool
- sisfb_bridgeisslave(struct sis_video_info *ivideo)
- {
- unsigned char P1_00;
- if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE))
- return false;
- P1_00 = SiS_GetReg(SISPART1, 0x00);
- if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
- ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
- return true;
- } else {
- return false;
- }
- }
- static bool
- sisfballowretracecrt1(struct sis_video_info *ivideo)
- {
- u8 temp;
- temp = SiS_GetReg(SISCR, 0x17);
- if(!(temp & 0x80))
- return false;
- temp = SiS_GetReg(SISSR, 0x1f);
- if(temp & 0xc0)
- return false;
- return true;
- }
- static bool
- sisfbcheckvretracecrt1(struct sis_video_info *ivideo)
- {
- if(!sisfballowretracecrt1(ivideo))
- return false;
- if (SiS_GetRegByte(SISINPSTAT) & 0x08)
- return true;
- else
- return false;
- }
- static void
- sisfbwaitretracecrt1(struct sis_video_info *ivideo)
- {
- int watchdog;
- if(!sisfballowretracecrt1(ivideo))
- return;
- watchdog = 65536;
- while ((!(SiS_GetRegByte(SISINPSTAT) & 0x08)) && --watchdog);
- watchdog = 65536;
- while ((SiS_GetRegByte(SISINPSTAT) & 0x08) && --watchdog);
- }
- static bool
- sisfbcheckvretracecrt2(struct sis_video_info *ivideo)
- {
- unsigned char temp, reg;
- switch(ivideo->sisvga_engine) {
- case SIS_300_VGA: reg = 0x25; break;
- case SIS_315_VGA: reg = 0x30; break;
- default: return false;
- }
- temp = SiS_GetReg(SISPART1, reg);
- if(temp & 0x02)
- return true;
- else
- return false;
- }
- static bool
- sisfb_CheckVBRetrace(struct sis_video_info *ivideo)
- {
- if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
- if(!sisfb_bridgeisslave(ivideo)) {
- return sisfbcheckvretracecrt2(ivideo);
- }
- }
- return sisfbcheckvretracecrt1(ivideo);
- }
- static u32
- sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount)
- {
- u8 idx, reg1, reg2, reg3, reg4;
- u32 ret = 0;
- (*vcount) = (*hcount) = 0;
- if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) {
- ret |= (FB_VBLANK_HAVE_VSYNC |
- FB_VBLANK_HAVE_HBLANK |
- FB_VBLANK_HAVE_VBLANK |
- FB_VBLANK_HAVE_VCOUNT |
- FB_VBLANK_HAVE_HCOUNT);
- switch(ivideo->sisvga_engine) {
- case SIS_300_VGA: idx = 0x25; break;
- default:
- case SIS_315_VGA: idx = 0x30; break;
- }
- reg1 = SiS_GetReg(SISPART1, (idx+0)); /* 30 */
- reg2 = SiS_GetReg(SISPART1, (idx+1)); /* 31 */
- reg3 = SiS_GetReg(SISPART1, (idx+2)); /* 32 */
- reg4 = SiS_GetReg(SISPART1, (idx+3)); /* 33 */
- if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
- if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING;
- if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING;
- (*vcount) = reg3 | ((reg4 & 0x70) << 4);
- (*hcount) = reg2 | ((reg4 & 0x0f) << 8);
- } else if(sisfballowretracecrt1(ivideo)) {
- ret |= (FB_VBLANK_HAVE_VSYNC |
- FB_VBLANK_HAVE_VBLANK |
- FB_VBLANK_HAVE_VCOUNT |
- FB_VBLANK_HAVE_HCOUNT);
- reg1 = SiS_GetRegByte(SISINPSTAT);
- if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
- if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
- reg1 = SiS_GetReg(SISCR, 0x20);
- reg1 = SiS_GetReg(SISCR, 0x1b);
- reg2 = SiS_GetReg(SISCR, 0x1c);
- reg3 = SiS_GetReg(SISCR, 0x1d);
- (*vcount) = reg2 | ((reg3 & 0x07) << 8);
- (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
- }
- return ret;
- }
- static int
- sisfb_myblank(struct sis_video_info *ivideo, int blank)
- {
- u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
- bool backlight = true;
- switch(blank) {
- case FB_BLANK_UNBLANK: /* on */
- sr01 = 0x00;
- sr11 = 0x00;
- sr1f = 0x00;
- cr63 = 0x00;
- p2_0 = 0x20;
- p1_13 = 0x00;
- backlight = true;
- break;
- case FB_BLANK_NORMAL: /* blank */
- sr01 = 0x20;
- sr11 = 0x00;
- sr1f = 0x00;
- cr63 = 0x00;
- p2_0 = 0x20;
- p1_13 = 0x00;
- backlight = true;
- break;
- case FB_BLANK_VSYNC_SUSPEND: /* no vsync */
- sr01 = 0x20;
- sr11 = 0x08;
- sr1f = 0x80;
- cr63 = 0x40;
- p2_0 = 0x40;
- p1_13 = 0x80;
- backlight = false;
- break;
- case FB_BLANK_HSYNC_SUSPEND: /* no hsync */
- sr01 = 0x20;
- sr11 = 0x08;
- sr1f = 0x40;
- cr63 = 0x40;
- p2_0 = 0x80;
- p1_13 = 0x40;
- backlight = false;
- break;
- case FB_BLANK_POWERDOWN: /* off */
- sr01 = 0x20;
- sr11 = 0x08;
- sr1f = 0xc0;
- cr63 = 0x40;
- p2_0 = 0xc0;
- p1_13 = 0xc0;
- backlight = false;
- break;
- default:
- return 1;
- }
- if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) {
- if( (!ivideo->sisfb_thismonitor.datavalid) ||
- ((ivideo->sisfb_thismonitor.datavalid) &&
- (ivideo->sisfb_thismonitor.feature & 0xe0))) {
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
- }
- if(!(sisfb_bridgeisslave(ivideo))) {
- SiS_SetRegANDOR(SISSR, 0x01, ~0x20, sr01);
- SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, sr1f);
- }
- }
- }
- if(ivideo->currentvbflags & CRT2_LCD) {
- if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
- if(backlight) {
- SiS_SiS30xBLOn(&ivideo->SiS_Pr);
- } else {
- SiS_SiS30xBLOff(&ivideo->SiS_Pr);
- }
- } else if(ivideo->sisvga_engine == SIS_315_VGA) {
- #ifdef CONFIG_FB_SIS_315
- if(ivideo->vbflags2 & VB2_CHRONTEL) {
- if(backlight) {
- SiS_Chrontel701xBLOn(&ivideo->SiS_Pr);
- } else {
- SiS_Chrontel701xBLOff(&ivideo->SiS_Pr);
- }
- }
- #endif
- }
- if(((ivideo->sisvga_engine == SIS_300_VGA) &&
- (ivideo->vbflags2 & (VB2_301|VB2_30xBDH|VB2_LVDS))) ||
- ((ivideo->sisvga_engine == SIS_315_VGA) &&
- ((ivideo->vbflags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS))) {
- SiS_SetRegANDOR(SISSR, 0x11, ~0x0c, sr11);
- }
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- if((ivideo->vbflags2 & VB2_30xB) &&
- (!(ivideo->vbflags2 & VB2_30xBDH))) {
- SiS_SetRegANDOR(SISPART1, 0x13, 0x3f, p1_13);
- }
- } else if(ivideo->sisvga_engine == SIS_315_VGA) {
- if((ivideo->vbflags2 & VB2_30xB) &&
- (!(ivideo->vbflags2 & VB2_30xBDH))) {
- SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
- }
- }
- } else if(ivideo->currentvbflags & CRT2_VGA) {
- if(ivideo->vbflags2 & VB2_30xB) {
- SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
- }
- }
- return 0;
- }
- /* ------------- Callbacks from init.c/init301.c -------------- */
- #ifdef CONFIG_FB_SIS_300
- unsigned int
- sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
- u32 val = 0;
- pci_read_config_dword(ivideo->nbridge, reg, &val);
- return (unsigned int)val;
- }
- void
- sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
- pci_write_config_dword(ivideo->nbridge, reg, (u32)val);
- }
- unsigned int
- sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
- u32 val = 0;
- if(!ivideo->lpcdev) return 0;
- pci_read_config_dword(ivideo->lpcdev, reg, &val);
- return (unsigned int)val;
- }
- #endif
- #ifdef CONFIG_FB_SIS_315
- void
- sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
- pci_write_config_byte(ivideo->nbridge, reg, (u8)val);
- }
- unsigned int
- sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
- u16 val = 0;
- if(!ivideo->lpcdev) return 0;
- pci_read_config_word(ivideo->lpcdev, reg, &val);
- return (unsigned int)val;
- }
- #endif
- /* ----------- FBDev related routines for all series ----------- */
- static int
- sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
- {
- return (var->bits_per_pixel == 8) ? 256 : 16;
- }
- static void
- sisfb_set_vparms(struct sis_video_info *ivideo)
- {
- switch(ivideo->video_bpp) {
- case 8:
- ivideo->DstColor = 0x0000;
- ivideo->SiS310_AccelDepth = 0x00000000;
- ivideo->video_cmap_len = 256;
- break;
- case 16:
- ivideo->DstColor = 0x8000;
- ivideo->SiS310_AccelDepth = 0x00010000;
- ivideo->video_cmap_len = 16;
- break;
- case 32:
- ivideo->DstColor = 0xC000;
- ivideo->SiS310_AccelDepth = 0x00020000;
- ivideo->video_cmap_len = 16;
- break;
- default:
- ivideo->video_cmap_len = 16;
- printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp);
- ivideo->accel = 0;
- }
- }
- static int
- sisfb_calc_maxyres(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
- {
- int maxyres = ivideo->sisfb_mem / (var->xres_virtual * (var->bits_per_pixel >> 3));
- if(maxyres > 32767) maxyres = 32767;
- return maxyres;
- }
- static void
- sisfb_calc_pitch(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
- {
- ivideo->video_linelength = var->xres_virtual * (var->bits_per_pixel >> 3);
- ivideo->scrnpitchCRT1 = ivideo->video_linelength;
- if(!(ivideo->currentvbflags & CRT1_LCDA)) {
- if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
- ivideo->scrnpitchCRT1 <<= 1;
- }
- }
- }
- static void
- sisfb_set_pitch(struct sis_video_info *ivideo)
- {
- bool isslavemode = false;
- unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3;
- unsigned short HDisplay2 = ivideo->video_linelength >> 3;
- if(sisfb_bridgeisslave(ivideo)) isslavemode = true;
- /* We need to set pitch for CRT1 if bridge is in slave mode, too */
- if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
- SiS_SetReg(SISCR, 0x13, (HDisplay1 & 0xFF));
- SiS_SetRegANDOR(SISSR, 0x0E, 0xF0, (HDisplay1 >> 8));
- }
- /* We must not set the pitch for CRT2 if bridge is in slave mode */
- if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) {
- SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
- SiS_SetReg(SISPART1, 0x07, (HDisplay2 & 0xFF));
- SiS_SetRegANDOR(SISPART1, 0x09, 0xF0, (HDisplay2 >> 8));
- }
- }
- static void
- sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
- {
- ivideo->video_cmap_len = sisfb_get_cmap_len(var);
- switch(var->bits_per_pixel) {
- case 8:
- var->red.offset = var->green.offset = var->blue.offset = 0;
- var->red.length = var->green.length = var->blue.length = 8;
- break;
- case 16:
- var->red.offset = 11;
- var->red.length = 5;
- var->green.offset = 5;
- var->green.length = 6;
- var->blue.offset = 0;
- var->blue.length = 5;
- var->transp.offset = 0;
- var->transp.length = 0;
- break;
- case 32:
- var->red.offset = 16;
- var->red.length = 8;
- var->green.offset = 8;
- var->green.length = 8;
- var->blue.offset = 0;
- var->blue.length = 8;
- var->transp.offset = 24;
- var->transp.length = 8;
- break;
- }
- }
- static int
- sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn)
- {
- unsigned short modeno = ivideo->mode_no;
- /* >=2.6.12's fbcon clears the screen anyway */
- modeno |= 0x80;
- SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
- sisfb_pre_setmode(ivideo);
- if(!SiSSetMode(&ivideo->SiS_Pr, modeno)) {
- printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
- return -EINVAL;
- }
- SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
- sisfb_post_setmode(ivideo);
- return 0;
- }
- static int
- sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- unsigned int htotal = 0, vtotal = 0;
- unsigned int drate = 0, hrate = 0;
- int found_mode = 0, ret;
- int old_mode;
- u32 pixclock;
- htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
- vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
- pixclock = var->pixclock;
- if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
- vtotal += var->yres;
- vtotal <<= 1;
- } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
- vtotal += var->yres;
- vtotal <<= 2;
- } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
- vtotal += var->yres;
- vtotal <<= 1;
- } else vtotal += var->yres;
- if(!(htotal) || !(vtotal)) {
- DPRINTK("sisfb: Invalid 'var' information\n");
- return -EINVAL;
- }
- if(pixclock && htotal && vtotal) {
- drate = 1000000000 / pixclock;
- hrate = (drate * 1000) / htotal;
- ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal);
- } else {
- ivideo->refresh_rate = 60;
- }
- old_mode = ivideo->sisfb_mode_idx;
- ivideo->sisfb_mode_idx = 0;
- while( (sisbios_mode[ivideo->sisfb_mode_idx].mode_no[0] != 0) &&
- (sisbios_mode[ivideo->sisfb_mode_idx].xres <= var->xres) ) {
- if( (sisbios_mode[ivideo->sisfb_mode_idx].xres == var->xres) &&
- (sisbios_mode[ivideo->sisfb_mode_idx].yres == var->yres) &&
- (sisbios_mode[ivideo->sisfb_mode_idx].bpp == var->bits_per_pixel)) {
- ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
- found_mode = 1;
- break;
- }
- ivideo->sisfb_mode_idx++;
- }
- if(found_mode) {
- ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
- ivideo->sisfb_mode_idx, ivideo->currentvbflags);
- } else {
- ivideo->sisfb_mode_idx = -1;
- }
- if(ivideo->sisfb_mode_idx < 0) {
- printk(KERN_ERR "sisfb: Mode %dx%dx%d not supported\n", var->xres,
- var->yres, var->bits_per_pixel);
- ivideo->sisfb_mode_idx = old_mode;
- return -EINVAL;
- }
- ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
- if(sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx) == 0) {
- ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
- ivideo->refresh_rate = 60;
- }
- if(isactive) {
- /* If acceleration to be used? Need to know
- * before pre/post_set_mode()
- */
- ivideo->accel = 0;
- #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
- #ifdef STUPID_ACCELF_TEXT_SHIT
- if(var->accel_flags & FB_ACCELF_TEXT) {
- info->flags &= ~FBINFO_HWACCEL_DISABLED;
- } else {
- info->flags |= FBINFO_HWACCEL_DISABLED;
- }
- #endif
- if(!(info->flags & FBINFO_HWACCEL_DISABLED)) ivideo->accel = -1;
- #else
- if(var->accel_flags & FB_ACCELF_TEXT) ivideo->accel = -1;
- #endif
- if((ret = sisfb_set_mode(ivideo, 1))) {
- return ret;
- }
- ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
- ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
- ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
- sisfb_calc_pitch(ivideo, var);
- sisfb_set_pitch(ivideo);
- sisfb_set_vparms(ivideo);
- ivideo->current_width = ivideo->video_width;
- ivideo->current_height = ivideo->video_height;
- ivideo->current_bpp = ivideo->video_bpp;
- ivideo->current_htotal = htotal;
- ivideo->current_vtotal = vtotal;
- ivideo->current_linelength = ivideo->video_linelength;
- ivideo->current_pixclock = var->pixclock;
- ivideo->current_refresh_rate = ivideo->refresh_rate;
- ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate;
- }
- return 0;
- }
- static void
- sisfb_set_base_CRT1(struct sis_video_info *ivideo, unsigned int base)
- {
- SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
- SiS_SetReg(SISCR, 0x0D, base & 0xFF);
- SiS_SetReg(SISCR, 0x0C, (base >> 8) & 0xFF);
- SiS_SetReg(SISSR, 0x0D, (base >> 16) & 0xFF);
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- SiS_SetRegANDOR(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
- }
- }
- static void
- sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base)
- {
- if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
- SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
- SiS_SetReg(SISPART1, 0x06, (base & 0xFF));
- SiS_SetReg(SISPART1, 0x05, ((base >> 8) & 0xFF));
- SiS_SetReg(SISPART1, 0x04, ((base >> 16) & 0xFF));
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- SiS_SetRegANDOR(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
- }
- }
- }
- static int
- sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
- {
- if(var->xoffset > (var->xres_virtual - var->xres)) {
- return -EINVAL;
- }
- if(var->yoffset > (var->yres_virtual - var->yres)) {
- return -EINVAL;
- }
- ivideo->current_base = (var->yoffset * var->xres_virtual) + var->xoffset;
- /* calculate base bpp dep. */
- switch(var->bits_per_pixel) {
- case 32:
- break;
- case 16:
- ivideo->current_base >>= 1;
- break;
- case 8:
- default:
- ivideo->current_base >>= 2;
- break;
- }
- ivideo->current_base += (ivideo->video_offset >> 2);
- sisfb_set_base_CRT1(ivideo, ivideo->current_base);
- sisfb_set_base_CRT2(ivideo, ivideo->current_base);
- return 0;
- }
- static int
- sisfb_open(struct fb_info *info, int user)
- {
- return 0;
- }
- static int
- sisfb_release(struct fb_info *info, int user)
- {
- return 0;
- }
- static int
- sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
- unsigned transp, struct fb_info *info)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- if(regno >= sisfb_get_cmap_len(&info->var))
- return 1;
- switch(info->var.bits_per_pixel) {
- case 8:
- SiS_SetRegByte(SISDACA, regno);
- SiS_SetRegByte(SISDACD, (red >> 10));
- SiS_SetRegByte(SISDACD, (green >> 10));
- SiS_SetRegByte(SISDACD, (blue >> 10));
- if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
- SiS_SetRegByte(SISDAC2A, regno);
- SiS_SetRegByte(SISDAC2D, (red >> 8));
- SiS_SetRegByte(SISDAC2D, (green >> 8));
- SiS_SetRegByte(SISDAC2D, (blue >> 8));
- }
- break;
- case 16:
- if (regno >= 16)
- break;
- ((u32 *)(info->pseudo_palette))[regno] =
- (red & 0xf800) |
- ((green & 0xfc00) >> 5) |
- ((blue & 0xf800) >> 11);
- break;
- case 32:
- if (regno >= 16)
- break;
- red >>= 8;
- green >>= 8;
- blue >>= 8;
- ((u32 *)(info->pseudo_palette))[regno] =
- (red << 16) | (green << 8) | (blue);
- break;
- }
- return 0;
- }
- static int
- sisfb_set_par(struct fb_info *info)
- {
- int err;
- if((err = sisfb_do_set_var(&info->var, 1, info)))
- return err;
- sisfb_get_fix(&info->fix, -1, info);
- return 0;
- }
- static int
- sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
- unsigned int drate = 0, hrate = 0, maxyres;
- int found_mode = 0;
- int refresh_rate, search_idx, tidx;
- bool recalc_clock = false;
- u32 pixclock;
- htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
- vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
- pixclock = var->pixclock;
- if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
- vtotal += var->yres;
- vtotal <<= 1;
- } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
- vtotal += var->yres;
- vtotal <<= 2;
- } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
- vtotal += var->yres;
- vtotal <<= 1;
- } else
- vtotal += var->yres;
- if(!(htotal) || !(vtotal)) {
- SISFAIL("sisfb: no valid timing data");
- }
- search_idx = 0;
- while( (sisbios_mode[search_idx].mode_no[0] != 0) &&
- (sisbios_mode[search_idx].xres <= var->xres) ) {
- if( (sisbios_mode[search_idx].xres == var->xres) &&
- (sisbios_mode[search_idx].yres == var->yres) &&
- (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) {
- if((tidx = sisfb_validate_mode(ivideo, search_idx,
- ivideo->currentvbflags)) > 0) {
- found_mode = 1;
- search_idx = tidx;
- break;
- }
- }
- search_idx++;
- }
- if(!found_mode) {
- search_idx = 0;
- while(sisbios_mode[search_idx].mode_no[0] != 0) {
- if( (var->xres <= sisbios_mode[search_idx].xres) &&
- (var->yres <= sisbios_mode[search_idx].yres) &&
- (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) {
- if((tidx = sisfb_validate_mode(ivideo,search_idx,
- ivideo->currentvbflags)) > 0) {
- found_mode = 1;
- search_idx = tidx;
- break;
- }
- }
- search_idx++;
- }
- if(found_mode) {
- printk(KERN_DEBUG
- "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
- var->xres, var->yres, var->bits_per_pixel,
- sisbios_mode[search_idx].xres,
- sisbios_mode[search_idx].yres,
- var->bits_per_pixel);
- var->xres = sisbios_mode[search_idx].xres;
- var->yres = sisbios_mode[search_idx].yres;
- } else {
- printk(KERN_ERR
- "sisfb: Failed to find supported mode near %dx%dx%d\n",
- var->xres, var->yres, var->bits_per_pixel);
- return -EINVAL;
- }
- }
- if( ((ivideo->vbflags2 & VB2_LVDS) ||
- ((ivideo->vbflags2 & VB2_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) &&
- (var->bits_per_pixel == 8) ) {
- /* Slave modes on LVDS and 301B-DH */
- refresh_rate = 60;
- recalc_clock = true;
- } else if( (ivideo->current_htotal == htotal) &&
- (ivideo->current_vtotal == vtotal) &&
- (ivideo->current_pixclock == pixclock) ) {
- /* x=x & y=y & c=c -> assume depth change */
- drate = 1000000000 / pixclock;
- hrate = (drate * 1000) / htotal;
- refresh_rate = (unsigned int) (hrate * 2 / vtotal);
- } else if( ( (ivideo->current_htotal != htotal) ||
- (ivideo->current_vtotal != vtotal) ) &&
- (ivideo->current_pixclock == var->pixclock) ) {
- /* x!=x | y!=y & c=c -> invalid pixclock */
- if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) {
- refresh_rate =
- ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];
- } else if(ivideo->sisfb_parm_rate != -1) {
- /* Sic, sisfb_parm_rate - want to know originally desired rate here */
- refresh_rate = ivideo->sisfb_parm_rate;
- } else {
- refresh_rate = 60;
- }
- recalc_clock = true;
- } else if((pixclock) && (htotal) && (vtotal)) {
- drate = 1000000000 / pixclock;
- hrate = (drate * 1000) / htotal;
- refresh_rate = (unsigned int) (hrate * 2 / vtotal);
- } else if(ivideo->current_refresh_rate) {
- refresh_rate = ivideo->current_refresh_rate;
- recalc_clock = true;
- } else {
- refresh_rate = 60;
- recalc_clock = true;
- }
- myrateindex = sisfb_search_refresh_rate(ivideo, refresh_rate, search_idx);
- /* Eventually recalculate timing and clock */
- if(recalc_clock) {
- if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
- var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr,
- sisbios_mode[search_idx].mode_no[ivideo->mni],
- myrateindex));
- sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr,
- sisbios_mode[search_idx].mode_no[ivideo->mni],
- myrateindex, var);
- if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
- var->pixclock <<= 1;
- }
- }
- if(ivideo->sisfb_thismonitor.datavalid) {
- if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx,
- myrateindex, refresh_rate)) {
- printk(KERN_INFO
- "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
- }
- }
- /* Adapt RGB settings */
- sisfb_bpp_to_var(ivideo, var);
- /* Sanity check for offsets */
- if(var->xoffset < 0) var->xoffset = 0;
- if(var->yoffset < 0) var->yoffset = 0;
- if(var->xres > var->xres_virtual)
- var->xres_virtual = var->xres;
- if(ivideo->sisfb_ypan) {
- maxyres = sisfb_calc_maxyres(ivideo, var);
- if(ivideo->sisfb_max) {
- var->yres_virtual = maxyres;
- } else {
- if(var->yres_virtual > maxyres) {
- var->yres_virtual = maxyres;
- }
- }
- if(var->yres_virtual <= var->yres) {
- var->yres_virtual = var->yres;
- }
- } else {
- if(var->yres != var->yres_virtual) {
- var->yres_virtual = var->yres;
- }
- var->xoffset = 0;
- var->yoffset = 0;
- }
- /* Truncate offsets to maximum if too high */
- if(var->xoffset > var->xres_virtual - var->xres) {
- var->xoffset = var->xres_virtual - var->xres - 1;
- }
- if(var->yoffset > var->yres_virtual - var->yres) {
- var->yoffset = var->yres_virtual - var->yres - 1;
- }
- /* Set everything else to 0 */
- var->red.msb_right =
- var->green.msb_right =
- var->blue.msb_right =
- var->transp.offset =
- var->transp.length =
- var->transp.msb_right = 0;
- return 0;
- }
- static int
- sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- int err;
- if(var->xoffset > (var->xres_virtual - var->xres))
- return -EINVAL;
- if(var->yoffset > (var->yres_virtual - var->yres))
- return -EINVAL;
- if(var->vmode & FB_VMODE_YWRAP)
- return -EINVAL;
- if(var->xoffset + info->var.xres > info->var.xres_virtual ||
- var->yoffset + info->var.yres > info->var.yres_virtual)
- return -EINVAL;
- if((err = sisfb_pan_var(ivideo, var)) < 0)
- return err;
- info->var.xoffset = var->xoffset;
- info->var.yoffset = var->yoffset;
- return 0;
- }
- static int
- sisfb_blank(int blank, struct fb_info *info)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- return sisfb_myblank(ivideo, blank);
- }
- /* ----------- FBDev related routines for all series ---------- */
- static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
- unsigned long arg)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- struct sis_memreq sismemreq;
- struct fb_vblank sisvbblank;
- u32 gpu32 = 0;
- #ifndef __user
- #define __user
- #endif
- u32 __user *argp = (u32 __user *)arg;
- switch(cmd) {
- case FBIO_ALLOC:
- if(!capable(CAP_SYS_RAWIO))
- return -EPERM;
- if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq)))
- return -EFAULT;
- sis_malloc(&sismemreq);
- if(copy_to_user((void __user *)arg, &sismemreq, sizeof(sismemreq))) {
- sis_free((u32)sismemreq.offset);
- return -EFAULT;
- }
- break;
- case FBIO_FREE:
- if(!capable(CAP_SYS_RAWIO))
- return -EPERM;
- if(get_user(gpu32, argp))
- return -EFAULT;
- sis_free(gpu32);
- break;
- case FBIOGET_VBLANK:
- memset(&sisvbblank, 0, sizeof(struct fb_vblank));
- sisvbblank.count = 0;
- sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);
- if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank)))
- return -EFAULT;
- break;
- case SISFB_GET_INFO_SIZE:
- return put_user(sizeof(struct sisfb_info), argp);
- case SISFB_GET_INFO_OLD:
- if(ivideo->warncount++ < 10)
- printk(KERN_INFO
- "sisfb: Deprecated ioctl call received - update your application!\n");
- case SISFB_GET_INFO: /* For communication with X driver */
- ivideo->sisfb_infoblock.sisfb_id = SISFB_ID;
- ivideo->sisfb_infoblock.sisfb_version = VER_MAJOR;
- ivideo->sisfb_infoblock.sisfb_revision = VER_MINOR;
- ivideo->sisfb_infoblock.sisfb_patchlevel = VER_LEVEL;
- ivideo->sisfb_infoblock.chip_id = ivideo->chip_id;
- ivideo->sisfb_infoblock.sisfb_pci_vendor = ivideo->chip_vendor;
- ivideo->sisfb_infoblock.memory = ivideo->video_size / 1024;
- ivideo->sisfb_infoblock.heapstart = ivideo->heapstart / 1024;
- if(ivideo->modechanged) {
- ivideo->sisfb_infoblock.fbvidmode = ivideo->mode_no;
- } else {
- ivideo->sisfb_infoblock.fbvidmode = ivideo->modeprechange;
- }
- ivideo->sisfb_infoblock.sisfb_caps = ivideo->caps;
- ivideo->sisfb_infoblock.sisfb_tqlen = ivideo->cmdQueueSize / 1024;
- ivideo->sisfb_infoblock.sisfb_pcibus = ivideo->pcibus;
- ivideo->sisfb_infoblock.sisfb_pcislot = ivideo->pcislot;
- ivideo->sisfb_infoblock.sisfb_pcifunc = ivideo->pcifunc;
- ivideo->sisfb_infoblock.sisfb_lcdpdc = ivideo->detectedpdc;
- ivideo->sisfb_infoblock.sisfb_lcdpdca = ivideo->detectedpdca;
- ivideo->sisfb_infoblock.sisfb_lcda = ivideo->detectedlcda;
- ivideo->sisfb_infoblock.sisfb_vbflags = ivideo->vbflags;
- ivideo->sisfb_infoblock.sisfb_currentvbflags = ivideo->currentvbflags;
- ivideo->sisfb_infoblock.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
- ivideo->sisfb_infoblock.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
- ivideo->sisfb_infoblock.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
- ivideo->sisfb_infoblock.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
- ivideo->sisfb_infoblock.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
- ivideo->sisfb_infoblock.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
- ivideo->sisfb_infoblock.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
- ivideo->sisfb_infoblock.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
- ivideo->sisfb_infoblock.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
- ivideo->sisfb_infoblock.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
- ivideo->sisfb_infoblock.sisfb_heapsize = ivideo->sisfb_heap_size / 1024;
- ivideo->sisfb_infoblock.sisfb_videooffset = ivideo->video_offset;
- ivideo->sisfb_infoblock.sisfb_curfstn = ivideo->curFSTN;
- ivideo->sisfb_infoblock.sisfb_curdstn = ivideo->curDSTN;
- ivideo->sisfb_infoblock.sisfb_vbflags2 = ivideo->vbflags2;
- ivideo->sisfb_infoblock.sisfb_can_post = ivideo->sisfb_can_post ? 1 : 0;
- ivideo->sisfb_infoblock.sisfb_card_posted = ivideo->sisfb_card_posted ? 1 : 0;
- ivideo->sisfb_infoblock.sisfb_was_boot_device = ivideo->sisfb_was_boot_device ? 1 : 0;
- if(copy_to_user((void __user *)arg, &ivideo->sisfb_infoblock,
- sizeof(ivideo->sisfb_infoblock)))
- return -EFAULT;
- break;
- case SISFB_GET_VBRSTATUS_OLD:
- if(ivideo->warncount++ < 10)
- printk(KERN_INFO
- "sisfb: Deprecated ioctl call received - update your application!\n");
- case SISFB_GET_VBRSTATUS:
- if(sisfb_CheckVBRetrace(ivideo))
- return put_user((u32)1, argp);
- else
- return put_user((u32)0, argp);
- case SISFB_GET_AUTOMAXIMIZE_OLD:
- if(ivideo->warncount++ < 10)
- printk(KERN_INFO
- "sisfb: Deprecated ioctl call received - update your application!\n");
- case SISFB_GET_AUTOMAXIMIZE:
- if(ivideo->sisfb_max)
- return put_user((u32)1, argp);
- else
- return put_user((u32)0, argp);
- case SISFB_SET_AUTOMAXIMIZE_OLD:
- if(ivideo->warncount++ < 10)
- printk(KERN_INFO
- "sisfb: Deprecated ioctl call received - update your application!\n");
- case SISFB_SET_AUTOMAXIMIZE:
- if(get_user(gpu32, argp))
- return -EFAULT;
- ivideo->sisfb_max = (gpu32) ? 1 : 0;
- break;
- case SISFB_SET_TVPOSOFFSET:
- if(get_user(gpu32, argp))
- return -EFAULT;
- sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32);
- sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32);
- break;
- case SISFB_GET_TVPOSOFFSET:
- return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)),
- argp);
- case SISFB_COMMAND:
- if(copy_from_user(&ivideo->sisfb_command, (void __user *)arg,
- sizeof(struct sisfb_cmd)))
- return -EFAULT;
- sisfb_handle_command(ivideo, &ivideo->sisfb_command);
- if(copy_to_user((void __user *)arg, &ivideo->sisfb_command,
- sizeof(struct sisfb_cmd)))
- return -EFAULT;
- break;
- case SISFB_SET_LOCK:
- if(get_user(gpu32, argp))
- return -EFAULT;
- ivideo->sisfblocked = (gpu32) ? 1 : 0;
- break;
- default:
- #ifdef SIS_NEW_CONFIG_COMPAT
- return -ENOIOCTLCMD;
- #else
- return -EINVAL;
- #endif
- }
- return 0;
- }
- static int
- sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- memset(fix, 0, sizeof(struct fb_fix_screeninfo));
- strlcpy(fix->id, ivideo->myid, sizeof(fix->id));
- mutex_lock(&info->mm_lock);
- fix->smem_start = ivideo->video_base + ivideo->video_offset;
- fix->smem_len = ivideo->sisfb_mem;
- mutex_unlock(&info->mm_lock);
- fix->type = FB_TYPE_PACKED_PIXELS;
- fix->type_aux = 0;
- fix->visual = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
- fix->xpanstep = 1;
- fix->ypanstep = (ivideo->sisfb_ypan) ? 1 : 0;
- fix->ywrapstep = 0;
- fix->line_length = ivideo->video_linelength;
- fix->mmio_start = ivideo->mmio_base;
- fix->mmio_len = ivideo->mmio_size;
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- fix->accel = FB_ACCEL_SIS_GLAMOUR;
- } else if((ivideo->chip == SIS_330) ||
- (ivideo->chip == SIS_760) ||
- (ivideo->chip == SIS_761)) {
- fix->accel = FB_ACCEL_SIS_XABRE;
- } else if(ivideo->chip == XGI_20) {
- fix->accel = FB_ACCEL_XGI_VOLARI_Z;
- } else if(ivideo->chip >= XGI_40) {
- fix->accel = FB_ACCEL_XGI_VOLARI_V;
- } else {
- fix->accel = FB_ACCEL_SIS_GLAMOUR_2;
- }
- return 0;
- }
- /* ---------------- fb_ops structures ----------------- */
- static struct fb_ops sisfb_ops = {
- .owner = THIS_MODULE,
- .fb_open = sisfb_open,
- .fb_release = sisfb_release,
- .fb_check_var = sisfb_check_var,
- .fb_set_par = sisfb_set_par,
- .fb_setcolreg = sisfb_setcolreg,
- .fb_pan_display = sisfb_pan_display,
- .fb_blank = sisfb_blank,
- .fb_fillrect = fbcon_sis_fillrect,
- .fb_copyarea = fbcon_sis_copyarea,
- .fb_imageblit = cfb_imageblit,
- .fb_sync = fbcon_sis_sync,
- #ifdef SIS_NEW_CONFIG_COMPAT
- .fb_compat_ioctl= sisfb_ioctl,
- #endif
- .fb_ioctl = sisfb_ioctl
- };
- /* ---------------- Chip generation dependent routines ---------------- */
- static struct pci_dev * __devinit
- sisfb_get_northbridge(int basechipid)
- {
- struct pci_dev *pdev = NULL;
- int nbridgenum, nbridgeidx, i;
- static const unsigned short nbridgeids[] = {
- PCI_DEVICE_ID_SI_540, /* for SiS 540 VGA */
- PCI_DEVICE_ID_SI_630, /* for SiS 630/730 VGA */
- PCI_DEVICE_ID_SI_730,
- PCI_DEVICE_ID_SI_550, /* for SiS 550 VGA */
- PCI_DEVICE_ID_SI_650, /* for SiS 650/651/740 VGA */
- PCI_DEVICE_ID_SI_651,
- PCI_DEVICE_ID_SI_740,
- PCI_DEVICE_ID_SI_661, /* for SiS 661/741/660/760/761 VGA */
- PCI_DEVICE_ID_SI_741,
- PCI_DEVICE_ID_SI_660,
- PCI_DEVICE_ID_SI_760,
- PCI_DEVICE_ID_SI_761
- };
- switch(basechipid) {
- #ifdef CONFIG_FB_SIS_300
- case SIS_540: nbridgeidx = 0; nbridgenum = 1; break;
- case SIS_630: nbridgeidx = 1; nbridgenum = 2; break;
- #endif
- #ifdef CONFIG_FB_SIS_315
- case SIS_550: nbridgeidx = 3; nbridgenum = 1; break;
- case SIS_650: nbridgeidx = 4; nbridgenum = 3; break;
- case SIS_660: nbridgeidx = 7; nbridgenum = 5; break;
- #endif
- default: return NULL;
- }
- for(i = 0; i < nbridgenum; i++) {
- if((pdev = pci_get_device(PCI_VENDOR_ID_SI,
- nbridgeids[nbridgeidx+i], NULL)))
- break;
- }
- return pdev;
- }
- static int __devinit
- sisfb_get_dram_size(struct sis_video_info *ivideo)
- {
- #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
- u8 reg;
- #endif
- ivideo->video_size = 0;
- ivideo->UMAsize = ivideo->LFBsize = 0;
- switch(ivideo->chip) {
- #ifdef CONFIG_FB_SIS_300
- case SIS_300:
- reg = SiS_GetReg(SISSR, 0x14);
- ivideo->video_size = ((reg & 0x3F) + 1) << 20;
- break;
- case SIS_540:
- case SIS_630:
- case SIS_730:
- if(!ivideo->nbridge)
- return -1;
- pci_read_config_byte(ivideo->nbridge, 0x63, ®);
- ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21);
- break;
- #endif
- #ifdef CONFIG_FB_SIS_315
- case SIS_315H:
- case SIS_315PRO:
- case SIS_315:
- reg = SiS_GetReg(SISSR, 0x14);
- ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
- switch((reg >> 2) & 0x03) {
- case 0x01:
- case 0x03:
- ivideo->video_size <<= 1;
- break;
- case 0x02:
- ivideo->video_size += (ivideo->video_size/2);
- }
- break;
- case SIS_330:
- reg = SiS_GetReg(SISSR, 0x14);
- ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
- if(reg & 0x0c) ivideo->video_size <<= 1;
- break;
- case SIS_550:
- case SIS_650:
- case SIS_740:
- reg = SiS_GetReg(SISSR, 0x14);
- ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;
- break;
- case SIS_661:
- case SIS_741:
- reg = SiS_GetReg(SISCR, 0x79);
- ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
- break;
- case SIS_660:
- case SIS_760:
- case SIS_761:
- reg = SiS_GetReg(SISCR, 0x79);
- reg = (reg & 0xf0) >> 4;
- if(reg) {
- ivideo->video_size = (1 << reg) << 20;
- ivideo->UMAsize = ivideo->video_size;
- }
- reg = SiS_GetReg(SISCR, 0x78);
- reg &= 0x30;
- if(reg) {
- if(reg == 0x10) {
- ivideo->LFBsize = (32 << 20);
- } else {
- ivideo->LFBsize = (64 << 20);
- }
- ivideo->video_size += ivideo->LFBsize;
- }
- break;
- case SIS_340:
- case XGI_20:
- case XGI_40:
- reg = SiS_GetReg(SISSR, 0x14);
- ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
- if(ivideo->chip != XGI_20) {
- reg = (reg & 0x0c) >> 2;
- if(ivideo->revision_id == 2) {
- if(reg & 0x01) reg = 0x02;
- else reg = 0x00;
- }
- if(reg == 0x02) ivideo->video_size <<= 1;
- else if(reg == 0x03) ivideo->video_size <<= 2;
- }
- break;
- #endif
- default:
- return -1;
- }
- return 0;
- }
- /* -------------- video bridge device detection --------------- */
- static void __devinit
- sisfb_detect_VB_connect(struct sis_video_info *ivideo)
- {
- u8 cr32, temp;
- /* No CRT2 on XGI Z7 */
- if(ivideo->chip == XGI_20) {
- ivideo->sisfb_crt1off = 0;
- return;
- }
- #ifdef CONFIG_FB_SIS_300
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- temp = SiS_GetReg(SISSR, 0x17);
- if((temp & 0x0F) && (ivideo->chip != SIS_300)) {
- /* PAL/NTSC is stored on SR16 on such machines */
- if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
- temp = SiS_GetReg(SISSR, 0x16);
- if(temp & 0x20)
- ivideo->vbflags |= TV_PAL;
- else
- ivideo->vbflags |= TV_NTSC;
- }
- }
- }
- #endif
- cr32 = SiS_GetReg(SISCR, 0x32);
- if(cr32 & SIS_CRT1) {
- ivideo->sisfb_crt1off = 0;
- } else {
- ivideo->sisfb_crt1off = (cr32 & 0xDF) ? 1 : 0;
- }
- ivideo->vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA);
- if(cr32 & SIS_VB_TV) ivideo->vbflags |= CRT2_TV;
- if(cr32 & SIS_VB_LCD) ivideo->vbflags |= CRT2_LCD;
- if(cr32 & SIS_VB_CRT2) ivideo->vbflags |= CRT2_VGA;
- /* Check given parms for hardware compatibility.
- * (Cannot do this in the search_xx routines since we don't
- * know what hardware we are running on then)
- */
- if(ivideo->chip != SIS_550) {
- ivideo->sisfb_dstn = ivideo->sisfb_fstn = 0;
- }
- if(ivideo->sisfb_tvplug != -1) {
- if( (ivideo->sisvga_engine != SIS_315_VGA) ||
- (!(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) ) {
- if(ivideo->sisfb_tvplug & TV_YPBPR) {
- ivideo->sisfb_tvplug = -1;
- printk(KERN_ERR "sisfb: YPbPr not supported\n");
- }
- }
- }
- if(ivideo->sisfb_tvplug != -1) {
- if( (ivideo->sisvga_engine != SIS_315_VGA) ||
- (!(ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) ) {
- if(ivideo->sisfb_tvplug & TV_HIVISION) {
- ivideo->sisfb_tvplug = -1;
- printk(KERN_ERR "sisfb: HiVision not supported\n");
- }
- }
- }
- if(ivideo->sisfb_tvstd != -1) {
- if( (!(ivideo->vbflags2 & VB2_SISBRIDGE)) &&
- (!((ivideo->sisvga_engine == SIS_315_VGA) &&
- (ivideo->vbflags2 & VB2_CHRONTEL))) ) {
- if(ivideo->sisfb_tvstd & (TV_PALM | TV_PALN | TV_NTSCJ)) {
- ivideo->sisfb_tvstd = -1;
- printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
- }
- }
- }
- /* Detect/set TV plug & type */
- if(ivideo->sisfb_tvplug != -1) {
- ivideo->vbflags |= ivideo->sisfb_tvplug;
- } else {
- if(cr32 & SIS_VB_YPBPR) ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */
- else if(cr32 & SIS_VB_HIVISION) ivideo->vbflags |= TV_HIVISION;
- else if(cr32 & SIS_VB_SCART) ivideo->vbflags |= TV_SCART;
- else {
- if(cr32 & SIS_VB_SVIDEO) ivideo->vbflags |= TV_SVIDEO;
- if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO;
- }
- }
- if(!(ivideo->vbflags & (TV_YPBPR | TV_HIVISION))) {
- if(ivideo->sisfb_tvstd != -1) {
- ivideo->vbflags &= ~(TV_NTSC | TV_PAL | TV_PALM | TV_PALN | TV_NTSCJ);
- ivideo->vbflags |= ivideo->sisfb_tvstd;
- }
- if(ivideo->vbflags & TV_SCART) {
- ivideo->vbflags &= ~(TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ);
- ivideo->vbflags |= TV_PAL;
- }
- if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) {
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- temp = SiS_GetReg(SISSR, 0x38);
- if(temp & 0x01) ivideo->vbflags |= TV_PAL;
- else ivideo->vbflags |= TV_NTSC;
- } else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) {
- temp = SiS_GetReg(SISSR, 0x38);
- if(temp & 0x01) ivideo->vbflags |= TV_PAL;
- else ivideo->vbflags |= TV_NTSC;
- } else {
- temp = SiS_GetReg(SISCR, 0x79);
- if(temp & 0x20) ivideo->vbflags |= TV_PAL;
- else ivideo->vbflags |= TV_NTSC;
- }
- }
- }
- /* Copy forceCRT1 option to CRT1off if option is given */
- if(ivideo->sisfb_forcecrt1 != -1) {
- ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1;
- }
- }
- /* ------------------ Sensing routines ------------------ */
- static bool __devinit
- sisfb_test_DDC1(struct sis_video_info *ivideo)
- {
- unsigned short old;
- int count = 48;
- old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr);
- do {
- if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
- } while(count--);
- return (count != -1);
- }
- static void __devinit
- sisfb_sense_crt1(struct sis_video_info *ivideo)
- {
- bool mustwait = false;
- u8 sr1F, cr17;
- #ifdef CONFIG_FB_SIS_315
- u8 cr63=0;
- #endif
- u16 temp = 0xffff;
- int i;
- sr1F = SiS_GetReg(SISSR, 0x1F);
- SiS_SetRegOR(SISSR, 0x1F, 0x04);
- SiS_SetRegAND(SISSR, 0x1F, 0x3F);
- if(sr1F & 0xc0) mustwait = true;
- #ifdef CONFIG_FB_SIS_315
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- cr63 = SiS_GetReg(SISCR, ivideo->SiS_Pr.SiS_MyCR63);
- cr63 &= 0x40;
- SiS_SetRegAND(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF);
- }
- #endif
- cr17 = SiS_GetReg(SISCR, 0x17);
- cr17 &= 0x80;
- if(!cr17) {
- SiS_SetRegOR(SISCR, 0x17, 0x80);
- mustwait = true;
- SiS_SetReg(SISSR, 0x00, 0x01);
- SiS_SetReg(SISSR, 0x00, 0x03);
- }
- if(mustwait) {
- for(i=0; i < 10; i++) sisfbwaitretracecrt1(ivideo);
- }
- #ifdef CONFIG_FB_SIS_315
- if(ivideo->chip >= SIS_330) {
- SiS_SetRegAND(SISCR, 0x32, ~0x20);
- if(ivideo->chip >= SIS_340) {
- SiS_SetReg(SISCR, 0x57, 0x4a);
- } else {
- SiS_SetReg(SISCR, 0x57, 0x5f);
- }
- SiS_SetRegOR(SISCR, 0x53, 0x02);
- while ((SiS_GetRegByte(SISINPSTAT)) & 0x01) break;
- while (!((SiS_GetRegByte(SISINPSTAT)) & 0x01)) break;
- if ((SiS_GetRegByte(SISMISCW)) & 0x10) temp = 1;
- SiS_SetRegAND(SISCR, 0x53, 0xfd);
- SiS_SetRegAND(SISCR, 0x57, 0x00);
- }
- #endif
- if(temp == 0xffff) {
- i = 3;
- do {
- temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
- ivideo->sisvga_engine, 0, 0, NULL, ivideo->vbflags2);
- } while(((temp == 0) || (temp == 0xffff)) && i--);
- if((temp == 0) || (temp == 0xffff)) {
- if(sisfb_test_DDC1(ivideo)) temp = 1;
- }
- }
- if((temp) && (temp != 0xffff)) {
- SiS_SetRegOR(SISCR, 0x32, 0x20);
- }
- #ifdef CONFIG_FB_SIS_315
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF, cr63);
- }
- #endif
- SiS_SetRegANDOR(SISCR, 0x17, 0x7F, cr17);
- SiS_SetReg(SISSR, 0x1F, sr1F);
- }
- /* Determine and detect attached devices on SiS30x */
- static void __devinit
- SiS_SenseLCD(struct sis_video_info *ivideo)
- {
- unsigned char buffer[256];
- unsigned short temp, realcrtno, i;
- u8 reg, cr37 = 0, paneltype = 0;
- u16 xres, yres;
- ivideo->SiS_Pr.PanelSelfDetected = false;
- /* LCD detection only for TMDS bridges */
- if(!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE))
- return;
- if(ivideo->vbflags2 & VB2_30xBDH)
- return;
- /* If LCD already set up by BIOS, skip it */
- reg = SiS_GetReg(SISCR, 0x32);
- if(reg & 0x08)
- return;
- realcrtno = 1;
- if(ivideo->SiS_Pr.DDCPortMixup)
- realcrtno = 0;
- /* Check DDC capabilities */
- temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
- realcrtno, 0, &buffer[0], ivideo->vbflags2);
- if((!temp) || (temp == 0xffff) || (!(temp & 0x02)))
- return;
- /* Read DDC data */
- i = 3; /* Number of retrys */
- do {
- temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
- ivideo->sisvga_engine, realcrtno, 1,
- &buffer[0], ivideo->vbflags2);
- } while((temp) && i--);
- if(temp)
- return;
- /* No digital device */
- if(!(buffer[0x14] & 0x80))
- return;
- /* First detailed timing preferred timing? */
- if(!(buffer[0x18] & 0x02))
- return;
- xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
- yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4);
- switch(xres) {
- case 1024:
- if(yres == 768)
- paneltype = 0x02;
- break;
- case 1280:
- if(yres == 1024)
- paneltype = 0x03;
- break;
- case 1600:
- if((yres == 1200) && (ivideo->vbflags2 & VB2_30xC))
- paneltype = 0x0b;
- break;
- }
- if(!paneltype)
- return;
- if(buffer[0x23])
- cr37 |= 0x10;
- if((buffer[0x47] & 0x18) == 0x18)
- cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
- else
- cr37 |= 0xc0;
- SiS_SetReg(SISCR, 0x36, paneltype);
- cr37 &= 0xf1;
- SiS_SetRegANDOR(SISCR, 0x37, 0x0c, cr37);
- SiS_SetRegOR(SISCR, 0x32, 0x08);
- ivideo->SiS_Pr.PanelSelfDetected = true;
- }
- static int __devinit
- SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
- {
- int temp, mytest, result, i, j;
- for(j = 0; j < 10; j++) {
- result = 0;
- for(i = 0; i < 3; i++) {
- mytest = test;
- SiS_SetReg(SISPART4, 0x11, (type & 0x00ff));
- temp = (type >> 8) | (mytest & 0x00ff);
- SiS_SetRegANDOR(SISPART4, 0x10, 0xe0, temp);
- SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500);
- mytest >>= 8;
- mytest &= 0x7f;
- temp = SiS_GetReg(SISPART4, 0x03);
- temp ^= 0x0e;
- temp &= mytest;
- if(temp == mytest) result++;
- #if 1
- SiS_SetReg(SISPART4, 0x11, 0x00);
- SiS_SetRegAND(SISPART4, 0x10, 0xe0);
- SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);
- #endif
- }
- if((result == 0) || (result >= 2)) break;
- }
- return result;
- }
- static void __devinit
- SiS_Sense30x(struct sis_video_info *ivideo)
- {
- u8 backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0;
- u16 svhs=0, svhs_c=0;
- u16 cvbs=0, cvbs_c=0;
- u16 vga2=0, vga2_c=0;
- int myflag, result;
- char stdstr[] = "sisfb: Detected";
- char tvstr[] = "TV connected to";
- if(ivideo->vbflags2 & VB2_301) {
- svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
- myflag = SiS_GetReg(SISPART4, 0x01);
- if(myflag & 0x04) {
- svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
- }
- } else if(ivideo->vbflags2 & (VB2_301B | VB2_302B)) {
- svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190;
- } else if(ivideo->vbflags2 & (VB2_301LV | VB2_302LV)) {
- svhs = 0x0200; cvbs = 0x0100;
- } else if(ivideo->vbflags2 & (VB2_301C | VB2_302ELV | VB2_307T | VB2_307LV)) {
- svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190;
- } else
- return;
- vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804;
- if(ivideo->vbflags & (VB2_301LV|VB2_302LV|VB2_302ELV|VB2_307LV)) {
- svhs_c = 0x0408; cvbs_c = 0x0808;
- }
- biosflag = 2;
- if(ivideo->haveXGIROM) {
- biosflag = ivideo->bios_abase[0x58] & 0x03;
- } else if(ivideo->newrom) {
- if(ivideo->bios_abase[0x5d] & 0x04) biosflag |= 0x01;
- } else if(ivideo->sisvga_engine == SIS_300_VGA) {
- if(ivideo->bios_abase) {
- biosflag = ivideo->bios_abase[0xfe] & 0x03;
- }
- }
- if(ivideo->chip == SIS_300) {
- myflag = SiS_GetReg(SISSR, 0x3b);
- if(!(myflag & 0x01)) vga2 = vga2_c = 0;
- }
- if(!(ivideo->vbflags2 & VB2_SISVGA2BRIDGE)) {
- vga2 = vga2_c = 0;
- }
- backupSR_1e = SiS_GetReg(SISSR, 0x1e);
- SiS_SetRegOR(SISSR, 0x1e, 0x20);
- backupP4_0d = SiS_GetReg(SISPART4, 0x0d);
- if(ivideo->vbflags2 & VB2_30xC) {
- SiS_SetRegANDOR(SISPART4, 0x0d, ~0x07, 0x01);
- } else {
- SiS_SetRegOR(SISPART4, 0x0d, 0x04);
- }
- SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
- backupP2_00 = SiS_GetReg(SISPART2, 0x00);
- SiS_SetReg(SISPART2, 0x00, ((backupP2_00 | 0x1c) & 0xfc));
- backupP2_4d = SiS_GetReg(SISPART2, 0x4d);
- if(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE) {
- SiS_SetReg(SISPART2, 0x4d, (backupP2_4d & ~0x10));
- }
- if(!(ivideo->vbflags2 & VB2_30xCLV)) {
- SISDoSense(ivideo, 0, 0);
- }
- SiS_SetRegAND(SISCR, 0x32, ~0x14);
- if(vga2_c || vga2) {
- if(SISDoSense(ivideo, vga2, vga2_c)) {
- if(biosflag & 0x01) {
- printk(KERN_INFO "%s %s SCART output\n", stdstr, tvstr);
- SiS_SetRegOR(SISCR, 0x32, 0x04);
- } else {
- printk(KERN_INFO "%s secondary VGA connection\n", stdstr);
- SiS_SetRegOR(SISCR, 0x32, 0x10);
- }
- }
- }
- SiS_SetRegAND(SISCR, 0x32, 0x3f);
- if(ivideo->vbflags2 & VB2_30xCLV) {
- SiS_SetRegOR(SISPART4, 0x0d, 0x04);
- }
- if((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
- SiS_SetReg(SISPART2, 0x4d, (backupP2_4d | 0x10));
- SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
- if((result = SISDoSense(ivideo, svhs, 0x0604))) {
- if((result = SISDoSense(ivideo, cvbs, 0x0804))) {
- printk(KERN_INFO "%s %s YPbPr component output\n", stdstr, tvstr);
- SiS_SetRegOR(SISCR, 0x32, 0x80);
- }
- }
- SiS_SetReg(SISPART2, 0x4d, backupP2_4d);
- }
- SiS_SetRegAND(SISCR, 0x32, ~0x03);
- if(!(ivideo->vbflags & TV_YPBPR)) {
- if((result = SISDoSense(ivideo, svhs, svhs_c))) {
- printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr);
- SiS_SetRegOR(SISCR, 0x32, 0x02);
- }
- if((biosflag & 0x02) || (!result)) {
- if(SISDoSense(ivideo, cvbs, cvbs_c)) {
- printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr);
- SiS_SetRegOR(SISCR, 0x32, 0x01);
- }
- }
- }
- SISDoSense(ivideo, 0, 0);
- SiS_SetReg(SISPART2, 0x00, backupP2_00);
- SiS_SetReg(SISPART4, 0x0d, backupP4_0d);
- SiS_SetReg(SISSR, 0x1e, backupSR_1e);
- if(ivideo->vbflags2 & VB2_30xCLV) {
- biosflag = SiS_GetReg(SISPART2, 0x00);
- if(biosflag & 0x20) {
- for(myflag = 2; myflag > 0; myflag--) {
- biosflag ^= 0x20;
- SiS_SetReg(SISPART2, 0x00, biosflag);
- }
- }
- }
- SiS_SetReg(SISPART2, 0x00, backupP2_00);
- }
- /* Determine and detect attached TV's on Chrontel */
- static void __devinit
- SiS_SenseCh(struct sis_video_info *ivideo)
- {
- #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
- u8 temp1, temp2;
- char stdstr[] = "sisfb: Chrontel: Detected TV connected to";
- #endif
- #ifdef CONFIG_FB_SIS_300
- unsigned char test[3];
- int i;
- #endif
- if(ivideo->chip < SIS_315H) {
- #ifdef CONFIG_FB_SIS_300
- ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 1; /* Chrontel 700x */
- SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x9c); /* Set general purpose IO for Chrontel communication */
- SiS_DDC2Delay(&ivideo->SiS_Pr, 1000);
- temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
- /* See Chrontel TB31 for explanation */
- temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
- if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
- SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e, 0x0b);
- SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
- }
- temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
- if(temp2 != temp1) temp1 = temp2;
- if((temp1 >= 0x22) && (temp1 <= 0x50)) {
- /* Read power status */
- temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
- if((temp1 & 0x03) != 0x03) {
- /* Power all outputs */
- SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e,0x0b);
- SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
- }
- /* Sense connected TV devices */
- for(i = 0; i < 3; i++) {
- SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x01);
- SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
- SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x00);
- SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
- temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10);
- if(!(temp1 & 0x08)) test[i] = 0x02;
- else if(!(temp1 & 0x02)) test[i] = 0x01;
- else test[i] = 0;
- SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
- }
- if(test[0] == test[1]) temp1 = test[0];
- else if(test[0] == test[2]) temp1 = test[0];
- else if(test[1] == test[2]) temp1 = test[1];
- else {
- printk(KERN_INFO
- "sisfb: TV detection unreliable - test results varied\n");
- temp1 = test[2];
- }
- if(temp1 == 0x02) {
- printk(KERN_INFO "%s SVIDEO output\n", stdstr);
- ivideo->vbflags |= TV_SVIDEO;
- SiS_SetRegOR(SISCR, 0x32, 0x02);
- SiS_SetRegAND(SISCR, 0x32, ~0x05);
- } else if (temp1 == 0x01) {
- printk(KERN_INFO "%s CVBS output\n", stdstr);
- ivideo->vbflags |= TV_AVIDEO;
- SiS_SetRegOR(SISCR, 0x32, 0x01);
- SiS_SetRegAND(SISCR, 0x32, ~0x06);
- } else {
- SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
- SiS_SetRegAND(SISCR, 0x32, ~0x07);
- }
- } else if(temp1 == 0) {
- SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
- SiS_SetRegAND(SISCR, 0x32, ~0x07);
- }
- /* Set general purpose IO for Chrontel communication */
- SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x00);
- #endif
- } else {
- #ifdef CONFIG_FB_SIS_315
- ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2; /* Chrontel 7019 */
- temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49);
- SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, 0x20);
- SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
- temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
- temp2 |= 0x01;
- SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
- SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
- temp2 ^= 0x01;
- SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
- SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
- temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
- SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, temp1);
- temp1 = 0;
- if(temp2 & 0x02) temp1 |= 0x01;
- if(temp2 & 0x10) temp1 |= 0x01;
- if(temp2 & 0x04) temp1 |= 0x02;
- if( (temp1 & 0x01) && (temp1 & 0x02) ) temp1 = 0x04;
- switch(temp1) {
- case 0x01:
- printk(KERN_INFO "%s CVBS output\n", stdstr);
- ivideo->vbflags |= TV_AVIDEO;
- SiS_SetRegOR(SISCR, 0x32, 0x01);
- SiS_SetRegAND(SISCR, 0x32, ~0x06);
- break;
- case 0x02:
- printk(KERN_INFO "%s SVIDEO output\n", stdstr);
- ivideo->vbflags |= TV_SVIDEO;
- SiS_SetRegOR(SISCR, 0x32, 0x02);
- SiS_SetRegAND(SISCR, 0x32, ~0x05);
- break;
- case 0x04:
- printk(KERN_INFO "%s SCART output\n", stdstr);
- SiS_SetRegOR(SISCR, 0x32, 0x04);
- SiS_SetRegAND(SISCR, 0x32, ~0x03);
- break;
- default:
- SiS_SetRegAND(SISCR, 0x32, ~0x07);
- }
- #endif
- }
- }
- static void __devinit
- sisfb_get_VB_type(struct sis_video_info *ivideo)
- {
- char stdstr[] = "sisfb: Detected";
- char bridgestr[] = "video bridge";
- u8 vb_chipid;
- u8 reg;
- /* No CRT2 on XGI Z7 */
- if(ivideo->chip == XGI_20)
- return;
- vb_chipid = SiS_GetReg(SISPART4, 0x00);
- switch(vb_chipid) {
- case 0x01:
- reg = SiS_GetReg(SISPART4, 0x01);
- if(reg < 0xb0) {
- ivideo->vbflags |= VB_301; /* Deprecated */
- ivideo->vbflags2 |= VB2_301;
- printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
- } else if(reg < 0xc0) {
- ivideo->vbflags |= VB_301B; /* Deprecated */
- ivideo->vbflags2 |= VB2_301B;
- reg = SiS_GetReg(SISPART4, 0x23);
- if(!(reg & 0x02)) {
- ivideo->vbflags |= VB_30xBDH; /* Deprecated */
- ivideo->vbflags2 |= VB2_30xBDH;
- printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
- } else {
- printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
- }
- } else if(reg < 0xd0) {
- ivideo->vbflags |= VB_301C; /* Deprecated */
- ivideo->vbflags2 |= VB2_301C;
- printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
- } else if(reg < 0xe0) {
- ivideo->vbflags |= VB_301LV; /* Deprecated */
- ivideo->vbflags2 |= VB2_301LV;
- printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
- } else if(reg <= 0xe1) {
- reg = SiS_GetReg(SISPART4, 0x39);
- if(reg == 0xff) {
- ivideo->vbflags |= VB_302LV; /* Deprecated */
- ivideo->vbflags2 |= VB2_302LV;
- printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
- } else {
- ivideo->vbflags |= VB_301C; /* Deprecated */
- ivideo->vbflags2 |= VB2_301C;
- printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
- #if 0
- ivideo->vbflags |= VB_302ELV; /* Deprecated */
- ivideo->vbflags2 |= VB2_302ELV;
- printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
- #endif
- }
- }
- break;
- case 0x02:
- ivideo->vbflags |= VB_302B; /* Deprecated */
- ivideo->vbflags2 |= VB2_302B;
- printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
- break;
- }
- if((!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
- reg = SiS_GetReg(SISCR, 0x37);
- reg &= SIS_EXTERNAL_CHIP_MASK;
- reg >>= 1;
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- #ifdef CONFIG_FB_SIS_300
- switch(reg) {
- case SIS_EXTERNAL_CHIP_LVDS:
- ivideo->vbflags |= VB_LVDS; /* Deprecated */
- ivideo->vbflags2 |= VB2_LVDS;
- break;
- case SIS_EXTERNAL_CHIP_TRUMPION:
- ivideo->vbflags |= (VB_LVDS | VB_TRUMPION); /* Deprecated */
- ivideo->vbflags2 |= (VB2_LVDS | VB2_TRUMPION);
- break;
- case SIS_EXTERNAL_CHIP_CHRONTEL:
- ivideo->vbflags |= VB_CHRONTEL; /* Deprecated */
- ivideo->vbflags2 |= VB2_CHRONTEL;
- break;
- case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
- ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
- ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
- break;
- }
- if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 1;
- #endif
- } else if(ivideo->chip < SIS_661) {
- #ifdef CONFIG_FB_SIS_315
- switch (reg) {
- case SIS310_EXTERNAL_CHIP_LVDS:
- ivideo->vbflags |= VB_LVDS; /* Deprecated */
- ivideo->vbflags2 |= VB2_LVDS;
- break;
- case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
- ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
- ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
- break;
- }
- if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
- #endif
- } else if(ivideo->chip >= SIS_661) {
- #ifdef CONFIG_FB_SIS_315
- reg = SiS_GetReg(SISCR, 0x38);
- reg >>= 5;
- switch(reg) {
- case 0x02:
- ivideo->vbflags |= VB_LVDS; /* Deprecated */
- ivideo->vbflags2 |= VB2_LVDS;
- break;
- case 0x03:
- ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
- ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
- break;
- case 0x04:
- ivideo->vbflags |= (VB_LVDS | VB_CONEXANT); /* Deprecated */
- ivideo->vbflags2 |= (VB2_LVDS | VB2_CONEXANT);
- break;
- }
- if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
- #endif
- }
- if(ivideo->vbflags2 & VB2_LVDS) {
- printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
- }
- if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags2 & VB2_TRUMPION)) {
- printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
- }
- if(ivideo->vbflags2 & VB2_CHRONTEL) {
- printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
- }
- if((ivideo->chip >= SIS_661) && (ivideo->vbflags2 & VB2_CONEXANT)) {
- printk(KERN_INFO "%s Conexant external device\n", stdstr);
- }
- }
- if(ivideo->vbflags2 & VB2_SISBRIDGE) {
- SiS_SenseLCD(ivideo);
- SiS_Sense30x(ivideo);
- } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
- SiS_SenseCh(ivideo);
- }
- }
- /* ---------- Engine initialization routines ------------ */
- static void
- sisfb_engine_init(struct sis_video_info *ivideo)
- {
- /* Initialize command queue (we use MMIO only) */
- /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
- ivideo->caps &= ~(TURBO_QUEUE_CAP |
- MMIO_CMD_QUEUE_CAP |
- VM_CMD_QUEUE_CAP |
- AGP_CMD_QUEUE_CAP);
- #ifdef CONFIG_FB_SIS_300
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- u32 tqueue_pos;
- u8 tq_state;
- tqueue_pos = (ivideo->video_size - ivideo->cmdQueueSize) / (64 * 1024);
- tq_state = SiS_GetReg(SISSR, IND_SIS_TURBOQUEUE_SET);
- tq_state |= 0xf0;
- tq_state &= 0xfc;
- tq_state |= (u8)(tqueue_pos >> 8);
- SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
- SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
- ivideo->caps |= TURBO_QUEUE_CAP;
- }
- #endif
- #ifdef CONFIG_FB_SIS_315
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- u32 tempq = 0, templ;
- u8 temp;
- if(ivideo->chip == XGI_20) {
- switch(ivideo->cmdQueueSize) {
- case (64 * 1024):
- temp = SIS_CMD_QUEUE_SIZE_Z7_64k;
- break;
- case (128 * 1024):
- default:
- temp = SIS_CMD_QUEUE_SIZE_Z7_128k;
- }
- } else {
- switch(ivideo->cmdQueueSize) {
- case (4 * 1024 * 1024):
- temp = SIS_CMD_QUEUE_SIZE_4M;
- break;
- case (2 * 1024 * 1024):
- temp = SIS_CMD_QUEUE_SIZE_2M;
- break;
- case (1 * 1024 * 1024):
- temp = SIS_CMD_QUEUE_SIZE_1M;
- break;
- default:
- case (512 * 1024):
- temp = SIS_CMD_QUEUE_SIZE_512k;
- }
- }
- SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
- SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
- if((ivideo->chip >= XGI_40) && ivideo->modechanged) {
- /* Must disable dual pipe on XGI_40. Can't do
- * this in MMIO mode, because it requires
- * setting/clearing a bit in the MMIO fire trigger
- * register.
- */
- if(!((templ = MMIO_IN32(ivideo->mmio_vbase, 0x8240)) & (1 << 10))) {
- MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, 0);
- SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, (temp | SIS_VRAM_CMDQUEUE_ENABLE));
- tempq = MMIO_IN32(ivideo->mmio_vbase, Q_READ_PTR);
- MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, tempq);
- tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
- MMIO_OUT32(ivideo->mmio_vbase, Q_BASE_ADDR, tempq);
- writel(0x16800000 + 0x8240, ivideo->video_vbase + tempq);
- writel(templ | (1 << 10), ivideo->video_vbase + tempq + 4);
- writel(0x168F0000, ivideo->video_vbase + tempq + 8);
- writel(0x168F0000, ivideo->video_vbase + tempq + 12);
- MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, (tempq + 16));
- sisfb_syncaccel(ivideo);
- SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
- }
- }
- tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT);
- MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
- temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
- SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, temp);
- tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
- MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
- ivideo->caps |= MMIO_CMD_QUEUE_CAP;
- }
- #endif
- ivideo->engineok = 1;
- }
- static void __devinit
- sisfb_detect_lcd_type(struct sis_video_info *ivideo)
- {
- u8 reg;
- int i;
- reg = SiS_GetReg(SISCR, 0x36);
- reg &= 0x0f;
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- ivideo->CRT2LCDType = sis300paneltype[reg];
- } else if(ivideo->chip >= SIS_661) {
- ivideo->CRT2LCDType = sis661paneltype[reg];
- } else {
- ivideo->CRT2LCDType = sis310paneltype[reg];
- if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
- if((ivideo->CRT2LCDType != LCD_320x240_2) &&
- (ivideo->CRT2LCDType != LCD_320x240_3)) {
- ivideo->CRT2LCDType = LCD_320x240;
- }
- }
- }
- if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
- /* For broken BIOSes: Assume 1024x768, RGB18 */
- ivideo->CRT2LCDType = LCD_1024x768;
- SiS_SetRegANDOR(SISCR, 0x36, 0xf0, 0x02);
- SiS_SetRegANDOR(SISCR, 0x37, 0xee, 0x01);
- printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
- }
- for(i = 0; i < SIS_LCD_NUMBER; i++) {
- if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) {
- ivideo->lcdxres = sis_lcd_data[i].xres;
- ivideo->lcdyres = sis_lcd_data[i].yres;
- ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
- break;
- }
- }
- #ifdef CONFIG_FB_SIS_300
- if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
- ivideo->lcdxres = 1360; ivideo->lcdyres = 1024;
- ivideo->lcddefmodeidx = DEFAULT_MODE_1360;
- } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
- ivideo->lcdxres = 848; ivideo->lcdyres = 480;
- ivideo->lcddefmodeidx = DEFAULT_MODE_848;
- } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL856) {
- ivideo->lcdxres = 856; ivideo->lcdyres = 480;
- ivideo->lcddefmodeidx = DEFAULT_MODE_856;
- }
- #endif
- printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n",
- ivideo->lcdxres, ivideo->lcdyres);
- }
- static void __devinit
- sisfb_save_pdc_emi(struct sis_video_info *ivideo)
- {
- #ifdef CONFIG_FB_SIS_300
- /* Save the current PanelDelayCompensation if the LCD is currently used */
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- if(ivideo->vbflags2 & (VB2_LVDS | VB2_30xBDH)) {
- int tmp;
- tmp = SiS_GetReg(SISCR, 0x30);
- if(tmp & 0x20) {
- /* Currently on LCD? If yes, read current pdc */
- ivideo->detectedpdc = SiS_GetReg(SISPART1, 0x13);
- ivideo->detectedpdc &= 0x3c;
- if(ivideo->SiS_Pr.PDC == -1) {
- /* Let option override detection */
- ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
- }
- printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
- ivideo->detectedpdc);
- }
- if((ivideo->SiS_Pr.PDC != -1) &&
- (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
- printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
- ivideo->SiS_Pr.PDC);
- }
- }
- }
- #endif
- #ifdef CONFIG_FB_SIS_315
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- /* Try to find about LCDA */
- if(ivideo->vbflags2 & VB2_SISLCDABRIDGE) {
- int tmp;
- tmp = SiS_GetReg(SISPART1, 0x13);
- if(tmp & 0x04) {
- ivideo->SiS_Pr.SiS_UseLCDA = true;
- ivideo->detectedlcda = 0x03;
- }
- }
- /* Save PDC */
- if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
- int tmp;
- tmp = SiS_GetReg(SISCR, 0x30);
- if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
- /* Currently on LCD? If yes, read current pdc */
- u8 pdc;
- pdc = SiS_GetReg(SISPART1, 0x2D);
- ivideo->detectedpdc = (pdc & 0x0f) << 1;
- ivideo->detectedpdca = (pdc & 0xf0) >> 3;
- pdc = SiS_GetReg(SISPART1, 0x35);
- ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
- pdc = SiS_GetReg(SISPART1, 0x20);
- ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
- if(ivideo->newrom) {
- /* New ROM invalidates other PDC resp. */
- if(ivideo->detectedlcda != 0xff) {
- ivideo->detectedpdc = 0xff;
- } else {
- ivideo->detectedpdca = 0xff;
- }
- }
- if(ivideo->SiS_Pr.PDC == -1) {
- if(ivideo->detectedpdc != 0xff) {
- ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
- }
- }
- if(ivideo->SiS_Pr.PDCA == -1) {
- if(ivideo->detectedpdca != 0xff) {
- ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
- }
- }
- if(ivideo->detectedpdc != 0xff) {
- printk(KERN_INFO
- "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
- ivideo->detectedpdc);
- }
- if(ivideo->detectedpdca != 0xff) {
- printk(KERN_INFO
- "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
- ivideo->detectedpdca);
- }
- }
- /* Save EMI */
- if(ivideo->vbflags2 & VB2_SISEMIBRIDGE) {
- ivideo->SiS_Pr.EMI_30 = SiS_GetReg(SISPART4, 0x30);
- ivideo->SiS_Pr.EMI_31 = SiS_GetReg(SISPART4, 0x31);
- ivideo->SiS_Pr.EMI_32 = SiS_GetReg(SISPART4, 0x32);
- ivideo->SiS_Pr.EMI_33 = SiS_GetReg(SISPART4, 0x33);
- ivideo->SiS_Pr.HaveEMI = true;
- if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
- ivideo->SiS_Pr.HaveEMILCD = true;
- }
- }
- }
- /* Let user override detected PDCs (all bridges) */
- if(ivideo->vbflags2 & VB2_30xBLV) {
- if((ivideo->SiS_Pr.PDC != -1) &&
- (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
- printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
- ivideo->SiS_Pr.PDC);
- }
- if((ivideo->SiS_Pr.PDCA != -1) &&
- (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
- printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
- ivideo->SiS_Pr.PDCA);
- }
- }
- }
- #endif
- }
- /* -------------------- Memory manager routines ---------------------- */
- static u32 __devinit
- sisfb_getheapstart(struct sis_video_info *ivideo)
- {
- u32 ret = ivideo->sisfb_parm_mem * 1024;
- u32 maxoffs = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
- u32 def;
- /* Calculate heap start = end of memory for console
- *
- * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
- * C = console, D = heap, H = HWCursor, Q = cmd-queue
- *
- * On 76x in UMA+LFB mode, the layout is as follows:
- * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
- * where the heap is the entire UMA area, eventually
- * into the LFB area if the given mem parameter is
- * higher than the size of the UMA memory.
- *
- * Basically given by "mem" parameter
- *
- * maximum = videosize - cmd_queue - hwcursor
- * (results in a heap of size 0)
- * default = SiS 300: depends on videosize
- * SiS 315/330/340/XGI: 32k below max
- */
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- if(ivideo->video_size > 0x1000000) {
- def = 0xc00000;
- } else if(ivideo->video_size > 0x800000) {
- def = 0x800000;
- } else {
- def = 0x400000;
- }
- } else if(ivideo->UMAsize && ivideo->LFBsize) {
- ret = def = 0;
- } else {
- def = maxoffs - 0x8000;
- }
- /* Use default for secondary card for now (FIXME) */
- if((!ret) || (ret > maxoffs) || (ivideo->cardnumber != 0))
- ret = def;
- return ret;
- }
- static u32 __devinit
- sisfb_getheapsize(struct sis_video_info *ivideo)
- {
- u32 max = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
- u32 ret = 0;
- if(ivideo->UMAsize && ivideo->LFBsize) {
- if( (!ivideo->sisfb_parm_mem) ||
- ((ivideo->sisfb_parm_mem * 1024) > max) ||
- ((max - (ivideo->sisfb_parm_mem * 1024)) < ivideo->UMAsize) ) {
- ret = ivideo->UMAsize;
- max -= ivideo->UMAsize;
- } else {
- ret = max - (ivideo->sisfb_parm_mem * 1024);
- max = ivideo->sisfb_parm_mem * 1024;
- }
- ivideo->video_offset = ret;
- ivideo->sisfb_mem = max;
- } else {
- ret = max - ivideo->heapstart;
- ivideo->sisfb_mem = ivideo->heapstart;
- }
- return ret;
- }
- static int __devinit
- sisfb_heap_init(struct sis_video_info *ivideo)
- {
- struct SIS_OH *poh;
- ivideo->video_offset = 0;
- if(ivideo->sisfb_parm_mem) {
- if( (ivideo->sisfb_parm_mem < (2 * 1024 * 1024)) ||
- (ivideo->sisfb_parm_mem > ivideo->video_size) ) {
- ivideo->sisfb_parm_mem = 0;
- }
- }
- ivideo->heapstart = sisfb_getheapstart(ivideo);
- ivideo->sisfb_heap_size = sisfb_getheapsize(ivideo);
- ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart;
- ivideo->sisfb_heap_end = ivideo->sisfb_heap_start + ivideo->sisfb_heap_size;
- printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n",
- (int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024));
- ivideo->sisfb_heap.vinfo = ivideo;
- ivideo->sisfb_heap.poha_chain = NULL;
- ivideo->sisfb_heap.poh_freelist = NULL;
- poh = sisfb_poh_new_node(&ivideo->sisfb_heap);
- if(poh == NULL)
- return 1;
- poh->poh_next = &ivideo->sisfb_heap.oh_free;
- poh->poh_prev = &ivideo->sisfb_heap.oh_free;
- poh->size = ivideo->sisfb_heap_size;
- poh->offset = ivideo->heapstart;
- ivideo->sisfb_heap.oh_free.poh_next = poh;
- ivideo->sisfb_heap.oh_free.poh_prev = poh;
- ivideo->sisfb_heap.oh_free.size = 0;
- ivideo->sisfb_heap.max_freesize = poh->size;
- ivideo->sisfb_heap.oh_used.poh_next = &ivideo->sisfb_heap.oh_used;
- ivideo->sisfb_heap.oh_used.poh_prev = &ivideo->sisfb_heap.oh_used;
- ivideo->sisfb_heap.oh_used.size = SENTINEL;
- if(ivideo->cardnumber == 0) {
- /* For the first card, make this heap the "global" one
- * for old DRM (which could handle only one card)
- */
- sisfb_heap = &ivideo->sisfb_heap;
- }
- return 0;
- }
- static struct SIS_OH *
- sisfb_poh_new_node(struct SIS_HEAP *memheap)
- {
- struct SIS_OHALLOC *poha;
- struct SIS_OH *poh;
- unsigned long cOhs;
- int i;
- if(memheap->poh_freelist == NULL) {
- poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL);
- if(!poha)
- return NULL;
- poha->poha_next = memheap->poha_chain;
- memheap->poha_chain = poha;
- cOhs = (SIS_OH_ALLOC_SIZE - sizeof(struct SIS_OHALLOC)) / sizeof(struct SIS_OH) + 1;
- poh = &poha->aoh[0];
- for(i = cOhs - 1; i != 0; i--) {
- poh->poh_next = poh + 1;
- poh = poh + 1;
- }
- poh->poh_next = NULL;
- memheap->poh_freelist = &poha->aoh[0];
- }
- poh = memheap->poh_freelist;
- memheap->poh_freelist = poh->poh_next;
- return poh;
- }
- static struct SIS_OH *
- sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size)
- {
- struct SIS_OH *pohThis;
- struct SIS_OH *pohRoot;
- int bAllocated = 0;
- if(size > memheap->max_freesize) {
- DPRINTK("sisfb: Can't allocate %dk video memory\n",
- (unsigned int) size / 1024);
- return NULL;
- }
- pohThis = memheap->oh_free.poh_next;
- while(pohThis != &memheap->oh_free) {
- if(size <= pohThis->size) {
- bAllocated = 1;
- break;
- }
- pohThis = pohThis->poh_next;
- }
- if(!bAllocated) {
- DPRINTK("sisfb: Can't allocate %dk video memory\n",
- (unsigned int) size / 1024);
- return NULL;
- }
- if(size == pohThis->size) {
- pohRoot = pohThis;
- sisfb_delete_node(pohThis);
- } else {
- pohRoot = sisfb_poh_new_node(memheap);
- if(pohRoot == NULL)
- return NULL;
- pohRoot->offset = pohThis->offset;
- pohRoot->size = size;
- pohThis->offset += size;
- pohThis->size -= size;
- }
- memheap->max_freesize -= size;
- pohThis = &memheap->oh_used;
- sisfb_insert_node(pohThis, pohRoot);
- return pohRoot;
- }
- static void
- sisfb_delete_node(struct SIS_OH *poh)
- {
- poh->poh_prev->poh_next = poh->poh_next;
- poh->poh_next->poh_prev = poh->poh_prev;
- }
- static void
- sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh)
- {
- struct SIS_OH *pohTemp = pohList->poh_next;
- pohList->poh_next = poh;
- pohTemp->poh_prev = poh;
- poh->poh_prev = pohList;
- poh->poh_next = pohTemp;
- }
- static struct SIS_OH *
- sisfb_poh_free(struct SIS_HEAP *memheap, u32 base)
- {
- struct SIS_OH *pohThis;
- struct SIS_OH *poh_freed;
- struct SIS_OH *poh_prev;
- struct SIS_OH *poh_next;
- u32 ulUpper;
- u32 ulLower;
- int foundNode = 0;
- poh_freed = memheap->oh_used.poh_next;
- while(poh_freed != &memheap->oh_used) {
- if(poh_freed->offset == base) {
- foundNode = 1;
- break;
- }
- poh_freed = poh_freed->poh_next;
- }
- if(!foundNode)
- return NULL;
- memheap->max_freesize += poh_freed->size;
- poh_prev = poh_next = NULL;
- ulUpper = poh_freed->offset + poh_freed->size;
- ulLower = poh_freed->offset;
- pohThis = memheap->oh_free.poh_next;
- while(pohThis != &memheap->oh_free) {
- if(pohThis->offset == ulUpper) {
- poh_next = pohThis;
- } else if((pohThis->offset + pohThis->size) == ulLower) {
- poh_prev = pohThis;
- }
- pohThis = pohThis->poh_next;
- }
- sisfb_delete_node(poh_freed);
- if(poh_prev && poh_next) {
- poh_prev->size += (poh_freed->size + poh_next->size);
- sisfb_delete_node(poh_next);
- sisfb_free_node(memheap, poh_freed);
- sisfb_free_node(memheap, poh_next);
- return poh_prev;
- }
- if(poh_prev) {
- poh_prev->size += poh_freed->size;
- sisfb_free_node(memheap, poh_freed);
- return poh_prev;
- }
- if(poh_next) {
- poh_next->size += poh_freed->size;
- poh_next->offset = poh_freed->offset;
- sisfb_free_node(memheap, poh_freed);
- return poh_next;
- }
- sisfb_insert_node(&memheap->oh_free, poh_freed);
- return poh_freed;
- }
- static void
- sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh)
- {
- if(poh == NULL)
- return;
- poh->poh_next = memheap->poh_freelist;
- memheap->poh_freelist = poh;
- }
- static void
- sis_int_malloc(struct sis_video_info *ivideo, struct sis_memreq *req)
- {
- struct SIS_OH *poh = NULL;
- if((ivideo) && (ivideo->sisfb_id == SISFB_ID) && (!ivideo->havenoheap))
- poh = sisfb_poh_allocate(&ivideo->sisfb_heap, (u32)req->size);
- if(poh == NULL) {
- req->offset = req->size = 0;
- DPRINTK("sisfb: Video RAM allocation failed\n");
- } else {
- req->offset = poh->offset;
- req->size = poh->size;
- DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
- (poh->offset + ivideo->video_vbase));
- }
- }
- void
- sis_malloc(struct sis_memreq *req)
- {
- struct sis_video_info *ivideo = sisfb_heap->vinfo;
- if(&ivideo->sisfb_heap == sisfb_heap)
- sis_int_malloc(ivideo, req);
- else
- req->offset = req->size = 0;
- }
- void
- sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req)
- {
- struct sis_video_info *ivideo = pci_get_drvdata(pdev);
- sis_int_malloc(ivideo, req);
- }
- /* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
- static void
- sis_int_free(struct sis_video_info *ivideo, u32 base)
- {
- struct SIS_OH *poh;
- if((!ivideo) || (ivideo->sisfb_id != SISFB_ID) || (ivideo->havenoheap))
- return;
- poh = sisfb_poh_free(&ivideo->sisfb_heap, base);
- if(poh == NULL) {
- DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
- (unsigned int) base);
- }
- }
- void
- sis_free(u32 base)
- {
- struct sis_video_info *ivideo = sisfb_heap->vinfo;
- sis_int_free(ivideo, base);
- }
- void
- sis_free_new(struct pci_dev *pdev, u32 base)
- {
- struct sis_video_info *ivideo = pci_get_drvdata(pdev);
- sis_int_free(ivideo, base);
- }
- /* --------------------- SetMode routines ------------------------- */
- static void
- sisfb_check_engine_and_sync(struct sis_video_info *ivideo)
- {
- u8 cr30, cr31;
- /* Check if MMIO and engines are enabled,
- * and sync in case they are. Can't use
- * ivideo->accel here, as this might have
- * been changed before this is called.
- */
- cr30 = SiS_GetReg(SISSR, IND_SIS_PCI_ADDRESS_SET);
- cr31 = SiS_GetReg(SISSR, IND_SIS_MODULE_ENABLE);
- /* MMIO and 2D/3D engine enabled? */
- if((cr30 & SIS_MEM_MAP_IO_ENABLE) && (cr31 & 0x42)) {
- #ifdef CONFIG_FB_SIS_300
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- /* Don't care about TurboQueue. It's
- * enough to know that the engines
- * are enabled
- */
- sisfb_syncaccel(ivideo);
- }
- #endif
- #ifdef CONFIG_FB_SIS_315
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- /* Check that any queue mode is
- * enabled, and that the queue
- * is not in the state of "reset"
- */
- cr30 = SiS_GetReg(SISSR, 0x26);
- if((cr30 & 0xe0) && (!(cr30 & 0x01))) {
- sisfb_syncaccel(ivideo);
- }
- }
- #endif
- }
- }
- static void
- sisfb_pre_setmode(struct sis_video_info *ivideo)
- {
- u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0;
- int tvregnum = 0;
- ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
- SiS_SetReg(SISSR, 0x05, 0x86);
- cr31 = SiS_GetReg(SISCR, 0x31);
- cr31 &= ~0x60;
- cr31 |= 0x04;
- cr33 = ivideo->rate_idx & 0x0F;
- #ifdef CONFIG_FB_SIS_315
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- if(ivideo->chip >= SIS_661) {
- cr38 = SiS_GetReg(SISCR, 0x38);
- cr38 &= ~0x07; /* Clear LCDA/DualEdge and YPbPr bits */
- } else {
- tvregnum = 0x38;
- cr38 = SiS_GetReg(SISCR, tvregnum);
- cr38 &= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */
- }
- }
- #endif
- #ifdef CONFIG_FB_SIS_300
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- tvregnum = 0x35;
- cr38 = SiS_GetReg(SISCR, tvregnum);
- }
- #endif
- SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
- SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
- ivideo->curFSTN = ivideo->curDSTN = 0;
- switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
- case CRT2_TV:
- cr38 &= ~0xc0; /* Clear PAL-M / PAL-N bits */
- if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
- #ifdef CONFIG_FB_SIS_315
- if(ivideo->chip >= SIS_661) {
- cr38 |= 0x04;
- if(ivideo->vbflags & TV_YPBPR525P) cr35 |= 0x20;
- else if(ivideo->vbflags & TV_YPBPR750P) cr35 |= 0x40;
- else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60;
- cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
- cr35 &= ~0x01;
- ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
- } else if(ivideo->sisvga_engine == SIS_315_VGA) {
- cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE);
- cr38 |= 0x08;
- if(ivideo->vbflags & TV_YPBPR525P) cr38 |= 0x10;
- else if(ivideo->vbflags & TV_YPBPR750P) cr38 |= 0x20;
- else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30;
- cr31 &= ~0x01;
- ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
- }
- #endif
- } else if((ivideo->vbflags & TV_HIVISION) &&
- (ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) {
- if(ivideo->chip >= SIS_661) {
- cr38 |= 0x04;
- cr35 |= 0x60;
- } else {
- cr30 |= 0x80;
- }
- cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
- cr31 |= 0x01;
- cr35 |= 0x01;
- ivideo->currentvbflags |= TV_HIVISION;
- } else if(ivideo->vbflags & TV_SCART) {
- cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE);
- cr31 |= 0x01;
- cr35 |= 0x01;
- ivideo->currentvbflags |= TV_SCART;
- } else {
- if(ivideo->vbflags & TV_SVIDEO) {
- cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE);
- ivideo->currentvbflags |= TV_SVIDEO;
- }
- if(ivideo->vbflags & TV_AVIDEO) {
- cr30 = (SIS_VB_OUTPUT_COMPOSITE | SIS_SIMULTANEOUS_VIEW_ENABLE);
- ivideo->currentvbflags |= TV_AVIDEO;
- }
- }
- cr31 |= SIS_DRIVER_MODE;
- if(ivideo->vbflags & (TV_AVIDEO | TV_SVIDEO)) {
- if(ivideo->vbflags & TV_PAL) {
- cr31 |= 0x01; cr35 |= 0x01;
- ivideo->currentvbflags |= TV_PAL;
- if(ivideo->vbflags & TV_PALM) {
- cr38 |= 0x40; cr35 |= 0x04;
- ivideo->currentvbflags |= TV_PALM;
- } else if(ivideo->vbflags & TV_PALN) {
- cr38 |= 0x80; cr35 |= 0x08;
- ivideo->currentvbflags |= TV_PALN;
- }
- } else {
- cr31 &= ~0x01; cr35 &= ~0x01;
- ivideo->currentvbflags |= TV_NTSC;
- if(ivideo->vbflags & TV_NTSCJ) {
- cr38 |= 0x40; cr35 |= 0x02;
- ivideo->currentvbflags |= TV_NTSCJ;
- }
- }
- }
- break;
- case CRT2_LCD:
- cr30 = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
- cr31 |= SIS_DRIVER_MODE;
- SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn);
- SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->sisfb_fstn);
- ivideo->curFSTN = ivideo->sisfb_fstn;
- ivideo->curDSTN = ivideo->sisfb_dstn;
- break;
- case CRT2_VGA:
- cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
- cr31 |= SIS_DRIVER_MODE;
- if(ivideo->sisfb_nocrt2rate) {
- cr33 |= (sisbios_mode[ivideo->sisfb_mode_idx].rate_idx << 4);
- } else {
- cr33 |= ((ivideo->rate_idx & 0x0F) << 4);
- }
- break;
- default: /* disable CRT2 */
- cr30 = 0x00;
- cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
- }
- SiS_SetReg(SISCR, 0x30, cr30);
- SiS_SetReg(SISCR, 0x33, cr33);
- if(ivideo->chip >= SIS_661) {
- #ifdef CONFIG_FB_SIS_315
- cr31 &= ~0x01; /* Clear PAL flag (now in CR35) */
- SiS_SetRegANDOR(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */
- cr38 &= 0x07; /* Use only LCDA and HiVision/YPbPr bits */
- SiS_SetRegANDOR(SISCR, 0x38, 0xf8, cr38);
- #endif
- } else if(ivideo->chip != SIS_300) {
- SiS_SetReg(SISCR, tvregnum, cr38);
- }
- SiS_SetReg(SISCR, 0x31, cr31);
- ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem;
- sisfb_check_engine_and_sync(ivideo);
- }
- /* Fix SR11 for 661 and later */
- #ifdef CONFIG_FB_SIS_315
- static void
- sisfb_fixup_SR11(struct sis_video_info *ivideo)
- {
- u8 tmpreg;
- if(ivideo->chip >= SIS_661) {
- tmpreg = SiS_GetReg(SISSR, 0x11);
- if(tmpreg & 0x20) {
- tmpreg = SiS_GetReg(SISSR, 0x3e);
- tmpreg = (tmpreg + 1) & 0xff;
- SiS_SetReg(SISSR, 0x3e, tmpreg);
- tmpreg = SiS_GetReg(SISSR, 0x11);
- }
- if(tmpreg & 0xf0) {
- SiS_SetRegAND(SISSR, 0x11, 0x0f);
- }
- }
- }
- #endif
- static void
- sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
- {
- if(val > 32) val = 32;
- if(val < -32) val = -32;
- ivideo->tvxpos = val;
- if(ivideo->sisfblocked) return;
- if(!ivideo->modechanged) return;
- if(ivideo->currentvbflags & CRT2_TV) {
- if(ivideo->vbflags2 & VB2_CHRONTEL) {
- int x = ivideo->tvx;
- switch(ivideo->chronteltype) {
- case 1:
- x += val;
- if(x < 0) x = 0;
- SiS_SetReg(SISSR, 0x05, 0x86);
- SiS_SetCH700x(&ivideo->SiS_Pr, 0x0a, (x & 0xff));
- SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD);
- break;
- case 2:
- /* Not supported by hardware */
- break;
- }
- } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
- u8 p2_1f,p2_20,p2_2b,p2_42,p2_43;
- unsigned short temp;
- p2_1f = ivideo->p2_1f;
- p2_20 = ivideo->p2_20;
- p2_2b = ivideo->p2_2b;
- p2_42 = ivideo->p2_42;
- p2_43 = ivideo->p2_43;
- temp = p2_1f | ((p2_20 & 0xf0) << 4);
- temp += (val * 2);
- p2_1f = temp & 0xff;
- p2_20 = (temp & 0xf00) >> 4;
- p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f;
- temp = p2_43 | ((p2_42 & 0xf0) << 4);
- temp += (val * 2);
- p2_43 = temp & 0xff;
- p2_42 = (temp & 0xf00) >> 4;
- SiS_SetReg(SISPART2, 0x1f, p2_1f);
- SiS_SetRegANDOR(SISPART2, 0x20, 0x0F, p2_20);
- SiS_SetRegANDOR(SISPART2, 0x2b, 0xF0, p2_2b);
- SiS_SetRegANDOR(SISPART2, 0x42, 0x0F, p2_42);
- SiS_SetReg(SISPART2, 0x43, p2_43);
- }
- }
- }
- static void
- sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
- {
- if(val > 32) val = 32;
- if(val < -32) val = -32;
- ivideo->tvypos = val;
- if(ivideo->sisfblocked) return;
- if(!ivideo->modechanged) return;
- if(ivideo->currentvbflags & CRT2_TV) {
- if(ivideo->vbflags2 & VB2_CHRONTEL) {
- int y = ivideo->tvy;
- switch(ivideo->chronteltype) {
- case 1:
- y -= val;
- if(y < 0) y = 0;
- SiS_SetReg(SISSR, 0x05, 0x86);
- SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b, (y & 0xff));
- SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE);
- break;
- case 2:
- /* Not supported by hardware */
- break;
- }
- } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
- char p2_01, p2_02;
- val /= 2;
- p2_01 = ivideo->p2_01;
- p2_02 = ivideo->p2_02;
- p2_01 += val;
- p2_02 += val;
- if(!(ivideo->currentvbflags & (TV_HIVISION | TV_YPBPR))) {
- while((p2_01 <= 0) || (p2_02 <= 0)) {
- p2_01 += 2;
- p2_02 += 2;
- }
- }
- SiS_SetReg(SISPART2, 0x01, p2_01);
- SiS_SetReg(SISPART2, 0x02, p2_02);
- }
- }
- }
- static void
- sisfb_post_setmode(struct sis_video_info *ivideo)
- {
- bool crt1isoff = false;
- bool doit = true;
- #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
- u8 reg;
- #endif
- #ifdef CONFIG_FB_SIS_315
- u8 reg1;
- #endif
- SiS_SetReg(SISSR, 0x05, 0x86);
- #ifdef CONFIG_FB_SIS_315
- sisfb_fixup_SR11(ivideo);
- #endif
- /* Now we actually HAVE changed the display mode */
- ivideo->modechanged = 1;
- /* We can't switch off CRT1 if bridge is in slave mode */
- if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
- if(sisfb_bridgeisslave(ivideo)) doit = false;
- } else
- ivideo->sisfb_crt1off = 0;
- #ifdef CONFIG_FB_SIS_300
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- if((ivideo->sisfb_crt1off) && (doit)) {
- crt1isoff = true;
- reg = 0x00;
- } else {
- crt1isoff = false;
- reg = 0x80;
- }
- SiS_SetRegANDOR(SISCR, 0x17, 0x7f, reg);
- }
- #endif
- #ifdef CONFIG_FB_SIS_315
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- if((ivideo->sisfb_crt1off) && (doit)) {
- crt1isoff = true;
- reg = 0x40;
- reg1 = 0xc0;
- } else {
- crt1isoff = false;
- reg = 0x00;
- reg1 = 0x00;
- }
- SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
- SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, reg1);
- }
- #endif
- if(crt1isoff) {
- ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1;
- ivideo->currentvbflags |= VB_SINGLE_MODE;
- } else {
- ivideo->currentvbflags |= VB_DISPTYPE_CRT1;
- if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) {
- ivideo->currentvbflags |= VB_MIRROR_MODE;
- } else {
- ivideo->currentvbflags |= VB_SINGLE_MODE;
- }
- }
- SiS_SetRegAND(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
- if(ivideo->currentvbflags & CRT2_TV) {
- if(ivideo->vbflags2 & VB2_SISBRIDGE) {
- ivideo->p2_1f = SiS_GetReg(SISPART2, 0x1f);
- ivideo->p2_20 = SiS_GetReg(SISPART2, 0x20);
- ivideo->p2_2b = SiS_GetReg(SISPART2, 0x2b);
- ivideo->p2_42 = SiS_GetReg(SISPART2, 0x42);
- ivideo->p2_43 = SiS_GetReg(SISPART2, 0x43);
- ivideo->p2_01 = SiS_GetReg(SISPART2, 0x01);
- ivideo->p2_02 = SiS_GetReg(SISPART2, 0x02);
- } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
- if(ivideo->chronteltype == 1) {
- ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
- ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8);
- ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b);
- ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8);
- }
- }
- }
- if(ivideo->tvxpos) {
- sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos);
- }
- if(ivideo->tvypos) {
- sisfb_set_TVyposoffset(ivideo, ivideo->tvypos);
- }
- /* Eventually sync engines */
- sisfb_check_engine_and_sync(ivideo);
- /* (Re-)Initialize chip engines */
- if(ivideo->accel) {
- sisfb_engine_init(ivideo);
- } else {
- ivideo->engineok = 0;
- }
- }
- static int
- sisfb_reset_mode(struct sis_video_info *ivideo)
- {
- if(sisfb_set_mode(ivideo, 0))
- return 1;
- sisfb_set_pitch(ivideo);
- sisfb_set_base_CRT1(ivideo, ivideo->current_base);
- sisfb_set_base_CRT2(ivideo, ivideo->current_base);
- return 0;
- }
- static void
- sisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_command)
- {
- int mycrt1off;
- switch(sisfb_command->sisfb_cmd) {
- case SISFB_CMD_GETVBFLAGS:
- if(!ivideo->modechanged) {
- sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
- } else {
- sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
- sisfb_command->sisfb_result[1] = ivideo->currentvbflags;
- sisfb_command->sisfb_result[2] = ivideo->vbflags2;
- }
- break;
- case SISFB_CMD_SWITCHCRT1:
- /* arg[0]: 0 = off, 1 = on, 99 = query */
- if(!ivideo->modechanged) {
- sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
- } else if(sisfb_command->sisfb_arg[0] == 99) {
- /* Query */
- sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
- sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
- } else if(ivideo->sisfblocked) {
- sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_LOCKED;
- } else if((!(ivideo->currentvbflags & CRT2_ENABLE)) &&
- (sisfb_command->sisfb_arg[0] == 0)) {
- sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_NOCRT2;
- } else {
- sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
- mycrt1off = sisfb_command->sisfb_arg[0] ? 0 : 1;
- if( ((ivideo->currentvbflags & VB_DISPTYPE_CRT1) && mycrt1off) ||
- ((!(ivideo->currentvbflags & VB_DISPTYPE_CRT1)) && !mycrt1off) ) {
- ivideo->sisfb_crt1off = mycrt1off;
- if(sisfb_reset_mode(ivideo)) {
- sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OTHER;
- }
- }
- sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
- }
- break;
- /* more to come */
- default:
- sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_UNKNOWN;
- printk(KERN_ERR "sisfb: Unknown command 0x%x\n",
- sisfb_command->sisfb_cmd);
- }
- }
- #ifndef MODULE
- static int __init sisfb_setup(char *options)
- {
- char *this_opt;
- sisfb_setdefaultparms();
- if(!options || !(*options))
- return 0;
- while((this_opt = strsep(&options, ",")) != NULL) {
- if(!(*this_opt)) continue;
- if(!strnicmp(this_opt, "off", 3)) {
- sisfb_off = 1;
- } else if(!strnicmp(this_opt, "forcecrt2type:", 14)) {
- /* Need to check crt2 type first for fstn/dstn */
- sisfb_search_crt2type(this_opt + 14);
- } else if(!strnicmp(this_opt, "tvmode:",7)) {
- sisfb_search_tvstd(this_opt + 7);
- } else if(!strnicmp(this_opt, "tvstandard:",11)) {
- sisfb_search_tvstd(this_opt + 11);
- } else if(!strnicmp(this_opt, "mode:", 5)) {
- sisfb_search_mode(this_opt + 5, false);
- } else if(!strnicmp(this_opt, "vesa:", 5)) {
- sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), false);
- } else if(!strnicmp(this_opt, "rate:", 5)) {
- sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
- } else if(!strnicmp(this_opt, "forcecrt1:", 10)) {
- sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
- } else if(!strnicmp(this_opt, "mem:",4)) {
- sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
- } else if(!strnicmp(this_opt, "pdc:", 4)) {
- sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
- } else if(!strnicmp(this_opt, "pdc1:", 5)) {
- sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
- } else if(!strnicmp(this_opt, "noaccel", 7)) {
- sisfb_accel = 0;
- } else if(!strnicmp(this_opt, "accel", 5)) {
- sisfb_accel = -1;
- } else if(!strnicmp(this_opt, "noypan", 6)) {
- sisfb_ypan = 0;
- } else if(!strnicmp(this_opt, "ypan", 4)) {
- sisfb_ypan = -1;
- } else if(!strnicmp(this_opt, "nomax", 5)) {
- sisfb_max = 0;
- } else if(!strnicmp(this_opt, "max", 3)) {
- sisfb_max = -1;
- } else if(!strnicmp(this_opt, "userom:", 7)) {
- sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
- } else if(!strnicmp(this_opt, "useoem:", 7)) {
- sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
- } else if(!strnicmp(this_opt, "nocrt2rate", 10)) {
- sisfb_nocrt2rate = 1;
- } else if(!strnicmp(this_opt, "scalelcd:", 9)) {
- unsigned long temp = 2;
- temp = simple_strtoul(this_opt + 9, NULL, 0);
- if((temp == 0) || (temp == 1)) {
- sisfb_scalelcd = temp ^ 1;
- }
- } else if(!strnicmp(this_opt, "tvxposoffset:", 13)) {
- int temp = 0;
- temp = (int)simple_strtol(this_opt + 13, NULL, 0);
- if((temp >= -32) && (temp <= 32)) {
- sisfb_tvxposoffset = temp;
- }
- } else if(!strnicmp(this_opt, "tvyposoffset:", 13)) {
- int temp = 0;
- temp = (int)simple_strtol(this_opt + 13, NULL, 0);
- if((temp >= -32) && (temp <= 32)) {
- sisfb_tvyposoffset = temp;
- }
- } else if(!strnicmp(this_opt, "specialtiming:", 14)) {
- sisfb_search_specialtiming(this_opt + 14);
- } else if(!strnicmp(this_opt, "lvdshl:", 7)) {
- int temp = 4;
- temp = simple_strtoul(this_opt + 7, NULL, 0);
- if((temp >= 0) && (temp <= 3)) {
- sisfb_lvdshl = temp;
- }
- } else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
- sisfb_search_mode(this_opt, true);
- #if !defined(__i386__) && !defined(__x86_64__)
- } else if(!strnicmp(this_opt, "resetcard", 9)) {
- sisfb_resetcard = 1;
- } else if(!strnicmp(this_opt, "videoram:", 9)) {
- sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
- #endif
- } else {
- printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt);
- }
- }
- return 0;
- }
- #endif
- static int __devinit
- sisfb_check_rom(void __iomem *rom_base, struct sis_video_info *ivideo)
- {
- void __iomem *rom;
- int romptr;
- if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa))
- return 0;
- romptr = (readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
- if(romptr > (0x10000 - 8))
- return 0;
- rom = rom_base + romptr;
- if((readb(rom) != 'P') || (readb(rom + 1) != 'C') ||
- (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R'))
- return 0;
- if((readb(rom + 4) | (readb(rom + 5) << 8)) != ivideo->chip_vendor)
- return 0;
- if((readb(rom + 6) | (readb(rom + 7) << 8)) != ivideo->chip_id)
- return 0;
- return 1;
- }
- static unsigned char * __devinit
- sisfb_find_rom(struct pci_dev *pdev)
- {
- struct sis_video_info *ivideo = pci_get_drvdata(pdev);
- void __iomem *rom_base;
- unsigned char *myrombase = NULL;
- size_t romsize;
- /* First, try the official pci ROM functions (except
- * on integrated chipsets which have no ROM).
- */
- if(!ivideo->nbridge) {
- if((rom_base = pci_map_rom(pdev, &romsize))) {
- if(sisfb_check_rom(rom_base, ivideo)) {
- if((myrombase = vmalloc(65536))) {
- memcpy_fromio(myrombase, rom_base,
- (romsize > 65536) ? 65536 : romsize);
- }
- }
- pci_unmap_rom(pdev, rom_base);
- }
- }
- if(myrombase) return myrombase;
- /* Otherwise do it the conventional way. */
- #if defined(__i386__) || defined(__x86_64__)
- {
- u32 temp;
- for (temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
- rom_base = ioremap(temp, 65536);
- if (!rom_base)
- continue;
- if (!sisfb_check_rom(rom_base, ivideo)) {
- iounmap(rom_base);
- continue;
- }
- if ((myrombase = vmalloc(65536)))
- memcpy_fromio(myrombase, rom_base, 65536);
- iounmap(rom_base);
- break;
- }
- }
- #endif
- return myrombase;
- }
- static void __devinit
- sisfb_post_map_vram(struct sis_video_info *ivideo, unsigned int *mapsize,
- unsigned int min)
- {
- if (*mapsize < (min << 20))
- return;
- ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize));
- if(!ivideo->video_vbase) {
- printk(KERN_ERR
- "sisfb: Unable to map maximum video RAM for size detection\n");
- (*mapsize) >>= 1;
- while((!(ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize))))) {
- (*mapsize) >>= 1;
- if((*mapsize) < (min << 20))
- break;
- }
- if(ivideo->video_vbase) {
- printk(KERN_ERR
- "sisfb: Video RAM size detection limited to %dMB\n",
- (int)((*mapsize) >> 20));
- }
- }
- }
- #ifdef CONFIG_FB_SIS_300
- static int __devinit
- sisfb_post_300_buswidth(struct sis_video_info *ivideo)
- {
- void __iomem *FBAddress = ivideo->video_vbase;
- unsigned short temp;
- unsigned char reg;
- int i, j;
- SiS_SetRegAND(SISSR, 0x15, 0xFB);
- SiS_SetRegOR(SISSR, 0x15, 0x04);
- SiS_SetReg(SISSR, 0x13, 0x00);
- SiS_SetReg(SISSR, 0x14, 0xBF);
- for(i = 0; i < 2; i++) {
- temp = 0x1234;
- for(j = 0; j < 4; j++) {
- writew(temp, FBAddress);
- if(readw(FBAddress) == temp)
- break;
- SiS_SetRegOR(SISSR, 0x3c, 0x01);
- reg = SiS_GetReg(SISSR, 0x05);
- reg = SiS_GetReg(SISSR, 0x05);
- SiS_SetRegAND(SISSR, 0x3c, 0xfe);
- reg = SiS_GetReg(SISSR, 0x05);
- reg = SiS_GetReg(SISSR, 0x05);
- temp++;
- }
- }
- writel(0x01234567L, FBAddress);
- writel(0x456789ABL, (FBAddress + 4));
- writel(0x89ABCDEFL, (FBAddress + 8));
- writel(0xCDEF0123L, (FBAddress + 12));
- reg = SiS_GetReg(SISSR, 0x3b);
- if(reg & 0x01) {
- if(readl((FBAddress + 12)) == 0xCDEF0123L)
- return 4; /* Channel A 128bit */
- }
- if(readl((FBAddress + 4)) == 0x456789ABL)
- return 2; /* Channel B 64bit */
- return 1; /* 32bit */
- }
- static int __devinit
- sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration, int buswidth,
- int PseudoRankCapacity, int PseudoAdrPinCount,
- unsigned int mapsize)
- {
- void __iomem *FBAddr = ivideo->video_vbase;
- unsigned short sr14;
- unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid;
- unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage;
- static const unsigned short SiS_DRAMType[17][5] = {
- {0x0C,0x0A,0x02,0x40,0x39},
- {0x0D,0x0A,0x01,0x40,0x48},
- {0x0C,0x09,0x02,0x20,0x35},
- {0x0D,0x09,0x01,0x20,0x44},
- {0x0C,0x08,0x02,0x10,0x31},
- {0x0D,0x08,0x01,0x10,0x40},
- {0x0C,0x0A,0x01,0x20,0x34},
- {0x0C,0x09,0x01,0x08,0x32},
- {0x0B,0x08,0x02,0x08,0x21},
- {0x0C,0x08,0x01,0x08,0x30},
- {0x0A,0x08,0x02,0x04,0x11},
- {0x0B,0x0A,0x01,0x10,0x28},
- {0x09,0x08,0x02,0x02,0x01},
- {0x0B,0x09,0x01,0x08,0x24},
- {0x0B,0x08,0x01,0x04,0x20},
- {0x0A,0x08,0x01,0x02,0x10},
- {0x09,0x08,0x01,0x01,0x00}
- };
- for(k = 0; k <= 16; k++) {
- RankCapacity = buswidth * SiS_DRAMType[k][3];
- if(RankCapacity != PseudoRankCapacity)
- continue;
- if((SiS_DRAMType[k][2] + SiS_DRAMType[k][0]) > PseudoAdrPinCount)
- continue;
- BankNumHigh = RankCapacity * 16 * iteration - 1;
- if(iteration == 3) { /* Rank No */
- BankNumMid = RankCapacity * 16 - 1;
- } else {
- BankNumMid = RankCapacity * 16 * iteration / 2 - 1;
- }
- PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
- PhysicalAdrHigh = BankNumHigh;
- PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
- PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
- SiS_SetRegAND(SISSR, 0x15, 0xFB); /* Test */
- SiS_SetRegOR(SISSR, 0x15, 0x04); /* Test */
- sr14 = (SiS_DRAMType[k][3] * buswidth) - 1;
- if(buswidth == 4) sr14 |= 0x80;
- else if(buswidth == 2) sr14 |= 0x40;
- SiS_SetReg(SISSR, 0x13, SiS_DRAMType[k][4]);
- SiS_SetReg(SISSR, 0x14, sr14);
- BankNumHigh <<= 16;
- BankNumMid <<= 16;
- if((BankNumHigh + PhysicalAdrHigh >= mapsize) ||
- (BankNumMid + PhysicalAdrHigh >= mapsize) ||
- (BankNumHigh + PhysicalAdrHalfPage >= mapsize) ||
- (BankNumHigh + PhysicalAdrOtherPage >= mapsize))
- continue;
- /* Write data */
- writew(((unsigned short)PhysicalAdrHigh),
- (FBAddr + BankNumHigh + PhysicalAdrHigh));
- writew(((unsigned short)BankNumMid),
- (FBAddr + BankNumMid + PhysicalAdrHigh));
- writew(((unsigned short)PhysicalAdrHalfPage),
- (FBAddr + BankNumHigh + PhysicalAdrHalfPage));
- writew(((unsigned short)PhysicalAdrOtherPage),
- (FBAddr + BankNumHigh + PhysicalAdrOtherPage));
- /* Read data */
- if(readw(FBAddr + BankNumHigh + PhysicalAdrHigh) == PhysicalAdrHigh)
- return 1;
- }
- return 0;
- }
- static void __devinit
- sisfb_post_300_ramsize(struct pci_dev *pdev, unsigned int mapsize)
- {
- struct sis_video_info *ivideo = pci_get_drvdata(pdev);
- int i, j, buswidth;
- int PseudoRankCapacity, PseudoAdrPinCount;
- buswidth = sisfb_post_300_buswidth(ivideo);
- for(i = 6; i >= 0; i--) {
- PseudoRankCapacity = 1 << i;
- for(j = 4; j >= 1; j--) {
- PseudoAdrPinCount = 15 - j;
- if((PseudoRankCapacity * j) <= 64) {
- if(sisfb_post_300_rwtest(ivideo,
- j,
- buswidth,
- PseudoRankCapacity,
- PseudoAdrPinCount,
- mapsize))
- return;
- }
- }
- }
- }
- static void __devinit
- sisfb_post_sis300(struct pci_dev *pdev)
- {
- struct sis_video_info *ivideo = pci_get_drvdata(pdev);
- unsigned char *bios = ivideo->SiS_Pr.VirtualRomBase;
- u8 reg, v1, v2, v3, v4, v5, v6, v7, v8;
- u16 index, rindex, memtype = 0;
- unsigned int mapsize;
- if(!ivideo->SiS_Pr.UseROM)
- bios = NULL;
- SiS_SetReg(SISSR, 0x05, 0x86);
- if(bios) {
- if(bios[0x52] & 0x80) {
- memtype = bios[0x52];
- } else {
- memtype = SiS_GetReg(SISSR, 0x3a);
- }
- memtype &= 0x07;
- }
- v3 = 0x80; v6 = 0x80;
- if(ivideo->revision_id <= 0x13) {
- v1 = 0x44; v2 = 0x42;
- v4 = 0x44; v5 = 0x42;
- } else {
- v1 = 0x68; v2 = 0x43; /* Assume 125Mhz MCLK */
- v4 = 0x68; v5 = 0x43; /* Assume 125Mhz ECLK */
- if(bios) {
- index = memtype * 5;
- rindex = index + 0x54;
- v1 = bios[rindex++];
- v2 = bios[rindex++];
- v3 = bios[rindex++];
- rindex = index + 0x7c;
- v4 = bios[rindex++];
- v5 = bios[rindex++];
- v6 = bios[rindex++];
- }
- }
- SiS_SetReg(SISSR, 0x28, v1);
- SiS_SetReg(SISSR, 0x29, v2);
- SiS_SetReg(SISSR, 0x2a, v3);
- SiS_SetReg(SISSR, 0x2e, v4);
- SiS_SetReg(SISSR, 0x2f, v5);
- SiS_SetReg(SISSR, 0x30, v6);
- v1 = 0x10;
- if(bios)
- v1 = bios[0xa4];
- SiS_SetReg(SISSR, 0x07, v1); /* DAC speed */
- SiS_SetReg(SISSR, 0x11, 0x0f); /* DDC, power save */
- v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
- v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
- if(bios) {
- memtype += 0xa5;
- v1 = bios[memtype];
- v2 = bios[memtype + 8];
- v3 = bios[memtype + 16];
- v4 = bios[memtype + 24];
- v5 = bios[memtype + 32];
- v6 = bios[memtype + 40];
- v7 = bios[memtype + 48];
- v8 = bios[memtype + 56];
- }
- if(ivideo->revision_id >= 0x80)
- v3 &= 0xfd;
- SiS_SetReg(SISSR, 0x15, v1); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
- SiS_SetReg(SISSR, 0x16, v2);
- SiS_SetReg(SISSR, 0x17, v3);
- SiS_SetReg(SISSR, 0x18, v4);
- SiS_SetReg(SISSR, 0x19, v5);
- SiS_SetReg(SISSR, 0x1a, v6);
- SiS_SetReg(SISSR, 0x1b, v7);
- SiS_SetReg(SISSR, 0x1c, v8); /* ---- */
- SiS_SetRegAND(SISSR, 0x15, 0xfb);
- SiS_SetRegOR(SISSR, 0x15, 0x04);
- if(bios) {
- if(bios[0x53] & 0x02) {
- SiS_SetRegOR(SISSR, 0x19, 0x20);
- }
- }
- v1 = 0x04; /* DAC pedestal (BIOS 0xe5) */
- if(ivideo->revision_id >= 0x80)
- v1 |= 0x01;
- SiS_SetReg(SISSR, 0x1f, v1);
- SiS_SetReg(SISSR, 0x20, 0xa4); /* linear & relocated io & disable a0000 */
- v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
- if(bios) {
- v1 = bios[0xe8];
- v2 = bios[0xe9];
- v3 = bios[0xea];
- }
- SiS_SetReg(SISSR, 0x23, v1);
- SiS_SetReg(SISSR, 0x24, v2);
- SiS_SetReg(SISSR, 0x25, v3);
- SiS_SetReg(SISSR, 0x21, 0x84);
- SiS_SetReg(SISSR, 0x22, 0x00);
- SiS_SetReg(SISCR, 0x37, 0x00);
- SiS_SetRegOR(SISPART1, 0x24, 0x01); /* unlock crt2 */
- SiS_SetReg(SISPART1, 0x00, 0x00);
- v1 = 0x40; v2 = 0x11;
- if(bios) {
- v1 = bios[0xec];
- v2 = bios[0xeb];
- }
- SiS_SetReg(SISPART1, 0x02, v1);
- if(ivideo->revision_id >= 0x80)
- v2 &= ~0x01;
- reg = SiS_GetReg(SISPART4, 0x00);
- if((reg == 1) || (reg == 2)) {
- SiS_SetReg(SISCR, 0x37, 0x02);
- SiS_SetReg(SISPART2, 0x00, 0x1c);
- v4 = 0x00; v5 = 0x00; v6 = 0x10;
- if(ivideo->SiS_Pr.UseROM) {
- v4 = bios[0xf5];
- v5 = bios[0xf6];
- v6 = bios[0xf7];
- }
- SiS_SetReg(SISPART4, 0x0d, v4);
- SiS_SetReg(SISPART4, 0x0e, v5);
- SiS_SetReg(SISPART4, 0x10, v6);
- SiS_SetReg(SISPART4, 0x0f, 0x3f);
- reg = SiS_GetReg(SISPART4, 0x01);
- if(reg >= 0xb0) {
- reg = SiS_GetReg(SISPART4, 0x23);
- reg &= 0x20;
- reg <<= 1;
- SiS_SetReg(SISPART4, 0x23, reg);
- }
- } else {
- v2 &= ~0x10;
- }
- SiS_SetReg(SISSR, 0x32, v2);
- SiS_SetRegAND(SISPART1, 0x24, 0xfe); /* Lock CRT2 */
- reg = SiS_GetReg(SISSR, 0x16);
- reg &= 0xc3;
- SiS_SetReg(SISCR, 0x35, reg);
- SiS_SetReg(SISCR, 0x83, 0x00);
- #if !defined(__i386__) && !defined(__x86_64__)
- if(sisfb_videoram) {
- SiS_SetReg(SISSR, 0x13, 0x28); /* ? */
- reg = ((sisfb_videoram >> 10) - 1) | 0x40;
- SiS_SetReg(SISSR, 0x14, reg);
- } else {
- #endif
- /* Need to map max FB size for finding out about RAM size */
- mapsize = ivideo->video_size;
- sisfb_post_map_vram(ivideo, &mapsize, 4);
- if(ivideo->video_vbase) {
- sisfb_post_300_ramsize(pdev, mapsize);
- iounmap(ivideo->video_vbase);
- } else {
- printk(KERN_DEBUG
- "sisfb: Failed to map memory for size detection, assuming 8MB\n");
- SiS_SetReg(SISSR, 0x13, 0x28); /* ? */
- SiS_SetReg(SISSR, 0x14, 0x47); /* 8MB, 64bit default */
- }
- #if !defined(__i386__) && !defined(__x86_64__)
- }
- #endif
- if(bios) {
- v1 = bios[0xe6];
- v2 = bios[0xe7];
- } else {
- reg = SiS_GetReg(SISSR, 0x3a);
- if((reg & 0x30) == 0x30) {
- v1 = 0x04; /* PCI */
- v2 = 0x92;
- } else {
- v1 = 0x14; /* AGP */
- v2 = 0xb2;
- }
- }
- SiS_SetReg(SISSR, 0x21, v1);
- SiS_SetReg(SISSR, 0x22, v2);
- /* Sense CRT1 */
- sisfb_sense_crt1(ivideo);
- /* Set default mode, don't clear screen */
- ivideo->SiS_Pr.SiS_UseOEM = false;
- SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
- SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
- ivideo->curFSTN = ivideo->curDSTN = 0;
- ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
- SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
- SiS_SetReg(SISSR, 0x05, 0x86);
- /* Display off */
- SiS_SetRegOR(SISSR, 0x01, 0x20);
- /* Save mode number in CR34 */
- SiS_SetReg(SISCR, 0x34, 0x2e);
- /* Let everyone know what the current mode is */
- ivideo->modeprechange = 0x2e;
- }
- #endif
- #ifdef CONFIG_FB_SIS_315
- #if 0
- static void __devinit
- sisfb_post_sis315330(struct pci_dev *pdev)
- {
- /* TODO */
- }
- #endif
- static inline int sisfb_xgi_is21(struct sis_video_info *ivideo)
- {
- return ivideo->chip_real_id == XGI_21;
- }
- static void __devinit
- sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay)
- {
- unsigned int i;
- u8 reg;
- for(i = 0; i <= (delay * 10 * 36); i++) {
- reg = SiS_GetReg(SISSR, 0x05);
- reg++;
- }
- }
- static int __devinit
- sisfb_find_host_bridge(struct sis_video_info *ivideo, struct pci_dev *mypdev,
- unsigned short pcivendor)
- {
- struct pci_dev *pdev = NULL;
- unsigned short temp;
- int ret = 0;
- while((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST, pdev))) {
- temp = pdev->vendor;
- if(temp == pcivendor) {
- ret = 1;
- pci_dev_put(pdev);
- break;
- }
- }
- return ret;
- }
- static int __devinit
- sisfb_post_xgi_rwtest(struct sis_video_info *ivideo, int starta,
- unsigned int enda, unsigned int mapsize)
- {
- unsigned int pos;
- int i;
- writel(0, ivideo->video_vbase);
- for(i = starta; i <= enda; i++) {
- pos = 1 << i;
- if(pos < mapsize)
- writel(pos, ivideo->video_vbase + pos);
- }
- sisfb_post_xgi_delay(ivideo, 150);
- if(readl(ivideo->video_vbase) != 0)
- return 0;
- for(i = starta; i <= enda; i++) {
- pos = 1 << i;
- if(pos < mapsize) {
- if(readl(ivideo->video_vbase + pos) != pos)
- return 0;
- } else
- return 0;
- }
- return 1;
- }
- static int __devinit
- sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
- {
- unsigned int buswidth, ranksize, channelab, mapsize;
- int i, j, k, l, status;
- u8 reg, sr14;
- static const u8 dramsr13[12 * 5] = {
- 0x02, 0x0e, 0x0b, 0x80, 0x5d,
- 0x02, 0x0e, 0x0a, 0x40, 0x59,
- 0x02, 0x0d, 0x0b, 0x40, 0x4d,
- 0x02, 0x0e, 0x09, 0x20, 0x55,
- 0x02, 0x0d, 0x0a, 0x20, 0x49,
- 0x02, 0x0c, 0x0b, 0x20, 0x3d,
- 0x02, 0x0e, 0x08, 0x10, 0x51,
- 0x02, 0x0d, 0x09, 0x10, 0x45,
- 0x02, 0x0c, 0x0a, 0x10, 0x39,
- 0x02, 0x0d, 0x08, 0x08, 0x41,
- 0x02, 0x0c, 0x09, 0x08, 0x35,
- 0x02, 0x0c, 0x08, 0x04, 0x31
- };
- static const u8 dramsr13_4[4 * 5] = {
- 0x02, 0x0d, 0x09, 0x40, 0x45,
- 0x02, 0x0c, 0x09, 0x20, 0x35,
- 0x02, 0x0c, 0x08, 0x10, 0x31,
- 0x02, 0x0b, 0x08, 0x08, 0x21
- };
- /* Enable linear mode, disable 0xa0000 address decoding */
- /* We disable a0000 address decoding, because
- * - if running on x86, if the card is disabled, it means
- * that another card is in the system. We don't want
- * to interphere with that primary card's textmode.
- * - if running on non-x86, there usually is no VGA window
- * at a0000.
- */
- SiS_SetRegOR(SISSR, 0x20, (0x80 | 0x04));
- /* Need to map max FB size for finding out about RAM size */
- mapsize = ivideo->video_size;
- sisfb_post_map_vram(ivideo, &mapsize, 32);
- if(!ivideo->video_vbase) {
- printk(KERN_ERR "sisfb: Unable to detect RAM size. Setting default.\n");
- SiS_SetReg(SISSR, 0x13, 0x35);
- SiS_SetReg(SISSR, 0x14, 0x41);
- /* TODO */
- return -ENOMEM;
- }
- /* Non-interleaving */
- SiS_SetReg(SISSR, 0x15, 0x00);
- /* No tiling */
- SiS_SetReg(SISSR, 0x1c, 0x00);
- if(ivideo->chip == XGI_20) {
- channelab = 1;
- reg = SiS_GetReg(SISCR, 0x97);
- if(!(reg & 0x01)) { /* Single 32/16 */
- buswidth = 32;
- SiS_SetReg(SISSR, 0x13, 0xb1);
- SiS_SetReg(SISSR, 0x14, 0x52);
- sisfb_post_xgi_delay(ivideo, 1);
- sr14 = 0x02;
- if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
- goto bail_out;
- SiS_SetReg(SISSR, 0x13, 0x31);
- SiS_SetReg(SISSR, 0x14, 0x42);
- sisfb_post_xgi_delay(ivideo, 1);
- if(sisfb_post_xgi_rwtest(ivideo, 23, 23, mapsize))
- goto bail_out;
- buswidth = 16;
- SiS_SetReg(SISSR, 0x13, 0xb1);
- SiS_SetReg(SISSR, 0x14, 0x41);
- sisfb_post_xgi_delay(ivideo, 1);
- sr14 = 0x01;
- if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
- goto bail_out;
- else
- SiS_SetReg(SISSR, 0x13, 0x31);
- } else { /* Dual 16/8 */
- buswidth = 16;
- SiS_SetReg(SISSR, 0x13, 0xb1);
- SiS_SetReg(SISSR, 0x14, 0x41);
- sisfb_post_xgi_delay(ivideo, 1);
- sr14 = 0x01;
- if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
- goto bail_out;
- SiS_SetReg(SISSR, 0x13, 0x31);
- SiS_SetReg(SISSR, 0x14, 0x31);
- sisfb_post_xgi_delay(ivideo, 1);
- if(sisfb_post_xgi_rwtest(ivideo, 22, 22, mapsize))
- goto bail_out;
- buswidth = 8;
- SiS_SetReg(SISSR, 0x13, 0xb1);
- SiS_SetReg(SISSR, 0x14, 0x30);
- sisfb_post_xgi_delay(ivideo, 1);
- sr14 = 0x00;
- if(sisfb_post_xgi_rwtest(ivideo, 21, 22, mapsize))
- goto bail_out;
- else
- SiS_SetReg(SISSR, 0x13, 0x31);
- }
- } else { /* XGI_40 */
- reg = SiS_GetReg(SISCR, 0x97);
- if(!(reg & 0x10)) {
- reg = SiS_GetReg(SISSR, 0x39);
- reg >>= 1;
- }
- if(reg & 0x01) { /* DDRII */
- buswidth = 32;
- if(ivideo->revision_id == 2) {
- channelab = 2;
- SiS_SetReg(SISSR, 0x13, 0xa1);
- SiS_SetReg(SISSR, 0x14, 0x44);
- sr14 = 0x04;
- sisfb_post_xgi_delay(ivideo, 1);
- if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
- goto bail_out;
- SiS_SetReg(SISSR, 0x13, 0x21);
- SiS_SetReg(SISSR, 0x14, 0x34);
- if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
- goto bail_out;
- channelab = 1;
- SiS_SetReg(SISSR, 0x13, 0xa1);
- SiS_SetReg(SISSR, 0x14, 0x40);
- sr14 = 0x00;
- if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
- goto bail_out;
- SiS_SetReg(SISSR, 0x13, 0x21);
- SiS_SetReg(SISSR, 0x14, 0x30);
- } else {
- channelab = 3;
- SiS_SetReg(SISSR, 0x13, 0xa1);
- SiS_SetReg(SISSR, 0x14, 0x4c);
- sr14 = 0x0c;
- sisfb_post_xgi_delay(ivideo, 1);
- if(sisfb_post_xgi_rwtest(ivideo, 23, 25, mapsize))
- goto bail_out;
- channelab = 2;
- SiS_SetReg(SISSR, 0x14, 0x48);
- sisfb_post_xgi_delay(ivideo, 1);
- sr14 = 0x08;
- if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
- goto bail_out;
- SiS_SetReg(SISSR, 0x13, 0x21);
- SiS_SetReg(SISSR, 0x14, 0x3c);
- sr14 = 0x0c;
- if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) {
- channelab = 3;
- } else {
- channelab = 2;
- SiS_SetReg(SISSR, 0x14, 0x38);
- sr14 = 0x08;
- }
- }
- sisfb_post_xgi_delay(ivideo, 1);
- } else { /* DDR */
- buswidth = 64;
- if(ivideo->revision_id == 2) {
- channelab = 1;
- SiS_SetReg(SISSR, 0x13, 0xa1);
- SiS_SetReg(SISSR, 0x14, 0x52);
- sisfb_post_xgi_delay(ivideo, 1);
- sr14 = 0x02;
- if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
- goto bail_out;
- SiS_SetReg(SISSR, 0x13, 0x21);
- SiS_SetReg(SISSR, 0x14, 0x42);
- } else {
- channelab = 2;
- SiS_SetReg(SISSR, 0x13, 0xa1);
- SiS_SetReg(SISSR, 0x14, 0x5a);
- sisfb_post_xgi_delay(ivideo, 1);
- sr14 = 0x0a;
- if(sisfb_post_xgi_rwtest(ivideo, 24, 25, mapsize))
- goto bail_out;
- SiS_SetReg(SISSR, 0x13, 0x21);
- SiS_SetReg(SISSR, 0x14, 0x4a);
- }
- sisfb_post_xgi_delay(ivideo, 1);
- }
- }
- bail_out:
- SiS_SetRegANDOR(SISSR, 0x14, 0xf0, sr14);
- sisfb_post_xgi_delay(ivideo, 1);
- j = (ivideo->chip == XGI_20) ? 5 : 9;
- k = (ivideo->chip == XGI_20) ? 12 : 4;
- status = -EIO;
- for(i = 0; i < k; i++) {
- reg = (ivideo->chip == XGI_20) ?
- dramsr13[(i * 5) + 4] : dramsr13_4[(i * 5) + 4];
- SiS_SetRegANDOR(SISSR, 0x13, 0x80, reg);
- sisfb_post_xgi_delay(ivideo, 50);
- ranksize = (ivideo->chip == XGI_20) ?
- dramsr13[(i * 5) + 3] : dramsr13_4[(i * 5) + 3];
- reg = SiS_GetReg(SISSR, 0x13);
- if(reg & 0x80) ranksize <<= 1;
- if(ivideo->chip == XGI_20) {
- if(buswidth == 16) ranksize <<= 1;
- else if(buswidth == 32) ranksize <<= 2;
- } else {
- if(buswidth == 64) ranksize <<= 1;
- }
- reg = 0;
- l = channelab;
- if(l == 3) l = 4;
- if((ranksize * l) <= 256) {
- while((ranksize >>= 1)) reg += 0x10;
- }
- if(!reg) continue;
- SiS_SetRegANDOR(SISSR, 0x14, 0x0f, (reg & 0xf0));
- sisfb_post_xgi_delay(ivideo, 1);
- if (sisfb_post_xgi_rwtest(ivideo, j, ((reg >> 4) + channelab - 2 + 20), mapsize)) {
- status = 0;
- break;
- }
- }
- iounmap(ivideo->video_vbase);
- return status;
- }
- static void __devinit
- sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb)
- {
- u8 v1, v2, v3;
- int index;
- static const u8 cs90[8 * 3] = {
- 0x16, 0x01, 0x01,
- 0x3e, 0x03, 0x01,
- 0x7c, 0x08, 0x01,
- 0x79, 0x06, 0x01,
- 0x29, 0x01, 0x81,
- 0x5c, 0x23, 0x01,
- 0x5c, 0x23, 0x01,
- 0x5c, 0x23, 0x01
- };
- static const u8 csb8[8 * 3] = {
- 0x5c, 0x23, 0x01,
- 0x29, 0x01, 0x01,
- 0x7c, 0x08, 0x01,
- 0x79, 0x06, 0x01,
- 0x29, 0x01, 0x81,
- 0x5c, 0x23, 0x01,
- 0x5c, 0x23, 0x01,
- 0x5c, 0x23, 0x01
- };
- regb = 0; /* ! */
- index = regb * 3;
- v1 = cs90[index]; v2 = cs90[index + 1]; v3 = cs90[index + 2];
- if(ivideo->haveXGIROM) {
- v1 = ivideo->bios_abase[0x90 + index];
- v2 = ivideo->bios_abase[0x90 + index + 1];
- v3 = ivideo->bios_abase[0x90 + index + 2];
- }
- SiS_SetReg(SISSR, 0x28, v1);
- SiS_SetReg(SISSR, 0x29, v2);
- SiS_SetReg(SISSR, 0x2a, v3);
- sisfb_post_xgi_delay(ivideo, 0x43);
- sisfb_post_xgi_delay(ivideo, 0x43);
- sisfb_post_xgi_delay(ivideo, 0x43);
- index = regb * 3;
- v1 = csb8[index]; v2 = csb8[index + 1]; v3 = csb8[index + 2];
- if(ivideo->haveXGIROM) {
- v1 = ivideo->bios_abase[0xb8 + index];
- v2 = ivideo->bios_abase[0xb8 + index + 1];
- v3 = ivideo->bios_abase[0xb8 + index + 2];
- }
- SiS_SetReg(SISSR, 0x2e, v1);
- SiS_SetReg(SISSR, 0x2f, v2);
- SiS_SetReg(SISSR, 0x30, v3);
- sisfb_post_xgi_delay(ivideo, 0x43);
- sisfb_post_xgi_delay(ivideo, 0x43);
- sisfb_post_xgi_delay(ivideo, 0x43);
- }
- static void __devinit
- sisfb_post_xgi_ddr2_mrs_default(struct sis_video_info *ivideo, u8 regb)
- {
- unsigned char *bios = ivideo->bios_abase;
- u8 v1;
- SiS_SetReg(SISSR, 0x28, 0x64);
- SiS_SetReg(SISSR, 0x29, 0x63);
- sisfb_post_xgi_delay(ivideo, 15);
- SiS_SetReg(SISSR, 0x18, 0x00);
- SiS_SetReg(SISSR, 0x19, 0x20);
- SiS_SetReg(SISSR, 0x16, 0x00);
- SiS_SetReg(SISSR, 0x16, 0x80);
- SiS_SetReg(SISSR, 0x18, 0xc5);
- SiS_SetReg(SISSR, 0x19, 0x23);
- SiS_SetReg(SISSR, 0x16, 0x00);
- SiS_SetReg(SISSR, 0x16, 0x80);
- sisfb_post_xgi_delay(ivideo, 1);
- SiS_SetReg(SISCR, 0x97, 0x11);
- sisfb_post_xgi_setclocks(ivideo, regb);
- sisfb_post_xgi_delay(ivideo, 0x46);
- SiS_SetReg(SISSR, 0x18, 0xc5);
- SiS_SetReg(SISSR, 0x19, 0x23);
- SiS_SetReg(SISSR, 0x16, 0x00);
- SiS_SetReg(SISSR, 0x16, 0x80);
- sisfb_post_xgi_delay(ivideo, 1);
- SiS_SetReg(SISSR, 0x1b, 0x04);
- sisfb_post_xgi_delay(ivideo, 1);
- SiS_SetReg(SISSR, 0x1b, 0x00);
- sisfb_post_xgi_delay(ivideo, 1);
- v1 = 0x31;
- if (ivideo->haveXGIROM) {
- v1 = bios[0xf0];
- }
- SiS_SetReg(SISSR, 0x18, v1);
- SiS_SetReg(SISSR, 0x19, 0x06);
- SiS_SetReg(SISSR, 0x16, 0x04);
- SiS_SetReg(SISSR, 0x16, 0x84);
- sisfb_post_xgi_delay(ivideo, 1);
- }
- static void __devinit
- sisfb_post_xgi_ddr2_mrs_xg21(struct sis_video_info *ivideo)
- {
- sisfb_post_xgi_setclocks(ivideo, 1);
- SiS_SetReg(SISCR, 0x97, 0x11);
- sisfb_post_xgi_delay(ivideo, 0x46);
- SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS2 */
- SiS_SetReg(SISSR, 0x19, 0x80);
- SiS_SetReg(SISSR, 0x16, 0x05);
- SiS_SetReg(SISSR, 0x16, 0x85);
- SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS3 */
- SiS_SetReg(SISSR, 0x19, 0xc0);
- SiS_SetReg(SISSR, 0x16, 0x05);
- SiS_SetReg(SISSR, 0x16, 0x85);
- SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS1 */
- SiS_SetReg(SISSR, 0x19, 0x40);
- SiS_SetReg(SISSR, 0x16, 0x05);
- SiS_SetReg(SISSR, 0x16, 0x85);
- SiS_SetReg(SISSR, 0x18, 0x42); /* MRS1 */
- SiS_SetReg(SISSR, 0x19, 0x02);
- SiS_SetReg(SISSR, 0x16, 0x05);
- SiS_SetReg(SISSR, 0x16, 0x85);
- sisfb_post_xgi_delay(ivideo, 1);
- SiS_SetReg(SISSR, 0x1b, 0x04);
- sisfb_post_xgi_delay(ivideo, 1);
- SiS_SetReg(SISSR, 0x1b, 0x00);
- sisfb_post_xgi_delay(ivideo, 1);
- SiS_SetReg(SISSR, 0x18, 0x42); /* MRS1 */
- SiS_SetReg(SISSR, 0x19, 0x00);
- SiS_SetReg(SISSR, 0x16, 0x05);
- SiS_SetReg(SISSR, 0x16, 0x85);
- sisfb_post_xgi_delay(ivideo, 1);
- }
- static void __devinit
- sisfb_post_xgi_ddr2(struct sis_video_info *ivideo, u8 regb)
- {
- unsigned char *bios = ivideo->bios_abase;
- static const u8 cs158[8] = {
- 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
- };
- static const u8 cs160[8] = {
- 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
- };
- static const u8 cs168[8] = {
- 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
- };
- u8 reg;
- u8 v1;
- u8 v2;
- u8 v3;
- SiS_SetReg(SISCR, 0xb0, 0x80); /* DDR2 dual frequency mode */
- SiS_SetReg(SISCR, 0x82, 0x77);
- SiS_SetReg(SISCR, 0x86, 0x00);
- reg = SiS_GetReg(SISCR, 0x86);
- SiS_SetReg(SISCR, 0x86, 0x88);
- reg = SiS_GetReg(SISCR, 0x86);
- v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb];
- if (ivideo->haveXGIROM) {
- v1 = bios[regb + 0x168];
- v2 = bios[regb + 0x160];
- v3 = bios[regb + 0x158];
- }
- SiS_SetReg(SISCR, 0x86, v1);
- SiS_SetReg(SISCR, 0x82, 0x77);
- SiS_SetReg(SISCR, 0x85, 0x00);
- reg = SiS_GetReg(SISCR, 0x85);
- SiS_SetReg(SISCR, 0x85, 0x88);
- reg = SiS_GetReg(SISCR, 0x85);
- SiS_SetReg(SISCR, 0x85, v2);
- SiS_SetReg(SISCR, 0x82, v3);
- SiS_SetReg(SISCR, 0x98, 0x01);
- SiS_SetReg(SISCR, 0x9a, 0x02);
- if (sisfb_xgi_is21(ivideo))
- sisfb_post_xgi_ddr2_mrs_xg21(ivideo);
- else
- sisfb_post_xgi_ddr2_mrs_default(ivideo, regb);
- }
- static u8 __devinit
- sisfb_post_xgi_ramtype(struct sis_video_info *ivideo)
- {
- unsigned char *bios = ivideo->bios_abase;
- u8 ramtype;
- u8 reg;
- u8 v1;
- ramtype = 0x00; v1 = 0x10;
- if (ivideo->haveXGIROM) {
- ramtype = bios[0x62];
- v1 = bios[0x1d2];
- }
- if (!(ramtype & 0x80)) {
- if (sisfb_xgi_is21(ivideo)) {
- SiS_SetRegAND(SISCR, 0xb4, 0xfd); /* GPIO control */
- SiS_SetRegOR(SISCR, 0x4a, 0x80); /* GPIOH EN */
- reg = SiS_GetReg(SISCR, 0x48);
- SiS_SetRegOR(SISCR, 0xb4, 0x02);
- ramtype = reg & 0x01; /* GPIOH */
- } else if (ivideo->chip == XGI_20) {
- SiS_SetReg(SISCR, 0x97, v1);
- reg = SiS_GetReg(SISCR, 0x97);
- if (reg & 0x10) {
- ramtype = (reg & 0x01) << 1;
- }
- } else {
- reg = SiS_GetReg(SISSR, 0x39);
- ramtype = reg & 0x02;
- if (!(ramtype)) {
- reg = SiS_GetReg(SISSR, 0x3a);
- ramtype = (reg >> 1) & 0x01;
- }
- }
- }
- ramtype &= 0x07;
- return ramtype;
- }
- static int __devinit
- sisfb_post_xgi(struct pci_dev *pdev)
- {
- struct sis_video_info *ivideo = pci_get_drvdata(pdev);
- unsigned char *bios = ivideo->bios_abase;
- struct pci_dev *mypdev = NULL;
- const u8 *ptr, *ptr2;
- u8 v1, v2, v3, v4, v5, reg, ramtype;
- u32 rega, regb, regd;
- int i, j, k, index;
- static const u8 cs78[3] = { 0xf6, 0x0d, 0x00 };
- static const u8 cs76[2] = { 0xa3, 0xfb };
- static const u8 cs7b[3] = { 0xc0, 0x11, 0x00 };
- static const u8 cs158[8] = {
- 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
- };
- static const u8 cs160[8] = {
- 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
- };
- static const u8 cs168[8] = {
- 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
- };
- static const u8 cs128[3 * 8] = {
- 0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
- };
- static const u8 cs148[2 * 8] = {
- 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
- static const u8 cs31a[8 * 4] = {
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
- static const u8 cs33a[8 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
- static const u8 cs45a[8 * 2] = {
- 0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
- static const u8 cs170[7 * 8] = {
- 0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
- };
- static const u8 cs1a8[3 * 8] = {
- 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
- static const u8 cs100[2 * 8] = {
- 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
- };
- /* VGA enable */
- reg = SiS_GetRegByte(SISVGAENABLE) | 0x01;
- SiS_SetRegByte(SISVGAENABLE, reg);
- /* Misc */
- reg = SiS_GetRegByte(SISMISCR) | 0x01;
- SiS_SetRegByte(SISMISCW, reg);
- /* Unlock SR */
- SiS_SetReg(SISSR, 0x05, 0x86);
- reg = SiS_GetReg(SISSR, 0x05);
- if(reg != 0xa1)
- return 0;
- /* Clear some regs */
- for(i = 0; i < 0x22; i++) {
- if(0x06 + i == 0x20) continue;
- SiS_SetReg(SISSR, 0x06 + i, 0x00);
- }
- for(i = 0; i < 0x0b; i++) {
- SiS_SetReg(SISSR, 0x31 + i, 0x00);
- }
- for(i = 0; i < 0x10; i++) {
- SiS_SetReg(SISCR, 0x30 + i, 0x00);
- }
- ptr = cs78;
- if(ivideo->haveXGIROM) {
- ptr = (const u8 *)&bios[0x78];
- }
- for(i = 0; i < 3; i++) {
- SiS_SetReg(SISSR, 0x23 + i, ptr[i]);
- }
- ptr = cs76;
- if(ivideo->haveXGIROM) {
- ptr = (const u8 *)&bios[0x76];
- }
- for(i = 0; i < 2; i++) {
- SiS_SetReg(SISSR, 0x21 + i, ptr[i]);
- }
- v1 = 0x18; v2 = 0x00;
- if(ivideo->haveXGIROM) {
- v1 = bios[0x74];
- v2 = bios[0x75];
- }
- SiS_SetReg(SISSR, 0x07, v1);
- SiS_SetReg(SISSR, 0x11, 0x0f);
- SiS_SetReg(SISSR, 0x1f, v2);
- /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
- SiS_SetReg(SISSR, 0x20, 0x80 | 0x20 | 0x04);
- SiS_SetReg(SISSR, 0x27, 0x74);
- ptr = cs7b;
- if(ivideo->haveXGIROM) {
- ptr = (const u8 *)&bios[0x7b];
- }
- for(i = 0; i < 3; i++) {
- SiS_SetReg(SISSR, 0x31 + i, ptr[i]);
- }
- if(ivideo->chip == XGI_40) {
- if(ivideo->revision_id == 2) {
- SiS_SetRegANDOR(SISSR, 0x3b, 0x3f, 0xc0);
- }
- SiS_SetReg(SISCR, 0x7d, 0xfe);
- SiS_SetReg(SISCR, 0x7e, 0x0f);
- }
- if(ivideo->revision_id == 0) { /* 40 *and* 20? */
- SiS_SetRegAND(SISCR, 0x58, 0xd7);
- reg = SiS_GetReg(SISCR, 0xcb);
- if(reg & 0x20) {
- SiS_SetRegANDOR(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
- }
- }
- reg = (ivideo->chip == XGI_40) ? 0x20 : 0x00;
- SiS_SetRegANDOR(SISCR, 0x38, 0x1f, reg);
- if(ivideo->chip == XGI_20) {
- SiS_SetReg(SISSR, 0x36, 0x70);
- } else {
- SiS_SetReg(SISVID, 0x00, 0x86);
- SiS_SetReg(SISVID, 0x32, 0x00);
- SiS_SetReg(SISVID, 0x30, 0x00);
- SiS_SetReg(SISVID, 0x32, 0x01);
- SiS_SetReg(SISVID, 0x30, 0x00);
- SiS_SetRegAND(SISVID, 0x2f, 0xdf);
- SiS_SetRegAND(SISCAP, 0x00, 0x3f);
- SiS_SetReg(SISPART1, 0x2f, 0x01);
- SiS_SetReg(SISPART1, 0x00, 0x00);
- SiS_SetReg(SISPART1, 0x02, bios[0x7e]);
- SiS_SetReg(SISPART1, 0x2e, 0x08);
- SiS_SetRegAND(SISPART1, 0x35, 0x7f);
- SiS_SetRegAND(SISPART1, 0x50, 0xfe);
- reg = SiS_GetReg(SISPART4, 0x00);
- if(reg == 1 || reg == 2) {
- SiS_SetReg(SISPART2, 0x00, 0x1c);
- SiS_SetReg(SISPART4, 0x0d, bios[0x7f]);
- SiS_SetReg(SISPART4, 0x0e, bios[0x80]);
- SiS_SetReg(SISPART4, 0x10, bios[0x81]);
- SiS_SetRegAND(SISPART4, 0x0f, 0x3f);
- reg = SiS_GetReg(SISPART4, 0x01);
- if((reg & 0xf0) >= 0xb0) {
- reg = SiS_GetReg(SISPART4, 0x23);
- if(reg & 0x20) reg |= 0x40;
- SiS_SetReg(SISPART4, 0x23, reg);
- reg = (reg & 0x20) ? 0x02 : 0x00;
- SiS_SetRegANDOR(SISPART1, 0x1e, 0xfd, reg);
- }
- }
- v1 = bios[0x77];
- reg = SiS_GetReg(SISSR, 0x3b);
- if(reg & 0x02) {
- reg = SiS_GetReg(SISSR, 0x3a);
- v2 = (reg & 0x30) >> 3;
- if(!(v2 & 0x04)) v2 ^= 0x02;
- reg = SiS_GetReg(SISSR, 0x39);
- if(reg & 0x80) v2 |= 0x80;
- v2 |= 0x01;
- if((mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0730, NULL))) {
- pci_dev_put(mypdev);
- if(((v2 & 0x06) == 2) || ((v2 & 0x06) == 4))
- v2 &= 0xf9;
- v2 |= 0x08;
- v1 &= 0xfe;
- } else {
- mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0735, NULL);
- if(!mypdev)
- mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0645, NULL);
- if(!mypdev)
- mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0650, NULL);
- if(mypdev) {
- pci_read_config_dword(mypdev, 0x94, ®d);
- regd &= 0xfffffeff;
- pci_write_config_dword(mypdev, 0x94, regd);
- v1 &= 0xfe;
- pci_dev_put(mypdev);
- } else if(sisfb_find_host_bridge(ivideo, pdev, PCI_VENDOR_ID_SI)) {
- v1 &= 0xfe;
- } else if(sisfb_find_host_bridge(ivideo, pdev, 0x1106) ||
- sisfb_find_host_bridge(ivideo, pdev, 0x1022) ||
- sisfb_find_host_bridge(ivideo, pdev, 0x700e) ||
- sisfb_find_host_bridge(ivideo, pdev, 0x10de)) {
- if((v2 & 0x06) == 4)
- v2 ^= 0x06;
- v2 |= 0x08;
- }
- }
- SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, v2);
- }
- SiS_SetReg(SISSR, 0x22, v1);
- if(ivideo->revision_id == 2) {
- v1 = SiS_GetReg(SISSR, 0x3b);
- v2 = SiS_GetReg(SISSR, 0x3a);
- regd = bios[0x90 + 3] | (bios[0x90 + 4] << 8);
- if( (!(v1 & 0x02)) && (v2 & 0x30) && (regd < 0xcf) )
- SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
- if((mypdev = pci_get_device(0x10de, 0x01e0, NULL))) {
- /* TODO: set CR5f &0xf1 | 0x01 for version 6570
- * of nforce 2 ROM
- */
- if(0)
- SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
- pci_dev_put(mypdev);
- }
- }
- v1 = 0x30;
- reg = SiS_GetReg(SISSR, 0x3b);
- v2 = SiS_GetReg(SISCR, 0x5f);
- if((!(reg & 0x02)) && (v2 & 0x0e))
- v1 |= 0x08;
- SiS_SetReg(SISSR, 0x27, v1);
- if(bios[0x64] & 0x01) {
- SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, bios[0x64]);
- }
- v1 = bios[0x4f7];
- pci_read_config_dword(pdev, 0x50, ®d);
- regd = (regd >> 20) & 0x0f;
- if(regd == 1) {
- v1 &= 0xfc;
- SiS_SetRegOR(SISCR, 0x5f, 0x08);
- }
- SiS_SetReg(SISCR, 0x48, v1);
- SiS_SetRegANDOR(SISCR, 0x47, 0x04, bios[0x4f6] & 0xfb);
- SiS_SetRegANDOR(SISCR, 0x49, 0xf0, bios[0x4f8] & 0x0f);
- SiS_SetRegANDOR(SISCR, 0x4a, 0x60, bios[0x4f9] & 0x9f);
- SiS_SetRegANDOR(SISCR, 0x4b, 0x08, bios[0x4fa] & 0xf7);
- SiS_SetRegANDOR(SISCR, 0x4c, 0x80, bios[0x4fb] & 0x7f);
- SiS_SetReg(SISCR, 0x70, bios[0x4fc]);
- SiS_SetRegANDOR(SISCR, 0x71, 0xf0, bios[0x4fd] & 0x0f);
- SiS_SetReg(SISCR, 0x74, 0xd0);
- SiS_SetRegANDOR(SISCR, 0x74, 0xcf, bios[0x4fe] & 0x30);
- SiS_SetRegANDOR(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f);
- SiS_SetRegANDOR(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f);
- v1 = bios[0x501];
- if((mypdev = pci_get_device(0x8086, 0x2530, NULL))) {
- v1 = 0xf0;
- pci_dev_put(mypdev);
- }
- SiS_SetReg(SISCR, 0x77, v1);
- }
- /* RAM type:
- *
- * 0 == DDR1, 1 == DDR2, 2..7 == reserved?
- *
- * The code seems to written so that regb should equal ramtype,
- * however, so far it has been hardcoded to 0. Enable other values only
- * on XGI Z9, as it passes the POST, and add a warning for others.
- */
- ramtype = sisfb_post_xgi_ramtype(ivideo);
- if (!sisfb_xgi_is21(ivideo) && ramtype) {
- dev_warn(&pdev->dev,
- "RAM type something else than expected: %d\n",
- ramtype);
- regb = 0;
- } else {
- regb = ramtype;
- }
- v1 = 0xff;
- if(ivideo->haveXGIROM) {
- v1 = bios[0x140 + regb];
- }
- SiS_SetReg(SISCR, 0x6d, v1);
- ptr = cs128;
- if(ivideo->haveXGIROM) {
- ptr = (const u8 *)&bios[0x128];
- }
- for(i = 0, j = 0; i < 3; i++, j += 8) {
- SiS_SetReg(SISCR, 0x68 + i, ptr[j + regb]);
- }
- ptr = cs31a;
- ptr2 = cs33a;
- if(ivideo->haveXGIROM) {
- index = (ivideo->chip == XGI_20) ? 0x31a : 0x3a6;
- ptr = (const u8 *)&bios[index];
- ptr2 = (const u8 *)&bios[index + 0x20];
- }
- for(i = 0; i < 2; i++) {
- if(i == 0) {
- regd = le32_to_cpu(((u32 *)ptr)[regb]);
- rega = 0x6b;
- } else {
- regd = le32_to_cpu(((u32 *)ptr2)[regb]);
- rega = 0x6e;
- }
- reg = 0x00;
- for(j = 0; j < 16; j++) {
- reg &= 0xf3;
- if(regd & 0x01) reg |= 0x04;
- if(regd & 0x02) reg |= 0x08;
- regd >>= 2;
- SiS_SetReg(SISCR, rega, reg);
- reg = SiS_GetReg(SISCR, rega);
- reg = SiS_GetReg(SISCR, rega);
- reg += 0x10;
- }
- }
- SiS_SetRegAND(SISCR, 0x6e, 0xfc);
- ptr = NULL;
- if(ivideo->haveXGIROM) {
- index = (ivideo->chip == XGI_20) ? 0x35a : 0x3e6;
- ptr = (const u8 *)&bios[index];
- }
- for(i = 0; i < 4; i++) {
- SiS_SetRegANDOR(SISCR, 0x6e, 0xfc, i);
- reg = 0x00;
- for(j = 0; j < 2; j++) {
- regd = 0;
- if(ptr) {
- regd = le32_to_cpu(((u32 *)ptr)[regb * 8]);
- ptr += 4;
- }
- /* reg = 0x00; */
- for(k = 0; k < 16; k++) {
- reg &= 0xfc;
- if(regd & 0x01) reg |= 0x01;
- if(regd & 0x02) reg |= 0x02;
- regd >>= 2;
- SiS_SetReg(SISCR, 0x6f, reg);
- reg = SiS_GetReg(SISCR, 0x6f);
- reg = SiS_GetReg(SISCR, 0x6f);
- reg += 0x08;
- }
- }
- }
- ptr = cs148;
- if(ivideo->haveXGIROM) {
- ptr = (const u8 *)&bios[0x148];
- }
- for(i = 0, j = 0; i < 2; i++, j += 8) {
- SiS_SetReg(SISCR, 0x80 + i, ptr[j + regb]);
- }
- SiS_SetRegAND(SISCR, 0x89, 0x8f);
- ptr = cs45a;
- if(ivideo->haveXGIROM) {
- index = (ivideo->chip == XGI_20) ? 0x45a : 0x4e6;
- ptr = (const u8 *)&bios[index];
- }
- regd = le16_to_cpu(((const u16 *)ptr)[regb]);
- reg = 0x80;
- for(i = 0; i < 5; i++) {
- reg &= 0xfc;
- if(regd & 0x01) reg |= 0x01;
- if(regd & 0x02) reg |= 0x02;
- regd >>= 2;
- SiS_SetReg(SISCR, 0x89, reg);
- reg = SiS_GetReg(SISCR, 0x89);
- reg = SiS_GetReg(SISCR, 0x89);
- reg += 0x10;
- }
- v1 = 0xb5; v2 = 0x20; v3 = 0xf0; v4 = 0x13;
- if(ivideo->haveXGIROM) {
- v1 = bios[0x118 + regb];
- v2 = bios[0xf8 + regb];
- v3 = bios[0x120 + regb];
- v4 = bios[0x1ca];
- }
- SiS_SetReg(SISCR, 0x45, v1 & 0x0f);
- SiS_SetReg(SISCR, 0x99, (v1 >> 4) & 0x07);
- SiS_SetRegOR(SISCR, 0x40, v1 & 0x80);
- SiS_SetReg(SISCR, 0x41, v2);
- ptr = cs170;
- if(ivideo->haveXGIROM) {
- ptr = (const u8 *)&bios[0x170];
- }
- for(i = 0, j = 0; i < 7; i++, j += 8) {
- SiS_SetReg(SISCR, 0x90 + i, ptr[j + regb]);
- }
- SiS_SetReg(SISCR, 0x59, v3);
- ptr = cs1a8;
- if(ivideo->haveXGIROM) {
- ptr = (const u8 *)&bios[0x1a8];
- }
- for(i = 0, j = 0; i < 3; i++, j += 8) {
- SiS_SetReg(SISCR, 0xc3 + i, ptr[j + regb]);
- }
- ptr = cs100;
- if(ivideo->haveXGIROM) {
- ptr = (const u8 *)&bios[0x100];
- }
- for(i = 0, j = 0; i < 2; i++, j += 8) {
- SiS_SetReg(SISCR, 0x8a + i, ptr[j + regb]);
- }
- SiS_SetReg(SISCR, 0xcf, v4);
- SiS_SetReg(SISCR, 0x83, 0x09);
- SiS_SetReg(SISCR, 0x87, 0x00);
- if(ivideo->chip == XGI_40) {
- if( (ivideo->revision_id == 1) ||
- (ivideo->revision_id == 2) ) {
- SiS_SetReg(SISCR, 0x8c, 0x87);
- }
- }
- if (regb == 1)
- SiS_SetReg(SISSR, 0x17, 0x80); /* DDR2 */
- else
- SiS_SetReg(SISSR, 0x17, 0x00); /* DDR1 */
- SiS_SetReg(SISSR, 0x1a, 0x87);
- if(ivideo->chip == XGI_20) {
- SiS_SetReg(SISSR, 0x15, 0x00);
- SiS_SetReg(SISSR, 0x1c, 0x00);
- }
- switch(ramtype) {
- case 0:
- sisfb_post_xgi_setclocks(ivideo, regb);
- if((ivideo->chip == XGI_20) ||
- (ivideo->revision_id == 1) ||
- (ivideo->revision_id == 2)) {
- v1 = cs158[regb]; v2 = cs160[regb]; v3 = cs168[regb];
- if(ivideo->haveXGIROM) {
- v1 = bios[regb + 0x158];
- v2 = bios[regb + 0x160];
- v3 = bios[regb + 0x168];
- }
- SiS_SetReg(SISCR, 0x82, v1);
- SiS_SetReg(SISCR, 0x85, v2);
- SiS_SetReg(SISCR, 0x86, v3);
- } else {
- SiS_SetReg(SISCR, 0x82, 0x88);
- SiS_SetReg(SISCR, 0x86, 0x00);
- reg = SiS_GetReg(SISCR, 0x86);
- SiS_SetReg(SISCR, 0x86, 0x88);
- reg = SiS_GetReg(SISCR, 0x86);
- SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
- SiS_SetReg(SISCR, 0x82, 0x77);
- SiS_SetReg(SISCR, 0x85, 0x00);
- reg = SiS_GetReg(SISCR, 0x85);
- SiS_SetReg(SISCR, 0x85, 0x88);
- reg = SiS_GetReg(SISCR, 0x85);
- SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
- SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
- }
- if(ivideo->chip == XGI_40) {
- SiS_SetReg(SISCR, 0x97, 0x00);
- }
- SiS_SetReg(SISCR, 0x98, 0x01);
- SiS_SetReg(SISCR, 0x9a, 0x02);
- SiS_SetReg(SISSR, 0x18, 0x01);
- if((ivideo->chip == XGI_20) ||
- (ivideo->revision_id == 2)) {
- SiS_SetReg(SISSR, 0x19, 0x40);
- } else {
- SiS_SetReg(SISSR, 0x19, 0x20);
- }
- SiS_SetReg(SISSR, 0x16, 0x00);
- SiS_SetReg(SISSR, 0x16, 0x80);
- if((ivideo->chip == XGI_20) || (bios[0x1cb] != 0x0c)) {
- sisfb_post_xgi_delay(ivideo, 0x43);
- sisfb_post_xgi_delay(ivideo, 0x43);
- sisfb_post_xgi_delay(ivideo, 0x43);
- SiS_SetReg(SISSR, 0x18, 0x00);
- if((ivideo->chip == XGI_20) ||
- (ivideo->revision_id == 2)) {
- SiS_SetReg(SISSR, 0x19, 0x40);
- } else {
- SiS_SetReg(SISSR, 0x19, 0x20);
- }
- } else if((ivideo->chip == XGI_40) && (bios[0x1cb] == 0x0c)) {
- /* SiS_SetReg(SISSR, 0x16, 0x0c); */ /* ? */
- }
- SiS_SetReg(SISSR, 0x16, 0x00);
- SiS_SetReg(SISSR, 0x16, 0x80);
- sisfb_post_xgi_delay(ivideo, 4);
- v1 = 0x31; v2 = 0x03; v3 = 0x83; v4 = 0x03; v5 = 0x83;
- if(ivideo->haveXGIROM) {
- v1 = bios[0xf0];
- index = (ivideo->chip == XGI_20) ? 0x4b2 : 0x53e;
- v2 = bios[index];
- v3 = bios[index + 1];
- v4 = bios[index + 2];
- v5 = bios[index + 3];
- }
- SiS_SetReg(SISSR, 0x18, v1);
- SiS_SetReg(SISSR, 0x19, ((ivideo->chip == XGI_20) ? 0x02 : 0x01));
- SiS_SetReg(SISSR, 0x16, v2);
- SiS_SetReg(SISSR, 0x16, v3);
- sisfb_post_xgi_delay(ivideo, 0x43);
- SiS_SetReg(SISSR, 0x1b, 0x03);
- sisfb_post_xgi_delay(ivideo, 0x22);
- SiS_SetReg(SISSR, 0x18, v1);
- SiS_SetReg(SISSR, 0x19, 0x00);
- SiS_SetReg(SISSR, 0x16, v4);
- SiS_SetReg(SISSR, 0x16, v5);
- SiS_SetReg(SISSR, 0x1b, 0x00);
- break;
- case 1:
- sisfb_post_xgi_ddr2(ivideo, regb);
- break;
- default:
- sisfb_post_xgi_setclocks(ivideo, regb);
- if((ivideo->chip == XGI_40) &&
- ((ivideo->revision_id == 1) ||
- (ivideo->revision_id == 2))) {
- SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
- SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
- SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
- } else {
- SiS_SetReg(SISCR, 0x82, 0x88);
- SiS_SetReg(SISCR, 0x86, 0x00);
- reg = SiS_GetReg(SISCR, 0x86);
- SiS_SetReg(SISCR, 0x86, 0x88);
- SiS_SetReg(SISCR, 0x82, 0x77);
- SiS_SetReg(SISCR, 0x85, 0x00);
- reg = SiS_GetReg(SISCR, 0x85);
- SiS_SetReg(SISCR, 0x85, 0x88);
- reg = SiS_GetReg(SISCR, 0x85);
- v1 = cs160[regb]; v2 = cs158[regb];
- if(ivideo->haveXGIROM) {
- v1 = bios[regb + 0x160];
- v2 = bios[regb + 0x158];
- }
- SiS_SetReg(SISCR, 0x85, v1);
- SiS_SetReg(SISCR, 0x82, v2);
- }
- if(ivideo->chip == XGI_40) {
- SiS_SetReg(SISCR, 0x97, 0x11);
- }
- if((ivideo->chip == XGI_40) && (ivideo->revision_id == 2)) {
- SiS_SetReg(SISCR, 0x98, 0x01);
- } else {
- SiS_SetReg(SISCR, 0x98, 0x03);
- }
- SiS_SetReg(SISCR, 0x9a, 0x02);
- if(ivideo->chip == XGI_40) {
- SiS_SetReg(SISSR, 0x18, 0x01);
- } else {
- SiS_SetReg(SISSR, 0x18, 0x00);
- }
- SiS_SetReg(SISSR, 0x19, 0x40);
- SiS_SetReg(SISSR, 0x16, 0x00);
- SiS_SetReg(SISSR, 0x16, 0x80);
- if((ivideo->chip == XGI_40) && (bios[0x1cb] != 0x0c)) {
- sisfb_post_xgi_delay(ivideo, 0x43);
- sisfb_post_xgi_delay(ivideo, 0x43);
- sisfb_post_xgi_delay(ivideo, 0x43);
- SiS_SetReg(SISSR, 0x18, 0x00);
- SiS_SetReg(SISSR, 0x19, 0x40);
- SiS_SetReg(SISSR, 0x16, 0x00);
- SiS_SetReg(SISSR, 0x16, 0x80);
- }
- sisfb_post_xgi_delay(ivideo, 4);
- v1 = 0x31;
- if(ivideo->haveXGIROM) {
- v1 = bios[0xf0];
- }
- SiS_SetReg(SISSR, 0x18, v1);
- SiS_SetReg(SISSR, 0x19, 0x01);
- if(ivideo->chip == XGI_40) {
- SiS_SetReg(SISSR, 0x16, bios[0x53e]);
- SiS_SetReg(SISSR, 0x16, bios[0x53f]);
- } else {
- SiS_SetReg(SISSR, 0x16, 0x05);
- SiS_SetReg(SISSR, 0x16, 0x85);
- }
- sisfb_post_xgi_delay(ivideo, 0x43);
- if(ivideo->chip == XGI_40) {
- SiS_SetReg(SISSR, 0x1b, 0x01);
- } else {
- SiS_SetReg(SISSR, 0x1b, 0x03);
- }
- sisfb_post_xgi_delay(ivideo, 0x22);
- SiS_SetReg(SISSR, 0x18, v1);
- SiS_SetReg(SISSR, 0x19, 0x00);
- if(ivideo->chip == XGI_40) {
- SiS_SetReg(SISSR, 0x16, bios[0x540]);
- SiS_SetReg(SISSR, 0x16, bios[0x541]);
- } else {
- SiS_SetReg(SISSR, 0x16, 0x05);
- SiS_SetReg(SISSR, 0x16, 0x85);
- }
- SiS_SetReg(SISSR, 0x1b, 0x00);
- }
- regb = 0; /* ! */
- v1 = 0x03;
- if(ivideo->haveXGIROM) {
- v1 = bios[0x110 + regb];
- }
- SiS_SetReg(SISSR, 0x1b, v1);
- /* RAM size */
- v1 = 0x00; v2 = 0x00;
- if(ivideo->haveXGIROM) {
- v1 = bios[0x62];
- v2 = bios[0x63];
- }
- regb = 0; /* ! */
- regd = 1 << regb;
- if((v1 & 0x40) && (v2 & regd) && ivideo->haveXGIROM) {
- SiS_SetReg(SISSR, 0x13, bios[regb + 0xe0]);
- SiS_SetReg(SISSR, 0x14, bios[regb + 0xe0 + 8]);
- } else {
- int err;
- /* Set default mode, don't clear screen */
- ivideo->SiS_Pr.SiS_UseOEM = false;
- SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
- SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
- ivideo->curFSTN = ivideo->curDSTN = 0;
- ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
- SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
- SiS_SetReg(SISSR, 0x05, 0x86);
- /* Disable read-cache */
- SiS_SetRegAND(SISSR, 0x21, 0xdf);
- err = sisfb_post_xgi_ramsize(ivideo);
- /* Enable read-cache */
- SiS_SetRegOR(SISSR, 0x21, 0x20);
- if (err) {
- dev_err(&pdev->dev,
- "%s: RAM size detection failed: %d\n",
- __func__, err);
- return 0;
- }
- }
- #if 0
- printk(KERN_DEBUG "-----------------\n");
- for(i = 0; i < 0xff; i++) {
- reg = SiS_GetReg(SISCR, i);
- printk(KERN_DEBUG "CR%02x(%x) = 0x%02x\n", i, SISCR, reg);
- }
- for(i = 0; i < 0x40; i++) {
- reg = SiS_GetReg(SISSR, i);
- printk(KERN_DEBUG "SR%02x(%x) = 0x%02x\n", i, SISSR, reg);
- }
- printk(KERN_DEBUG "-----------------\n");
- #endif
- /* Sense CRT1 */
- if(ivideo->chip == XGI_20) {
- SiS_SetRegOR(SISCR, 0x32, 0x20);
- } else {
- reg = SiS_GetReg(SISPART4, 0x00);
- if((reg == 1) || (reg == 2)) {
- sisfb_sense_crt1(ivideo);
- } else {
- SiS_SetRegOR(SISCR, 0x32, 0x20);
- }
- }
- /* Set default mode, don't clear screen */
- ivideo->SiS_Pr.SiS_UseOEM = false;
- SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
- SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
- ivideo->curFSTN = ivideo->curDSTN = 0;
- SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
- SiS_SetReg(SISSR, 0x05, 0x86);
- /* Display off */
- SiS_SetRegOR(SISSR, 0x01, 0x20);
- /* Save mode number in CR34 */
- SiS_SetReg(SISCR, 0x34, 0x2e);
- /* Let everyone know what the current mode is */
- ivideo->modeprechange = 0x2e;
- if(ivideo->chip == XGI_40) {
- reg = SiS_GetReg(SISCR, 0xca);
- v1 = SiS_GetReg(SISCR, 0xcc);
- if((reg & 0x10) && (!(v1 & 0x04))) {
- printk(KERN_ERR
- "sisfb: Please connect power to the card.\n");
- return 0;
- }
- }
- return 1;
- }
- #endif
- static int __devinit
- sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
- {
- struct sisfb_chip_info *chipinfo = &sisfb_chip_info[ent->driver_data];
- struct sis_video_info *ivideo = NULL;
- struct fb_info *sis_fb_info = NULL;
- u16 reg16;
- u8 reg;
- int i, ret;
- if(sisfb_off)
- return -ENXIO;
- sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev);
- if(!sis_fb_info)
- return -ENOMEM;
- ivideo = (struct sis_video_info *)sis_fb_info->par;
- ivideo->memyselfandi = sis_fb_info;
- ivideo->sisfb_id = SISFB_ID;
- if(card_list == NULL) {
- ivideo->cardnumber = 0;
- } else {
- struct sis_video_info *countvideo = card_list;
- ivideo->cardnumber = 1;
- while((countvideo = countvideo->next) != NULL)
- ivideo->cardnumber++;
- }
- strncpy(ivideo->myid, chipinfo->chip_name, 30);
- ivideo->warncount = 0;
- ivideo->chip_id = pdev->device;
- ivideo->chip_vendor = pdev->vendor;
- ivideo->revision_id = pdev->revision;
- ivideo->SiS_Pr.ChipRevision = ivideo->revision_id;
- pci_read_config_word(pdev, PCI_COMMAND, ®16);
- ivideo->sisvga_enabled = reg16 & 0x01;
- ivideo->pcibus = pdev->bus->number;
- ivideo->pcislot = PCI_SLOT(pdev->devfn);
- ivideo->pcifunc = PCI_FUNC(pdev->devfn);
- ivideo->subsysvendor = pdev->subsystem_vendor;
- ivideo->subsysdevice = pdev->subsystem_device;
- #ifndef MODULE
- if(sisfb_mode_idx == -1) {
- sisfb_get_vga_mode_from_kernel();
- }
- #endif
- ivideo->chip = chipinfo->chip;
- ivideo->chip_real_id = chipinfo->chip;
- ivideo->sisvga_engine = chipinfo->vgaengine;
- ivideo->hwcursor_size = chipinfo->hwcursor_size;
- ivideo->CRT2_write_enable = chipinfo->CRT2_write_enable;
- ivideo->mni = chipinfo->mni;
- ivideo->detectedpdc = 0xff;
- ivideo->detectedpdca = 0xff;
- ivideo->detectedlcda = 0xff;
- ivideo->sisfb_thismonitor.datavalid = false;
- ivideo->current_base = 0;
- ivideo->engineok = 0;
- ivideo->sisfb_was_boot_device = 0;
- if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) {
- if(ivideo->sisvga_enabled)
- ivideo->sisfb_was_boot_device = 1;
- else {
- printk(KERN_DEBUG "sisfb: PCI device is disabled, "
- "but marked as boot video device ???\n");
- printk(KERN_DEBUG "sisfb: I will not accept this "
- "as the primary VGA device\n");
- }
- }
- ivideo->sisfb_parm_mem = sisfb_parm_mem;
- ivideo->sisfb_accel = sisfb_accel;
- ivideo->sisfb_ypan = sisfb_ypan;
- ivideo->sisfb_max = sisfb_max;
- ivideo->sisfb_userom = sisfb_userom;
- ivideo->sisfb_useoem = sisfb_useoem;
- ivideo->sisfb_mode_idx = sisfb_mode_idx;
- ivideo->sisfb_parm_rate = sisfb_parm_rate;
- ivideo->sisfb_crt1off = sisfb_crt1off;
- ivideo->sisfb_forcecrt1 = sisfb_forcecrt1;
- ivideo->sisfb_crt2type = sisfb_crt2type;
- ivideo->sisfb_crt2flags = sisfb_crt2flags;
- /* pdc(a), scalelcd, special timing, lvdshl handled below */
- ivideo->sisfb_dstn = sisfb_dstn;
- ivideo->sisfb_fstn = sisfb_fstn;
- ivideo->sisfb_tvplug = sisfb_tvplug;
- ivideo->sisfb_tvstd = sisfb_tvstd;
- ivideo->tvxpos = sisfb_tvxposoffset;
- ivideo->tvypos = sisfb_tvyposoffset;
- ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate;
- ivideo->refresh_rate = 0;
- if(ivideo->sisfb_parm_rate != -1) {
- ivideo->refresh_rate = ivideo->sisfb_parm_rate;
- }
- ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd;
- ivideo->SiS_Pr.CenterScreen = -1;
- ivideo->SiS_Pr.SiS_CustomT = sisfb_specialtiming;
- ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl;
- ivideo->SiS_Pr.SiS_Backup70xx = 0xff;
- ivideo->SiS_Pr.SiS_CHOverScan = -1;
- ivideo->SiS_Pr.SiS_ChSW = false;
- ivideo->SiS_Pr.SiS_UseLCDA = false;
- ivideo->SiS_Pr.HaveEMI = false;
- ivideo->SiS_Pr.HaveEMILCD = false;
- ivideo->SiS_Pr.OverruleEMI = false;
- ivideo->SiS_Pr.SiS_SensibleSR11 = false;
- ivideo->SiS_Pr.SiS_MyCR63 = 0x63;
- ivideo->SiS_Pr.PDC = -1;
- ivideo->SiS_Pr.PDCA = -1;
- ivideo->SiS_Pr.DDCPortMixup = false;
- #ifdef CONFIG_FB_SIS_315
- if(ivideo->chip >= SIS_330) {
- ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
- if(ivideo->chip >= SIS_661) {
- ivideo->SiS_Pr.SiS_SensibleSR11 = true;
- }
- }
- #endif
- memcpy(&ivideo->default_var, &my_default_var, sizeof(my_default_var));
- pci_set_drvdata(pdev, ivideo);
- /* Patch special cases */
- if((ivideo->nbridge = sisfb_get_northbridge(ivideo->chip))) {
- switch(ivideo->nbridge->device) {
- #ifdef CONFIG_FB_SIS_300
- case PCI_DEVICE_ID_SI_730:
- ivideo->chip = SIS_730;
- strcpy(ivideo->myid, "SiS 730");
- break;
- #endif
- #ifdef CONFIG_FB_SIS_315
- case PCI_DEVICE_ID_SI_651:
- /* ivideo->chip is ok */
- strcpy(ivideo->myid, "SiS 651");
- break;
- case PCI_DEVICE_ID_SI_740:
- ivideo->chip = SIS_740;
- strcpy(ivideo->myid, "SiS 740");
- break;
- case PCI_DEVICE_ID_SI_661:
- ivideo->chip = SIS_661;
- strcpy(ivideo->myid, "SiS 661");
- break;
- case PCI_DEVICE_ID_SI_741:
- ivideo->chip = SIS_741;
- strcpy(ivideo->myid, "SiS 741");
- break;
- case PCI_DEVICE_ID_SI_760:
- ivideo->chip = SIS_760;
- strcpy(ivideo->myid, "SiS 760");
- break;
- case PCI_DEVICE_ID_SI_761:
- ivideo->chip = SIS_761;
- strcpy(ivideo->myid, "SiS 761");
- break;
- #endif
- default:
- break;
- }
- }
- ivideo->SiS_Pr.ChipType = ivideo->chip;
- ivideo->SiS_Pr.ivideo = (void *)ivideo;
- #ifdef CONFIG_FB_SIS_315
- if((ivideo->SiS_Pr.ChipType == SIS_315PRO) ||
- (ivideo->SiS_Pr.ChipType == SIS_315)) {
- ivideo->SiS_Pr.ChipType = SIS_315H;
- }
- #endif
- if(!ivideo->sisvga_enabled) {
- if(pci_enable_device(pdev)) {
- if(ivideo->nbridge) pci_dev_put(ivideo->nbridge);
- pci_set_drvdata(pdev, NULL);
- framebuffer_release(sis_fb_info);
- return -EIO;
- }
- }
- ivideo->video_base = pci_resource_start(pdev, 0);
- ivideo->video_size = pci_resource_len(pdev, 0);
- ivideo->mmio_base = pci_resource_start(pdev, 1);
- ivideo->mmio_size = pci_resource_len(pdev, 1);
- ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
- ivideo->SiS_Pr.IOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;
- SiSRegInit(&ivideo->SiS_Pr, ivideo->SiS_Pr.IOAddress);
- #ifdef CONFIG_FB_SIS_300
- /* Find PCI systems for Chrontel/GPIO communication setup */
- if(ivideo->chip == SIS_630) {
- i = 0;
- do {
- if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
- mychswtable[i].subsysCard == ivideo->subsysdevice) {
- ivideo->SiS_Pr.SiS_ChSW = true;
- printk(KERN_DEBUG "sisfb: Identified [%s %s] "
- "requiring Chrontel/GPIO setup\n",
- mychswtable[i].vendorName,
- mychswtable[i].cardName);
- ivideo->lpcdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0008, NULL);
- break;
- }
- i++;
- } while(mychswtable[i].subsysVendor != 0);
- }
- #endif
- #ifdef CONFIG_FB_SIS_315
- if((ivideo->chip == SIS_760) && (ivideo->nbridge)) {
- ivideo->lpcdev = pci_get_slot(ivideo->nbridge->bus, (2 << 3));
- }
- #endif
- SiS_SetReg(SISSR, 0x05, 0x86);
- if( (!ivideo->sisvga_enabled)
- #if !defined(__i386__) && !defined(__x86_64__)
- || (sisfb_resetcard)
- #endif
- ) {
- for(i = 0x30; i <= 0x3f; i++) {
- SiS_SetReg(SISCR, i, 0x00);
- }
- }
- /* Find out about current video mode */
- ivideo->modeprechange = 0x03;
- reg = SiS_GetReg(SISCR, 0x34);
- if(reg & 0x7f) {
- ivideo->modeprechange = reg & 0x7f;
- } else if(ivideo->sisvga_enabled) {
- #if defined(__i386__) || defined(__x86_64__)
- unsigned char __iomem *tt = ioremap(0x400, 0x100);
- if(tt) {
- ivideo->modeprechange = readb(tt + 0x49);
- iounmap(tt);
- }
- #endif
- }
- /* Search and copy ROM image */
- ivideo->bios_abase = NULL;
- ivideo->SiS_Pr.VirtualRomBase = NULL;
- ivideo->SiS_Pr.UseROM = false;
- ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = false;
- if(ivideo->sisfb_userom) {
- ivideo->SiS_Pr.VirtualRomBase = sisfb_find_rom(pdev);
- ivideo->bios_abase = ivideo->SiS_Pr.VirtualRomBase;
- ivideo->SiS_Pr.UseROM = (bool)(ivideo->SiS_Pr.VirtualRomBase);
- printk(KERN_INFO "sisfb: Video ROM %sfound\n",
- ivideo->SiS_Pr.UseROM ? "" : "not ");
- if((ivideo->SiS_Pr.UseROM) && (ivideo->chip >= XGI_20)) {
- ivideo->SiS_Pr.UseROM = false;
- ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = true;
- if( (ivideo->revision_id == 2) &&
- (!(ivideo->bios_abase[0x1d1] & 0x01)) ) {
- ivideo->SiS_Pr.DDCPortMixup = true;
- }
- }
- } else {
- printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
- }
- /* Find systems for special custom timing */
- if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) {
- sisfb_detect_custom_timing(ivideo);
- }
- #ifdef CONFIG_FB_SIS_315
- if (ivideo->chip == XGI_20) {
- /* Check if our Z7 chip is actually Z9 */
- SiS_SetRegOR(SISCR, 0x4a, 0x40); /* GPIOG EN */
- reg = SiS_GetReg(SISCR, 0x48);
- if (reg & 0x02) { /* GPIOG */
- ivideo->chip_real_id = XGI_21;
- dev_info(&pdev->dev, "Z9 detected\n");
- }
- }
- #endif
- /* POST card in case this has not been done by the BIOS */
- if( (!ivideo->sisvga_enabled)
- #if !defined(__i386__) && !defined(__x86_64__)
- || (sisfb_resetcard)
- #endif
- ) {
- #ifdef CONFIG_FB_SIS_300
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- if(ivideo->chip == SIS_300) {
- sisfb_post_sis300(pdev);
- ivideo->sisfb_can_post = 1;
- }
- }
- #endif
- #ifdef CONFIG_FB_SIS_315
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- int result = 1;
- /* if((ivideo->chip == SIS_315H) ||
- (ivideo->chip == SIS_315) ||
- (ivideo->chip == SIS_315PRO) ||
- (ivideo->chip == SIS_330)) {
- sisfb_post_sis315330(pdev);
- } else */ if(ivideo->chip == XGI_20) {
- result = sisfb_post_xgi(pdev);
- ivideo->sisfb_can_post = 1;
- } else if((ivideo->chip == XGI_40) && ivideo->haveXGIROM) {
- result = sisfb_post_xgi(pdev);
- ivideo->sisfb_can_post = 1;
- } else {
- printk(KERN_INFO "sisfb: Card is not "
- "POSTed and sisfb can't do this either.\n");
- }
- if(!result) {
- printk(KERN_ERR "sisfb: Failed to POST card\n");
- ret = -ENODEV;
- goto error_3;
- }
- }
- #endif
- }
- ivideo->sisfb_card_posted = 1;
- /* Find out about RAM size */
- if(sisfb_get_dram_size(ivideo)) {
- printk(KERN_INFO "sisfb: Fatal error: Unable to determine VRAM size.\n");
- ret = -ENODEV;
- goto error_3;
- }
- /* Enable PCI addressing and MMIO */
- if((ivideo->sisfb_mode_idx < 0) ||
- ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
- /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
- SiS_SetRegOR(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
- /* Enable 2D accelerator engine */
- SiS_SetRegOR(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
- }
- if(sisfb_pdc != 0xff) {
- if(ivideo->sisvga_engine == SIS_300_VGA)
- sisfb_pdc &= 0x3c;
- else
- sisfb_pdc &= 0x1f;
- ivideo->SiS_Pr.PDC = sisfb_pdc;
- }
- #ifdef CONFIG_FB_SIS_315
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- if(sisfb_pdca != 0xff)
- ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
- }
- #endif
- if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) {
- printk(KERN_ERR "sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
- (int)(ivideo->video_size >> 20));
- printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n");
- ret = -ENODEV;
- goto error_3;
- }
- if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) {
- printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n");
- ret = -ENODEV;
- goto error_2;
- }
- ivideo->video_vbase = ioremap(ivideo->video_base, ivideo->video_size);
- ivideo->SiS_Pr.VideoMemoryAddress = ivideo->video_vbase;
- if(!ivideo->video_vbase) {
- printk(KERN_ERR "sisfb: Fatal error: Unable to map framebuffer memory\n");
- ret = -ENODEV;
- goto error_1;
- }
- ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size);
- if(!ivideo->mmio_vbase) {
- printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
- ret = -ENODEV;
- error_0: iounmap(ivideo->video_vbase);
- error_1: release_mem_region(ivideo->video_base, ivideo->video_size);
- error_2: release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
- error_3: vfree(ivideo->bios_abase);
- if(ivideo->lpcdev)
- pci_dev_put(ivideo->lpcdev);
- if(ivideo->nbridge)
- pci_dev_put(ivideo->nbridge);
- pci_set_drvdata(pdev, NULL);
- if(!ivideo->sisvga_enabled)
- pci_disable_device(pdev);
- framebuffer_release(sis_fb_info);
- return ret;
- }
- printk(KERN_INFO "sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
- ivideo->video_base, (unsigned long)ivideo->video_vbase, ivideo->video_size / 1024);
- if(ivideo->video_offset) {
- printk(KERN_INFO "sisfb: Viewport offset %ldk\n",
- ivideo->video_offset / 1024);
- }
- printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
- ivideo->mmio_base, (unsigned long)ivideo->mmio_vbase, ivideo->mmio_size / 1024);
- /* Determine the size of the command queue */
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- ivideo->cmdQueueSize = TURBO_QUEUE_AREA_SIZE;
- } else {
- if(ivideo->chip == XGI_20) {
- ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE_Z7;
- } else {
- ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE;
- }
- }
- /* Engines are no longer initialized here; this is
- * now done after the first mode-switch (if the
- * submitted var has its acceleration flags set).
- */
- /* Calculate the base of the (unused) hw cursor */
- ivideo->hwcursor_vbase = ivideo->video_vbase
- + ivideo->video_size
- - ivideo->cmdQueueSize
- - ivideo->hwcursor_size;
- ivideo->caps |= HW_CURSOR_CAP;
- /* Initialize offscreen memory manager */
- if((ivideo->havenoheap = sisfb_heap_init(ivideo))) {
- printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n");
- }
- /* Used for clearing the screen only, therefore respect our mem limit */
- ivideo->SiS_Pr.VideoMemoryAddress += ivideo->video_offset;
- ivideo->SiS_Pr.VideoMemorySize = ivideo->sisfb_mem;
- ivideo->mtrr = -1;
- ivideo->vbflags = 0;
- ivideo->lcddefmodeidx = DEFAULT_LCDMODE;
- ivideo->tvdefmodeidx = DEFAULT_TVMODE;
- ivideo->defmodeidx = DEFAULT_MODE;
- ivideo->newrom = 0;
- if(ivideo->chip < XGI_20) {
- if(ivideo->bios_abase) {
- ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr);
- }
- }
- if((ivideo->sisfb_mode_idx < 0) ||
- ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
- sisfb_sense_crt1(ivideo);
- sisfb_get_VB_type(ivideo);
- if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
- sisfb_detect_VB_connect(ivideo);
- }
- ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
- /* Decide on which CRT2 device to use */
- if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
- if(ivideo->sisfb_crt2type != -1) {
- if((ivideo->sisfb_crt2type == CRT2_LCD) &&
- (ivideo->vbflags & CRT2_LCD)) {
- ivideo->currentvbflags |= CRT2_LCD;
- } else if(ivideo->sisfb_crt2type != CRT2_LCD) {
- ivideo->currentvbflags |= ivideo->sisfb_crt2type;
- }
- } else {
- /* Chrontel 700x TV detection often unreliable, therefore
- * use a different default order on such machines
- */
- if((ivideo->sisvga_engine == SIS_300_VGA) &&
- (ivideo->vbflags2 & VB2_CHRONTEL)) {
- if(ivideo->vbflags & CRT2_LCD)
- ivideo->currentvbflags |= CRT2_LCD;
- else if(ivideo->vbflags & CRT2_TV)
- ivideo->currentvbflags |= CRT2_TV;
- else if(ivideo->vbflags & CRT2_VGA)
- ivideo->currentvbflags |= CRT2_VGA;
- } else {
- if(ivideo->vbflags & CRT2_TV)
- ivideo->currentvbflags |= CRT2_TV;
- else if(ivideo->vbflags & CRT2_LCD)
- ivideo->currentvbflags |= CRT2_LCD;
- else if(ivideo->vbflags & CRT2_VGA)
- ivideo->currentvbflags |= CRT2_VGA;
- }
- }
- }
- if(ivideo->vbflags & CRT2_LCD) {
- sisfb_detect_lcd_type(ivideo);
- }
- sisfb_save_pdc_emi(ivideo);
- if(!ivideo->sisfb_crt1off) {
- sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0);
- } else {
- if((ivideo->vbflags2 & VB2_SISTMDSBRIDGE) &&
- (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
- sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1);
- }
- }
- if(ivideo->sisfb_mode_idx >= 0) {
- int bu = ivideo->sisfb_mode_idx;
- ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
- ivideo->sisfb_mode_idx, ivideo->currentvbflags);
- if(bu != ivideo->sisfb_mode_idx) {
- printk(KERN_ERR "Mode %dx%dx%d failed validation\n",
- sisbios_mode[bu].xres,
- sisbios_mode[bu].yres,
- sisbios_mode[bu].bpp);
- }
- }
- if(ivideo->sisfb_mode_idx < 0) {
- switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
- case CRT2_LCD:
- ivideo->sisfb_mode_idx = ivideo->lcddefmodeidx;
- break;
- case CRT2_TV:
- ivideo->sisfb_mode_idx = ivideo->tvdefmodeidx;
- break;
- default:
- ivideo->sisfb_mode_idx = ivideo->defmodeidx;
- break;
- }
- }
- ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
- if(ivideo->refresh_rate != 0) {
- sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate,
- ivideo->sisfb_mode_idx);
- }
- if(ivideo->rate_idx == 0) {
- ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
- ivideo->refresh_rate = 60;
- }
- if(ivideo->sisfb_thismonitor.datavalid) {
- if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor,
- ivideo->sisfb_mode_idx,
- ivideo->rate_idx,
- ivideo->refresh_rate)) {
- printk(KERN_INFO "sisfb: WARNING: Refresh rate "
- "exceeds monitor specs!\n");
- }
- }
- ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
- ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
- ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
- sisfb_set_vparms(ivideo);
- printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n",
- ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
- ivideo->refresh_rate);
- /* Set up the default var according to chosen default display mode */
- ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width;
- ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height;
- ivideo->default_var.bits_per_pixel = ivideo->video_bpp;
- sisfb_bpp_to_var(ivideo, &ivideo->default_var);
- ivideo->default_var.pixclock = (u32) (1000000000 /
- sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, ivideo->mode_no, ivideo->rate_idx));
- if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, ivideo->mode_no,
- ivideo->rate_idx, &ivideo->default_var)) {
- if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
- ivideo->default_var.pixclock <<= 1;
- }
- }
- if(ivideo->sisfb_ypan) {
- /* Maximize regardless of sisfb_max at startup */
- ivideo->default_var.yres_virtual =
- sisfb_calc_maxyres(ivideo, &ivideo->default_var);
- if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) {
- ivideo->default_var.yres_virtual = ivideo->default_var.yres;
- }
- }
- sisfb_calc_pitch(ivideo, &ivideo->default_var);
- ivideo->accel = 0;
- if(ivideo->sisfb_accel) {
- ivideo->accel = -1;
- #ifdef STUPID_ACCELF_TEXT_SHIT
- ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
- #endif
- }
- sisfb_initaccel(ivideo);
- #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
- sis_fb_info->flags = FBINFO_DEFAULT |
- FBINFO_HWACCEL_YPAN |
- FBINFO_HWACCEL_XPAN |
- FBINFO_HWACCEL_COPYAREA |
- FBINFO_HWACCEL_FILLRECT |
- ((ivideo->accel) ? 0 : FBINFO_HWACCEL_DISABLED);
- #else
- sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
- #endif
- sis_fb_info->var = ivideo->default_var;
- sis_fb_info->fix = ivideo->sisfb_fix;
- sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset;
- sis_fb_info->fbops = &sisfb_ops;
- sis_fb_info->pseudo_palette = ivideo->pseudo_palette;
- fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
- printk(KERN_DEBUG "sisfb: Initial vbflags 0x%x\n", (int)ivideo->vbflags);
- #ifdef CONFIG_MTRR
- ivideo->mtrr = mtrr_add(ivideo->video_base, ivideo->video_size,
- MTRR_TYPE_WRCOMB, 1);
- if(ivideo->mtrr < 0) {
- printk(KERN_DEBUG "sisfb: Failed to add MTRRs\n");
- }
- #endif
- if(register_framebuffer(sis_fb_info) < 0) {
- printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
- ret = -EINVAL;
- iounmap(ivideo->mmio_vbase);
- goto error_0;
- }
- ivideo->registered = 1;
- /* Enlist us */
- ivideo->next = card_list;
- card_list = ivideo;
- printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n",
- ivideo->sisfb_accel ? "enabled" : "disabled",
- ivideo->sisfb_ypan ?
- (ivideo->sisfb_max ? "enabled (auto-max)" :
- "enabled (no auto-max)") :
- "disabled");
- printk(KERN_INFO "fb%d: %s frame buffer device version %d.%d.%d\n",
- sis_fb_info->node, ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
- printk(KERN_INFO "sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
- } /* if mode = "none" */
- return 0;
- }
- /*****************************************************/
- /* PCI DEVICE HANDLING */
- /*****************************************************/
- static void __devexit sisfb_remove(struct pci_dev *pdev)
- {
- struct sis_video_info *ivideo = pci_get_drvdata(pdev);
- struct fb_info *sis_fb_info = ivideo->memyselfandi;
- int registered = ivideo->registered;
- int modechanged = ivideo->modechanged;
- /* Unmap */
- iounmap(ivideo->mmio_vbase);
- iounmap(ivideo->video_vbase);
- /* Release mem regions */
- release_mem_region(ivideo->video_base, ivideo->video_size);
- release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
- vfree(ivideo->bios_abase);
- if(ivideo->lpcdev)
- pci_dev_put(ivideo->lpcdev);
- if(ivideo->nbridge)
- pci_dev_put(ivideo->nbridge);
- #ifdef CONFIG_MTRR
- /* Release MTRR region */
- if(ivideo->mtrr >= 0)
- mtrr_del(ivideo->mtrr, ivideo->video_base, ivideo->video_size);
- #endif
- pci_set_drvdata(pdev, NULL);
- /* If device was disabled when starting, disable
- * it when quitting.
- */
- if(!ivideo->sisvga_enabled)
- pci_disable_device(pdev);
- /* Unregister the framebuffer */
- if(ivideo->registered) {
- unregister_framebuffer(sis_fb_info);
- framebuffer_release(sis_fb_info);
- }
- /* OK, our ivideo is gone for good from here. */
- /* TODO: Restore the initial mode
- * This sounds easy but is as good as impossible
- * on many machines with SiS chip and video bridge
- * since text modes are always set up differently
- * from machine to machine. Depends on the type
- * of integration between chipset and bridge.
- */
- if(registered && modechanged)
- printk(KERN_INFO
- "sisfb: Restoring of text mode not supported yet\n");
- };
- static struct pci_driver sisfb_driver = {
- .name = "sisfb",
- .id_table = sisfb_pci_table,
- .probe = sisfb_probe,
- .remove = __devexit_p(sisfb_remove)
- };
- static int __init sisfb_init(void)
- {
- #ifndef MODULE
- char *options = NULL;
- if(fb_get_options("sisfb", &options))
- return -ENODEV;
- sisfb_setup(options);
- #endif
- return pci_register_driver(&sisfb_driver);
- }
- #ifndef MODULE
- module_init(sisfb_init);
- #endif
- /*****************************************************/
- /* MODULE */
- /*****************************************************/
- #ifdef MODULE
- static char *mode = NULL;
- static int vesa = -1;
- static unsigned int rate = 0;
- static unsigned int crt1off = 1;
- static unsigned int mem = 0;
- static char *forcecrt2type = NULL;
- static int forcecrt1 = -1;
- static int pdc = -1;
- static int pdc1 = -1;
- static int noaccel = -1;
- static int noypan = -1;
- static int nomax = -1;
- static int userom = -1;
- static int useoem = -1;
- static char *tvstandard = NULL;
- static int nocrt2rate = 0;
- static int scalelcd = -1;
- static char *specialtiming = NULL;
- static int lvdshl = -1;
- static int tvxposoffset = 0, tvyposoffset = 0;
- #if !defined(__i386__) && !defined(__x86_64__)
- static int resetcard = 0;
- static int videoram = 0;
- #endif
- static int __init sisfb_init_module(void)
- {
- sisfb_setdefaultparms();
- if(rate)
- sisfb_parm_rate = rate;
- if((scalelcd == 0) || (scalelcd == 1))
- sisfb_scalelcd = scalelcd ^ 1;
- /* Need to check crt2 type first for fstn/dstn */
- if(forcecrt2type)
- sisfb_search_crt2type(forcecrt2type);
- if(tvstandard)
- sisfb_search_tvstd(tvstandard);
- if(mode)
- sisfb_search_mode(mode, false);
- else if(vesa != -1)
- sisfb_search_vesamode(vesa, false);
- sisfb_crt1off = (crt1off == 0) ? 1 : 0;
- sisfb_forcecrt1 = forcecrt1;
- if(forcecrt1 == 1)
- sisfb_crt1off = 0;
- else if(forcecrt1 == 0)
- sisfb_crt1off = 1;
- if(noaccel == 1)
- sisfb_accel = 0;
- else if(noaccel == 0)
- sisfb_accel = 1;
- if(noypan == 1)
- sisfb_ypan = 0;
- else if(noypan == 0)
- sisfb_ypan = 1;
- if(nomax == 1)
- sisfb_max = 0;
- else if(nomax == 0)
- sisfb_max = 1;
- if(mem)
- sisfb_parm_mem = mem;
- if(userom != -1)
- sisfb_userom = userom;
- if(useoem != -1)
- sisfb_useoem = useoem;
- if(pdc != -1)
- sisfb_pdc = (pdc & 0x7f);
- if(pdc1 != -1)
- sisfb_pdca = (pdc1 & 0x1f);
- sisfb_nocrt2rate = nocrt2rate;
- if(specialtiming)
- sisfb_search_specialtiming(specialtiming);
- if((lvdshl >= 0) && (lvdshl <= 3))
- sisfb_lvdshl = lvdshl;
- sisfb_tvxposoffset = tvxposoffset;
- sisfb_tvyposoffset = tvyposoffset;
- #if !defined(__i386__) && !defined(__x86_64__)
- sisfb_resetcard = (resetcard) ? 1 : 0;
- if(videoram)
- sisfb_videoram = videoram;
- #endif
- return sisfb_init();
- }
- static void __exit sisfb_remove_module(void)
- {
- pci_unregister_driver(&sisfb_driver);
- printk(KERN_DEBUG "sisfb: Module unloaded\n");
- }
- module_init(sisfb_init_module);
- module_exit(sisfb_remove_module);
- MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
- module_param(mem, int, 0);
- module_param(noaccel, int, 0);
- module_param(noypan, int, 0);
- module_param(nomax, int, 0);
- module_param(userom, int, 0);
- module_param(useoem, int, 0);
- module_param(mode, charp, 0);
- module_param(vesa, int, 0);
- module_param(rate, int, 0);
- module_param(forcecrt1, int, 0);
- module_param(forcecrt2type, charp, 0);
- module_param(scalelcd, int, 0);
- module_param(pdc, int, 0);
- module_param(pdc1, int, 0);
- module_param(specialtiming, charp, 0);
- module_param(lvdshl, int, 0);
- module_param(tvstandard, charp, 0);
- module_param(tvxposoffset, int, 0);
- module_param(tvyposoffset, int, 0);
- module_param(nocrt2rate, int, 0);
- #if !defined(__i386__) && !defined(__x86_64__)
- module_param(resetcard, int, 0);
- module_param(videoram, int, 0);
- #endif
- MODULE_PARM_DESC(mem,
- "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
- "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
- "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
- "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
- "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
- "The value is to be specified without 'KB'.\n");
- MODULE_PARM_DESC(noaccel,
- "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
- "(default: 0)\n");
- MODULE_PARM_DESC(noypan,
- "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
- "will be performed by redrawing the screen. (default: 0)\n");
- MODULE_PARM_DESC(nomax,
- "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
- "memory for the virtual screen in order to optimize scrolling performance. If\n"
- "this is set to anything other than 0, sisfb will not do this and thereby \n"
- "enable the user to positively specify a virtual Y size of the screen using\n"
- "fbset. (default: 0)\n");
- MODULE_PARM_DESC(mode,
- "\nSelects the desired default display mode in the format XxYxDepth,\n"
- "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
- "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
- "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
- MODULE_PARM_DESC(vesa,
- "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
- "0x117 (default: 0x0103)\n");
- MODULE_PARM_DESC(rate,
- "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
- "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
- "will be ignored (default: 60)\n");
- MODULE_PARM_DESC(forcecrt1,
- "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
- "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
- "0=CRT1 OFF) (default: [autodetected])\n");
- MODULE_PARM_DESC(forcecrt2type,
- "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
- "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
- "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
- "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
- "be used instead of TV to override the TV detection. Furthermore, on systems\n"
- "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
- "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
- "depends on the very hardware in use. (default: [autodetected])\n");
- MODULE_PARM_DESC(scalelcd,
- "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
- "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
- "show black bars around the image, TMDS panels will probably do the scaling\n"
- "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
- MODULE_PARM_DESC(pdc,
- "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
- "should detect this correctly in most cases; however, sometimes this is not\n"
- "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
- "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
- "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
- "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
- #ifdef CONFIG_FB_SIS_315
- MODULE_PARM_DESC(pdc1,
- "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
- "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
- "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
- "implemented yet.\n");
- #endif
- MODULE_PARM_DESC(specialtiming,
- "\nPlease refer to documentation for more information on this option.\n");
- MODULE_PARM_DESC(lvdshl,
- "\nPlease refer to documentation for more information on this option.\n");
- MODULE_PARM_DESC(tvstandard,
- "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
- "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
- MODULE_PARM_DESC(tvxposoffset,
- "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
- "Default: 0\n");
- MODULE_PARM_DESC(tvyposoffset,
- "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
- "Default: 0\n");
- MODULE_PARM_DESC(nocrt2rate,
- "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
- "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
- #if !defined(__i386__) && !defined(__x86_64__)
- #ifdef CONFIG_FB_SIS_300
- MODULE_PARM_DESC(resetcard,
- "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
- "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
- "currently). Default: 0\n");
- MODULE_PARM_DESC(videoram,
- "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
- "some non-x86 architectures where the memory auto detection fails. Only\n"
- "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
- #endif
- #endif
- #endif /* /MODULE */
- /* _GPL only for new symbols. */
- EXPORT_SYMBOL(sis_malloc);
- EXPORT_SYMBOL(sis_free);
- EXPORT_SYMBOL_GPL(sis_malloc_new);
- EXPORT_SYMBOL_GPL(sis_free_new);
|