sis_main.c 193 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126
  1. /*
  2. * SiS 300/540/630[S]/730[S],
  3. * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX],
  4. * XGI V3XT/V5/V8, Z7
  5. * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
  6. *
  7. * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the named License,
  12. * or any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
  22. *
  23. * Author: Thomas Winischhofer <thomas@winischhofer.net>
  24. *
  25. * Author of (practically wiped) code base:
  26. * SiS (www.sis.com)
  27. * Copyright (C) 1999 Silicon Integrated Systems, Inc.
  28. *
  29. * See http://www.winischhofer.net/ for more information and updates
  30. *
  31. * Originally based on the VBE 2.0 compliant graphic boards framebuffer driver,
  32. * which is (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
  33. *
  34. */
  35. #include <linux/version.h>
  36. #include <linux/module.h>
  37. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
  38. #include <linux/moduleparam.h>
  39. #endif
  40. #include <linux/kernel.h>
  41. #include <linux/smp_lock.h>
  42. #include <linux/spinlock.h>
  43. #include <linux/errno.h>
  44. #include <linux/string.h>
  45. #include <linux/mm.h>
  46. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
  47. #include <linux/tty.h>
  48. #else
  49. #include <linux/screen_info.h>
  50. #endif
  51. #include <linux/slab.h>
  52. #include <linux/fb.h>
  53. #include <linux/selection.h>
  54. #include <linux/ioport.h>
  55. #include <linux/init.h>
  56. #include <linux/pci.h>
  57. #include <linux/vmalloc.h>
  58. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
  59. #include <linux/vt_kern.h>
  60. #endif
  61. #include <linux/capability.h>
  62. #include <linux/fs.h>
  63. #include <linux/types.h>
  64. #include <asm/uaccess.h>
  65. #include <asm/io.h>
  66. #ifdef CONFIG_MTRR
  67. #include <asm/mtrr.h>
  68. #endif
  69. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
  70. #include <video/fbcon.h>
  71. #include <video/fbcon-cfb8.h>
  72. #include <video/fbcon-cfb16.h>
  73. #include <video/fbcon-cfb24.h>
  74. #include <video/fbcon-cfb32.h>
  75. #endif
  76. #include "sis.h"
  77. #include "sis_main.h"
  78. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
  79. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3)
  80. #error "This version of sisfb requires at least 2.6.3"
  81. #endif
  82. #endif
  83. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
  84. #ifdef FBCON_HAS_CFB8
  85. extern struct display_switch fbcon_sis8;
  86. #endif
  87. #ifdef FBCON_HAS_CFB16
  88. extern struct display_switch fbcon_sis16;
  89. #endif
  90. #ifdef FBCON_HAS_CFB32
  91. extern struct display_switch fbcon_sis32;
  92. #endif
  93. #endif
  94. static void sisfb_handle_command(struct sis_video_info *ivideo,
  95. struct sisfb_cmd *sisfb_command);
  96. /* ------------------ Internal helper routines ----------------- */
  97. static void __init
  98. sisfb_setdefaultparms(void)
  99. {
  100. sisfb_off = 0;
  101. sisfb_parm_mem = 0;
  102. sisfb_accel = -1;
  103. sisfb_ypan = -1;
  104. sisfb_max = -1;
  105. sisfb_userom = -1;
  106. sisfb_useoem = -1;
  107. #ifdef MODULE
  108. /* Module: "None" for 2.4, default mode for 2.5+ */
  109. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
  110. sisfb_mode_idx = -1;
  111. #else
  112. sisfb_mode_idx = MODE_INDEX_NONE;
  113. #endif
  114. #else
  115. /* Static: Default mode */
  116. sisfb_mode_idx = -1;
  117. #endif
  118. sisfb_parm_rate = -1;
  119. sisfb_crt1off = 0;
  120. sisfb_forcecrt1 = -1;
  121. sisfb_crt2type = -1;
  122. sisfb_crt2flags = 0;
  123. sisfb_pdc = 0xff;
  124. sisfb_pdca = 0xff;
  125. sisfb_scalelcd = -1;
  126. sisfb_specialtiming = CUT_NONE;
  127. sisfb_lvdshl = -1;
  128. sisfb_dstn = 0;
  129. sisfb_fstn = 0;
  130. sisfb_tvplug = -1;
  131. sisfb_tvstd = -1;
  132. sisfb_tvxposoffset = 0;
  133. sisfb_tvyposoffset = 0;
  134. sisfb_nocrt2rate = 0;
  135. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
  136. sisfb_inverse = 0;
  137. sisfb_fontname[0] = 0;
  138. #endif
  139. #if !defined(__i386__) && !defined(__x86_64__)
  140. sisfb_resetcard = 0;
  141. sisfb_videoram = 0;
  142. #endif
  143. }
  144. /* ------------- Parameter parsing -------------- */
  145. static void __devinit
  146. sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet)
  147. {
  148. int i = 0, j = 0;
  149. /* We don't know the hardware specs yet and there is no ivideo */
  150. if(vesamode == 0) {
  151. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
  152. sisfb_mode_idx = MODE_INDEX_NONE;
  153. #else
  154. if(!quiet)
  155. printk(KERN_ERR "sisfb: Invalid mode. Using default.\n");
  156. sisfb_mode_idx = DEFAULT_MODE;
  157. #endif
  158. return;
  159. }
  160. vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
  161. while(sisbios_mode[i++].mode_no[0] != 0) {
  162. if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) ||
  163. (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) {
  164. if(sisfb_fstn) {
  165. if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
  166. sisbios_mode[i-1].mode_no[1] == 0x56 ||
  167. sisbios_mode[i-1].mode_no[1] == 0x53)
  168. continue;
  169. } else {
  170. if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
  171. sisbios_mode[i-1].mode_no[1] == 0x5b)
  172. continue;
  173. }
  174. sisfb_mode_idx = i - 1;
  175. j = 1;
  176. break;
  177. }
  178. }
  179. if((!j) && !quiet)
  180. printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
  181. }
  182. static void __devinit
  183. sisfb_search_mode(char *name, BOOLEAN quiet)
  184. {
  185. unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
  186. int i = 0;
  187. char strbuf[16], strbuf1[20];
  188. char *nameptr = name;
  189. /* We don't know the hardware specs yet and there is no ivideo */
  190. if(name == NULL) {
  191. if(!quiet)
  192. printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
  193. sisfb_mode_idx = DEFAULT_MODE;
  194. return;
  195. }
  196. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
  197. if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
  198. if(!quiet)
  199. printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
  200. sisfb_mode_idx = DEFAULT_MODE;
  201. return;
  202. }
  203. #endif
  204. if(strlen(name) <= 19) {
  205. strcpy(strbuf1, name);
  206. for(i = 0; i < strlen(strbuf1); i++) {
  207. if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
  208. }
  209. /* This does some fuzzy mode naming detection */
  210. if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
  211. if((rate <= 32) || (depth > 32)) {
  212. j = rate; rate = depth; depth = j;
  213. }
  214. sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
  215. nameptr = strbuf;
  216. sisfb_parm_rate = rate;
  217. } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
  218. sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
  219. nameptr = strbuf;
  220. } else {
  221. xres = 0;
  222. if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
  223. sprintf(strbuf, "%ux%ux8", xres, yres);
  224. nameptr = strbuf;
  225. } else {
  226. sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
  227. return;
  228. }
  229. }
  230. }
  231. i = 0; j = 0;
  232. while(sisbios_mode[i].mode_no[0] != 0) {
  233. if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
  234. if(sisfb_fstn) {
  235. if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
  236. sisbios_mode[i-1].mode_no[1] == 0x56 ||
  237. sisbios_mode[i-1].mode_no[1] == 0x53)
  238. continue;
  239. } else {
  240. if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
  241. sisbios_mode[i-1].mode_no[1] == 0x5b)
  242. continue;
  243. }
  244. sisfb_mode_idx = i - 1;
  245. j = 1;
  246. break;
  247. }
  248. }
  249. if((!j) && !quiet)
  250. printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
  251. }
  252. #ifndef MODULE
  253. static void __devinit
  254. sisfb_get_vga_mode_from_kernel(void)
  255. {
  256. #ifdef CONFIG_X86
  257. char mymode[32];
  258. int mydepth = screen_info.lfb_depth;
  259. if(screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return;
  260. if( (screen_info.lfb_width >= 320) && (screen_info.lfb_width <= 2048) &&
  261. (screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) &&
  262. (mydepth >= 8) && (mydepth <= 32) ) {
  263. if(mydepth == 24) mydepth = 32;
  264. sprintf(mymode, "%ux%ux%u", screen_info.lfb_width,
  265. screen_info.lfb_height,
  266. mydepth);
  267. printk(KERN_DEBUG
  268. "sisfb: Using vga mode %s pre-set by kernel as default\n",
  269. mymode);
  270. sisfb_search_mode(mymode, TRUE);
  271. }
  272. #endif
  273. return;
  274. }
  275. #endif
  276. static void __init
  277. sisfb_search_crt2type(const char *name)
  278. {
  279. int i = 0;
  280. /* We don't know the hardware specs yet and there is no ivideo */
  281. if(name == NULL) return;
  282. while(sis_crt2type[i].type_no != -1) {
  283. if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
  284. sisfb_crt2type = sis_crt2type[i].type_no;
  285. sisfb_tvplug = sis_crt2type[i].tvplug_no;
  286. sisfb_crt2flags = sis_crt2type[i].flags;
  287. break;
  288. }
  289. i++;
  290. }
  291. sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0;
  292. sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0;
  293. if(sisfb_crt2type < 0)
  294. printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
  295. }
  296. static void __init
  297. sisfb_search_tvstd(const char *name)
  298. {
  299. int i = 0;
  300. /* We don't know the hardware specs yet and there is no ivideo */
  301. if(name == NULL)
  302. return;
  303. while(sis_tvtype[i].type_no != -1) {
  304. if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
  305. sisfb_tvstd = sis_tvtype[i].type_no;
  306. break;
  307. }
  308. i++;
  309. }
  310. }
  311. static void __init
  312. sisfb_search_specialtiming(const char *name)
  313. {
  314. int i = 0;
  315. BOOLEAN found = FALSE;
  316. /* We don't know the hardware specs yet and there is no ivideo */
  317. if(name == NULL)
  318. return;
  319. if(!strnicmp(name, "none", 4)) {
  320. sisfb_specialtiming = CUT_FORCENONE;
  321. printk(KERN_DEBUG "sisfb: Special timing disabled\n");
  322. } else {
  323. while(mycustomttable[i].chipID != 0) {
  324. if(!strnicmp(name,mycustomttable[i].optionName,
  325. strlen(mycustomttable[i].optionName))) {
  326. sisfb_specialtiming = mycustomttable[i].SpecialID;
  327. found = TRUE;
  328. printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
  329. mycustomttable[i].vendorName,
  330. mycustomttable[i].cardName,
  331. mycustomttable[i].optionName);
  332. break;
  333. }
  334. i++;
  335. }
  336. if(!found) {
  337. printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
  338. printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
  339. i = 0;
  340. while(mycustomttable[i].chipID != 0) {
  341. printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
  342. mycustomttable[i].optionName,
  343. mycustomttable[i].vendorName,
  344. mycustomttable[i].cardName);
  345. i++;
  346. }
  347. }
  348. }
  349. }
  350. /* ----------- Various detection routines ----------- */
  351. static void __devinit
  352. sisfb_detect_custom_timing(struct sis_video_info *ivideo)
  353. {
  354. unsigned char *biosver = NULL;
  355. unsigned char *biosdate = NULL;
  356. BOOLEAN footprint;
  357. u32 chksum = 0;
  358. int i, j;
  359. if(ivideo->SiS_Pr.UseROM) {
  360. biosver = ivideo->SiS_Pr.VirtualRomBase + 0x06;
  361. biosdate = ivideo->SiS_Pr.VirtualRomBase + 0x2c;
  362. for(i = 0; i < 32768; i++)
  363. chksum += ivideo->SiS_Pr.VirtualRomBase[i];
  364. }
  365. i = 0;
  366. do {
  367. if( (mycustomttable[i].chipID == ivideo->chip) &&
  368. ((!strlen(mycustomttable[i].biosversion)) ||
  369. (ivideo->SiS_Pr.UseROM &&
  370. (!strncmp(mycustomttable[i].biosversion, biosver,
  371. strlen(mycustomttable[i].biosversion))))) &&
  372. ((!strlen(mycustomttable[i].biosdate)) ||
  373. (ivideo->SiS_Pr.UseROM &&
  374. (!strncmp(mycustomttable[i].biosdate, biosdate,
  375. strlen(mycustomttable[i].biosdate))))) &&
  376. ((!mycustomttable[i].bioschksum) ||
  377. (ivideo->SiS_Pr.UseROM &&
  378. (mycustomttable[i].bioschksum == chksum))) &&
  379. (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
  380. (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
  381. footprint = TRUE;
  382. for(j = 0; j < 5; j++) {
  383. if(mycustomttable[i].biosFootprintAddr[j]) {
  384. if(ivideo->SiS_Pr.UseROM) {
  385. if(ivideo->SiS_Pr.VirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
  386. mycustomttable[i].biosFootprintData[j]) {
  387. footprint = FALSE;
  388. }
  389. } else
  390. footprint = FALSE;
  391. }
  392. }
  393. if(footprint) {
  394. ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
  395. printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
  396. mycustomttable[i].vendorName,
  397. mycustomttable[i].cardName);
  398. printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n",
  399. mycustomttable[i].optionName);
  400. break;
  401. }
  402. }
  403. i++;
  404. } while(mycustomttable[i].chipID);
  405. }
  406. static BOOLEAN __devinit
  407. sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
  408. {
  409. int i, j, xres, yres, refresh, index;
  410. u32 emodes;
  411. if(buffer[0] != 0x00 || buffer[1] != 0xff ||
  412. buffer[2] != 0xff || buffer[3] != 0xff ||
  413. buffer[4] != 0xff || buffer[5] != 0xff ||
  414. buffer[6] != 0xff || buffer[7] != 0x00) {
  415. printk(KERN_DEBUG "sisfb: Bad EDID header\n");
  416. return FALSE;
  417. }
  418. if(buffer[0x12] != 0x01) {
  419. printk(KERN_INFO "sisfb: EDID version %d not supported\n",
  420. buffer[0x12]);
  421. return FALSE;
  422. }
  423. monitor->feature = buffer[0x18];
  424. if(!buffer[0x14] & 0x80) {
  425. if(!(buffer[0x14] & 0x08)) {
  426. printk(KERN_INFO
  427. "sisfb: WARNING: Monitor does not support separate syncs\n");
  428. }
  429. }
  430. if(buffer[0x13] >= 0x01) {
  431. /* EDID V1 rev 1 and 2: Search for monitor descriptor
  432. * to extract ranges
  433. */
  434. j = 0x36;
  435. for(i=0; i<4; i++) {
  436. if(buffer[j] == 0x00 && buffer[j + 1] == 0x00 &&
  437. buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd &&
  438. buffer[j + 4] == 0x00) {
  439. monitor->hmin = buffer[j + 7];
  440. monitor->hmax = buffer[j + 8];
  441. monitor->vmin = buffer[j + 5];
  442. monitor->vmax = buffer[j + 6];
  443. monitor->dclockmax = buffer[j + 9] * 10 * 1000;
  444. monitor->datavalid = TRUE;
  445. break;
  446. }
  447. j += 18;
  448. }
  449. }
  450. if(!monitor->datavalid) {
  451. /* Otherwise: Get a range from the list of supported
  452. * Estabished Timings. This is not entirely accurate,
  453. * because fixed frequency monitors are not supported
  454. * that way.
  455. */
  456. monitor->hmin = 65535; monitor->hmax = 0;
  457. monitor->vmin = 65535; monitor->vmax = 0;
  458. monitor->dclockmax = 0;
  459. emodes = buffer[0x23] | (buffer[0x24] << 8) | (buffer[0x25] << 16);
  460. for(i = 0; i < 13; i++) {
  461. if(emodes & sisfb_ddcsmodes[i].mask) {
  462. if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h;
  463. if(monitor->hmax < sisfb_ddcsmodes[i].h) monitor->hmax = sisfb_ddcsmodes[i].h + 1;
  464. if(monitor->vmin > sisfb_ddcsmodes[i].v) monitor->vmin = sisfb_ddcsmodes[i].v;
  465. if(monitor->vmax < sisfb_ddcsmodes[i].v) monitor->vmax = sisfb_ddcsmodes[i].v;
  466. if(monitor->dclockmax < sisfb_ddcsmodes[i].d) monitor->dclockmax = sisfb_ddcsmodes[i].d;
  467. }
  468. }
  469. index = 0x26;
  470. for(i = 0; i < 8; i++) {
  471. xres = (buffer[index] + 31) * 8;
  472. switch(buffer[index + 1] & 0xc0) {
  473. case 0xc0: yres = (xres * 9) / 16; break;
  474. case 0x80: yres = (xres * 4) / 5; break;
  475. case 0x40: yres = (xres * 3) / 4; break;
  476. default: yres = xres; break;
  477. }
  478. refresh = (buffer[index + 1] & 0x3f) + 60;
  479. if((xres >= 640) && (yres >= 480)) {
  480. for(j = 0; j < 8; j++) {
  481. if((xres == sisfb_ddcfmodes[j].x) &&
  482. (yres == sisfb_ddcfmodes[j].y) &&
  483. (refresh == sisfb_ddcfmodes[j].v)) {
  484. if(monitor->hmin > sisfb_ddcfmodes[j].h) monitor->hmin = sisfb_ddcfmodes[j].h;
  485. if(monitor->hmax < sisfb_ddcfmodes[j].h) monitor->hmax = sisfb_ddcfmodes[j].h + 1;
  486. if(monitor->vmin > sisfb_ddcsmodes[j].v) monitor->vmin = sisfb_ddcsmodes[j].v;
  487. if(monitor->vmax < sisfb_ddcsmodes[j].v) monitor->vmax = sisfb_ddcsmodes[j].v;
  488. if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[j].d;
  489. }
  490. }
  491. }
  492. index += 2;
  493. }
  494. if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) {
  495. monitor->datavalid = TRUE;
  496. }
  497. }
  498. return monitor->datavalid;
  499. }
  500. static void __devinit
  501. sisfb_handle_ddc(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, int crtno)
  502. {
  503. unsigned short temp, i, realcrtno = crtno;
  504. unsigned char buffer[256];
  505. monitor->datavalid = FALSE;
  506. if(crtno) {
  507. if(ivideo->vbflags & CRT2_LCD) realcrtno = 1;
  508. else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2;
  509. else return;
  510. }
  511. if((ivideo->sisfb_crt1off) && (!crtno))
  512. return;
  513. temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
  514. realcrtno, 0, &buffer[0], ivideo->vbflags2);
  515. if((!temp) || (temp == 0xffff)) {
  516. printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
  517. return;
  518. } else {
  519. printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1);
  520. printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n",
  521. crtno + 1,
  522. (temp & 0x1a) ? "" : "[none of the supported]",
  523. (temp & 0x02) ? "2 " : "",
  524. (temp & 0x08) ? "D&P" : "",
  525. (temp & 0x10) ? "FPDI-2" : "");
  526. if(temp & 0x02) {
  527. i = 3; /* Number of retrys */
  528. do {
  529. temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
  530. realcrtno, 1, &buffer[0], ivideo->vbflags2);
  531. } while((temp) && i--);
  532. if(!temp) {
  533. if(sisfb_interpret_edid(monitor, &buffer[0])) {
  534. printk(KERN_INFO "sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
  535. monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax,
  536. monitor->dclockmax / 1000);
  537. } else {
  538. printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1);
  539. }
  540. } else {
  541. printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1);
  542. }
  543. } else {
  544. printk(KERN_INFO "sisfb: VESA D&P and FPDI-2 not supported yet\n");
  545. }
  546. }
  547. }
  548. /* -------------- Mode validation --------------- */
  549. static BOOLEAN
  550. sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
  551. int mode_idx, int rate_idx, int rate)
  552. {
  553. int htotal, vtotal;
  554. unsigned int dclock, hsync;
  555. if(!monitor->datavalid)
  556. return TRUE;
  557. if(mode_idx < 0)
  558. return FALSE;
  559. /* Skip for 320x200, 320x240, 640x400 */
  560. switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) {
  561. case 0x59:
  562. case 0x41:
  563. case 0x4f:
  564. case 0x50:
  565. case 0x56:
  566. case 0x53:
  567. case 0x2f:
  568. case 0x5d:
  569. case 0x5e:
  570. return TRUE;
  571. #ifdef CONFIG_FB_SIS_315
  572. case 0x5a:
  573. case 0x5b:
  574. if(ivideo->sisvga_engine == SIS_315_VGA) return TRUE;
  575. #endif
  576. }
  577. if(rate < (monitor->vmin - 1))
  578. return FALSE;
  579. if(rate > (monitor->vmax + 1))
  580. return FALSE;
  581. if(sisfb_gettotalfrommode(&ivideo->SiS_Pr,
  582. sisbios_mode[mode_idx].mode_no[ivideo->mni],
  583. &htotal, &vtotal, rate_idx)) {
  584. dclock = (htotal * vtotal * rate) / 1000;
  585. if(dclock > (monitor->dclockmax + 1000))
  586. return FALSE;
  587. hsync = dclock / htotal;
  588. if(hsync < (monitor->hmin - 1))
  589. return FALSE;
  590. if(hsync > (monitor->hmax + 1))
  591. return FALSE;
  592. } else {
  593. return FALSE;
  594. }
  595. return TRUE;
  596. }
  597. static int
  598. sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
  599. {
  600. u16 xres=0, yres, myres;
  601. #ifdef CONFIG_FB_SIS_300
  602. if(ivideo->sisvga_engine == SIS_300_VGA) {
  603. if(!(sisbios_mode[myindex].chipset & MD_SIS300))
  604. return -1 ;
  605. }
  606. #endif
  607. #ifdef CONFIG_FB_SIS_315
  608. if(ivideo->sisvga_engine == SIS_315_VGA) {
  609. if(!(sisbios_mode[myindex].chipset & MD_SIS315))
  610. return -1;
  611. }
  612. #endif
  613. myres = sisbios_mode[myindex].yres;
  614. switch(vbflags & VB_DISPTYPE_DISP2) {
  615. case CRT2_LCD:
  616. xres = ivideo->lcdxres; yres = ivideo->lcdyres;
  617. if((ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) &&
  618. (ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL856)) {
  619. if(sisbios_mode[myindex].xres > xres)
  620. return -1;
  621. if(myres > yres)
  622. return -1;
  623. }
  624. if(ivideo->sisfb_fstn) {
  625. if(sisbios_mode[myindex].xres == 320) {
  626. if(myres == 240) {
  627. switch(sisbios_mode[myindex].mode_no[1]) {
  628. case 0x50: myindex = MODE_FSTN_8; break;
  629. case 0x56: myindex = MODE_FSTN_16; break;
  630. case 0x53: return -1;
  631. }
  632. }
  633. }
  634. }
  635. if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
  636. sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn,
  637. ivideo->SiS_Pr.SiS_CustomT, xres, yres, ivideo->vbflags2) < 0x14) {
  638. return -1;
  639. }
  640. break;
  641. case CRT2_TV:
  642. if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
  643. sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
  644. return -1;
  645. }
  646. break;
  647. case CRT2_VGA:
  648. if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
  649. sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
  650. return -1;
  651. }
  652. break;
  653. }
  654. return myindex;
  655. }
  656. static u8
  657. sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx)
  658. {
  659. int i = 0;
  660. u16 xres = sisbios_mode[mode_idx].xres;
  661. u16 yres = sisbios_mode[mode_idx].yres;
  662. ivideo->rate_idx = 0;
  663. while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
  664. if((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) {
  665. if(sisfb_vrate[i].refresh == rate) {
  666. ivideo->rate_idx = sisfb_vrate[i].idx;
  667. break;
  668. } else if(sisfb_vrate[i].refresh > rate) {
  669. if((sisfb_vrate[i].refresh - rate) <= 3) {
  670. DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
  671. rate, sisfb_vrate[i].refresh);
  672. ivideo->rate_idx = sisfb_vrate[i].idx;
  673. ivideo->refresh_rate = sisfb_vrate[i].refresh;
  674. } else if(((rate - sisfb_vrate[i-1].refresh) <= 2)
  675. && (sisfb_vrate[i].idx != 1)) {
  676. DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
  677. rate, sisfb_vrate[i-1].refresh);
  678. ivideo->rate_idx = sisfb_vrate[i-1].idx;
  679. ivideo->refresh_rate = sisfb_vrate[i-1].refresh;
  680. }
  681. break;
  682. } else if((rate - sisfb_vrate[i].refresh) <= 2) {
  683. DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
  684. rate, sisfb_vrate[i].refresh);
  685. ivideo->rate_idx = sisfb_vrate[i].idx;
  686. break;
  687. }
  688. }
  689. i++;
  690. }
  691. if(ivideo->rate_idx > 0) {
  692. return ivideo->rate_idx;
  693. } else {
  694. printk(KERN_INFO "sisfb: Unsupported rate %d for %dx%d\n",
  695. rate, xres, yres);
  696. return 0;
  697. }
  698. }
  699. static BOOLEAN
  700. sisfb_bridgeisslave(struct sis_video_info *ivideo)
  701. {
  702. unsigned char P1_00;
  703. if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE))
  704. return FALSE;
  705. inSISIDXREG(SISPART1,0x00,P1_00);
  706. if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
  707. ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
  708. return TRUE;
  709. } else {
  710. return FALSE;
  711. }
  712. }
  713. static BOOLEAN
  714. sisfballowretracecrt1(struct sis_video_info *ivideo)
  715. {
  716. u8 temp;
  717. inSISIDXREG(SISCR,0x17,temp);
  718. if(!(temp & 0x80))
  719. return FALSE;
  720. inSISIDXREG(SISSR,0x1f,temp);
  721. if(temp & 0xc0)
  722. return FALSE;
  723. return TRUE;
  724. }
  725. static BOOLEAN
  726. sisfbcheckvretracecrt1(struct sis_video_info *ivideo)
  727. {
  728. if(!sisfballowretracecrt1(ivideo))
  729. return FALSE;
  730. if(inSISREG(SISINPSTAT) & 0x08)
  731. return TRUE;
  732. else
  733. return FALSE;
  734. }
  735. static void
  736. sisfbwaitretracecrt1(struct sis_video_info *ivideo)
  737. {
  738. int watchdog;
  739. if(!sisfballowretracecrt1(ivideo))
  740. return;
  741. watchdog = 65536;
  742. while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog);
  743. watchdog = 65536;
  744. while((inSISREG(SISINPSTAT) & 0x08) && --watchdog);
  745. }
  746. static BOOLEAN
  747. sisfbcheckvretracecrt2(struct sis_video_info *ivideo)
  748. {
  749. unsigned char temp, reg;
  750. switch(ivideo->sisvga_engine) {
  751. case SIS_300_VGA: reg = 0x25; break;
  752. case SIS_315_VGA: reg = 0x30; break;
  753. default: return FALSE;
  754. }
  755. inSISIDXREG(SISPART1, reg, temp);
  756. if(temp & 0x02)
  757. return TRUE;
  758. else
  759. return FALSE;
  760. }
  761. static BOOLEAN
  762. sisfb_CheckVBRetrace(struct sis_video_info *ivideo)
  763. {
  764. if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
  765. if(!sisfb_bridgeisslave(ivideo)) {
  766. return sisfbcheckvretracecrt2(ivideo);
  767. }
  768. }
  769. return sisfbcheckvretracecrt1(ivideo);
  770. }
  771. static u32
  772. sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount)
  773. {
  774. u8 idx, reg1, reg2, reg3, reg4;
  775. u32 ret = 0;
  776. (*vcount) = (*hcount) = 0;
  777. if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) {
  778. ret |= (FB_VBLANK_HAVE_VSYNC |
  779. FB_VBLANK_HAVE_HBLANK |
  780. FB_VBLANK_HAVE_VBLANK |
  781. FB_VBLANK_HAVE_VCOUNT |
  782. FB_VBLANK_HAVE_HCOUNT);
  783. switch(ivideo->sisvga_engine) {
  784. case SIS_300_VGA: idx = 0x25; break;
  785. default:
  786. case SIS_315_VGA: idx = 0x30; break;
  787. }
  788. inSISIDXREG(SISPART1,(idx+0),reg1); /* 30 */
  789. inSISIDXREG(SISPART1,(idx+1),reg2); /* 31 */
  790. inSISIDXREG(SISPART1,(idx+2),reg3); /* 32 */
  791. inSISIDXREG(SISPART1,(idx+3),reg4); /* 33 */
  792. if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
  793. if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING;
  794. if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING;
  795. (*vcount) = reg3 | ((reg4 & 0x70) << 4);
  796. (*hcount) = reg2 | ((reg4 & 0x0f) << 8);
  797. } else if(sisfballowretracecrt1(ivideo)) {
  798. ret |= (FB_VBLANK_HAVE_VSYNC |
  799. FB_VBLANK_HAVE_VBLANK |
  800. FB_VBLANK_HAVE_VCOUNT |
  801. FB_VBLANK_HAVE_HCOUNT);
  802. reg1 = inSISREG(SISINPSTAT);
  803. if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
  804. if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
  805. inSISIDXREG(SISCR,0x20,reg1);
  806. inSISIDXREG(SISCR,0x1b,reg1);
  807. inSISIDXREG(SISCR,0x1c,reg2);
  808. inSISIDXREG(SISCR,0x1d,reg3);
  809. (*vcount) = reg2 | ((reg3 & 0x07) << 8);
  810. (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
  811. }
  812. return ret;
  813. }
  814. static int
  815. sisfb_myblank(struct sis_video_info *ivideo, int blank)
  816. {
  817. u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
  818. BOOLEAN backlight = TRUE;
  819. switch(blank) {
  820. case FB_BLANK_UNBLANK: /* on */
  821. sr01 = 0x00;
  822. sr11 = 0x00;
  823. sr1f = 0x00;
  824. cr63 = 0x00;
  825. p2_0 = 0x20;
  826. p1_13 = 0x00;
  827. backlight = TRUE;
  828. break;
  829. case FB_BLANK_NORMAL: /* blank */
  830. sr01 = 0x20;
  831. sr11 = 0x00;
  832. sr1f = 0x00;
  833. cr63 = 0x00;
  834. p2_0 = 0x20;
  835. p1_13 = 0x00;
  836. backlight = TRUE;
  837. break;
  838. case FB_BLANK_VSYNC_SUSPEND: /* no vsync */
  839. sr01 = 0x20;
  840. sr11 = 0x08;
  841. sr1f = 0x80;
  842. cr63 = 0x40;
  843. p2_0 = 0x40;
  844. p1_13 = 0x80;
  845. backlight = FALSE;
  846. break;
  847. case FB_BLANK_HSYNC_SUSPEND: /* no hsync */
  848. sr01 = 0x20;
  849. sr11 = 0x08;
  850. sr1f = 0x40;
  851. cr63 = 0x40;
  852. p2_0 = 0x80;
  853. p1_13 = 0x40;
  854. backlight = FALSE;
  855. break;
  856. case FB_BLANK_POWERDOWN: /* off */
  857. sr01 = 0x20;
  858. sr11 = 0x08;
  859. sr1f = 0xc0;
  860. cr63 = 0x40;
  861. p2_0 = 0xc0;
  862. p1_13 = 0xc0;
  863. backlight = FALSE;
  864. break;
  865. default:
  866. return 1;
  867. }
  868. if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) {
  869. if( (!ivideo->sisfb_thismonitor.datavalid) ||
  870. ((ivideo->sisfb_thismonitor.datavalid) &&
  871. (ivideo->sisfb_thismonitor.feature & 0xe0))) {
  872. if(ivideo->sisvga_engine == SIS_315_VGA) {
  873. setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
  874. }
  875. if(!(sisfb_bridgeisslave(ivideo))) {
  876. setSISIDXREG(SISSR, 0x01, ~0x20, sr01);
  877. setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f);
  878. }
  879. }
  880. }
  881. if(ivideo->currentvbflags & CRT2_LCD) {
  882. if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
  883. if(backlight) {
  884. SiS_SiS30xBLOn(&ivideo->SiS_Pr);
  885. } else {
  886. SiS_SiS30xBLOff(&ivideo->SiS_Pr);
  887. }
  888. } else if(ivideo->sisvga_engine == SIS_315_VGA) {
  889. #ifdef CONFIG_FB_SIS_315
  890. if(ivideo->vbflags2 & VB2_CHRONTEL) {
  891. if(backlight) {
  892. SiS_Chrontel701xBLOn(&ivideo->SiS_Pr);
  893. } else {
  894. SiS_Chrontel701xBLOff(&ivideo->SiS_Pr);
  895. }
  896. }
  897. #endif
  898. }
  899. if(((ivideo->sisvga_engine == SIS_300_VGA) &&
  900. (ivideo->vbflags2 & (VB2_301|VB2_30xBDH|VB2_LVDS))) ||
  901. ((ivideo->sisvga_engine == SIS_315_VGA) &&
  902. ((ivideo->vbflags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS))) {
  903. setSISIDXREG(SISSR, 0x11, ~0x0c, sr11);
  904. }
  905. if(ivideo->sisvga_engine == SIS_300_VGA) {
  906. if((ivideo->vbflags2 & VB2_30xB) &&
  907. (!(ivideo->vbflags2 & VB2_30xBDH))) {
  908. setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13);
  909. }
  910. } else if(ivideo->sisvga_engine == SIS_315_VGA) {
  911. if((ivideo->vbflags2 & VB2_30xB) &&
  912. (!(ivideo->vbflags2 & VB2_30xBDH))) {
  913. setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
  914. }
  915. }
  916. } else if(ivideo->currentvbflags & CRT2_VGA) {
  917. if(ivideo->vbflags2 & VB2_30xB) {
  918. setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
  919. }
  920. }
  921. return 0;
  922. }
  923. /* ------------- Callbacks from init.c/init301.c -------------- */
  924. #ifdef CONFIG_FB_SIS_300
  925. unsigned int
  926. sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg)
  927. {
  928. struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
  929. u32 val = 0;
  930. pci_read_config_dword(ivideo->nbridge, reg, &val);
  931. return (unsigned int)val;
  932. }
  933. void
  934. sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val)
  935. {
  936. struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
  937. pci_write_config_dword(ivideo->nbridge, reg, (u32)val);
  938. }
  939. unsigned int
  940. sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg)
  941. {
  942. struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
  943. u32 val = 0;
  944. if(!ivideo->lpcdev) return 0;
  945. pci_read_config_dword(ivideo->lpcdev, reg, &val);
  946. return (unsigned int)val;
  947. }
  948. #endif
  949. #ifdef CONFIG_FB_SIS_315
  950. void
  951. sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val)
  952. {
  953. struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
  954. pci_write_config_byte(ivideo->nbridge, reg, (u8)val);
  955. }
  956. unsigned int
  957. sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg)
  958. {
  959. struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
  960. u16 val = 0;
  961. if(!ivideo->lpcdev) return 0;
  962. pci_read_config_word(ivideo->lpcdev, reg, &val);
  963. return (unsigned int)val;
  964. }
  965. #endif
  966. /* ----------- FBDev related routines for all series ----------- */
  967. static int
  968. sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
  969. {
  970. return (var->bits_per_pixel == 8) ? 256 : 16;
  971. }
  972. static void
  973. sisfb_set_vparms(struct sis_video_info *ivideo)
  974. {
  975. switch(ivideo->video_bpp) {
  976. case 8:
  977. ivideo->DstColor = 0x0000;
  978. ivideo->SiS310_AccelDepth = 0x00000000;
  979. ivideo->video_cmap_len = 256;
  980. break;
  981. case 16:
  982. ivideo->DstColor = 0x8000;
  983. ivideo->SiS310_AccelDepth = 0x00010000;
  984. ivideo->video_cmap_len = 16;
  985. break;
  986. case 32:
  987. ivideo->DstColor = 0xC000;
  988. ivideo->SiS310_AccelDepth = 0x00020000;
  989. ivideo->video_cmap_len = 16;
  990. break;
  991. default:
  992. ivideo->video_cmap_len = 16;
  993. printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp);
  994. ivideo->accel = 0;
  995. }
  996. }
  997. static int
  998. sisfb_calc_maxyres(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
  999. {
  1000. int maxyres = ivideo->sisfb_mem / (var->xres_virtual * (var->bits_per_pixel >> 3));
  1001. if(maxyres > 32767) maxyres = 32767;
  1002. return maxyres;
  1003. }
  1004. static void
  1005. sisfb_calc_pitch(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
  1006. {
  1007. ivideo->video_linelength = var->xres_virtual * (var->bits_per_pixel >> 3);
  1008. ivideo->scrnpitchCRT1 = ivideo->video_linelength;
  1009. if(!(ivideo->currentvbflags & CRT1_LCDA)) {
  1010. if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
  1011. ivideo->scrnpitchCRT1 <<= 1;
  1012. }
  1013. }
  1014. }
  1015. static void
  1016. sisfb_set_pitch(struct sis_video_info *ivideo)
  1017. {
  1018. BOOLEAN isslavemode = FALSE;
  1019. unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3;
  1020. unsigned short HDisplay2 = ivideo->video_linelength >> 3;
  1021. if(sisfb_bridgeisslave(ivideo)) isslavemode = TRUE;
  1022. /* We need to set pitch for CRT1 if bridge is in slave mode, too */
  1023. if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
  1024. outSISIDXREG(SISCR,0x13,(HDisplay1 & 0xFF));
  1025. setSISIDXREG(SISSR,0x0E,0xF0,(HDisplay1 >> 8));
  1026. }
  1027. /* We must not set the pitch for CRT2 if bridge is in slave mode */
  1028. if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) {
  1029. orSISIDXREG(SISPART1,ivideo->CRT2_write_enable,0x01);
  1030. outSISIDXREG(SISPART1,0x07,(HDisplay2 & 0xFF));
  1031. setSISIDXREG(SISPART1,0x09,0xF0,(HDisplay2 >> 8));
  1032. }
  1033. }
  1034. static void
  1035. sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
  1036. {
  1037. ivideo->video_cmap_len = sisfb_get_cmap_len(var);
  1038. switch(var->bits_per_pixel) {
  1039. case 8:
  1040. var->red.offset = var->green.offset = var->blue.offset = 0;
  1041. var->red.length = var->green.length = var->blue.length = 6;
  1042. break;
  1043. case 16:
  1044. var->red.offset = 11;
  1045. var->red.length = 5;
  1046. var->green.offset = 5;
  1047. var->green.length = 6;
  1048. var->blue.offset = 0;
  1049. var->blue.length = 5;
  1050. var->transp.offset = 0;
  1051. var->transp.length = 0;
  1052. break;
  1053. case 32:
  1054. var->red.offset = 16;
  1055. var->red.length = 8;
  1056. var->green.offset = 8;
  1057. var->green.length = 8;
  1058. var->blue.offset = 0;
  1059. var->blue.length = 8;
  1060. var->transp.offset = 24;
  1061. var->transp.length = 8;
  1062. break;
  1063. }
  1064. }
  1065. static int
  1066. sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn)
  1067. {
  1068. unsigned short modeno = ivideo->mode_no;
  1069. /* >=2.6.12's fbcon clears the screen anyway */
  1070. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)
  1071. if(!clrscrn) modeno |= 0x80;
  1072. #else
  1073. modeno |= 0x80;
  1074. #endif
  1075. outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
  1076. sisfb_pre_setmode(ivideo);
  1077. if(SiSSetMode(&ivideo->SiS_Pr, modeno) == 0) {
  1078. printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
  1079. return -EINVAL;
  1080. }
  1081. outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
  1082. sisfb_post_setmode(ivideo);
  1083. return 0;
  1084. }
  1085. static int
  1086. sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info)
  1087. {
  1088. struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
  1089. unsigned int htotal = 0, vtotal = 0;
  1090. unsigned int drate = 0, hrate = 0;
  1091. int found_mode = 0, ret;
  1092. int old_mode;
  1093. u32 pixclock;
  1094. htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
  1095. vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
  1096. pixclock = var->pixclock;
  1097. if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
  1098. vtotal += var->yres;
  1099. vtotal <<= 1;
  1100. } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
  1101. vtotal += var->yres;
  1102. vtotal <<= 2;
  1103. } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
  1104. vtotal += var->yres;
  1105. vtotal <<= 1;
  1106. } else vtotal += var->yres;
  1107. if(!(htotal) || !(vtotal)) {
  1108. DPRINTK("sisfb: Invalid 'var' information\n");
  1109. return -EINVAL;
  1110. }
  1111. if(pixclock && htotal && vtotal) {
  1112. drate = 1000000000 / pixclock;
  1113. hrate = (drate * 1000) / htotal;
  1114. ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal);
  1115. } else {
  1116. ivideo->refresh_rate = 60;
  1117. }
  1118. old_mode = ivideo->sisfb_mode_idx;
  1119. ivideo->sisfb_mode_idx = 0;
  1120. while( (sisbios_mode[ivideo->sisfb_mode_idx].mode_no[0] != 0) &&
  1121. (sisbios_mode[ivideo->sisfb_mode_idx].xres <= var->xres) ) {
  1122. if( (sisbios_mode[ivideo->sisfb_mode_idx].xres == var->xres) &&
  1123. (sisbios_mode[ivideo->sisfb_mode_idx].yres == var->yres) &&
  1124. (sisbios_mode[ivideo->sisfb_mode_idx].bpp == var->bits_per_pixel)) {
  1125. ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
  1126. found_mode = 1;
  1127. break;
  1128. }
  1129. ivideo->sisfb_mode_idx++;
  1130. }
  1131. if(found_mode) {
  1132. ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
  1133. ivideo->sisfb_mode_idx, ivideo->currentvbflags);
  1134. ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
  1135. } else {
  1136. ivideo->sisfb_mode_idx = -1;
  1137. }
  1138. if(ivideo->sisfb_mode_idx < 0) {
  1139. printk(KERN_ERR "sisfb: Mode %dx%dx%d not supported\n", var->xres,
  1140. var->yres, var->bits_per_pixel);
  1141. ivideo->sisfb_mode_idx = old_mode;
  1142. return -EINVAL;
  1143. }
  1144. if(sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx) == 0) {
  1145. ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
  1146. ivideo->refresh_rate = 60;
  1147. }
  1148. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
  1149. if(ivideo->sisfb_thismonitor.datavalid) {
  1150. if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, ivideo->sisfb_mode_idx,
  1151. ivideo->rate_idx, ivideo->refresh_rate)) {
  1152. printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
  1153. }
  1154. }
  1155. #endif
  1156. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
  1157. if(((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) {
  1158. #else
  1159. if(isactive) {
  1160. #endif
  1161. /* If acceleration to be used? Need to know
  1162. * before pre/post_set_mode()
  1163. */
  1164. ivideo->accel = 0;
  1165. #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
  1166. #ifdef STUPID_ACCELF_TEXT_SHIT
  1167. if(var->accel_flags & FB_ACCELF_TEXT) {
  1168. info->flags &= ~FBINFO_HWACCEL_DISABLED;
  1169. } else {
  1170. info->flags |= FBINFO_HWACCEL_DISABLED;
  1171. }
  1172. #endif
  1173. if(!(info->flags & FBINFO_HWACCEL_DISABLED)) ivideo->accel = -1;
  1174. #else
  1175. if(var->accel_flags & FB_ACCELF_TEXT) ivideo->accel = -1;
  1176. #endif
  1177. if((ret = sisfb_set_mode(ivideo, 1))) {
  1178. return ret;
  1179. }
  1180. ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
  1181. ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
  1182. ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
  1183. sisfb_calc_pitch(ivideo, var);
  1184. sisfb_set_pitch(ivideo);
  1185. sisfb_set_vparms(ivideo);
  1186. ivideo->current_width = ivideo->video_width;
  1187. ivideo->current_height = ivideo->video_height;
  1188. ivideo->current_bpp = ivideo->video_bpp;
  1189. ivideo->current_htotal = htotal;
  1190. ivideo->current_vtotal = vtotal;
  1191. ivideo->current_linelength = ivideo->video_linelength;
  1192. ivideo->current_pixclock = var->pixclock;
  1193. ivideo->current_refresh_rate = ivideo->refresh_rate;
  1194. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
  1195. ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate;
  1196. #endif
  1197. }
  1198. return 0;
  1199. }
  1200. static void
  1201. sisfb_set_base_CRT1(struct sis_video_info *ivideo, unsigned int base)
  1202. {
  1203. outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
  1204. outSISIDXREG(SISCR, 0x0D, base & 0xFF);
  1205. outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF);
  1206. outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF);
  1207. if(ivideo->sisvga_engine == SIS_315_VGA) {
  1208. setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
  1209. }
  1210. }
  1211. static void
  1212. sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base)
  1213. {
  1214. if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
  1215. orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01);
  1216. outSISIDXREG(SISPART1, 0x06, (base & 0xFF));
  1217. outSISIDXREG(SISPART1, 0x05, ((base >> 8) & 0xFF));
  1218. outSISIDXREG(SISPART1, 0x04, ((base >> 16) & 0xFF));
  1219. if(ivideo->sisvga_engine == SIS_315_VGA) {
  1220. setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
  1221. }
  1222. }
  1223. }
  1224. static int
  1225. sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
  1226. {
  1227. if(var->xoffset > (var->xres_virtual - var->xres)) {
  1228. return -EINVAL;
  1229. }
  1230. if(var->yoffset > (var->yres_virtual - var->yres)) {
  1231. return -EINVAL;
  1232. }
  1233. ivideo->current_base = (var->yoffset * var->xres_virtual) + var->xoffset;
  1234. /* calculate base bpp dep. */
  1235. switch(var->bits_per_pixel) {
  1236. case 32:
  1237. break;
  1238. case 16:
  1239. ivideo->current_base >>= 1;
  1240. break;
  1241. case 8:
  1242. default:
  1243. ivideo->current_base >>= 2;
  1244. break;
  1245. }
  1246. ivideo->current_base += (ivideo->video_offset >> 2);
  1247. sisfb_set_base_CRT1(ivideo, ivideo->current_base);
  1248. sisfb_set_base_CRT2(ivideo, ivideo->current_base);
  1249. return 0;
  1250. }
  1251. /* ------------ FBDev related routines for 2.4 series ----------- */
  1252. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
  1253. #include "sisfb_fbdev_2_4.h"
  1254. #endif
  1255. /* ------------ FBDev related routines for 2.6 series ----------- */
  1256. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
  1257. static int
  1258. sisfb_open(struct fb_info *info, int user)
  1259. {
  1260. return 0;
  1261. }
  1262. static int
  1263. sisfb_release(struct fb_info *info, int user)
  1264. {
  1265. return 0;
  1266. }
  1267. static int
  1268. sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
  1269. unsigned transp, struct fb_info *info)
  1270. {
  1271. struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
  1272. if(regno >= sisfb_get_cmap_len(&info->var))
  1273. return 1;
  1274. switch(info->var.bits_per_pixel) {
  1275. case 8:
  1276. outSISREG(SISDACA, regno);
  1277. outSISREG(SISDACD, (red >> 10));
  1278. outSISREG(SISDACD, (green >> 10));
  1279. outSISREG(SISDACD, (blue >> 10));
  1280. if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
  1281. outSISREG(SISDAC2A, regno);
  1282. outSISREG(SISDAC2D, (red >> 8));
  1283. outSISREG(SISDAC2D, (green >> 8));
  1284. outSISREG(SISDAC2D, (blue >> 8));
  1285. }
  1286. break;
  1287. case 16:
  1288. ((u32 *)(info->pseudo_palette))[regno] =
  1289. (red & 0xf800) |
  1290. ((green & 0xfc00) >> 5) |
  1291. ((blue & 0xf800) >> 11);
  1292. break;
  1293. case 32:
  1294. red >>= 8;
  1295. green >>= 8;
  1296. blue >>= 8;
  1297. ((u32 *)(info->pseudo_palette))[regno] =
  1298. (red << 16) | (green << 8) | (blue);
  1299. break;
  1300. }
  1301. return 0;
  1302. }
  1303. static int
  1304. sisfb_set_par(struct fb_info *info)
  1305. {
  1306. int err;
  1307. if((err = sisfb_do_set_var(&info->var, 1, info)))
  1308. return err;
  1309. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
  1310. sisfb_get_fix(&info->fix, info->currcon, info);
  1311. #else
  1312. sisfb_get_fix(&info->fix, -1, info);
  1313. #endif
  1314. return 0;
  1315. }
  1316. static int
  1317. sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
  1318. {
  1319. struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
  1320. unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
  1321. unsigned int drate = 0, hrate = 0, maxyres;
  1322. int found_mode = 0;
  1323. int refresh_rate, search_idx, tidx;
  1324. BOOLEAN recalc_clock = FALSE;
  1325. u32 pixclock;
  1326. htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
  1327. vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
  1328. pixclock = var->pixclock;
  1329. if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
  1330. vtotal += var->yres;
  1331. vtotal <<= 1;
  1332. } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
  1333. vtotal += var->yres;
  1334. vtotal <<= 2;
  1335. } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
  1336. vtotal += var->yres;
  1337. vtotal <<= 1;
  1338. } else
  1339. vtotal += var->yres;
  1340. if(!(htotal) || !(vtotal)) {
  1341. SISFAIL("sisfb: no valid timing data");
  1342. }
  1343. search_idx = 0;
  1344. while( (sisbios_mode[search_idx].mode_no[0] != 0) &&
  1345. (sisbios_mode[search_idx].xres <= var->xres) ) {
  1346. if( (sisbios_mode[search_idx].xres == var->xres) &&
  1347. (sisbios_mode[search_idx].yres == var->yres) &&
  1348. (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) {
  1349. if((tidx = sisfb_validate_mode(ivideo, search_idx,
  1350. ivideo->currentvbflags)) > 0) {
  1351. found_mode = 1;
  1352. search_idx = tidx;
  1353. break;
  1354. }
  1355. }
  1356. search_idx++;
  1357. }
  1358. if(!found_mode) {
  1359. search_idx = 0;
  1360. while(sisbios_mode[search_idx].mode_no[0] != 0) {
  1361. if( (var->xres <= sisbios_mode[search_idx].xres) &&
  1362. (var->yres <= sisbios_mode[search_idx].yres) &&
  1363. (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) {
  1364. if((tidx = sisfb_validate_mode(ivideo,search_idx,
  1365. ivideo->currentvbflags)) > 0) {
  1366. found_mode = 1;
  1367. search_idx = tidx;
  1368. break;
  1369. }
  1370. }
  1371. search_idx++;
  1372. }
  1373. if(found_mode) {
  1374. printk(KERN_DEBUG
  1375. "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
  1376. var->xres, var->yres, var->bits_per_pixel,
  1377. sisbios_mode[search_idx].xres,
  1378. sisbios_mode[search_idx].yres,
  1379. var->bits_per_pixel);
  1380. var->xres = sisbios_mode[search_idx].xres;
  1381. var->yres = sisbios_mode[search_idx].yres;
  1382. } else {
  1383. printk(KERN_ERR
  1384. "sisfb: Failed to find supported mode near %dx%dx%d\n",
  1385. var->xres, var->yres, var->bits_per_pixel);
  1386. return -EINVAL;
  1387. }
  1388. }
  1389. if( ((ivideo->vbflags2 & VB2_LVDS) ||
  1390. ((ivideo->vbflags2 & VB2_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) &&
  1391. (var->bits_per_pixel == 8) ) {
  1392. /* Slave modes on LVDS and 301B-DH */
  1393. refresh_rate = 60;
  1394. recalc_clock = TRUE;
  1395. } else if( (ivideo->current_htotal == htotal) &&
  1396. (ivideo->current_vtotal == vtotal) &&
  1397. (ivideo->current_pixclock == pixclock) ) {
  1398. /* x=x & y=y & c=c -> assume depth change */
  1399. drate = 1000000000 / pixclock;
  1400. hrate = (drate * 1000) / htotal;
  1401. refresh_rate = (unsigned int) (hrate * 2 / vtotal);
  1402. } else if( ( (ivideo->current_htotal != htotal) ||
  1403. (ivideo->current_vtotal != vtotal) ) &&
  1404. (ivideo->current_pixclock == var->pixclock) ) {
  1405. /* x!=x | y!=y & c=c -> invalid pixclock */
  1406. if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) {
  1407. refresh_rate =
  1408. ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];
  1409. } else if(ivideo->sisfb_parm_rate != -1) {
  1410. /* Sic, sisfb_parm_rate - want to know originally desired rate here */
  1411. refresh_rate = ivideo->sisfb_parm_rate;
  1412. } else {
  1413. refresh_rate = 60;
  1414. }
  1415. recalc_clock = TRUE;
  1416. } else if((pixclock) && (htotal) && (vtotal)) {
  1417. drate = 1000000000 / pixclock;
  1418. hrate = (drate * 1000) / htotal;
  1419. refresh_rate = (unsigned int) (hrate * 2 / vtotal);
  1420. } else if(ivideo->current_refresh_rate) {
  1421. refresh_rate = ivideo->current_refresh_rate;
  1422. recalc_clock = TRUE;
  1423. } else {
  1424. refresh_rate = 60;
  1425. recalc_clock = TRUE;
  1426. }
  1427. myrateindex = sisfb_search_refresh_rate(ivideo, refresh_rate, search_idx);
  1428. /* Eventually recalculate timing and clock */
  1429. if(recalc_clock) {
  1430. if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
  1431. var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr,
  1432. sisbios_mode[search_idx].mode_no[ivideo->mni],
  1433. myrateindex));
  1434. sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr,
  1435. sisbios_mode[search_idx].mode_no[ivideo->mni],
  1436. myrateindex, var);
  1437. if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
  1438. var->pixclock <<= 1;
  1439. }
  1440. }
  1441. if(ivideo->sisfb_thismonitor.datavalid) {
  1442. if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx,
  1443. myrateindex, refresh_rate)) {
  1444. printk(KERN_INFO
  1445. "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
  1446. }
  1447. }
  1448. /* Adapt RGB settings */
  1449. sisfb_bpp_to_var(ivideo, var);
  1450. /* Sanity check for offsets */
  1451. if(var->xoffset < 0) var->xoffset = 0;
  1452. if(var->yoffset < 0) var->yoffset = 0;
  1453. if(var->xres > var->xres_virtual)
  1454. var->xres_virtual = var->xres;
  1455. if(ivideo->sisfb_ypan) {
  1456. maxyres = sisfb_calc_maxyres(ivideo, var);
  1457. if(ivideo->sisfb_max) {
  1458. var->yres_virtual = maxyres;
  1459. } else {
  1460. if(var->yres_virtual > maxyres) {
  1461. var->yres_virtual = maxyres;
  1462. }
  1463. }
  1464. if(var->yres_virtual <= var->yres) {
  1465. var->yres_virtual = var->yres;
  1466. }
  1467. } else {
  1468. if(var->yres != var->yres_virtual) {
  1469. var->yres_virtual = var->yres;
  1470. }
  1471. var->xoffset = 0;
  1472. var->yoffset = 0;
  1473. }
  1474. /* Truncate offsets to maximum if too high */
  1475. if(var->xoffset > var->xres_virtual - var->xres) {
  1476. var->xoffset = var->xres_virtual - var->xres - 1;
  1477. }
  1478. if(var->yoffset > var->yres_virtual - var->yres) {
  1479. var->yoffset = var->yres_virtual - var->yres - 1;
  1480. }
  1481. /* Set everything else to 0 */
  1482. var->red.msb_right =
  1483. var->green.msb_right =
  1484. var->blue.msb_right =
  1485. var->transp.offset =
  1486. var->transp.length =
  1487. var->transp.msb_right = 0;
  1488. return 0;
  1489. }
  1490. static int
  1491. sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
  1492. {
  1493. struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
  1494. int err;
  1495. if(var->xoffset > (var->xres_virtual - var->xres))
  1496. return -EINVAL;
  1497. if(var->yoffset > (var->yres_virtual - var->yres))
  1498. return -EINVAL;
  1499. if(var->vmode & FB_VMODE_YWRAP)
  1500. return -EINVAL;
  1501. if(var->xoffset + info->var.xres > info->var.xres_virtual ||
  1502. var->yoffset + info->var.yres > info->var.yres_virtual)
  1503. return -EINVAL;
  1504. if((err = sisfb_pan_var(ivideo, var)) < 0)
  1505. return err;
  1506. info->var.xoffset = var->xoffset;
  1507. info->var.yoffset = var->yoffset;
  1508. return 0;
  1509. }
  1510. static int
  1511. sisfb_blank(int blank, struct fb_info *info)
  1512. {
  1513. struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
  1514. return sisfb_myblank(ivideo, blank);
  1515. }
  1516. #endif
  1517. /* ----------- FBDev related routines for all series ---------- */
  1518. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
  1519. static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
  1520. unsigned long arg)
  1521. #else
  1522. static int sisfb_ioctl(struct inode *inode, struct file *file,
  1523. unsigned int cmd, unsigned long arg,
  1524. struct fb_info *info)
  1525. #endif
  1526. {
  1527. struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
  1528. struct sis_memreq sismemreq;
  1529. struct fb_vblank sisvbblank;
  1530. u32 gpu32 = 0;
  1531. #ifndef __user
  1532. #define __user
  1533. #endif
  1534. u32 __user *argp = (u32 __user *)arg;
  1535. switch(cmd) {
  1536. case FBIO_ALLOC:
  1537. if(!capable(CAP_SYS_RAWIO))
  1538. return -EPERM;
  1539. if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq)))
  1540. return -EFAULT;
  1541. sis_malloc(&sismemreq);
  1542. if(copy_to_user((void __user *)arg, &sismemreq, sizeof(sismemreq))) {
  1543. sis_free((u32)sismemreq.offset);
  1544. return -EFAULT;
  1545. }
  1546. break;
  1547. case FBIO_FREE:
  1548. if(!capable(CAP_SYS_RAWIO))
  1549. return -EPERM;
  1550. if(get_user(gpu32, argp))
  1551. return -EFAULT;
  1552. sis_free(gpu32);
  1553. break;
  1554. case FBIOGET_VBLANK:
  1555. sisvbblank.count = 0;
  1556. sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);
  1557. if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank)))
  1558. return -EFAULT;
  1559. break;
  1560. case SISFB_GET_INFO_SIZE:
  1561. return put_user(sizeof(struct sisfb_info), argp);
  1562. case SISFB_GET_INFO_OLD:
  1563. if(ivideo->warncount++ < 10)
  1564. printk(KERN_INFO
  1565. "sisfb: Deprecated ioctl call received - update your application!\n");
  1566. case SISFB_GET_INFO: /* For communication with X driver */
  1567. ivideo->sisfb_infoblock.sisfb_id = SISFB_ID;
  1568. ivideo->sisfb_infoblock.sisfb_version = VER_MAJOR;
  1569. ivideo->sisfb_infoblock.sisfb_revision = VER_MINOR;
  1570. ivideo->sisfb_infoblock.sisfb_patchlevel = VER_LEVEL;
  1571. ivideo->sisfb_infoblock.chip_id = ivideo->chip_id;
  1572. ivideo->sisfb_infoblock.sisfb_pci_vendor = ivideo->chip_vendor;
  1573. ivideo->sisfb_infoblock.memory = ivideo->video_size / 1024;
  1574. ivideo->sisfb_infoblock.heapstart = ivideo->heapstart / 1024;
  1575. if(ivideo->modechanged) {
  1576. ivideo->sisfb_infoblock.fbvidmode = ivideo->mode_no;
  1577. } else {
  1578. ivideo->sisfb_infoblock.fbvidmode = ivideo->modeprechange;
  1579. }
  1580. ivideo->sisfb_infoblock.sisfb_caps = ivideo->caps;
  1581. ivideo->sisfb_infoblock.sisfb_tqlen = ivideo->cmdQueueSize / 1024;
  1582. ivideo->sisfb_infoblock.sisfb_pcibus = ivideo->pcibus;
  1583. ivideo->sisfb_infoblock.sisfb_pcislot = ivideo->pcislot;
  1584. ivideo->sisfb_infoblock.sisfb_pcifunc = ivideo->pcifunc;
  1585. ivideo->sisfb_infoblock.sisfb_lcdpdc = ivideo->detectedpdc;
  1586. ivideo->sisfb_infoblock.sisfb_lcdpdca = ivideo->detectedpdca;
  1587. ivideo->sisfb_infoblock.sisfb_lcda = ivideo->detectedlcda;
  1588. ivideo->sisfb_infoblock.sisfb_vbflags = ivideo->vbflags;
  1589. ivideo->sisfb_infoblock.sisfb_currentvbflags = ivideo->currentvbflags;
  1590. ivideo->sisfb_infoblock.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
  1591. ivideo->sisfb_infoblock.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
  1592. ivideo->sisfb_infoblock.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
  1593. ivideo->sisfb_infoblock.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
  1594. ivideo->sisfb_infoblock.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
  1595. ivideo->sisfb_infoblock.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
  1596. ivideo->sisfb_infoblock.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
  1597. ivideo->sisfb_infoblock.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
  1598. ivideo->sisfb_infoblock.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
  1599. ivideo->sisfb_infoblock.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
  1600. ivideo->sisfb_infoblock.sisfb_heapsize = ivideo->sisfb_heap_size / 1024;
  1601. ivideo->sisfb_infoblock.sisfb_videooffset = ivideo->video_offset;
  1602. ivideo->sisfb_infoblock.sisfb_curfstn = ivideo->curFSTN;
  1603. ivideo->sisfb_infoblock.sisfb_curdstn = ivideo->curDSTN;
  1604. ivideo->sisfb_infoblock.sisfb_vbflags2 = ivideo->vbflags2;
  1605. ivideo->sisfb_infoblock.sisfb_can_post = ivideo->sisfb_can_post ? 1 : 0;
  1606. ivideo->sisfb_infoblock.sisfb_card_posted = ivideo->sisfb_card_posted ? 1 : 0;
  1607. ivideo->sisfb_infoblock.sisfb_was_boot_device = ivideo->sisfb_was_boot_device ? 1 : 0;
  1608. if(copy_to_user((void __user *)arg, &ivideo->sisfb_infoblock,
  1609. sizeof(ivideo->sisfb_infoblock)))
  1610. return -EFAULT;
  1611. break;
  1612. case SISFB_GET_VBRSTATUS_OLD:
  1613. if(ivideo->warncount++ < 10)
  1614. printk(KERN_INFO
  1615. "sisfb: Deprecated ioctl call received - update your application!\n");
  1616. case SISFB_GET_VBRSTATUS:
  1617. if(sisfb_CheckVBRetrace(ivideo))
  1618. return put_user((u32)1, argp);
  1619. else
  1620. return put_user((u32)0, argp);
  1621. case SISFB_GET_AUTOMAXIMIZE_OLD:
  1622. if(ivideo->warncount++ < 10)
  1623. printk(KERN_INFO
  1624. "sisfb: Deprecated ioctl call received - update your application!\n");
  1625. case SISFB_GET_AUTOMAXIMIZE:
  1626. if(ivideo->sisfb_max)
  1627. return put_user((u32)1, argp);
  1628. else
  1629. return put_user((u32)0, argp);
  1630. case SISFB_SET_AUTOMAXIMIZE_OLD:
  1631. if(ivideo->warncount++ < 10)
  1632. printk(KERN_INFO
  1633. "sisfb: Deprecated ioctl call received - update your application!\n");
  1634. case SISFB_SET_AUTOMAXIMIZE:
  1635. if(get_user(gpu32, argp))
  1636. return -EFAULT;
  1637. ivideo->sisfb_max = (gpu32) ? 1 : 0;
  1638. break;
  1639. case SISFB_SET_TVPOSOFFSET:
  1640. if(get_user(gpu32, argp))
  1641. return -EFAULT;
  1642. sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32);
  1643. sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32);
  1644. break;
  1645. case SISFB_GET_TVPOSOFFSET:
  1646. return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)),
  1647. argp);
  1648. case SISFB_COMMAND:
  1649. if(copy_from_user(&ivideo->sisfb_command, (void __user *)arg,
  1650. sizeof(struct sisfb_cmd)))
  1651. return -EFAULT;
  1652. sisfb_handle_command(ivideo, &ivideo->sisfb_command);
  1653. if(copy_to_user((void __user *)arg, &ivideo->sisfb_command,
  1654. sizeof(struct sisfb_cmd)))
  1655. return -EFAULT;
  1656. break;
  1657. case SISFB_SET_LOCK:
  1658. if(get_user(gpu32, argp))
  1659. return -EFAULT;
  1660. ivideo->sisfblocked = (gpu32) ? 1 : 0;
  1661. break;
  1662. default:
  1663. #ifdef SIS_NEW_CONFIG_COMPAT
  1664. return -ENOIOCTLCMD;
  1665. #else
  1666. return -EINVAL;
  1667. #endif
  1668. }
  1669. return 0;
  1670. }
  1671. static int
  1672. sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
  1673. {
  1674. struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
  1675. memset(fix, 0, sizeof(struct fb_fix_screeninfo));
  1676. strcpy(fix->id, ivideo->myid);
  1677. fix->smem_start = ivideo->video_base + ivideo->video_offset;
  1678. fix->smem_len = ivideo->sisfb_mem;
  1679. fix->type = FB_TYPE_PACKED_PIXELS;
  1680. fix->type_aux = 0;
  1681. fix->visual = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
  1682. fix->xpanstep = 1;
  1683. fix->ypanstep = (ivideo->sisfb_ypan) ? 1 : 0;
  1684. fix->ywrapstep = 0;
  1685. fix->line_length = ivideo->video_linelength;
  1686. fix->mmio_start = ivideo->mmio_base;
  1687. fix->mmio_len = ivideo->mmio_size;
  1688. if(ivideo->sisvga_engine == SIS_300_VGA) {
  1689. fix->accel = FB_ACCEL_SIS_GLAMOUR;
  1690. } else if((ivideo->chip == SIS_330) ||
  1691. (ivideo->chip == SIS_760) ||
  1692. (ivideo->chip == SIS_761)) {
  1693. fix->accel = FB_ACCEL_SIS_XABRE;
  1694. } else if(ivideo->chip == XGI_20) {
  1695. fix->accel = FB_ACCEL_XGI_VOLARI_Z;
  1696. } else if(ivideo->chip >= XGI_40) {
  1697. fix->accel = FB_ACCEL_XGI_VOLARI_V;
  1698. } else {
  1699. fix->accel = FB_ACCEL_SIS_GLAMOUR_2;
  1700. }
  1701. return 0;
  1702. }
  1703. /* ---------------- fb_ops structures ----------------- */
  1704. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
  1705. static struct fb_ops sisfb_ops = {
  1706. .owner = THIS_MODULE,
  1707. .fb_get_fix = sisfb_get_fix,
  1708. .fb_get_var = sisfb_get_var,
  1709. .fb_set_var = sisfb_set_var,
  1710. .fb_get_cmap = sisfb_get_cmap,
  1711. .fb_set_cmap = sisfb_set_cmap,
  1712. .fb_pan_display = sisfb_pan_display,
  1713. .fb_ioctl = sisfb_ioctl
  1714. };
  1715. #endif
  1716. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
  1717. static struct fb_ops sisfb_ops = {
  1718. .owner = THIS_MODULE,
  1719. .fb_open = sisfb_open,
  1720. .fb_release = sisfb_release,
  1721. .fb_check_var = sisfb_check_var,
  1722. .fb_set_par = sisfb_set_par,
  1723. .fb_setcolreg = sisfb_setcolreg,
  1724. .fb_pan_display = sisfb_pan_display,
  1725. .fb_blank = sisfb_blank,
  1726. .fb_fillrect = fbcon_sis_fillrect,
  1727. .fb_copyarea = fbcon_sis_copyarea,
  1728. .fb_imageblit = cfb_imageblit,
  1729. #ifdef CONFIG_FB_SOFT_CURSOR
  1730. .fb_cursor = soft_cursor,
  1731. #endif
  1732. .fb_sync = fbcon_sis_sync,
  1733. #ifdef SIS_NEW_CONFIG_COMPAT
  1734. .fb_compat_ioctl= sisfb_ioctl,
  1735. #endif
  1736. .fb_ioctl = sisfb_ioctl
  1737. };
  1738. #endif
  1739. /* ---------------- Chip generation dependent routines ---------------- */
  1740. static struct pci_dev * __devinit
  1741. sisfb_get_northbridge(int basechipid)
  1742. {
  1743. struct pci_dev *pdev = NULL;
  1744. int nbridgenum, nbridgeidx, i;
  1745. static const unsigned short nbridgeids[] = {
  1746. PCI_DEVICE_ID_SI_540, /* for SiS 540 VGA */
  1747. PCI_DEVICE_ID_SI_630, /* for SiS 630/730 VGA */
  1748. PCI_DEVICE_ID_SI_730,
  1749. PCI_DEVICE_ID_SI_550, /* for SiS 550 VGA */
  1750. PCI_DEVICE_ID_SI_650, /* for SiS 650/651/740 VGA */
  1751. PCI_DEVICE_ID_SI_651,
  1752. PCI_DEVICE_ID_SI_740,
  1753. PCI_DEVICE_ID_SI_661, /* for SiS 661/741/660/760/761 VGA */
  1754. PCI_DEVICE_ID_SI_741,
  1755. PCI_DEVICE_ID_SI_660,
  1756. PCI_DEVICE_ID_SI_760,
  1757. PCI_DEVICE_ID_SI_761
  1758. };
  1759. switch(basechipid) {
  1760. #ifdef CONFIG_FB_SIS_300
  1761. case SIS_540: nbridgeidx = 0; nbridgenum = 1; break;
  1762. case SIS_630: nbridgeidx = 1; nbridgenum = 2; break;
  1763. #endif
  1764. #ifdef CONFIG_FB_SIS_315
  1765. case SIS_550: nbridgeidx = 3; nbridgenum = 1; break;
  1766. case SIS_650: nbridgeidx = 4; nbridgenum = 3; break;
  1767. case SIS_660: nbridgeidx = 7; nbridgenum = 5; break;
  1768. #endif
  1769. default: return NULL;
  1770. }
  1771. for(i = 0; i < nbridgenum; i++) {
  1772. if((pdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI,
  1773. nbridgeids[nbridgeidx+i], NULL)))
  1774. break;
  1775. }
  1776. return pdev;
  1777. }
  1778. static int __devinit
  1779. sisfb_get_dram_size(struct sis_video_info *ivideo)
  1780. {
  1781. #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
  1782. u8 reg;
  1783. #endif
  1784. ivideo->video_size = 0;
  1785. ivideo->UMAsize = ivideo->LFBsize = 0;
  1786. switch(ivideo->chip) {
  1787. #ifdef CONFIG_FB_SIS_300
  1788. case SIS_300:
  1789. inSISIDXREG(SISSR, 0x14, reg);
  1790. ivideo->video_size = ((reg & 0x3F) + 1) << 20;
  1791. break;
  1792. case SIS_540:
  1793. case SIS_630:
  1794. case SIS_730:
  1795. if(!ivideo->nbridge)
  1796. return -1;
  1797. pci_read_config_byte(ivideo->nbridge, 0x63, &reg);
  1798. ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21);
  1799. break;
  1800. #endif
  1801. #ifdef CONFIG_FB_SIS_315
  1802. case SIS_315H:
  1803. case SIS_315PRO:
  1804. case SIS_315:
  1805. inSISIDXREG(SISSR, 0x14, reg);
  1806. ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
  1807. switch((reg >> 2) & 0x03) {
  1808. case 0x01:
  1809. case 0x03:
  1810. ivideo->video_size <<= 1;
  1811. break;
  1812. case 0x02:
  1813. ivideo->video_size += (ivideo->video_size/2);
  1814. }
  1815. break;
  1816. case SIS_330:
  1817. inSISIDXREG(SISSR, 0x14, reg);
  1818. ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
  1819. if(reg & 0x0c) ivideo->video_size <<= 1;
  1820. break;
  1821. case SIS_550:
  1822. case SIS_650:
  1823. case SIS_740:
  1824. inSISIDXREG(SISSR, 0x14, reg);
  1825. ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;
  1826. break;
  1827. case SIS_661:
  1828. case SIS_741:
  1829. inSISIDXREG(SISCR, 0x79, reg);
  1830. ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
  1831. break;
  1832. case SIS_660:
  1833. case SIS_760:
  1834. case SIS_761:
  1835. inSISIDXREG(SISCR, 0x79, reg);
  1836. reg = (reg & 0xf0) >> 4;
  1837. if(reg) {
  1838. ivideo->video_size = (1 << reg) << 20;
  1839. ivideo->UMAsize = ivideo->video_size;
  1840. }
  1841. inSISIDXREG(SISCR, 0x78, reg);
  1842. reg &= 0x30;
  1843. if(reg) {
  1844. if(reg == 0x10) {
  1845. ivideo->LFBsize = (32 << 20);
  1846. } else {
  1847. ivideo->LFBsize = (64 << 20);
  1848. }
  1849. ivideo->video_size += ivideo->LFBsize;
  1850. }
  1851. break;
  1852. case SIS_340:
  1853. case XGI_20:
  1854. case XGI_40:
  1855. inSISIDXREG(SISSR, 0x14, reg);
  1856. ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
  1857. if(ivideo->chip != XGI_20) {
  1858. reg = (reg & 0x0c) >> 2;
  1859. if(ivideo->revision_id == 2) {
  1860. if(reg & 0x01) reg = 0x02;
  1861. else reg = 0x00;
  1862. }
  1863. if(reg == 0x02) ivideo->video_size <<= 1;
  1864. else if(reg == 0x03) ivideo->video_size <<= 2;
  1865. }
  1866. break;
  1867. #endif
  1868. default:
  1869. return -1;
  1870. }
  1871. return 0;
  1872. }
  1873. /* -------------- video bridge device detection --------------- */
  1874. static void __devinit
  1875. sisfb_detect_VB_connect(struct sis_video_info *ivideo)
  1876. {
  1877. u8 cr32, temp;
  1878. /* No CRT2 on XGI Z7 */
  1879. if(ivideo->chip == XGI_20) {
  1880. ivideo->sisfb_crt1off = 0;
  1881. return;
  1882. }
  1883. #ifdef CONFIG_FB_SIS_300
  1884. if(ivideo->sisvga_engine == SIS_300_VGA) {
  1885. inSISIDXREG(SISSR, 0x17, temp);
  1886. if((temp & 0x0F) && (ivideo->chip != SIS_300)) {
  1887. /* PAL/NTSC is stored on SR16 on such machines */
  1888. if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
  1889. inSISIDXREG(SISSR, 0x16, temp);
  1890. if(temp & 0x20)
  1891. ivideo->vbflags |= TV_PAL;
  1892. else
  1893. ivideo->vbflags |= TV_NTSC;
  1894. }
  1895. }
  1896. }
  1897. #endif
  1898. inSISIDXREG(SISCR, 0x32, cr32);
  1899. if(cr32 & SIS_CRT1) {
  1900. ivideo->sisfb_crt1off = 0;
  1901. } else {
  1902. ivideo->sisfb_crt1off = (cr32 & 0xDF) ? 1 : 0;
  1903. }
  1904. ivideo->vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA);
  1905. if(cr32 & SIS_VB_TV) ivideo->vbflags |= CRT2_TV;
  1906. if(cr32 & SIS_VB_LCD) ivideo->vbflags |= CRT2_LCD;
  1907. if(cr32 & SIS_VB_CRT2) ivideo->vbflags |= CRT2_VGA;
  1908. /* Check given parms for hardware compatibility.
  1909. * (Cannot do this in the search_xx routines since we don't
  1910. * know what hardware we are running on then)
  1911. */
  1912. if(ivideo->chip != SIS_550) {
  1913. ivideo->sisfb_dstn = ivideo->sisfb_fstn = 0;
  1914. }
  1915. if(ivideo->sisfb_tvplug != -1) {
  1916. if( (ivideo->sisvga_engine != SIS_315_VGA) ||
  1917. (!(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) ) {
  1918. if(ivideo->sisfb_tvplug & TV_YPBPR) {
  1919. ivideo->sisfb_tvplug = -1;
  1920. printk(KERN_ERR "sisfb: YPbPr not supported\n");
  1921. }
  1922. }
  1923. }
  1924. if(ivideo->sisfb_tvplug != -1) {
  1925. if( (ivideo->sisvga_engine != SIS_315_VGA) ||
  1926. (!(ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) ) {
  1927. if(ivideo->sisfb_tvplug & TV_HIVISION) {
  1928. ivideo->sisfb_tvplug = -1;
  1929. printk(KERN_ERR "sisfb: HiVision not supported\n");
  1930. }
  1931. }
  1932. }
  1933. if(ivideo->sisfb_tvstd != -1) {
  1934. if( (!(ivideo->vbflags2 & VB2_SISBRIDGE)) &&
  1935. (!((ivideo->sisvga_engine == SIS_315_VGA) &&
  1936. (ivideo->vbflags2 & VB2_CHRONTEL))) ) {
  1937. if(ivideo->sisfb_tvstd & (TV_PALN | TV_PALN | TV_NTSCJ)) {
  1938. ivideo->sisfb_tvstd = -1;
  1939. printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
  1940. }
  1941. }
  1942. }
  1943. /* Detect/set TV plug & type */
  1944. if(ivideo->sisfb_tvplug != -1) {
  1945. ivideo->vbflags |= ivideo->sisfb_tvplug;
  1946. } else {
  1947. if(cr32 & SIS_VB_YPBPR) ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */
  1948. else if(cr32 & SIS_VB_HIVISION) ivideo->vbflags |= TV_HIVISION;
  1949. else if(cr32 & SIS_VB_SCART) ivideo->vbflags |= TV_SCART;
  1950. else {
  1951. if(cr32 & SIS_VB_SVIDEO) ivideo->vbflags |= TV_SVIDEO;
  1952. if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO;
  1953. }
  1954. }
  1955. if(!(ivideo->vbflags & (TV_YPBPR | TV_HIVISION))) {
  1956. if(ivideo->sisfb_tvstd != -1) {
  1957. ivideo->vbflags &= ~(TV_NTSC | TV_PAL | TV_PALM | TV_PALN | TV_NTSCJ);
  1958. ivideo->vbflags |= ivideo->sisfb_tvstd;
  1959. }
  1960. if(ivideo->vbflags & TV_SCART) {
  1961. ivideo->vbflags &= ~(TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ);
  1962. ivideo->vbflags |= TV_PAL;
  1963. }
  1964. if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) {
  1965. if(ivideo->sisvga_engine == SIS_300_VGA) {
  1966. inSISIDXREG(SISSR, 0x38, temp);
  1967. if(temp & 0x01) ivideo->vbflags |= TV_PAL;
  1968. else ivideo->vbflags |= TV_NTSC;
  1969. } else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) {
  1970. inSISIDXREG(SISSR, 0x38, temp);
  1971. if(temp & 0x01) ivideo->vbflags |= TV_PAL;
  1972. else ivideo->vbflags |= TV_NTSC;
  1973. } else {
  1974. inSISIDXREG(SISCR, 0x79, temp);
  1975. if(temp & 0x20) ivideo->vbflags |= TV_PAL;
  1976. else ivideo->vbflags |= TV_NTSC;
  1977. }
  1978. }
  1979. }
  1980. /* Copy forceCRT1 option to CRT1off if option is given */
  1981. if(ivideo->sisfb_forcecrt1 != -1) {
  1982. ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1;
  1983. }
  1984. }
  1985. /* ------------------ Sensing routines ------------------ */
  1986. static BOOLEAN __devinit
  1987. sisfb_test_DDC1(struct sis_video_info *ivideo)
  1988. {
  1989. unsigned short old;
  1990. int count = 48;
  1991. old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr);
  1992. do {
  1993. if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
  1994. } while(count--);
  1995. return (count == -1) ? FALSE : TRUE;
  1996. }
  1997. static void __devinit
  1998. sisfb_sense_crt1(struct sis_video_info *ivideo)
  1999. {
  2000. BOOLEAN mustwait = FALSE;
  2001. u8 sr1F, cr17;
  2002. #ifdef CONFIG_FB_SIS_315
  2003. u8 cr63=0;
  2004. #endif
  2005. u16 temp = 0xffff;
  2006. int i;
  2007. inSISIDXREG(SISSR,0x1F,sr1F);
  2008. orSISIDXREG(SISSR,0x1F,0x04);
  2009. andSISIDXREG(SISSR,0x1F,0x3F);
  2010. if(sr1F & 0xc0) mustwait = TRUE;
  2011. #ifdef CONFIG_FB_SIS_315
  2012. if(ivideo->sisvga_engine == SIS_315_VGA) {
  2013. inSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,cr63);
  2014. cr63 &= 0x40;
  2015. andSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,0xBF);
  2016. }
  2017. #endif
  2018. inSISIDXREG(SISCR,0x17,cr17);
  2019. cr17 &= 0x80;
  2020. if(!cr17) {
  2021. orSISIDXREG(SISCR,0x17,0x80);
  2022. mustwait = TRUE;
  2023. outSISIDXREG(SISSR, 0x00, 0x01);
  2024. outSISIDXREG(SISSR, 0x00, 0x03);
  2025. }
  2026. if(mustwait) {
  2027. for(i=0; i < 10; i++) sisfbwaitretracecrt1(ivideo);
  2028. }
  2029. #ifdef CONFIG_FB_SIS_315
  2030. if(ivideo->chip >= SIS_330) {
  2031. andSISIDXREG(SISCR,0x32,~0x20);
  2032. if(ivideo->chip >= SIS_340) {
  2033. outSISIDXREG(SISCR, 0x57, 0x4a);
  2034. } else {
  2035. outSISIDXREG(SISCR, 0x57, 0x5f);
  2036. }
  2037. orSISIDXREG(SISCR, 0x53, 0x02);
  2038. while((inSISREG(SISINPSTAT)) & 0x01) break;
  2039. while(!((inSISREG(SISINPSTAT)) & 0x01)) break;
  2040. if((inSISREG(SISMISCW)) & 0x10) temp = 1;
  2041. andSISIDXREG(SISCR, 0x53, 0xfd);
  2042. andSISIDXREG(SISCR, 0x57, 0x00);
  2043. }
  2044. #endif
  2045. if(temp == 0xffff) {
  2046. i = 3;
  2047. do {
  2048. temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
  2049. ivideo->sisvga_engine, 0, 0, NULL, ivideo->vbflags2);
  2050. } while(((temp == 0) || (temp == 0xffff)) && i--);
  2051. if((temp == 0) || (temp == 0xffff)) {
  2052. if(sisfb_test_DDC1(ivideo)) temp = 1;
  2053. }
  2054. }
  2055. if((temp) && (temp != 0xffff)) {
  2056. orSISIDXREG(SISCR,0x32,0x20);
  2057. }
  2058. #ifdef CONFIG_FB_SIS_315
  2059. if(ivideo->sisvga_engine == SIS_315_VGA) {
  2060. setSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,0xBF,cr63);
  2061. }
  2062. #endif
  2063. setSISIDXREG(SISCR,0x17,0x7F,cr17);
  2064. outSISIDXREG(SISSR,0x1F,sr1F);
  2065. }
  2066. /* Determine and detect attached devices on SiS30x */
  2067. static void __devinit
  2068. SiS_SenseLCD(struct sis_video_info *ivideo)
  2069. {
  2070. unsigned char buffer[256];
  2071. unsigned short temp, realcrtno, i;
  2072. u8 reg, cr37 = 0, paneltype = 0;
  2073. u16 xres, yres;
  2074. ivideo->SiS_Pr.PanelSelfDetected = FALSE;
  2075. /* LCD detection only for TMDS bridges */
  2076. if(!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE))
  2077. return;
  2078. if(ivideo->vbflags2 & VB2_30xBDH)
  2079. return;
  2080. /* If LCD already set up by BIOS, skip it */
  2081. inSISIDXREG(SISCR, 0x32, reg);
  2082. if(reg & 0x08)
  2083. return;
  2084. realcrtno = 1;
  2085. if(ivideo->SiS_Pr.DDCPortMixup)
  2086. realcrtno = 0;
  2087. /* Check DDC capabilities */
  2088. temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
  2089. realcrtno, 0, &buffer[0], ivideo->vbflags2);
  2090. if((!temp) || (temp == 0xffff) || (!(temp & 0x02)))
  2091. return;
  2092. /* Read DDC data */
  2093. i = 3; /* Number of retrys */
  2094. do {
  2095. temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
  2096. ivideo->sisvga_engine, realcrtno, 1,
  2097. &buffer[0], ivideo->vbflags2);
  2098. } while((temp) && i--);
  2099. if(temp)
  2100. return;
  2101. /* No digital device */
  2102. if(!(buffer[0x14] & 0x80))
  2103. return;
  2104. /* First detailed timing preferred timing? */
  2105. if(!(buffer[0x18] & 0x02))
  2106. return;
  2107. xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
  2108. yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4);
  2109. switch(xres) {
  2110. case 1024:
  2111. if(yres == 768)
  2112. paneltype = 0x02;
  2113. break;
  2114. case 1280:
  2115. if(yres == 1024)
  2116. paneltype = 0x03;
  2117. break;
  2118. case 1600:
  2119. if((yres == 1200) && (ivideo->vbflags2 & VB2_30xC))
  2120. paneltype = 0x0b;
  2121. break;
  2122. }
  2123. if(!paneltype)
  2124. return;
  2125. if(buffer[0x23])
  2126. cr37 |= 0x10;
  2127. if((buffer[0x47] & 0x18) == 0x18)
  2128. cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
  2129. else
  2130. cr37 |= 0xc0;
  2131. outSISIDXREG(SISCR, 0x36, paneltype);
  2132. cr37 &= 0xf1;
  2133. setSISIDXREG(SISCR, 0x37, 0x0c, cr37);
  2134. orSISIDXREG(SISCR, 0x32, 0x08);
  2135. ivideo->SiS_Pr.PanelSelfDetected = TRUE;
  2136. }
  2137. static int __devinit
  2138. SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
  2139. {
  2140. int temp, mytest, result, i, j;
  2141. for(j = 0; j < 10; j++) {
  2142. result = 0;
  2143. for(i = 0; i < 3; i++) {
  2144. mytest = test;
  2145. outSISIDXREG(SISPART4,0x11,(type & 0x00ff));
  2146. temp = (type >> 8) | (mytest & 0x00ff);
  2147. setSISIDXREG(SISPART4,0x10,0xe0,temp);
  2148. SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500);
  2149. mytest >>= 8;
  2150. mytest &= 0x7f;
  2151. inSISIDXREG(SISPART4,0x03,temp);
  2152. temp ^= 0x0e;
  2153. temp &= mytest;
  2154. if(temp == mytest) result++;
  2155. #if 1
  2156. outSISIDXREG(SISPART4,0x11,0x00);
  2157. andSISIDXREG(SISPART4,0x10,0xe0);
  2158. SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);
  2159. #endif
  2160. }
  2161. if((result == 0) || (result >= 2)) break;
  2162. }
  2163. return result;
  2164. }
  2165. static void __devinit
  2166. SiS_Sense30x(struct sis_video_info *ivideo)
  2167. {
  2168. u8 backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0;
  2169. u16 svhs=0, svhs_c=0;
  2170. u16 cvbs=0, cvbs_c=0;
  2171. u16 vga2=0, vga2_c=0;
  2172. int myflag, result;
  2173. char stdstr[] = "sisfb: Detected";
  2174. char tvstr[] = "TV connected to";
  2175. if(ivideo->vbflags2 & VB2_301) {
  2176. svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
  2177. inSISIDXREG(SISPART4,0x01,myflag);
  2178. if(myflag & 0x04) {
  2179. svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
  2180. }
  2181. } else if(ivideo->vbflags2 & (VB2_301B | VB2_302B)) {
  2182. svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190;
  2183. } else if(ivideo->vbflags2 & (VB2_301LV | VB2_302LV)) {
  2184. svhs = 0x0200; cvbs = 0x0100;
  2185. } else if(ivideo->vbflags2 & (VB2_301C | VB2_302ELV | VB2_307T | VB2_307LV)) {
  2186. svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190;
  2187. } else
  2188. return;
  2189. vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804;
  2190. if(ivideo->vbflags & (VB2_301LV|VB2_302LV|VB2_302ELV|VB2_307LV)) {
  2191. svhs_c = 0x0408; cvbs_c = 0x0808;
  2192. }
  2193. biosflag = 2;
  2194. if(ivideo->haveXGIROM) {
  2195. biosflag = ivideo->bios_abase[0x58] & 0x03;
  2196. } else if(ivideo->newrom) {
  2197. if(ivideo->bios_abase[0x5d] & 0x04) biosflag |= 0x01;
  2198. } else if(ivideo->sisvga_engine == SIS_300_VGA) {
  2199. if(ivideo->bios_abase) {
  2200. biosflag = ivideo->bios_abase[0xfe] & 0x03;
  2201. }
  2202. }
  2203. if(ivideo->chip == SIS_300) {
  2204. inSISIDXREG(SISSR,0x3b,myflag);
  2205. if(!(myflag & 0x01)) vga2 = vga2_c = 0;
  2206. }
  2207. if(!(ivideo->vbflags2 & VB2_SISVGA2BRIDGE)) {
  2208. vga2 = vga2_c = 0;
  2209. }
  2210. inSISIDXREG(SISSR,0x1e,backupSR_1e);
  2211. orSISIDXREG(SISSR,0x1e,0x20);
  2212. inSISIDXREG(SISPART4,0x0d,backupP4_0d);
  2213. if(ivideo->vbflags2 & VB2_30xC) {
  2214. setSISIDXREG(SISPART4,0x0d,~0x07,0x01);
  2215. } else {
  2216. orSISIDXREG(SISPART4,0x0d,0x04);
  2217. }
  2218. SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
  2219. inSISIDXREG(SISPART2,0x00,backupP2_00);
  2220. outSISIDXREG(SISPART2,0x00,((backupP2_00 | 0x1c) & 0xfc));
  2221. inSISIDXREG(SISPART2,0x4d,backupP2_4d);
  2222. if(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE) {
  2223. outSISIDXREG(SISPART2,0x4d,(backupP2_4d & ~0x10));
  2224. }
  2225. if(!(ivideo->vbflags2 & VB2_30xCLV)) {
  2226. SISDoSense(ivideo, 0, 0);
  2227. }
  2228. andSISIDXREG(SISCR, 0x32, ~0x14);
  2229. if(vga2_c || vga2) {
  2230. if(SISDoSense(ivideo, vga2, vga2_c)) {
  2231. if(biosflag & 0x01) {
  2232. printk(KERN_INFO "%s %s SCART output\n", stdstr, tvstr);
  2233. orSISIDXREG(SISCR, 0x32, 0x04);
  2234. } else {
  2235. printk(KERN_INFO "%s secondary VGA connection\n", stdstr);
  2236. orSISIDXREG(SISCR, 0x32, 0x10);
  2237. }
  2238. }
  2239. }
  2240. andSISIDXREG(SISCR, 0x32, 0x3f);
  2241. if(ivideo->vbflags2 & VB2_30xCLV) {
  2242. orSISIDXREG(SISPART4,0x0d,0x04);
  2243. }
  2244. if((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
  2245. outSISIDXREG(SISPART2,0x4d,(backupP2_4d | 0x10));
  2246. SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
  2247. if((result = SISDoSense(ivideo, svhs, 0x0604))) {
  2248. if((result = SISDoSense(ivideo, cvbs, 0x0804))) {
  2249. printk(KERN_INFO "%s %s YPbPr component output\n", stdstr, tvstr);
  2250. orSISIDXREG(SISCR,0x32,0x80);
  2251. }
  2252. }
  2253. outSISIDXREG(SISPART2,0x4d,backupP2_4d);
  2254. }
  2255. andSISIDXREG(SISCR, 0x32, ~0x03);
  2256. if(!(ivideo->vbflags & TV_YPBPR)) {
  2257. if((result = SISDoSense(ivideo, svhs, svhs_c))) {
  2258. printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr);
  2259. orSISIDXREG(SISCR, 0x32, 0x02);
  2260. }
  2261. if((biosflag & 0x02) || (!result)) {
  2262. if(SISDoSense(ivideo, cvbs, cvbs_c)) {
  2263. printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr);
  2264. orSISIDXREG(SISCR, 0x32, 0x01);
  2265. }
  2266. }
  2267. }
  2268. SISDoSense(ivideo, 0, 0);
  2269. outSISIDXREG(SISPART2,0x00,backupP2_00);
  2270. outSISIDXREG(SISPART4,0x0d,backupP4_0d);
  2271. outSISIDXREG(SISSR,0x1e,backupSR_1e);
  2272. if(ivideo->vbflags2 & VB2_30xCLV) {
  2273. inSISIDXREG(SISPART2,0x00,biosflag);
  2274. if(biosflag & 0x20) {
  2275. for(myflag = 2; myflag > 0; myflag--) {
  2276. biosflag ^= 0x20;
  2277. outSISIDXREG(SISPART2,0x00,biosflag);
  2278. }
  2279. }
  2280. }
  2281. outSISIDXREG(SISPART2,0x00,backupP2_00);
  2282. }
  2283. /* Determine and detect attached TV's on Chrontel */
  2284. static void __devinit
  2285. SiS_SenseCh(struct sis_video_info *ivideo)
  2286. {
  2287. #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
  2288. u8 temp1, temp2;
  2289. char stdstr[] = "sisfb: Chrontel: Detected TV connected to";
  2290. #endif
  2291. #ifdef CONFIG_FB_SIS_300
  2292. unsigned char test[3];
  2293. int i;
  2294. #endif
  2295. if(ivideo->chip < SIS_315H) {
  2296. #ifdef CONFIG_FB_SIS_300
  2297. ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 1; /* Chrontel 700x */
  2298. SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x9c); /* Set general purpose IO for Chrontel communication */
  2299. SiS_DDC2Delay(&ivideo->SiS_Pr, 1000);
  2300. temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
  2301. /* See Chrontel TB31 for explanation */
  2302. temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
  2303. if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
  2304. SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e, 0x0b);
  2305. SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
  2306. }
  2307. temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
  2308. if(temp2 != temp1) temp1 = temp2;
  2309. if((temp1 >= 0x22) && (temp1 <= 0x50)) {
  2310. /* Read power status */
  2311. temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
  2312. if((temp1 & 0x03) != 0x03) {
  2313. /* Power all outputs */
  2314. SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e,0x0b);
  2315. SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
  2316. }
  2317. /* Sense connected TV devices */
  2318. for(i = 0; i < 3; i++) {
  2319. SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x01);
  2320. SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
  2321. SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x00);
  2322. SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
  2323. temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10);
  2324. if(!(temp1 & 0x08)) test[i] = 0x02;
  2325. else if(!(temp1 & 0x02)) test[i] = 0x01;
  2326. else test[i] = 0;
  2327. SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
  2328. }
  2329. if(test[0] == test[1]) temp1 = test[0];
  2330. else if(test[0] == test[2]) temp1 = test[0];
  2331. else if(test[1] == test[2]) temp1 = test[1];
  2332. else {
  2333. printk(KERN_INFO
  2334. "sisfb: TV detection unreliable - test results varied\n");
  2335. temp1 = test[2];
  2336. }
  2337. if(temp1 == 0x02) {
  2338. printk(KERN_INFO "%s SVIDEO output\n", stdstr);
  2339. ivideo->vbflags |= TV_SVIDEO;
  2340. orSISIDXREG(SISCR, 0x32, 0x02);
  2341. andSISIDXREG(SISCR, 0x32, ~0x05);
  2342. } else if (temp1 == 0x01) {
  2343. printk(KERN_INFO "%s CVBS output\n", stdstr);
  2344. ivideo->vbflags |= TV_AVIDEO;
  2345. orSISIDXREG(SISCR, 0x32, 0x01);
  2346. andSISIDXREG(SISCR, 0x32, ~0x06);
  2347. } else {
  2348. SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
  2349. andSISIDXREG(SISCR, 0x32, ~0x07);
  2350. }
  2351. } else if(temp1 == 0) {
  2352. SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
  2353. andSISIDXREG(SISCR, 0x32, ~0x07);
  2354. }
  2355. /* Set general purpose IO for Chrontel communication */
  2356. SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x00);
  2357. #endif
  2358. } else {
  2359. #ifdef CONFIG_FB_SIS_315
  2360. ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2; /* Chrontel 7019 */
  2361. temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49);
  2362. SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, 0x20);
  2363. SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
  2364. temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
  2365. temp2 |= 0x01;
  2366. SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
  2367. SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
  2368. temp2 ^= 0x01;
  2369. SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
  2370. SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
  2371. temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
  2372. SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, temp1);
  2373. temp1 = 0;
  2374. if(temp2 & 0x02) temp1 |= 0x01;
  2375. if(temp2 & 0x10) temp1 |= 0x01;
  2376. if(temp2 & 0x04) temp1 |= 0x02;
  2377. if( (temp1 & 0x01) && (temp1 & 0x02) ) temp1 = 0x04;
  2378. switch(temp1) {
  2379. case 0x01:
  2380. printk(KERN_INFO "%s CVBS output\n", stdstr);
  2381. ivideo->vbflags |= TV_AVIDEO;
  2382. orSISIDXREG(SISCR, 0x32, 0x01);
  2383. andSISIDXREG(SISCR, 0x32, ~0x06);
  2384. break;
  2385. case 0x02:
  2386. printk(KERN_INFO "%s SVIDEO output\n", stdstr);
  2387. ivideo->vbflags |= TV_SVIDEO;
  2388. orSISIDXREG(SISCR, 0x32, 0x02);
  2389. andSISIDXREG(SISCR, 0x32, ~0x05);
  2390. break;
  2391. case 0x04:
  2392. printk(KERN_INFO "%s SCART output\n", stdstr);
  2393. orSISIDXREG(SISCR, 0x32, 0x04);
  2394. andSISIDXREG(SISCR, 0x32, ~0x03);
  2395. break;
  2396. default:
  2397. andSISIDXREG(SISCR, 0x32, ~0x07);
  2398. }
  2399. #endif
  2400. }
  2401. }
  2402. static void __devinit
  2403. sisfb_get_VB_type(struct sis_video_info *ivideo)
  2404. {
  2405. char stdstr[] = "sisfb: Detected";
  2406. char bridgestr[] = "video bridge";
  2407. u8 vb_chipid;
  2408. u8 reg;
  2409. /* No CRT2 on XGI Z7 */
  2410. if(ivideo->chip == XGI_20)
  2411. return;
  2412. inSISIDXREG(SISPART4, 0x00, vb_chipid);
  2413. switch(vb_chipid) {
  2414. case 0x01:
  2415. inSISIDXREG(SISPART4, 0x01, reg);
  2416. if(reg < 0xb0) {
  2417. ivideo->vbflags |= VB_301; /* Deprecated */
  2418. ivideo->vbflags2 |= VB2_301;
  2419. printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
  2420. } else if(reg < 0xc0) {
  2421. ivideo->vbflags |= VB_301B; /* Deprecated */
  2422. ivideo->vbflags2 |= VB2_301B;
  2423. inSISIDXREG(SISPART4,0x23,reg);
  2424. if(!(reg & 0x02)) {
  2425. ivideo->vbflags |= VB_30xBDH; /* Deprecated */
  2426. ivideo->vbflags2 |= VB2_30xBDH;
  2427. printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
  2428. } else {
  2429. printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
  2430. }
  2431. } else if(reg < 0xd0) {
  2432. ivideo->vbflags |= VB_301C; /* Deprecated */
  2433. ivideo->vbflags2 |= VB2_301C;
  2434. printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
  2435. } else if(reg < 0xe0) {
  2436. ivideo->vbflags |= VB_301LV; /* Deprecated */
  2437. ivideo->vbflags2 |= VB2_301LV;
  2438. printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
  2439. } else if(reg <= 0xe1) {
  2440. inSISIDXREG(SISPART4,0x39,reg);
  2441. if(reg == 0xff) {
  2442. ivideo->vbflags |= VB_302LV; /* Deprecated */
  2443. ivideo->vbflags2 |= VB2_302LV;
  2444. printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
  2445. } else {
  2446. ivideo->vbflags |= VB_301C; /* Deprecated */
  2447. ivideo->vbflags2 |= VB2_301C;
  2448. printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
  2449. #if 0
  2450. ivideo->vbflags |= VB_302ELV; /* Deprecated */
  2451. ivideo->vbflags2 |= VB2_302ELV;
  2452. printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
  2453. #endif
  2454. }
  2455. }
  2456. break;
  2457. case 0x02:
  2458. ivideo->vbflags |= VB_302B; /* Deprecated */
  2459. ivideo->vbflags2 |= VB2_302B;
  2460. printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
  2461. break;
  2462. }
  2463. if((!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
  2464. inSISIDXREG(SISCR, 0x37, reg);
  2465. reg &= SIS_EXTERNAL_CHIP_MASK;
  2466. reg >>= 1;
  2467. if(ivideo->sisvga_engine == SIS_300_VGA) {
  2468. #ifdef CONFIG_FB_SIS_300
  2469. switch(reg) {
  2470. case SIS_EXTERNAL_CHIP_LVDS:
  2471. ivideo->vbflags |= VB_LVDS; /* Deprecated */
  2472. ivideo->vbflags2 |= VB2_LVDS;
  2473. break;
  2474. case SIS_EXTERNAL_CHIP_TRUMPION:
  2475. ivideo->vbflags |= (VB_LVDS | VB_TRUMPION); /* Deprecated */
  2476. ivideo->vbflags2 |= (VB2_LVDS | VB2_TRUMPION);
  2477. break;
  2478. case SIS_EXTERNAL_CHIP_CHRONTEL:
  2479. ivideo->vbflags |= VB_CHRONTEL; /* Deprecated */
  2480. ivideo->vbflags2 |= VB2_CHRONTEL;
  2481. break;
  2482. case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
  2483. ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
  2484. ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
  2485. break;
  2486. }
  2487. if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 1;
  2488. #endif
  2489. } else if(ivideo->chip < SIS_661) {
  2490. #ifdef CONFIG_FB_SIS_315
  2491. switch (reg) {
  2492. case SIS310_EXTERNAL_CHIP_LVDS:
  2493. ivideo->vbflags |= VB_LVDS; /* Deprecated */
  2494. ivideo->vbflags2 |= VB2_LVDS;
  2495. break;
  2496. case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
  2497. ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
  2498. ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
  2499. break;
  2500. }
  2501. if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
  2502. #endif
  2503. } else if(ivideo->chip >= SIS_661) {
  2504. #ifdef CONFIG_FB_SIS_315
  2505. inSISIDXREG(SISCR, 0x38, reg);
  2506. reg >>= 5;
  2507. switch(reg) {
  2508. case 0x02:
  2509. ivideo->vbflags |= VB_LVDS; /* Deprecated */
  2510. ivideo->vbflags2 |= VB2_LVDS;
  2511. break;
  2512. case 0x03:
  2513. ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
  2514. ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
  2515. break;
  2516. case 0x04:
  2517. ivideo->vbflags |= (VB_LVDS | VB_CONEXANT); /* Deprecated */
  2518. ivideo->vbflags2 |= (VB2_LVDS | VB2_CONEXANT);
  2519. break;
  2520. }
  2521. if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
  2522. #endif
  2523. }
  2524. if(ivideo->vbflags2 & VB2_LVDS) {
  2525. printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
  2526. }
  2527. if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags2 & VB2_TRUMPION)) {
  2528. printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
  2529. }
  2530. if(ivideo->vbflags2 & VB2_CHRONTEL) {
  2531. printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
  2532. }
  2533. if((ivideo->chip >= SIS_661) && (ivideo->vbflags2 & VB2_CONEXANT)) {
  2534. printk(KERN_INFO "%s Conexant external device\n", stdstr);
  2535. }
  2536. }
  2537. if(ivideo->vbflags2 & VB2_SISBRIDGE) {
  2538. SiS_SenseLCD(ivideo);
  2539. SiS_Sense30x(ivideo);
  2540. } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
  2541. SiS_SenseCh(ivideo);
  2542. }
  2543. }
  2544. /* ---------- Engine initialization routines ------------ */
  2545. static void
  2546. sisfb_engine_init(struct sis_video_info *ivideo)
  2547. {
  2548. /* Initialize command queue (we use MMIO only) */
  2549. /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
  2550. ivideo->caps &= ~(TURBO_QUEUE_CAP |
  2551. MMIO_CMD_QUEUE_CAP |
  2552. VM_CMD_QUEUE_CAP |
  2553. AGP_CMD_QUEUE_CAP);
  2554. #ifdef CONFIG_FB_SIS_300
  2555. if(ivideo->sisvga_engine == SIS_300_VGA) {
  2556. u32 tqueue_pos;
  2557. u8 tq_state;
  2558. tqueue_pos = (ivideo->video_size - ivideo->cmdQueueSize) / (64 * 1024);
  2559. inSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
  2560. tq_state |= 0xf0;
  2561. tq_state &= 0xfc;
  2562. tq_state |= (u8)(tqueue_pos >> 8);
  2563. outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
  2564. outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
  2565. ivideo->caps |= TURBO_QUEUE_CAP;
  2566. }
  2567. #endif
  2568. #ifdef CONFIG_FB_SIS_315
  2569. if(ivideo->sisvga_engine == SIS_315_VGA) {
  2570. u32 tempq = 0, templ;
  2571. u8 temp;
  2572. if(ivideo->chip == XGI_20) {
  2573. switch(ivideo->cmdQueueSize) {
  2574. case (64 * 1024):
  2575. temp = SIS_CMD_QUEUE_SIZE_Z7_64k;
  2576. break;
  2577. case (128 * 1024):
  2578. default:
  2579. temp = SIS_CMD_QUEUE_SIZE_Z7_128k;
  2580. }
  2581. } else {
  2582. switch(ivideo->cmdQueueSize) {
  2583. case (4 * 1024 * 1024):
  2584. temp = SIS_CMD_QUEUE_SIZE_4M;
  2585. break;
  2586. case (2 * 1024 * 1024):
  2587. temp = SIS_CMD_QUEUE_SIZE_2M;
  2588. break;
  2589. case (1 * 1024 * 1024):
  2590. temp = SIS_CMD_QUEUE_SIZE_1M;
  2591. break;
  2592. default:
  2593. case (512 * 1024):
  2594. temp = SIS_CMD_QUEUE_SIZE_512k;
  2595. }
  2596. }
  2597. outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
  2598. outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
  2599. if((ivideo->chip >= XGI_40) && ivideo->modechanged) {
  2600. /* Must disable dual pipe on XGI_40. Can't do
  2601. * this in MMIO mode, because it requires
  2602. * setting/clearing a bit in the MMIO fire trigger
  2603. * register.
  2604. */
  2605. if(!((templ = MMIO_IN32(ivideo->mmio_vbase, 0x8240)) & (1 << 10))) {
  2606. MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, 0);
  2607. outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, (temp | SIS_VRAM_CMDQUEUE_ENABLE));
  2608. tempq = MMIO_IN32(ivideo->mmio_vbase, Q_READ_PTR);
  2609. MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, tempq);
  2610. tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
  2611. MMIO_OUT32(ivideo->mmio_vbase, Q_BASE_ADDR, tempq);
  2612. writel(0x16800000 + 0x8240, ivideo->video_vbase + tempq);
  2613. writel(templ | (1 << 10), ivideo->video_vbase + tempq + 4);
  2614. writel(0x168F0000, ivideo->video_vbase + tempq + 8);
  2615. writel(0x168F0000, ivideo->video_vbase + tempq + 12);
  2616. MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, (tempq + 16));
  2617. sisfb_syncaccel(ivideo);
  2618. outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
  2619. }
  2620. }
  2621. tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT);
  2622. MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
  2623. temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
  2624. outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
  2625. tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
  2626. MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
  2627. ivideo->caps |= MMIO_CMD_QUEUE_CAP;
  2628. }
  2629. #endif
  2630. ivideo->engineok = 1;
  2631. }
  2632. static void __devinit
  2633. sisfb_detect_lcd_type(struct sis_video_info *ivideo)
  2634. {
  2635. u8 reg;
  2636. int i;
  2637. inSISIDXREG(SISCR, 0x36, reg);
  2638. reg &= 0x0f;
  2639. if(ivideo->sisvga_engine == SIS_300_VGA) {
  2640. ivideo->CRT2LCDType = sis300paneltype[reg];
  2641. } else if(ivideo->chip >= SIS_661) {
  2642. ivideo->CRT2LCDType = sis661paneltype[reg];
  2643. } else {
  2644. ivideo->CRT2LCDType = sis310paneltype[reg];
  2645. if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
  2646. if((ivideo->CRT2LCDType != LCD_320x240_2) &&
  2647. (ivideo->CRT2LCDType != LCD_320x240_3)) {
  2648. ivideo->CRT2LCDType = LCD_320x240;
  2649. }
  2650. }
  2651. }
  2652. if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
  2653. /* For broken BIOSes: Assume 1024x768, RGB18 */
  2654. ivideo->CRT2LCDType = LCD_1024x768;
  2655. setSISIDXREG(SISCR,0x36,0xf0,0x02);
  2656. setSISIDXREG(SISCR,0x37,0xee,0x01);
  2657. printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
  2658. }
  2659. for(i = 0; i < SIS_LCD_NUMBER; i++) {
  2660. if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) {
  2661. ivideo->lcdxres = sis_lcd_data[i].xres;
  2662. ivideo->lcdyres = sis_lcd_data[i].yres;
  2663. ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
  2664. break;
  2665. }
  2666. }
  2667. #ifdef CONFIG_FB_SIS_300
  2668. if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
  2669. ivideo->lcdxres = 1360; ivideo->lcdyres = 1024;
  2670. ivideo->lcddefmodeidx = DEFAULT_MODE_1360;
  2671. } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
  2672. ivideo->lcdxres = 848; ivideo->lcdyres = 480;
  2673. ivideo->lcddefmodeidx = DEFAULT_MODE_848;
  2674. } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL856) {
  2675. ivideo->lcdxres = 856; ivideo->lcdyres = 480;
  2676. ivideo->lcddefmodeidx = DEFAULT_MODE_856;
  2677. }
  2678. #endif
  2679. printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n",
  2680. ivideo->lcdxres, ivideo->lcdyres);
  2681. }
  2682. static void __devinit
  2683. sisfb_save_pdc_emi(struct sis_video_info *ivideo)
  2684. {
  2685. #ifdef CONFIG_FB_SIS_300
  2686. /* Save the current PanelDelayCompensation if the LCD is currently used */
  2687. if(ivideo->sisvga_engine == SIS_300_VGA) {
  2688. if(ivideo->vbflags2 & (VB2_LVDS | VB2_30xBDH)) {
  2689. int tmp;
  2690. inSISIDXREG(SISCR,0x30,tmp);
  2691. if(tmp & 0x20) {
  2692. /* Currently on LCD? If yes, read current pdc */
  2693. inSISIDXREG(SISPART1,0x13,ivideo->detectedpdc);
  2694. ivideo->detectedpdc &= 0x3c;
  2695. if(ivideo->SiS_Pr.PDC == -1) {
  2696. /* Let option override detection */
  2697. ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
  2698. }
  2699. printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
  2700. ivideo->detectedpdc);
  2701. }
  2702. if((ivideo->SiS_Pr.PDC != -1) &&
  2703. (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
  2704. printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
  2705. ivideo->SiS_Pr.PDC);
  2706. }
  2707. }
  2708. }
  2709. #endif
  2710. #ifdef CONFIG_FB_SIS_315
  2711. if(ivideo->sisvga_engine == SIS_315_VGA) {
  2712. /* Try to find about LCDA */
  2713. if(ivideo->vbflags2 & VB2_SISLCDABRIDGE) {
  2714. int tmp;
  2715. inSISIDXREG(SISPART1,0x13,tmp);
  2716. if(tmp & 0x04) {
  2717. ivideo->SiS_Pr.SiS_UseLCDA = TRUE;
  2718. ivideo->detectedlcda = 0x03;
  2719. }
  2720. }
  2721. /* Save PDC */
  2722. if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
  2723. int tmp;
  2724. inSISIDXREG(SISCR,0x30,tmp);
  2725. if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
  2726. /* Currently on LCD? If yes, read current pdc */
  2727. u8 pdc;
  2728. inSISIDXREG(SISPART1,0x2D,pdc);
  2729. ivideo->detectedpdc = (pdc & 0x0f) << 1;
  2730. ivideo->detectedpdca = (pdc & 0xf0) >> 3;
  2731. inSISIDXREG(SISPART1,0x35,pdc);
  2732. ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
  2733. inSISIDXREG(SISPART1,0x20,pdc);
  2734. ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
  2735. if(ivideo->newrom) {
  2736. /* New ROM invalidates other PDC resp. */
  2737. if(ivideo->detectedlcda != 0xff) {
  2738. ivideo->detectedpdc = 0xff;
  2739. } else {
  2740. ivideo->detectedpdca = 0xff;
  2741. }
  2742. }
  2743. if(ivideo->SiS_Pr.PDC == -1) {
  2744. if(ivideo->detectedpdc != 0xff) {
  2745. ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
  2746. }
  2747. }
  2748. if(ivideo->SiS_Pr.PDCA == -1) {
  2749. if(ivideo->detectedpdca != 0xff) {
  2750. ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
  2751. }
  2752. }
  2753. if(ivideo->detectedpdc != 0xff) {
  2754. printk(KERN_INFO
  2755. "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
  2756. ivideo->detectedpdc);
  2757. }
  2758. if(ivideo->detectedpdca != 0xff) {
  2759. printk(KERN_INFO
  2760. "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
  2761. ivideo->detectedpdca);
  2762. }
  2763. }
  2764. /* Save EMI */
  2765. if(ivideo->vbflags2 & VB2_SISEMIBRIDGE) {
  2766. inSISIDXREG(SISPART4,0x30,ivideo->SiS_Pr.EMI_30);
  2767. inSISIDXREG(SISPART4,0x31,ivideo->SiS_Pr.EMI_31);
  2768. inSISIDXREG(SISPART4,0x32,ivideo->SiS_Pr.EMI_32);
  2769. inSISIDXREG(SISPART4,0x33,ivideo->SiS_Pr.EMI_33);
  2770. ivideo->SiS_Pr.HaveEMI = TRUE;
  2771. if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
  2772. ivideo->SiS_Pr.HaveEMILCD = TRUE;
  2773. }
  2774. }
  2775. }
  2776. /* Let user override detected PDCs (all bridges) */
  2777. if(ivideo->vbflags2 & VB2_30xBLV) {
  2778. if((ivideo->SiS_Pr.PDC != -1) &&
  2779. (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
  2780. printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
  2781. ivideo->SiS_Pr.PDC);
  2782. }
  2783. if((ivideo->SiS_Pr.PDCA != -1) &&
  2784. (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
  2785. printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
  2786. ivideo->SiS_Pr.PDCA);
  2787. }
  2788. }
  2789. }
  2790. #endif
  2791. }
  2792. /* -------------------- Memory manager routines ---------------------- */
  2793. static u32 __devinit
  2794. sisfb_getheapstart(struct sis_video_info *ivideo)
  2795. {
  2796. u32 ret = ivideo->sisfb_parm_mem * 1024;
  2797. u32 maxoffs = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
  2798. u32 def;
  2799. /* Calculate heap start = end of memory for console
  2800. *
  2801. * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
  2802. * C = console, D = heap, H = HWCursor, Q = cmd-queue
  2803. *
  2804. * On 76x in UMA+LFB mode, the layout is as follows:
  2805. * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
  2806. * where the heap is the entire UMA area, eventually
  2807. * into the LFB area if the given mem parameter is
  2808. * higher than the size of the UMA memory.
  2809. *
  2810. * Basically given by "mem" parameter
  2811. *
  2812. * maximum = videosize - cmd_queue - hwcursor
  2813. * (results in a heap of size 0)
  2814. * default = SiS 300: depends on videosize
  2815. * SiS 315/330/340/XGI: 32k below max
  2816. */
  2817. if(ivideo->sisvga_engine == SIS_300_VGA) {
  2818. if(ivideo->video_size > 0x1000000) {
  2819. def = 0xc00000;
  2820. } else if(ivideo->video_size > 0x800000) {
  2821. def = 0x800000;
  2822. } else {
  2823. def = 0x400000;
  2824. }
  2825. } else if(ivideo->UMAsize && ivideo->LFBsize) {
  2826. ret = def = 0;
  2827. } else {
  2828. def = maxoffs - 0x8000;
  2829. }
  2830. /* Use default for secondary card for now (FIXME) */
  2831. if((!ret) || (ret > maxoffs) || (ivideo->cardnumber != 0))
  2832. ret = def;
  2833. return ret;
  2834. }
  2835. static u32 __devinit
  2836. sisfb_getheapsize(struct sis_video_info *ivideo)
  2837. {
  2838. u32 max = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
  2839. u32 ret = 0;
  2840. if(ivideo->UMAsize && ivideo->LFBsize) {
  2841. if( (!ivideo->sisfb_parm_mem) ||
  2842. ((ivideo->sisfb_parm_mem * 1024) > max) ||
  2843. ((max - (ivideo->sisfb_parm_mem * 1024)) < ivideo->UMAsize) ) {
  2844. ret = ivideo->UMAsize;
  2845. max -= ivideo->UMAsize;
  2846. } else {
  2847. ret = max - (ivideo->sisfb_parm_mem * 1024);
  2848. max = ivideo->sisfb_parm_mem * 1024;
  2849. }
  2850. ivideo->video_offset = ret;
  2851. ivideo->sisfb_mem = max;
  2852. } else {
  2853. ret = max - ivideo->heapstart;
  2854. ivideo->sisfb_mem = ivideo->heapstart;
  2855. }
  2856. return ret;
  2857. }
  2858. static int __devinit
  2859. sisfb_heap_init(struct sis_video_info *ivideo)
  2860. {
  2861. struct SIS_OH *poh;
  2862. ivideo->video_offset = 0;
  2863. if(ivideo->sisfb_parm_mem) {
  2864. if( (ivideo->sisfb_parm_mem < (2 * 1024 * 1024)) ||
  2865. (ivideo->sisfb_parm_mem > ivideo->video_size) ) {
  2866. ivideo->sisfb_parm_mem = 0;
  2867. }
  2868. }
  2869. ivideo->heapstart = sisfb_getheapstart(ivideo);
  2870. ivideo->sisfb_heap_size = sisfb_getheapsize(ivideo);
  2871. ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart;
  2872. ivideo->sisfb_heap_end = ivideo->sisfb_heap_start + ivideo->sisfb_heap_size;
  2873. printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n",
  2874. (int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024));
  2875. ivideo->sisfb_heap.vinfo = ivideo;
  2876. ivideo->sisfb_heap.poha_chain = NULL;
  2877. ivideo->sisfb_heap.poh_freelist = NULL;
  2878. poh = sisfb_poh_new_node(&ivideo->sisfb_heap);
  2879. if(poh == NULL)
  2880. return 1;
  2881. poh->poh_next = &ivideo->sisfb_heap.oh_free;
  2882. poh->poh_prev = &ivideo->sisfb_heap.oh_free;
  2883. poh->size = ivideo->sisfb_heap_size;
  2884. poh->offset = ivideo->heapstart;
  2885. ivideo->sisfb_heap.oh_free.poh_next = poh;
  2886. ivideo->sisfb_heap.oh_free.poh_prev = poh;
  2887. ivideo->sisfb_heap.oh_free.size = 0;
  2888. ivideo->sisfb_heap.max_freesize = poh->size;
  2889. ivideo->sisfb_heap.oh_used.poh_next = &ivideo->sisfb_heap.oh_used;
  2890. ivideo->sisfb_heap.oh_used.poh_prev = &ivideo->sisfb_heap.oh_used;
  2891. ivideo->sisfb_heap.oh_used.size = SENTINEL;
  2892. if(ivideo->cardnumber == 0) {
  2893. /* For the first card, make this heap the "global" one
  2894. * for old DRM (which could handle only one card)
  2895. */
  2896. sisfb_heap = &ivideo->sisfb_heap;
  2897. }
  2898. return 0;
  2899. }
  2900. static struct SIS_OH *
  2901. sisfb_poh_new_node(struct SIS_HEAP *memheap)
  2902. {
  2903. struct SIS_OHALLOC *poha;
  2904. struct SIS_OH *poh;
  2905. unsigned long cOhs;
  2906. int i;
  2907. if(memheap->poh_freelist == NULL) {
  2908. poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL);
  2909. if(!poha)
  2910. return NULL;
  2911. poha->poha_next = memheap->poha_chain;
  2912. memheap->poha_chain = poha;
  2913. cOhs = (SIS_OH_ALLOC_SIZE - sizeof(struct SIS_OHALLOC)) / sizeof(struct SIS_OH) + 1;
  2914. poh = &poha->aoh[0];
  2915. for(i = cOhs - 1; i != 0; i--) {
  2916. poh->poh_next = poh + 1;
  2917. poh = poh + 1;
  2918. }
  2919. poh->poh_next = NULL;
  2920. memheap->poh_freelist = &poha->aoh[0];
  2921. }
  2922. poh = memheap->poh_freelist;
  2923. memheap->poh_freelist = poh->poh_next;
  2924. return poh;
  2925. }
  2926. static struct SIS_OH *
  2927. sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size)
  2928. {
  2929. struct SIS_OH *pohThis;
  2930. struct SIS_OH *pohRoot;
  2931. int bAllocated = 0;
  2932. if(size > memheap->max_freesize) {
  2933. DPRINTK("sisfb: Can't allocate %dk video memory\n",
  2934. (unsigned int) size / 1024);
  2935. return NULL;
  2936. }
  2937. pohThis = memheap->oh_free.poh_next;
  2938. while(pohThis != &memheap->oh_free) {
  2939. if(size <= pohThis->size) {
  2940. bAllocated = 1;
  2941. break;
  2942. }
  2943. pohThis = pohThis->poh_next;
  2944. }
  2945. if(!bAllocated) {
  2946. DPRINTK("sisfb: Can't allocate %dk video memory\n",
  2947. (unsigned int) size / 1024);
  2948. return NULL;
  2949. }
  2950. if(size == pohThis->size) {
  2951. pohRoot = pohThis;
  2952. sisfb_delete_node(pohThis);
  2953. } else {
  2954. pohRoot = sisfb_poh_new_node(memheap);
  2955. if(pohRoot == NULL)
  2956. return NULL;
  2957. pohRoot->offset = pohThis->offset;
  2958. pohRoot->size = size;
  2959. pohThis->offset += size;
  2960. pohThis->size -= size;
  2961. }
  2962. memheap->max_freesize -= size;
  2963. pohThis = &memheap->oh_used;
  2964. sisfb_insert_node(pohThis, pohRoot);
  2965. return pohRoot;
  2966. }
  2967. static void
  2968. sisfb_delete_node(struct SIS_OH *poh)
  2969. {
  2970. poh->poh_prev->poh_next = poh->poh_next;
  2971. poh->poh_next->poh_prev = poh->poh_prev;
  2972. }
  2973. static void
  2974. sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh)
  2975. {
  2976. struct SIS_OH *pohTemp = pohList->poh_next;
  2977. pohList->poh_next = poh;
  2978. pohTemp->poh_prev = poh;
  2979. poh->poh_prev = pohList;
  2980. poh->poh_next = pohTemp;
  2981. }
  2982. static struct SIS_OH *
  2983. sisfb_poh_free(struct SIS_HEAP *memheap, u32 base)
  2984. {
  2985. struct SIS_OH *pohThis;
  2986. struct SIS_OH *poh_freed;
  2987. struct SIS_OH *poh_prev;
  2988. struct SIS_OH *poh_next;
  2989. u32 ulUpper;
  2990. u32 ulLower;
  2991. int foundNode = 0;
  2992. poh_freed = memheap->oh_used.poh_next;
  2993. while(poh_freed != &memheap->oh_used) {
  2994. if(poh_freed->offset == base) {
  2995. foundNode = 1;
  2996. break;
  2997. }
  2998. poh_freed = poh_freed->poh_next;
  2999. }
  3000. if(!foundNode)
  3001. return NULL;
  3002. memheap->max_freesize += poh_freed->size;
  3003. poh_prev = poh_next = NULL;
  3004. ulUpper = poh_freed->offset + poh_freed->size;
  3005. ulLower = poh_freed->offset;
  3006. pohThis = memheap->oh_free.poh_next;
  3007. while(pohThis != &memheap->oh_free) {
  3008. if(pohThis->offset == ulUpper) {
  3009. poh_next = pohThis;
  3010. } else if((pohThis->offset + pohThis->size) == ulLower) {
  3011. poh_prev = pohThis;
  3012. }
  3013. pohThis = pohThis->poh_next;
  3014. }
  3015. sisfb_delete_node(poh_freed);
  3016. if(poh_prev && poh_next) {
  3017. poh_prev->size += (poh_freed->size + poh_next->size);
  3018. sisfb_delete_node(poh_next);
  3019. sisfb_free_node(memheap, poh_freed);
  3020. sisfb_free_node(memheap, poh_next);
  3021. return poh_prev;
  3022. }
  3023. if(poh_prev) {
  3024. poh_prev->size += poh_freed->size;
  3025. sisfb_free_node(memheap, poh_freed);
  3026. return poh_prev;
  3027. }
  3028. if(poh_next) {
  3029. poh_next->size += poh_freed->size;
  3030. poh_next->offset = poh_freed->offset;
  3031. sisfb_free_node(memheap, poh_freed);
  3032. return poh_next;
  3033. }
  3034. sisfb_insert_node(&memheap->oh_free, poh_freed);
  3035. return poh_freed;
  3036. }
  3037. static void
  3038. sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh)
  3039. {
  3040. if(poh == NULL)
  3041. return;
  3042. poh->poh_next = memheap->poh_freelist;
  3043. memheap->poh_freelist = poh;
  3044. }
  3045. static void
  3046. sis_int_malloc(struct sis_video_info *ivideo, struct sis_memreq *req)
  3047. {
  3048. struct SIS_OH *poh = NULL;
  3049. if((ivideo) && (ivideo->sisfb_id == SISFB_ID) && (!ivideo->havenoheap))
  3050. poh = sisfb_poh_allocate(&ivideo->sisfb_heap, (u32)req->size);
  3051. if(poh == NULL) {
  3052. req->offset = req->size = 0;
  3053. DPRINTK("sisfb: Video RAM allocation failed\n");
  3054. } else {
  3055. req->offset = poh->offset;
  3056. req->size = poh->size;
  3057. DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
  3058. (poh->offset + ivideo->video_vbase));
  3059. }
  3060. }
  3061. void
  3062. sis_malloc(struct sis_memreq *req)
  3063. {
  3064. struct sis_video_info *ivideo = sisfb_heap->vinfo;
  3065. if(&ivideo->sisfb_heap == sisfb_heap)
  3066. sis_int_malloc(ivideo, req);
  3067. else
  3068. req->offset = req->size = 0;
  3069. }
  3070. void
  3071. sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req)
  3072. {
  3073. struct sis_video_info *ivideo = pci_get_drvdata(pdev);
  3074. sis_int_malloc(ivideo, req);
  3075. }
  3076. /* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
  3077. static void
  3078. sis_int_free(struct sis_video_info *ivideo, u32 base)
  3079. {
  3080. struct SIS_OH *poh;
  3081. if((!ivideo) || (ivideo->sisfb_id != SISFB_ID) || (ivideo->havenoheap))
  3082. return;
  3083. poh = sisfb_poh_free(&ivideo->sisfb_heap, base);
  3084. if(poh == NULL) {
  3085. DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
  3086. (unsigned int) base);
  3087. }
  3088. }
  3089. void
  3090. sis_free(u32 base)
  3091. {
  3092. struct sis_video_info *ivideo = sisfb_heap->vinfo;
  3093. sis_int_free(ivideo, base);
  3094. }
  3095. void
  3096. sis_free_new(struct pci_dev *pdev, u32 base)
  3097. {
  3098. struct sis_video_info *ivideo = pci_get_drvdata(pdev);
  3099. sis_int_free(ivideo, base);
  3100. }
  3101. /* --------------------- SetMode routines ------------------------- */
  3102. static void
  3103. sisfb_check_engine_and_sync(struct sis_video_info *ivideo)
  3104. {
  3105. u8 cr30, cr31;
  3106. /* Check if MMIO and engines are enabled,
  3107. * and sync in case they are. Can't use
  3108. * ivideo->accel here, as this might have
  3109. * been changed before this is called.
  3110. */
  3111. inSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, cr30);
  3112. inSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, cr31);
  3113. /* MMIO and 2D/3D engine enabled? */
  3114. if((cr30 & SIS_MEM_MAP_IO_ENABLE) && (cr31 & 0x42)) {
  3115. #ifdef CONFIG_FB_SIS_300
  3116. if(ivideo->sisvga_engine == SIS_300_VGA) {
  3117. /* Don't care about TurboQueue. It's
  3118. * enough to know that the engines
  3119. * are enabled
  3120. */
  3121. sisfb_syncaccel(ivideo);
  3122. }
  3123. #endif
  3124. #ifdef CONFIG_FB_SIS_315
  3125. if(ivideo->sisvga_engine == SIS_315_VGA) {
  3126. /* Check that any queue mode is
  3127. * enabled, and that the queue
  3128. * is not in the state of "reset"
  3129. */
  3130. inSISIDXREG(SISSR, 0x26, cr30);
  3131. if((cr30 & 0xe0) && (!(cr30 & 0x01))) {
  3132. sisfb_syncaccel(ivideo);
  3133. }
  3134. }
  3135. #endif
  3136. }
  3137. }
  3138. static void
  3139. sisfb_pre_setmode(struct sis_video_info *ivideo)
  3140. {
  3141. u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0;
  3142. int tvregnum = 0;
  3143. ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
  3144. outSISIDXREG(SISSR, 0x05, 0x86);
  3145. inSISIDXREG(SISCR, 0x31, cr31);
  3146. cr31 &= ~0x60;
  3147. cr31 |= 0x04;
  3148. cr33 = ivideo->rate_idx & 0x0F;
  3149. #ifdef CONFIG_FB_SIS_315
  3150. if(ivideo->sisvga_engine == SIS_315_VGA) {
  3151. if(ivideo->chip >= SIS_661) {
  3152. inSISIDXREG(SISCR, 0x38, cr38);
  3153. cr38 &= ~0x07; /* Clear LCDA/DualEdge and YPbPr bits */
  3154. } else {
  3155. tvregnum = 0x38;
  3156. inSISIDXREG(SISCR, tvregnum, cr38);
  3157. cr38 &= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */
  3158. }
  3159. }
  3160. #endif
  3161. #ifdef CONFIG_FB_SIS_300
  3162. if(ivideo->sisvga_engine == SIS_300_VGA) {
  3163. tvregnum = 0x35;
  3164. inSISIDXREG(SISCR, tvregnum, cr38);
  3165. }
  3166. #endif
  3167. SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
  3168. SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
  3169. ivideo->curFSTN = ivideo->curDSTN = 0;
  3170. switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
  3171. case CRT2_TV:
  3172. cr38 &= ~0xc0; /* Clear PAL-M / PAL-N bits */
  3173. if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
  3174. #ifdef CONFIG_FB_SIS_315
  3175. if(ivideo->chip >= SIS_661) {
  3176. cr38 |= 0x04;
  3177. if(ivideo->vbflags & TV_YPBPR525P) cr35 |= 0x20;
  3178. else if(ivideo->vbflags & TV_YPBPR750P) cr35 |= 0x40;
  3179. else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60;
  3180. cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
  3181. cr35 &= ~0x01;
  3182. ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
  3183. } else if(ivideo->sisvga_engine == SIS_315_VGA) {
  3184. cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE);
  3185. cr38 |= 0x08;
  3186. if(ivideo->vbflags & TV_YPBPR525P) cr38 |= 0x10;
  3187. else if(ivideo->vbflags & TV_YPBPR750P) cr38 |= 0x20;
  3188. else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30;
  3189. cr31 &= ~0x01;
  3190. ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
  3191. }
  3192. #endif
  3193. } else if((ivideo->vbflags & TV_HIVISION) &&
  3194. (ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) {
  3195. if(ivideo->chip >= SIS_661) {
  3196. cr38 |= 0x04;
  3197. cr35 |= 0x60;
  3198. } else {
  3199. cr30 |= 0x80;
  3200. }
  3201. cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
  3202. cr31 |= 0x01;
  3203. cr35 |= 0x01;
  3204. ivideo->currentvbflags |= TV_HIVISION;
  3205. } else if(ivideo->vbflags & TV_SCART) {
  3206. cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE);
  3207. cr31 |= 0x01;
  3208. cr35 |= 0x01;
  3209. ivideo->currentvbflags |= TV_SCART;
  3210. } else {
  3211. if(ivideo->vbflags & TV_SVIDEO) {
  3212. cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE);
  3213. ivideo->currentvbflags |= TV_SVIDEO;
  3214. }
  3215. if(ivideo->vbflags & TV_AVIDEO) {
  3216. cr30 = (SIS_VB_OUTPUT_COMPOSITE | SIS_SIMULTANEOUS_VIEW_ENABLE);
  3217. ivideo->currentvbflags |= TV_AVIDEO;
  3218. }
  3219. }
  3220. cr31 |= SIS_DRIVER_MODE;
  3221. if(ivideo->vbflags & (TV_AVIDEO | TV_SVIDEO)) {
  3222. if(ivideo->vbflags & TV_PAL) {
  3223. cr31 |= 0x01; cr35 |= 0x01;
  3224. ivideo->currentvbflags |= TV_PAL;
  3225. if(ivideo->vbflags & TV_PALM) {
  3226. cr38 |= 0x40; cr35 |= 0x04;
  3227. ivideo->currentvbflags |= TV_PALM;
  3228. } else if(ivideo->vbflags & TV_PALN) {
  3229. cr38 |= 0x80; cr35 |= 0x08;
  3230. ivideo->currentvbflags |= TV_PALN;
  3231. }
  3232. } else {
  3233. cr31 &= ~0x01; cr35 &= ~0x01;
  3234. ivideo->currentvbflags |= TV_NTSC;
  3235. if(ivideo->vbflags & TV_NTSCJ) {
  3236. cr38 |= 0x40; cr35 |= 0x02;
  3237. ivideo->currentvbflags |= TV_NTSCJ;
  3238. }
  3239. }
  3240. }
  3241. break;
  3242. case CRT2_LCD:
  3243. cr30 = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
  3244. cr31 |= SIS_DRIVER_MODE;
  3245. SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn);
  3246. SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->sisfb_fstn);
  3247. ivideo->curFSTN = ivideo->sisfb_fstn;
  3248. ivideo->curDSTN = ivideo->sisfb_dstn;
  3249. break;
  3250. case CRT2_VGA:
  3251. cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
  3252. cr31 |= SIS_DRIVER_MODE;
  3253. if(ivideo->sisfb_nocrt2rate) {
  3254. cr33 |= (sisbios_mode[ivideo->sisfb_mode_idx].rate_idx << 4);
  3255. } else {
  3256. cr33 |= ((ivideo->rate_idx & 0x0F) << 4);
  3257. }
  3258. break;
  3259. default: /* disable CRT2 */
  3260. cr30 = 0x00;
  3261. cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
  3262. }
  3263. outSISIDXREG(SISCR, 0x30, cr30);
  3264. outSISIDXREG(SISCR, 0x33, cr33);
  3265. if(ivideo->chip >= SIS_661) {
  3266. #ifdef CONFIG_FB_SIS_315
  3267. cr31 &= ~0x01; /* Clear PAL flag (now in CR35) */
  3268. setSISIDXREG(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */
  3269. cr38 &= 0x07; /* Use only LCDA and HiVision/YPbPr bits */
  3270. setSISIDXREG(SISCR, 0x38, 0xf8, cr38);
  3271. #endif
  3272. } else if(ivideo->chip != SIS_300) {
  3273. outSISIDXREG(SISCR, tvregnum, cr38);
  3274. }
  3275. outSISIDXREG(SISCR, 0x31, cr31);
  3276. ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem;
  3277. sisfb_check_engine_and_sync(ivideo);
  3278. }
  3279. /* Fix SR11 for 661 and later */
  3280. #ifdef CONFIG_FB_SIS_315
  3281. static void
  3282. sisfb_fixup_SR11(struct sis_video_info *ivideo)
  3283. {
  3284. u8 tmpreg;
  3285. if(ivideo->chip >= SIS_661) {
  3286. inSISIDXREG(SISSR,0x11,tmpreg);
  3287. if(tmpreg & 0x20) {
  3288. inSISIDXREG(SISSR,0x3e,tmpreg);
  3289. tmpreg = (tmpreg + 1) & 0xff;
  3290. outSISIDXREG(SISSR,0x3e,tmpreg);
  3291. inSISIDXREG(SISSR,0x11,tmpreg);
  3292. }
  3293. if(tmpreg & 0xf0) {
  3294. andSISIDXREG(SISSR,0x11,0x0f);
  3295. }
  3296. }
  3297. }
  3298. #endif
  3299. static void
  3300. sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
  3301. {
  3302. if(val > 32) val = 32;
  3303. if(val < -32) val = -32;
  3304. ivideo->tvxpos = val;
  3305. if(ivideo->sisfblocked) return;
  3306. if(!ivideo->modechanged) return;
  3307. if(ivideo->currentvbflags & CRT2_TV) {
  3308. if(ivideo->vbflags2 & VB2_CHRONTEL) {
  3309. int x = ivideo->tvx;
  3310. switch(ivideo->chronteltype) {
  3311. case 1:
  3312. x += val;
  3313. if(x < 0) x = 0;
  3314. outSISIDXREG(SISSR,0x05,0x86);
  3315. SiS_SetCH700x(&ivideo->SiS_Pr, 0x0a, (x & 0xff));
  3316. SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD);
  3317. break;
  3318. case 2:
  3319. /* Not supported by hardware */
  3320. break;
  3321. }
  3322. } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
  3323. u8 p2_1f,p2_20,p2_2b,p2_42,p2_43;
  3324. unsigned short temp;
  3325. p2_1f = ivideo->p2_1f;
  3326. p2_20 = ivideo->p2_20;
  3327. p2_2b = ivideo->p2_2b;
  3328. p2_42 = ivideo->p2_42;
  3329. p2_43 = ivideo->p2_43;
  3330. temp = p2_1f | ((p2_20 & 0xf0) << 4);
  3331. temp += (val * 2);
  3332. p2_1f = temp & 0xff;
  3333. p2_20 = (temp & 0xf00) >> 4;
  3334. p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f;
  3335. temp = p2_43 | ((p2_42 & 0xf0) << 4);
  3336. temp += (val * 2);
  3337. p2_43 = temp & 0xff;
  3338. p2_42 = (temp & 0xf00) >> 4;
  3339. outSISIDXREG(SISPART2,0x1f,p2_1f);
  3340. setSISIDXREG(SISPART2,0x20,0x0F,p2_20);
  3341. setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b);
  3342. setSISIDXREG(SISPART2,0x42,0x0F,p2_42);
  3343. outSISIDXREG(SISPART2,0x43,p2_43);
  3344. }
  3345. }
  3346. }
  3347. static void
  3348. sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
  3349. {
  3350. if(val > 32) val = 32;
  3351. if(val < -32) val = -32;
  3352. ivideo->tvypos = val;
  3353. if(ivideo->sisfblocked) return;
  3354. if(!ivideo->modechanged) return;
  3355. if(ivideo->currentvbflags & CRT2_TV) {
  3356. if(ivideo->vbflags2 & VB2_CHRONTEL) {
  3357. int y = ivideo->tvy;
  3358. switch(ivideo->chronteltype) {
  3359. case 1:
  3360. y -= val;
  3361. if(y < 0) y = 0;
  3362. outSISIDXREG(SISSR,0x05,0x86);
  3363. SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b, (y & 0xff));
  3364. SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE);
  3365. break;
  3366. case 2:
  3367. /* Not supported by hardware */
  3368. break;
  3369. }
  3370. } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
  3371. char p2_01, p2_02;
  3372. val /= 2;
  3373. p2_01 = ivideo->p2_01;
  3374. p2_02 = ivideo->p2_02;
  3375. p2_01 += val;
  3376. p2_02 += val;
  3377. if(!(ivideo->currentvbflags & (TV_HIVISION | TV_YPBPR))) {
  3378. while((p2_01 <= 0) || (p2_02 <= 0)) {
  3379. p2_01 += 2;
  3380. p2_02 += 2;
  3381. }
  3382. }
  3383. outSISIDXREG(SISPART2,0x01,p2_01);
  3384. outSISIDXREG(SISPART2,0x02,p2_02);
  3385. }
  3386. }
  3387. }
  3388. static void
  3389. sisfb_post_setmode(struct sis_video_info *ivideo)
  3390. {
  3391. BOOLEAN crt1isoff = FALSE;
  3392. BOOLEAN doit = TRUE;
  3393. #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
  3394. u8 reg;
  3395. #endif
  3396. #ifdef CONFIG_FB_SIS_315
  3397. u8 reg1;
  3398. #endif
  3399. outSISIDXREG(SISSR, 0x05, 0x86);
  3400. #ifdef CONFIG_FB_SIS_315
  3401. sisfb_fixup_SR11(ivideo);
  3402. #endif
  3403. /* Now we actually HAVE changed the display mode */
  3404. ivideo->modechanged = 1;
  3405. /* We can't switch off CRT1 if bridge is in slave mode */
  3406. if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
  3407. if(sisfb_bridgeisslave(ivideo)) doit = FALSE;
  3408. } else
  3409. ivideo->sisfb_crt1off = 0;
  3410. #ifdef CONFIG_FB_SIS_300
  3411. if(ivideo->sisvga_engine == SIS_300_VGA) {
  3412. if((ivideo->sisfb_crt1off) && (doit)) {
  3413. crt1isoff = TRUE;
  3414. reg = 0x00;
  3415. } else {
  3416. crt1isoff = FALSE;
  3417. reg = 0x80;
  3418. }
  3419. setSISIDXREG(SISCR, 0x17, 0x7f, reg);
  3420. }
  3421. #endif
  3422. #ifdef CONFIG_FB_SIS_315
  3423. if(ivideo->sisvga_engine == SIS_315_VGA) {
  3424. if((ivideo->sisfb_crt1off) && (doit)) {
  3425. crt1isoff = TRUE;
  3426. reg = 0x40;
  3427. reg1 = 0xc0;
  3428. } else {
  3429. crt1isoff = FALSE;
  3430. reg = 0x00;
  3431. reg1 = 0x00;
  3432. }
  3433. setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
  3434. setSISIDXREG(SISSR, 0x1f, ~0xc0, reg1);
  3435. }
  3436. #endif
  3437. if(crt1isoff) {
  3438. ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1;
  3439. ivideo->currentvbflags |= VB_SINGLE_MODE;
  3440. } else {
  3441. ivideo->currentvbflags |= VB_DISPTYPE_CRT1;
  3442. if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) {
  3443. ivideo->currentvbflags |= VB_MIRROR_MODE;
  3444. } else {
  3445. ivideo->currentvbflags |= VB_SINGLE_MODE;
  3446. }
  3447. }
  3448. andSISIDXREG(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
  3449. if(ivideo->currentvbflags & CRT2_TV) {
  3450. if(ivideo->vbflags2 & VB2_SISBRIDGE) {
  3451. inSISIDXREG(SISPART2,0x1f,ivideo->p2_1f);
  3452. inSISIDXREG(SISPART2,0x20,ivideo->p2_20);
  3453. inSISIDXREG(SISPART2,0x2b,ivideo->p2_2b);
  3454. inSISIDXREG(SISPART2,0x42,ivideo->p2_42);
  3455. inSISIDXREG(SISPART2,0x43,ivideo->p2_43);
  3456. inSISIDXREG(SISPART2,0x01,ivideo->p2_01);
  3457. inSISIDXREG(SISPART2,0x02,ivideo->p2_02);
  3458. } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
  3459. if(ivideo->chronteltype == 1) {
  3460. ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
  3461. ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8);
  3462. ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b);
  3463. ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8);
  3464. }
  3465. }
  3466. }
  3467. if(ivideo->tvxpos) {
  3468. sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos);
  3469. }
  3470. if(ivideo->tvypos) {
  3471. sisfb_set_TVyposoffset(ivideo, ivideo->tvypos);
  3472. }
  3473. /* Eventually sync engines */
  3474. sisfb_check_engine_and_sync(ivideo);
  3475. /* (Re-)Initialize chip engines */
  3476. if(ivideo->accel) {
  3477. sisfb_engine_init(ivideo);
  3478. } else {
  3479. ivideo->engineok = 0;
  3480. }
  3481. }
  3482. static int
  3483. sisfb_reset_mode(struct sis_video_info *ivideo)
  3484. {
  3485. if(sisfb_set_mode(ivideo, 0))
  3486. return 1;
  3487. sisfb_set_pitch(ivideo);
  3488. sisfb_set_base_CRT1(ivideo, ivideo->current_base);
  3489. sisfb_set_base_CRT2(ivideo, ivideo->current_base);
  3490. return 0;
  3491. }
  3492. static void
  3493. sisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_command)
  3494. {
  3495. int mycrt1off;
  3496. switch(sisfb_command->sisfb_cmd) {
  3497. case SISFB_CMD_GETVBFLAGS:
  3498. if(!ivideo->modechanged) {
  3499. sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
  3500. } else {
  3501. sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
  3502. sisfb_command->sisfb_result[1] = ivideo->currentvbflags;
  3503. sisfb_command->sisfb_result[2] = ivideo->vbflags2;
  3504. }
  3505. break;
  3506. case SISFB_CMD_SWITCHCRT1:
  3507. /* arg[0]: 0 = off, 1 = on, 99 = query */
  3508. if(!ivideo->modechanged) {
  3509. sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
  3510. } else if(sisfb_command->sisfb_arg[0] == 99) {
  3511. /* Query */
  3512. sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
  3513. sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
  3514. } else if(ivideo->sisfblocked) {
  3515. sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_LOCKED;
  3516. } else if((!(ivideo->currentvbflags & CRT2_ENABLE)) &&
  3517. (sisfb_command->sisfb_arg[0] == 0)) {
  3518. sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_NOCRT2;
  3519. } else {
  3520. sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
  3521. mycrt1off = sisfb_command->sisfb_arg[0] ? 0 : 1;
  3522. if( ((ivideo->currentvbflags & VB_DISPTYPE_CRT1) && mycrt1off) ||
  3523. ((!(ivideo->currentvbflags & VB_DISPTYPE_CRT1)) && !mycrt1off) ) {
  3524. ivideo->sisfb_crt1off = mycrt1off;
  3525. if(sisfb_reset_mode(ivideo)) {
  3526. sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OTHER;
  3527. }
  3528. }
  3529. sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
  3530. }
  3531. break;
  3532. /* more to come */
  3533. default:
  3534. sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_UNKNOWN;
  3535. printk(KERN_ERR "sisfb: Unknown command 0x%x\n",
  3536. sisfb_command->sisfb_cmd);
  3537. }
  3538. }
  3539. #ifndef MODULE
  3540. SISINITSTATIC int __init
  3541. sisfb_setup(char *options)
  3542. {
  3543. char *this_opt;
  3544. sisfb_setdefaultparms();
  3545. if(!options || !(*options))
  3546. return 0;
  3547. while((this_opt = strsep(&options, ",")) != NULL) {
  3548. if(!(*this_opt)) continue;
  3549. if(!strnicmp(this_opt, "off", 3)) {
  3550. sisfb_off = 1;
  3551. } else if(!strnicmp(this_opt, "forcecrt2type:", 14)) {
  3552. /* Need to check crt2 type first for fstn/dstn */
  3553. sisfb_search_crt2type(this_opt + 14);
  3554. } else if(!strnicmp(this_opt, "tvmode:",7)) {
  3555. sisfb_search_tvstd(this_opt + 7);
  3556. } else if(!strnicmp(this_opt, "tvstandard:",11)) {
  3557. sisfb_search_tvstd(this_opt + 11);
  3558. } else if(!strnicmp(this_opt, "mode:", 5)) {
  3559. sisfb_search_mode(this_opt + 5, FALSE);
  3560. } else if(!strnicmp(this_opt, "vesa:", 5)) {
  3561. sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), FALSE);
  3562. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
  3563. } else if(!strnicmp(this_opt, "inverse", 7)) {
  3564. sisfb_inverse = 1;
  3565. /* fb_invert_cmaps(); */
  3566. } else if(!strnicmp(this_opt, "font:", 5)) {
  3567. if(strlen(this_opt + 5) < 40) {
  3568. strncpy(sisfb_fontname, this_opt + 5, sizeof(sisfb_fontname) - 1);
  3569. sisfb_fontname[sizeof(sisfb_fontname) - 1] = '\0';
  3570. }
  3571. #endif
  3572. } else if(!strnicmp(this_opt, "rate:", 5)) {
  3573. sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
  3574. } else if(!strnicmp(this_opt, "forcecrt1:", 10)) {
  3575. sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
  3576. } else if(!strnicmp(this_opt, "mem:",4)) {
  3577. sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
  3578. } else if(!strnicmp(this_opt, "pdc:", 4)) {
  3579. sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
  3580. } else if(!strnicmp(this_opt, "pdc1:", 5)) {
  3581. sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
  3582. } else if(!strnicmp(this_opt, "noaccel", 7)) {
  3583. sisfb_accel = 0;
  3584. } else if(!strnicmp(this_opt, "accel", 5)) {
  3585. sisfb_accel = -1;
  3586. } else if(!strnicmp(this_opt, "noypan", 6)) {
  3587. sisfb_ypan = 0;
  3588. } else if(!strnicmp(this_opt, "ypan", 4)) {
  3589. sisfb_ypan = -1;
  3590. } else if(!strnicmp(this_opt, "nomax", 5)) {
  3591. sisfb_max = 0;
  3592. } else if(!strnicmp(this_opt, "max", 3)) {
  3593. sisfb_max = -1;
  3594. } else if(!strnicmp(this_opt, "userom:", 7)) {
  3595. sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
  3596. } else if(!strnicmp(this_opt, "useoem:", 7)) {
  3597. sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
  3598. } else if(!strnicmp(this_opt, "nocrt2rate", 10)) {
  3599. sisfb_nocrt2rate = 1;
  3600. } else if(!strnicmp(this_opt, "scalelcd:", 9)) {
  3601. unsigned long temp = 2;
  3602. temp = simple_strtoul(this_opt + 9, NULL, 0);
  3603. if((temp == 0) || (temp == 1)) {
  3604. sisfb_scalelcd = temp ^ 1;
  3605. }
  3606. } else if(!strnicmp(this_opt, "tvxposoffset:", 13)) {
  3607. int temp = 0;
  3608. temp = (int)simple_strtol(this_opt + 13, NULL, 0);
  3609. if((temp >= -32) && (temp <= 32)) {
  3610. sisfb_tvxposoffset = temp;
  3611. }
  3612. } else if(!strnicmp(this_opt, "tvyposoffset:", 13)) {
  3613. int temp = 0;
  3614. temp = (int)simple_strtol(this_opt + 13, NULL, 0);
  3615. if((temp >= -32) && (temp <= 32)) {
  3616. sisfb_tvyposoffset = temp;
  3617. }
  3618. } else if(!strnicmp(this_opt, "specialtiming:", 14)) {
  3619. sisfb_search_specialtiming(this_opt + 14);
  3620. } else if(!strnicmp(this_opt, "lvdshl:", 7)) {
  3621. int temp = 4;
  3622. temp = simple_strtoul(this_opt + 7, NULL, 0);
  3623. if((temp >= 0) && (temp <= 3)) {
  3624. sisfb_lvdshl = temp;
  3625. }
  3626. } else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
  3627. sisfb_search_mode(this_opt, TRUE);
  3628. #if !defined(__i386__) && !defined(__x86_64__)
  3629. } else if(!strnicmp(this_opt, "resetcard", 9)) {
  3630. sisfb_resetcard = 1;
  3631. } else if(!strnicmp(this_opt, "videoram:", 9)) {
  3632. sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
  3633. #endif
  3634. } else {
  3635. printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt);
  3636. }
  3637. }
  3638. return 0;
  3639. }
  3640. #endif
  3641. static int __devinit
  3642. sisfb_check_rom(SIS_IOTYPE1 *rom_base, struct sis_video_info *ivideo)
  3643. {
  3644. SIS_IOTYPE1 *rom;
  3645. int romptr;
  3646. if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa))
  3647. return 0;
  3648. romptr = (readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
  3649. if(romptr > (0x10000 - 8))
  3650. return 0;
  3651. rom = rom_base + romptr;
  3652. if((readb(rom) != 'P') || (readb(rom + 1) != 'C') ||
  3653. (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R'))
  3654. return 0;
  3655. if((readb(rom + 4) | (readb(rom + 5) << 8)) != ivideo->chip_vendor)
  3656. return 0;
  3657. if((readb(rom + 6) | (readb(rom + 7) << 8)) != ivideo->chip_id)
  3658. return 0;
  3659. return 1;
  3660. }
  3661. static unsigned char * __devinit
  3662. sisfb_find_rom(struct pci_dev *pdev)
  3663. {
  3664. struct sis_video_info *ivideo = pci_get_drvdata(pdev);
  3665. SIS_IOTYPE1 *rom_base;
  3666. unsigned char *myrombase = NULL;
  3667. u32 temp;
  3668. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
  3669. size_t romsize;
  3670. /* First, try the official pci ROM functions (except
  3671. * on integrated chipsets which have no ROM).
  3672. */
  3673. if(!ivideo->nbridge) {
  3674. if((rom_base = pci_map_rom(pdev, &romsize))) {
  3675. if(sisfb_check_rom(rom_base, ivideo)) {
  3676. if((myrombase = vmalloc(65536))) {
  3677. /* Work around bug in pci/rom.c: Folks forgot to check
  3678. * whether the size retrieved from the BIOS image eventually
  3679. * is larger than the mapped size
  3680. */
  3681. if(pci_resource_len(pdev, PCI_ROM_RESOURCE) < romsize)
  3682. romsize = pci_resource_len(pdev, PCI_ROM_RESOURCE);
  3683. memcpy_fromio(myrombase, rom_base,
  3684. (romsize > 65536) ? 65536 : romsize);
  3685. }
  3686. }
  3687. pci_unmap_rom(pdev, rom_base);
  3688. }
  3689. }
  3690. if(myrombase) return myrombase;
  3691. #endif
  3692. /* Otherwise do it the conventional way. */
  3693. #if defined(__i386__) || defined(__x86_64__)
  3694. for(temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
  3695. rom_base = ioremap(temp, 65536);
  3696. if(!rom_base)
  3697. continue;
  3698. if(!sisfb_check_rom(rom_base, ivideo)) {
  3699. iounmap(rom_base);
  3700. continue;
  3701. }
  3702. if((myrombase = vmalloc(65536)))
  3703. memcpy_fromio(myrombase, rom_base, 65536);
  3704. iounmap(rom_base);
  3705. break;
  3706. }
  3707. #else
  3708. pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &temp);
  3709. pci_write_config_dword(pdev, PCI_ROM_ADDRESS,
  3710. (ivideo->video_base & PCI_ROM_ADDRESS_MASK) | PCI_ROM_ADDRESS_ENABLE);
  3711. rom_base = ioremap(ivideo->video_base, 65536);
  3712. if(rom_base) {
  3713. if(sisfb_check_rom(rom_base, ivideo)) {
  3714. if((myrombase = vmalloc(65536)))
  3715. memcpy_fromio(myrombase, rom_base, 65536);
  3716. }
  3717. iounmap(rom_base);
  3718. }
  3719. pci_write_config_dword(pdev, PCI_ROM_ADDRESS, temp);
  3720. #endif
  3721. return myrombase;
  3722. }
  3723. static void __devinit
  3724. sisfb_post_map_vram(struct sis_video_info *ivideo, unsigned int *mapsize,
  3725. unsigned int min)
  3726. {
  3727. ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize));
  3728. if(!ivideo->video_vbase) {
  3729. printk(KERN_ERR
  3730. "sisfb: Unable to map maximum video RAM for size detection\n");
  3731. (*mapsize) >>= 1;
  3732. while((!(ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize))))) {
  3733. (*mapsize) >>= 1;
  3734. if((*mapsize) < (min << 20))
  3735. break;
  3736. }
  3737. if(ivideo->video_vbase) {
  3738. printk(KERN_ERR
  3739. "sisfb: Video RAM size detection limited to %dMB\n",
  3740. (int)((*mapsize) >> 20));
  3741. }
  3742. }
  3743. }
  3744. #ifdef CONFIG_FB_SIS_300
  3745. static int __devinit
  3746. sisfb_post_300_buswidth(struct sis_video_info *ivideo)
  3747. {
  3748. SIS_IOTYPE1 *FBAddress = ivideo->video_vbase;
  3749. unsigned short temp;
  3750. unsigned char reg;
  3751. int i, j;
  3752. andSISIDXREG(SISSR, 0x15, 0xFB);
  3753. orSISIDXREG(SISSR, 0x15, 0x04);
  3754. outSISIDXREG(SISSR, 0x13, 0x00);
  3755. outSISIDXREG(SISSR, 0x14, 0xBF);
  3756. for(i = 0; i < 2; i++) {
  3757. temp = 0x1234;
  3758. for(j = 0; j < 4; j++) {
  3759. writew(temp, FBAddress);
  3760. if(readw(FBAddress) == temp)
  3761. break;
  3762. orSISIDXREG(SISSR, 0x3c, 0x01);
  3763. inSISIDXREG(SISSR, 0x05, reg);
  3764. inSISIDXREG(SISSR, 0x05, reg);
  3765. andSISIDXREG(SISSR, 0x3c, 0xfe);
  3766. inSISIDXREG(SISSR, 0x05, reg);
  3767. inSISIDXREG(SISSR, 0x05, reg);
  3768. temp++;
  3769. }
  3770. }
  3771. writel(0x01234567L, FBAddress);
  3772. writel(0x456789ABL, (FBAddress + 4));
  3773. writel(0x89ABCDEFL, (FBAddress + 8));
  3774. writel(0xCDEF0123L, (FBAddress + 12));
  3775. inSISIDXREG(SISSR, 0x3b, reg);
  3776. if(reg & 0x01) {
  3777. if(readl((FBAddress + 12)) == 0xCDEF0123L)
  3778. return 4; /* Channel A 128bit */
  3779. }
  3780. if(readl((FBAddress + 4)) == 0x456789ABL)
  3781. return 2; /* Channel B 64bit */
  3782. return 1; /* 32bit */
  3783. }
  3784. static int __devinit
  3785. sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration, int buswidth,
  3786. int PseudoRankCapacity, int PseudoAdrPinCount,
  3787. unsigned int mapsize)
  3788. {
  3789. SIS_IOTYPE1 *FBAddr = ivideo->video_vbase;
  3790. unsigned short sr14;
  3791. unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid;
  3792. unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage;
  3793. static const unsigned short SiS_DRAMType[17][5] = {
  3794. {0x0C,0x0A,0x02,0x40,0x39},
  3795. {0x0D,0x0A,0x01,0x40,0x48},
  3796. {0x0C,0x09,0x02,0x20,0x35},
  3797. {0x0D,0x09,0x01,0x20,0x44},
  3798. {0x0C,0x08,0x02,0x10,0x31},
  3799. {0x0D,0x08,0x01,0x10,0x40},
  3800. {0x0C,0x0A,0x01,0x20,0x34},
  3801. {0x0C,0x09,0x01,0x08,0x32},
  3802. {0x0B,0x08,0x02,0x08,0x21},
  3803. {0x0C,0x08,0x01,0x08,0x30},
  3804. {0x0A,0x08,0x02,0x04,0x11},
  3805. {0x0B,0x0A,0x01,0x10,0x28},
  3806. {0x09,0x08,0x02,0x02,0x01},
  3807. {0x0B,0x09,0x01,0x08,0x24},
  3808. {0x0B,0x08,0x01,0x04,0x20},
  3809. {0x0A,0x08,0x01,0x02,0x10},
  3810. {0x09,0x08,0x01,0x01,0x00}
  3811. };
  3812. for(k = 0; k <= 16; k++) {
  3813. RankCapacity = buswidth * SiS_DRAMType[k][3];
  3814. if(RankCapacity != PseudoRankCapacity)
  3815. continue;
  3816. if((SiS_DRAMType[k][2] + SiS_DRAMType[k][0]) > PseudoAdrPinCount)
  3817. continue;
  3818. BankNumHigh = RankCapacity * 16 * iteration - 1;
  3819. if(iteration == 3) { /* Rank No */
  3820. BankNumMid = RankCapacity * 16 - 1;
  3821. } else {
  3822. BankNumMid = RankCapacity * 16 * iteration / 2 - 1;
  3823. }
  3824. PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
  3825. PhysicalAdrHigh = BankNumHigh;
  3826. PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
  3827. PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
  3828. andSISIDXREG(SISSR, 0x15, 0xFB); /* Test */
  3829. orSISIDXREG(SISSR, 0x15, 0x04); /* Test */
  3830. sr14 = (SiS_DRAMType[k][3] * buswidth) - 1;
  3831. if(buswidth == 4) sr14 |= 0x80;
  3832. else if(buswidth == 2) sr14 |= 0x40;
  3833. outSISIDXREG(SISSR, 0x13, SiS_DRAMType[k][4]);
  3834. outSISIDXREG(SISSR, 0x14, sr14);
  3835. BankNumHigh <<= 16;
  3836. BankNumMid <<= 16;
  3837. if((BankNumHigh + PhysicalAdrHigh >= mapsize) ||
  3838. (BankNumMid + PhysicalAdrHigh >= mapsize) ||
  3839. (BankNumHigh + PhysicalAdrHalfPage >= mapsize) ||
  3840. (BankNumHigh + PhysicalAdrOtherPage >= mapsize))
  3841. continue;
  3842. /* Write data */
  3843. writew(((unsigned short)PhysicalAdrHigh),
  3844. (FBAddr + BankNumHigh + PhysicalAdrHigh));
  3845. writew(((unsigned short)BankNumMid),
  3846. (FBAddr + BankNumMid + PhysicalAdrHigh));
  3847. writew(((unsigned short)PhysicalAdrHalfPage),
  3848. (FBAddr + BankNumHigh + PhysicalAdrHalfPage));
  3849. writew(((unsigned short)PhysicalAdrOtherPage),
  3850. (FBAddr + BankNumHigh + PhysicalAdrOtherPage));
  3851. /* Read data */
  3852. if(readw(FBAddr + BankNumHigh + PhysicalAdrHigh) == PhysicalAdrHigh)
  3853. return 1;
  3854. }
  3855. return 0;
  3856. }
  3857. static void __devinit
  3858. sisfb_post_300_ramsize(struct pci_dev *pdev, unsigned int mapsize)
  3859. {
  3860. struct sis_video_info *ivideo = pci_get_drvdata(pdev);
  3861. int i, j, buswidth;
  3862. int PseudoRankCapacity, PseudoAdrPinCount;
  3863. buswidth = sisfb_post_300_buswidth(ivideo);
  3864. for(i = 6; i >= 0; i--) {
  3865. PseudoRankCapacity = 1 << i;
  3866. for(j = 4; j >= 1; j--) {
  3867. PseudoAdrPinCount = 15 - j;
  3868. if((PseudoRankCapacity * j) <= 64) {
  3869. if(sisfb_post_300_rwtest(ivideo,
  3870. j,
  3871. buswidth,
  3872. PseudoRankCapacity,
  3873. PseudoAdrPinCount,
  3874. mapsize))
  3875. return;
  3876. }
  3877. }
  3878. }
  3879. }
  3880. static void __devinit
  3881. sisfb_post_sis300(struct pci_dev *pdev)
  3882. {
  3883. struct sis_video_info *ivideo = pci_get_drvdata(pdev);
  3884. unsigned char *bios = ivideo->SiS_Pr.VirtualRomBase;
  3885. u8 reg, v1, v2, v3, v4, v5, v6, v7, v8;
  3886. u16 index, rindex, memtype = 0;
  3887. unsigned int mapsize;
  3888. if(!ivideo->SiS_Pr.UseROM)
  3889. bios = NULL;
  3890. outSISIDXREG(SISSR, 0x05, 0x86);
  3891. if(bios) {
  3892. if(bios[0x52] & 0x80) {
  3893. memtype = bios[0x52];
  3894. } else {
  3895. inSISIDXREG(SISSR, 0x3a, memtype);
  3896. }
  3897. memtype &= 0x07;
  3898. }
  3899. v3 = 0x80; v6 = 0x80;
  3900. if(ivideo->revision_id <= 0x13) {
  3901. v1 = 0x44; v2 = 0x42;
  3902. v4 = 0x44; v5 = 0x42;
  3903. } else {
  3904. v1 = 0x68; v2 = 0x43; /* Assume 125Mhz MCLK */
  3905. v4 = 0x68; v5 = 0x43; /* Assume 125Mhz ECLK */
  3906. if(bios) {
  3907. index = memtype * 5;
  3908. rindex = index + 0x54;
  3909. v1 = bios[rindex++];
  3910. v2 = bios[rindex++];
  3911. v3 = bios[rindex++];
  3912. rindex = index + 0x7c;
  3913. v4 = bios[rindex++];
  3914. v5 = bios[rindex++];
  3915. v6 = bios[rindex++];
  3916. }
  3917. }
  3918. outSISIDXREG(SISSR, 0x28, v1);
  3919. outSISIDXREG(SISSR, 0x29, v2);
  3920. outSISIDXREG(SISSR, 0x2a, v3);
  3921. outSISIDXREG(SISSR, 0x2e, v4);
  3922. outSISIDXREG(SISSR, 0x2f, v5);
  3923. outSISIDXREG(SISSR, 0x30, v6);
  3924. v1 = 0x10;
  3925. if(bios)
  3926. v1 = bios[0xa4];
  3927. outSISIDXREG(SISSR, 0x07, v1); /* DAC speed */
  3928. outSISIDXREG(SISSR, 0x11, 0x0f); /* DDC, power save */
  3929. v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
  3930. v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
  3931. if(bios) {
  3932. memtype += 0xa5;
  3933. v1 = bios[memtype];
  3934. v2 = bios[memtype + 8];
  3935. v3 = bios[memtype + 16];
  3936. v4 = bios[memtype + 24];
  3937. v5 = bios[memtype + 32];
  3938. v6 = bios[memtype + 40];
  3939. v7 = bios[memtype + 48];
  3940. v8 = bios[memtype + 56];
  3941. }
  3942. if(ivideo->revision_id >= 0x80)
  3943. v3 &= 0xfd;
  3944. outSISIDXREG(SISSR, 0x15, v1); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
  3945. outSISIDXREG(SISSR, 0x16, v2);
  3946. outSISIDXREG(SISSR, 0x17, v3);
  3947. outSISIDXREG(SISSR, 0x18, v4);
  3948. outSISIDXREG(SISSR, 0x19, v5);
  3949. outSISIDXREG(SISSR, 0x1a, v6);
  3950. outSISIDXREG(SISSR, 0x1b, v7);
  3951. outSISIDXREG(SISSR, 0x1c, v8); /* ---- */
  3952. andSISIDXREG(SISSR, 0x15 ,0xfb);
  3953. orSISIDXREG(SISSR, 0x15, 0x04);
  3954. if(bios) {
  3955. if(bios[0x53] & 0x02) {
  3956. orSISIDXREG(SISSR, 0x19, 0x20);
  3957. }
  3958. }
  3959. v1 = 0x04; /* DAC pedestal (BIOS 0xe5) */
  3960. if(ivideo->revision_id >= 0x80)
  3961. v1 |= 0x01;
  3962. outSISIDXREG(SISSR, 0x1f, v1);
  3963. outSISIDXREG(SISSR, 0x20, 0xa4); /* linear & relocated io & disable a0000 */
  3964. v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
  3965. if(bios) {
  3966. v1 = bios[0xe8];
  3967. v2 = bios[0xe9];
  3968. v3 = bios[0xea];
  3969. }
  3970. outSISIDXREG(SISSR, 0x23, v1);
  3971. outSISIDXREG(SISSR, 0x24, v2);
  3972. outSISIDXREG(SISSR, 0x25, v3);
  3973. outSISIDXREG(SISSR, 0x21, 0x84);
  3974. outSISIDXREG(SISSR, 0x22, 0x00);
  3975. outSISIDXREG(SISCR, 0x37, 0x00);
  3976. orSISIDXREG(SISPART1, 0x24, 0x01); /* unlock crt2 */
  3977. outSISIDXREG(SISPART1, 0x00, 0x00);
  3978. v1 = 0x40; v2 = 0x11;
  3979. if(bios) {
  3980. v1 = bios[0xec];
  3981. v2 = bios[0xeb];
  3982. }
  3983. outSISIDXREG(SISPART1, 0x02, v1);
  3984. if(ivideo->revision_id >= 0x80)
  3985. v2 &= ~0x01;
  3986. inSISIDXREG(SISPART4, 0x00, reg);
  3987. if((reg == 1) || (reg == 2)) {
  3988. outSISIDXREG(SISCR, 0x37, 0x02);
  3989. outSISIDXREG(SISPART2, 0x00, 0x1c);
  3990. v4 = 0x00; v5 = 0x00; v6 = 0x10;
  3991. if(ivideo->SiS_Pr.UseROM) {
  3992. v4 = bios[0xf5];
  3993. v5 = bios[0xf6];
  3994. v6 = bios[0xf7];
  3995. }
  3996. outSISIDXREG(SISPART4, 0x0d, v4);
  3997. outSISIDXREG(SISPART4, 0x0e, v5);
  3998. outSISIDXREG(SISPART4, 0x10, v6);
  3999. outSISIDXREG(SISPART4, 0x0f, 0x3f);
  4000. inSISIDXREG(SISPART4, 0x01, reg);
  4001. if(reg >= 0xb0) {
  4002. inSISIDXREG(SISPART4, 0x23, reg);
  4003. reg &= 0x20;
  4004. reg <<= 1;
  4005. outSISIDXREG(SISPART4, 0x23, reg);
  4006. }
  4007. } else {
  4008. v2 &= ~0x10;
  4009. }
  4010. outSISIDXREG(SISSR, 0x32, v2);
  4011. andSISIDXREG(SISPART1, 0x24, 0xfe); /* Lock CRT2 */
  4012. inSISIDXREG(SISSR, 0x16, reg);
  4013. reg &= 0xc3;
  4014. outSISIDXREG(SISCR, 0x35, reg);
  4015. outSISIDXREG(SISCR, 0x83, 0x00);
  4016. #if !defined(__i386__) && !defined(__x86_64__)
  4017. if(sisfb_videoram) {
  4018. outSISIDXREG(SISSR, 0x13, 0x28); /* ? */
  4019. reg = ((sisfb_videoram >> 10) - 1) | 0x40;
  4020. outSISIDXREG(SISSR, 0x14, reg);
  4021. } else {
  4022. #endif
  4023. /* Need to map max FB size for finding out about RAM size */
  4024. mapsize = 64 << 20;
  4025. sisfb_post_map_vram(ivideo, &mapsize, 4);
  4026. if(ivideo->video_vbase) {
  4027. sisfb_post_300_ramsize(pdev, mapsize);
  4028. iounmap(ivideo->video_vbase);
  4029. } else {
  4030. printk(KERN_DEBUG
  4031. "sisfb: Failed to map memory for size detection, assuming 8MB\n");
  4032. outSISIDXREG(SISSR, 0x13, 0x28); /* ? */
  4033. outSISIDXREG(SISSR, 0x14, 0x47); /* 8MB, 64bit default */
  4034. }
  4035. #if !defined(__i386__) && !defined(__x86_64__)
  4036. }
  4037. #endif
  4038. if(bios) {
  4039. v1 = bios[0xe6];
  4040. v2 = bios[0xe7];
  4041. } else {
  4042. inSISIDXREG(SISSR, 0x3a, reg);
  4043. if((reg & 0x30) == 0x30) {
  4044. v1 = 0x04; /* PCI */
  4045. v2 = 0x92;
  4046. } else {
  4047. v1 = 0x14; /* AGP */
  4048. v2 = 0xb2;
  4049. }
  4050. }
  4051. outSISIDXREG(SISSR, 0x21, v1);
  4052. outSISIDXREG(SISSR, 0x22, v2);
  4053. /* Sense CRT1 */
  4054. sisfb_sense_crt1(ivideo);
  4055. /* Set default mode, don't clear screen */
  4056. ivideo->SiS_Pr.SiS_UseOEM = FALSE;
  4057. SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
  4058. SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
  4059. ivideo->curFSTN = ivideo->curDSTN = 0;
  4060. ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
  4061. SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
  4062. outSISIDXREG(SISSR, 0x05, 0x86);
  4063. /* Display off */
  4064. orSISIDXREG(SISSR, 0x01, 0x20);
  4065. /* Save mode number in CR34 */
  4066. outSISIDXREG(SISCR, 0x34, 0x2e);
  4067. /* Let everyone know what the current mode is */
  4068. ivideo->modeprechange = 0x2e;
  4069. }
  4070. #endif
  4071. #ifdef CONFIG_FB_SIS_315
  4072. #if 0
  4073. static void __devinit
  4074. sisfb_post_sis315330(struct pci_dev *pdev)
  4075. {
  4076. /* TODO */
  4077. }
  4078. #endif
  4079. static void __devinit
  4080. sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay)
  4081. {
  4082. unsigned int i;
  4083. u8 reg;
  4084. for(i = 0; i <= (delay * 10 * 36); i++) {
  4085. inSISIDXREG(SISSR, 0x05, reg);
  4086. reg++;
  4087. }
  4088. }
  4089. static int __devinit
  4090. sisfb_find_host_bridge(struct sis_video_info *ivideo, struct pci_dev *mypdev,
  4091. unsigned short pcivendor)
  4092. {
  4093. struct pci_dev *pdev = NULL;
  4094. unsigned short temp;
  4095. int ret = 0;
  4096. while((pdev = SIS_PCI_GET_CLASS(PCI_CLASS_BRIDGE_HOST, pdev))) {
  4097. temp = pdev->vendor;
  4098. SIS_PCI_PUT_DEVICE(pdev);
  4099. if(temp == pcivendor) {
  4100. ret = 1;
  4101. break;
  4102. }
  4103. }
  4104. return ret;
  4105. }
  4106. static int __devinit
  4107. sisfb_post_xgi_rwtest(struct sis_video_info *ivideo, int starta,
  4108. unsigned int enda, unsigned int mapsize)
  4109. {
  4110. unsigned int pos;
  4111. int i;
  4112. writel(0, ivideo->video_vbase);
  4113. for(i = starta; i <= enda; i++) {
  4114. pos = 1 << i;
  4115. if(pos < mapsize)
  4116. writel(pos, ivideo->video_vbase + pos);
  4117. }
  4118. sisfb_post_xgi_delay(ivideo, 150);
  4119. if(readl(ivideo->video_vbase) != 0)
  4120. return 0;
  4121. for(i = starta; i <= enda; i++) {
  4122. pos = 1 << i;
  4123. if(pos < mapsize) {
  4124. if(readl(ivideo->video_vbase + pos) != pos)
  4125. return 0;
  4126. } else
  4127. return 0;
  4128. }
  4129. return 1;
  4130. }
  4131. static void __devinit
  4132. sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
  4133. {
  4134. unsigned int buswidth, ranksize, channelab, mapsize;
  4135. int i, j, k, l;
  4136. u8 reg, sr14;
  4137. static const u8 dramsr13[12 * 5] = {
  4138. 0x02, 0x0e, 0x0b, 0x80, 0x5d,
  4139. 0x02, 0x0e, 0x0a, 0x40, 0x59,
  4140. 0x02, 0x0d, 0x0b, 0x40, 0x4d,
  4141. 0x02, 0x0e, 0x09, 0x20, 0x55,
  4142. 0x02, 0x0d, 0x0a, 0x20, 0x49,
  4143. 0x02, 0x0c, 0x0b, 0x20, 0x3d,
  4144. 0x02, 0x0e, 0x08, 0x10, 0x51,
  4145. 0x02, 0x0d, 0x09, 0x10, 0x45,
  4146. 0x02, 0x0c, 0x0a, 0x10, 0x39,
  4147. 0x02, 0x0d, 0x08, 0x08, 0x41,
  4148. 0x02, 0x0c, 0x09, 0x08, 0x35,
  4149. 0x02, 0x0c, 0x08, 0x04, 0x31
  4150. };
  4151. static const u8 dramsr13_4[4 * 5] = {
  4152. 0x02, 0x0d, 0x09, 0x40, 0x45,
  4153. 0x02, 0x0c, 0x09, 0x20, 0x35,
  4154. 0x02, 0x0c, 0x08, 0x10, 0x31,
  4155. 0x02, 0x0b, 0x08, 0x08, 0x21
  4156. };
  4157. /* Enable linear mode, disable 0xa0000 address decoding */
  4158. /* We disable a0000 address decoding, because
  4159. * - if running on x86, if the card is disabled, it means
  4160. * that another card is in the system. We don't want
  4161. * to interphere with that primary card's textmode.
  4162. * - if running on non-x86, there usually is no VGA window
  4163. * at a0000.
  4164. */
  4165. orSISIDXREG(SISSR, 0x20, (0x80 | 0x04));
  4166. /* Need to map max FB size for finding out about RAM size */
  4167. mapsize = 256 << 20;
  4168. sisfb_post_map_vram(ivideo, &mapsize, 32);
  4169. if(!ivideo->video_vbase) {
  4170. printk(KERN_ERR "sisfb: Unable to detect RAM size. Setting default.\n");
  4171. outSISIDXREG(SISSR, 0x13, 0x35);
  4172. outSISIDXREG(SISSR, 0x14, 0x41);
  4173. /* TODO */
  4174. return;
  4175. }
  4176. /* Non-interleaving */
  4177. outSISIDXREG(SISSR, 0x15, 0x00);
  4178. /* No tiling */
  4179. outSISIDXREG(SISSR, 0x1c, 0x00);
  4180. if(ivideo->chip == XGI_20) {
  4181. channelab = 1;
  4182. inSISIDXREG(SISCR, 0x97, reg);
  4183. if(!(reg & 0x01)) { /* Single 32/16 */
  4184. buswidth = 32;
  4185. outSISIDXREG(SISSR, 0x13, 0xb1);
  4186. outSISIDXREG(SISSR, 0x14, 0x52);
  4187. sisfb_post_xgi_delay(ivideo, 1);
  4188. sr14 = 0x02;
  4189. if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
  4190. goto bail_out;
  4191. outSISIDXREG(SISSR, 0x13, 0x31);
  4192. outSISIDXREG(SISSR, 0x14, 0x42);
  4193. sisfb_post_xgi_delay(ivideo, 1);
  4194. if(sisfb_post_xgi_rwtest(ivideo, 23, 23, mapsize))
  4195. goto bail_out;
  4196. buswidth = 16;
  4197. outSISIDXREG(SISSR, 0x13, 0xb1);
  4198. outSISIDXREG(SISSR, 0x14, 0x41);
  4199. sisfb_post_xgi_delay(ivideo, 1);
  4200. sr14 = 0x01;
  4201. if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
  4202. goto bail_out;
  4203. else
  4204. outSISIDXREG(SISSR, 0x13, 0x31);
  4205. } else { /* Dual 16/8 */
  4206. buswidth = 16;
  4207. outSISIDXREG(SISSR, 0x13, 0xb1);
  4208. outSISIDXREG(SISSR, 0x14, 0x41);
  4209. sisfb_post_xgi_delay(ivideo, 1);
  4210. sr14 = 0x01;
  4211. if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
  4212. goto bail_out;
  4213. outSISIDXREG(SISSR, 0x13, 0x31);
  4214. outSISIDXREG(SISSR, 0x14, 0x31);
  4215. sisfb_post_xgi_delay(ivideo, 1);
  4216. if(sisfb_post_xgi_rwtest(ivideo, 22, 22, mapsize))
  4217. goto bail_out;
  4218. buswidth = 8;
  4219. outSISIDXREG(SISSR, 0x13, 0xb1);
  4220. outSISIDXREG(SISSR, 0x14, 0x30);
  4221. sisfb_post_xgi_delay(ivideo, 1);
  4222. sr14 = 0x00;
  4223. if(sisfb_post_xgi_rwtest(ivideo, 21, 22, mapsize))
  4224. goto bail_out;
  4225. else
  4226. outSISIDXREG(SISSR, 0x13, 0x31);
  4227. }
  4228. } else { /* XGI_40 */
  4229. inSISIDXREG(SISCR, 0x97, reg);
  4230. if(!(reg & 0x10)) {
  4231. inSISIDXREG(SISSR, 0x39, reg);
  4232. reg >>= 1;
  4233. }
  4234. if(reg & 0x01) { /* DDRII */
  4235. buswidth = 32;
  4236. if(ivideo->revision_id == 2) {
  4237. channelab = 2;
  4238. outSISIDXREG(SISSR, 0x13, 0xa1);
  4239. outSISIDXREG(SISSR, 0x14, 0x44);
  4240. sr14 = 0x04;
  4241. sisfb_post_xgi_delay(ivideo, 1);
  4242. if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
  4243. goto bail_out;
  4244. outSISIDXREG(SISSR, 0x13, 0x21);
  4245. outSISIDXREG(SISSR, 0x14, 0x34);
  4246. if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
  4247. goto bail_out;
  4248. channelab = 1;
  4249. outSISIDXREG(SISSR, 0x13, 0xa1);
  4250. outSISIDXREG(SISSR, 0x14, 0x40);
  4251. sr14 = 0x00;
  4252. if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
  4253. goto bail_out;
  4254. outSISIDXREG(SISSR, 0x13, 0x21);
  4255. outSISIDXREG(SISSR, 0x14, 0x30);
  4256. } else {
  4257. channelab = 3;
  4258. outSISIDXREG(SISSR, 0x13, 0xa1);
  4259. outSISIDXREG(SISSR, 0x14, 0x4c);
  4260. sr14 = 0x0c;
  4261. sisfb_post_xgi_delay(ivideo, 1);
  4262. if(sisfb_post_xgi_rwtest(ivideo, 23, 25, mapsize))
  4263. goto bail_out;
  4264. channelab = 2;
  4265. outSISIDXREG(SISSR, 0x14, 0x48);
  4266. sisfb_post_xgi_delay(ivideo, 1);
  4267. sr14 = 0x08;
  4268. if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
  4269. goto bail_out;
  4270. outSISIDXREG(SISSR, 0x13, 0x21);
  4271. outSISIDXREG(SISSR, 0x14, 0x3c);
  4272. sr14 = 0x0c;
  4273. if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) {
  4274. channelab = 3;
  4275. } else {
  4276. channelab = 2;
  4277. outSISIDXREG(SISSR, 0x14, 0x38);
  4278. sr14 = 0x08;
  4279. }
  4280. }
  4281. sisfb_post_xgi_delay(ivideo, 1);
  4282. } else { /* DDR */
  4283. buswidth = 64;
  4284. if(ivideo->revision_id == 2) {
  4285. channelab = 1;
  4286. outSISIDXREG(SISSR, 0x13, 0xa1);
  4287. outSISIDXREG(SISSR, 0x14, 0x52);
  4288. sisfb_post_xgi_delay(ivideo, 1);
  4289. sr14 = 0x02;
  4290. if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
  4291. goto bail_out;
  4292. outSISIDXREG(SISSR, 0x13, 0x21);
  4293. outSISIDXREG(SISSR, 0x14, 0x42);
  4294. } else {
  4295. channelab = 2;
  4296. outSISIDXREG(SISSR, 0x13, 0xa1);
  4297. outSISIDXREG(SISSR, 0x14, 0x5a);
  4298. sisfb_post_xgi_delay(ivideo, 1);
  4299. sr14 = 0x0a;
  4300. if(sisfb_post_xgi_rwtest(ivideo, 24, 25, mapsize))
  4301. goto bail_out;
  4302. outSISIDXREG(SISSR, 0x13, 0x21);
  4303. outSISIDXREG(SISSR, 0x14, 0x4a);
  4304. }
  4305. sisfb_post_xgi_delay(ivideo, 1);
  4306. }
  4307. }
  4308. bail_out:
  4309. setSISIDXREG(SISSR, 0x14, 0xf0, sr14);
  4310. sisfb_post_xgi_delay(ivideo, 1);
  4311. j = (ivideo->chip == XGI_20) ? 5 : 9;
  4312. k = (ivideo->chip == XGI_20) ? 12 : 4;
  4313. for(i = 0; i < k; i++) {
  4314. reg = (ivideo->chip == XGI_20) ?
  4315. dramsr13[(i * 5) + 4] : dramsr13_4[(i * 5) + 4];
  4316. setSISIDXREG(SISSR, 0x13, 0x80, reg);
  4317. sisfb_post_xgi_delay(ivideo, 50);
  4318. ranksize = (ivideo->chip == XGI_20) ?
  4319. dramsr13[(i * 5) + 3] : dramsr13_4[(i * 5) + 3];
  4320. inSISIDXREG(SISSR, 0x13, reg);
  4321. if(reg & 0x80) ranksize <<= 1;
  4322. if(ivideo->chip == XGI_20) {
  4323. if(buswidth == 16) ranksize <<= 1;
  4324. else if(buswidth == 32) ranksize <<= 2;
  4325. } else {
  4326. if(buswidth == 64) ranksize <<= 1;
  4327. }
  4328. reg = 0;
  4329. l = channelab;
  4330. if(l == 3) l = 4;
  4331. if((ranksize * l) <= 256) {
  4332. while((ranksize >>= 1)) reg += 0x10;
  4333. }
  4334. if(!reg) continue;
  4335. setSISIDXREG(SISSR, 0x14, 0x0f, (reg & 0xf0));
  4336. sisfb_post_xgi_delay(ivideo, 1);
  4337. if(sisfb_post_xgi_rwtest(ivideo, j, ((reg >> 4) + channelab - 2 + 20), mapsize))
  4338. break;
  4339. }
  4340. iounmap(ivideo->video_vbase);
  4341. }
  4342. static void __devinit
  4343. sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb)
  4344. {
  4345. u8 v1, v2, v3;
  4346. int index;
  4347. static const u8 cs90[8 * 3] = {
  4348. 0x16, 0x01, 0x01,
  4349. 0x3e, 0x03, 0x01,
  4350. 0x7c, 0x08, 0x01,
  4351. 0x79, 0x06, 0x01,
  4352. 0x29, 0x01, 0x81,
  4353. 0x5c, 0x23, 0x01,
  4354. 0x5c, 0x23, 0x01,
  4355. 0x5c, 0x23, 0x01
  4356. };
  4357. static const u8 csb8[8 * 3] = {
  4358. 0x5c, 0x23, 0x01,
  4359. 0x29, 0x01, 0x01,
  4360. 0x7c, 0x08, 0x01,
  4361. 0x79, 0x06, 0x01,
  4362. 0x29, 0x01, 0x81,
  4363. 0x5c, 0x23, 0x01,
  4364. 0x5c, 0x23, 0x01,
  4365. 0x5c, 0x23, 0x01
  4366. };
  4367. regb = 0; /* ! */
  4368. index = regb * 3;
  4369. v1 = cs90[index]; v2 = cs90[index + 1]; v3 = cs90[index + 2];
  4370. if(ivideo->haveXGIROM) {
  4371. v1 = ivideo->bios_abase[0x90 + index];
  4372. v2 = ivideo->bios_abase[0x90 + index + 1];
  4373. v3 = ivideo->bios_abase[0x90 + index + 2];
  4374. }
  4375. outSISIDXREG(SISSR, 0x28, v1);
  4376. outSISIDXREG(SISSR, 0x29, v2);
  4377. outSISIDXREG(SISSR, 0x2a, v3);
  4378. sisfb_post_xgi_delay(ivideo, 0x43);
  4379. sisfb_post_xgi_delay(ivideo, 0x43);
  4380. sisfb_post_xgi_delay(ivideo, 0x43);
  4381. index = regb * 3;
  4382. v1 = csb8[index]; v2 = csb8[index + 1]; v3 = csb8[index + 2];
  4383. if(ivideo->haveXGIROM) {
  4384. v1 = ivideo->bios_abase[0xb8 + index];
  4385. v2 = ivideo->bios_abase[0xb8 + index + 1];
  4386. v3 = ivideo->bios_abase[0xb8 + index + 2];
  4387. }
  4388. outSISIDXREG(SISSR, 0x2e, v1);
  4389. outSISIDXREG(SISSR, 0x2f, v2);
  4390. outSISIDXREG(SISSR, 0x30, v3);
  4391. sisfb_post_xgi_delay(ivideo, 0x43);
  4392. sisfb_post_xgi_delay(ivideo, 0x43);
  4393. sisfb_post_xgi_delay(ivideo, 0x43);
  4394. }
  4395. static int __devinit
  4396. sisfb_post_xgi(struct pci_dev *pdev)
  4397. {
  4398. struct sis_video_info *ivideo = pci_get_drvdata(pdev);
  4399. unsigned char *bios = ivideo->bios_abase;
  4400. struct pci_dev *mypdev = NULL;
  4401. const u8 *ptr, *ptr2;
  4402. u8 v1, v2, v3, v4, v5, reg, ramtype;
  4403. u32 rega, regb, regd;
  4404. int i, j, k, index;
  4405. static const u8 cs78[3] = { 0xf6, 0x0d, 0x00 };
  4406. static const u8 cs76[2] = { 0xa3, 0xfb };
  4407. static const u8 cs7b[3] = { 0xc0, 0x11, 0x00 };
  4408. static const u8 cs158[8] = {
  4409. 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
  4410. };
  4411. static const u8 cs160[8] = {
  4412. 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
  4413. };
  4414. static const u8 cs168[8] = {
  4415. 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
  4416. };
  4417. static const u8 cs128[3 * 8] = {
  4418. 0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
  4419. 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
  4420. 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
  4421. };
  4422. static const u8 cs148[2 * 8] = {
  4423. 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
  4424. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  4425. };
  4426. static const u8 cs31a[8 * 4] = {
  4427. 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
  4428. 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
  4429. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  4430. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  4431. };
  4432. static const u8 cs33a[8 * 4] = {
  4433. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  4434. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  4435. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  4436. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  4437. };
  4438. static const u8 cs45a[8 * 2] = {
  4439. 0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
  4440. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  4441. };
  4442. static const u8 cs170[7 * 8] = {
  4443. 0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
  4444. 0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
  4445. 0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
  4446. 0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
  4447. 0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
  4448. 0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
  4449. 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
  4450. };
  4451. static const u8 cs1a8[3 * 8] = {
  4452. 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
  4453. 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
  4454. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  4455. };
  4456. static const u8 cs100[2 * 8] = {
  4457. 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
  4458. 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
  4459. };
  4460. /* VGA enable */
  4461. reg = inSISREG(SISVGAENABLE) | 0x01;
  4462. outSISREG(SISVGAENABLE, reg);
  4463. /* Misc */
  4464. reg = inSISREG(SISMISCR) | 0x01;
  4465. outSISREG(SISMISCW, reg);
  4466. /* Unlock SR */
  4467. outSISIDXREG(SISSR, 0x05, 0x86);
  4468. inSISIDXREG(SISSR, 0x05, reg);
  4469. if(reg != 0xa1)
  4470. return 0;
  4471. /* Clear some regs */
  4472. for(i = 0; i < 0x22; i++) {
  4473. if(0x06 + i == 0x20) continue;
  4474. outSISIDXREG(SISSR, 0x06 + i, 0x00);
  4475. }
  4476. for(i = 0; i < 0x0b; i++) {
  4477. outSISIDXREG(SISSR, 0x31 + i, 0x00);
  4478. }
  4479. for(i = 0; i < 0x10; i++) {
  4480. outSISIDXREG(SISCR, 0x30 + i, 0x00);
  4481. }
  4482. ptr = cs78;
  4483. if(ivideo->haveXGIROM) {
  4484. ptr = (const u8 *)&bios[0x78];
  4485. }
  4486. for(i = 0; i < 3; i++) {
  4487. outSISIDXREG(SISSR, 0x23 + i, ptr[i]);
  4488. }
  4489. ptr = cs76;
  4490. if(ivideo->haveXGIROM) {
  4491. ptr = (const u8 *)&bios[0x76];
  4492. }
  4493. for(i = 0; i < 2; i++) {
  4494. outSISIDXREG(SISSR, 0x21 + i, ptr[i]);
  4495. }
  4496. v1 = 0x18; v2 = 0x00;
  4497. if(ivideo->haveXGIROM) {
  4498. v1 = bios[0x74];
  4499. v2 = bios[0x75];
  4500. }
  4501. outSISIDXREG(SISSR, 0x07, v1);
  4502. outSISIDXREG(SISSR, 0x11, 0x0f);
  4503. outSISIDXREG(SISSR, 0x1f, v2);
  4504. /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
  4505. outSISIDXREG(SISSR, 0x20, 0x80 | 0x20 | 0x04);
  4506. outSISIDXREG(SISSR, 0x27, 0x74);
  4507. ptr = cs7b;
  4508. if(ivideo->haveXGIROM) {
  4509. ptr = (const u8 *)&bios[0x7b];
  4510. }
  4511. for(i = 0; i < 3; i++) {
  4512. outSISIDXREG(SISSR, 0x31 + i, ptr[i]);
  4513. }
  4514. if(ivideo->chip == XGI_40) {
  4515. if(ivideo->revision_id == 2) {
  4516. setSISIDXREG(SISSR, 0x3b, 0x3f, 0xc0);
  4517. }
  4518. outSISIDXREG(SISCR, 0x7d, 0xfe);
  4519. outSISIDXREG(SISCR, 0x7e, 0x0f);
  4520. }
  4521. if(ivideo->revision_id == 0) { /* 40 *and* 20? */
  4522. andSISIDXREG(SISCR, 0x58, 0xd7);
  4523. inSISIDXREG(SISCR, 0xcb, reg);
  4524. if(reg & 0x20) {
  4525. setSISIDXREG(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
  4526. }
  4527. }
  4528. reg = (ivideo->chip == XGI_40) ? 0x20 : 0x00;
  4529. setSISIDXREG(SISCR, 0x38, 0x1f, reg);
  4530. if(ivideo->chip == XGI_20) {
  4531. outSISIDXREG(SISSR, 0x36, 0x70);
  4532. } else {
  4533. outSISIDXREG(SISVID, 0x00, 0x86);
  4534. outSISIDXREG(SISVID, 0x32, 0x00);
  4535. outSISIDXREG(SISVID, 0x30, 0x00);
  4536. outSISIDXREG(SISVID, 0x32, 0x01);
  4537. outSISIDXREG(SISVID, 0x30, 0x00);
  4538. andSISIDXREG(SISVID, 0x2f, 0xdf);
  4539. andSISIDXREG(SISCAP, 0x00, 0x3f);
  4540. outSISIDXREG(SISPART1, 0x2f, 0x01);
  4541. outSISIDXREG(SISPART1, 0x00, 0x00);
  4542. outSISIDXREG(SISPART1, 0x02, bios[0x7e]);
  4543. outSISIDXREG(SISPART1, 0x2e, 0x08);
  4544. andSISIDXREG(SISPART1, 0x35, 0x7f);
  4545. andSISIDXREG(SISPART1, 0x50, 0xfe);
  4546. inSISIDXREG(SISPART4, 0x00, reg);
  4547. if(reg == 1 || reg == 2) {
  4548. outSISIDXREG(SISPART2, 0x00, 0x1c);
  4549. outSISIDXREG(SISPART4, 0x0d, bios[0x7f]);
  4550. outSISIDXREG(SISPART4, 0x0e, bios[0x80]);
  4551. outSISIDXREG(SISPART4, 0x10, bios[0x81]);
  4552. andSISIDXREG(SISPART4, 0x0f, 0x3f);
  4553. inSISIDXREG(SISPART4, 0x01, reg);
  4554. if((reg & 0xf0) >= 0xb0) {
  4555. inSISIDXREG(SISPART4, 0x23, reg);
  4556. if(reg & 0x20) reg |= 0x40;
  4557. outSISIDXREG(SISPART4, 0x23, reg);
  4558. reg = (reg & 0x20) ? 0x02 : 0x00;
  4559. setSISIDXREG(SISPART1, 0x1e, 0xfd, reg);
  4560. }
  4561. }
  4562. v1 = bios[0x77];
  4563. inSISIDXREG(SISSR, 0x3b, reg);
  4564. if(reg & 0x02) {
  4565. inSISIDXREG(SISSR, 0x3a, reg);
  4566. v2 = (reg & 0x30) >> 3;
  4567. if(!(v2 & 0x04)) v2 ^= 0x02;
  4568. inSISIDXREG(SISSR, 0x39, reg);
  4569. if(reg & 0x80) v2 |= 0x80;
  4570. v2 |= 0x01;
  4571. if((mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0730, NULL))) {
  4572. SIS_PCI_PUT_DEVICE(mypdev);
  4573. if(((v2 & 0x06) == 2) || ((v2 & 0x06) == 4))
  4574. v2 &= 0xf9;
  4575. v2 |= 0x08;
  4576. v1 &= 0xfe;
  4577. } else {
  4578. mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0735, NULL);
  4579. if(!mypdev)
  4580. mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0645, NULL);
  4581. if(!mypdev)
  4582. mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0650, NULL);
  4583. if(mypdev) {
  4584. pci_read_config_dword(mypdev, 0x94, &regd);
  4585. regd &= 0xfffffeff;
  4586. pci_write_config_dword(mypdev, 0x94, regd);
  4587. v1 &= 0xfe;
  4588. SIS_PCI_PUT_DEVICE(mypdev);
  4589. } else if(sisfb_find_host_bridge(ivideo, pdev, PCI_VENDOR_ID_SI)) {
  4590. v1 &= 0xfe;
  4591. } else if(sisfb_find_host_bridge(ivideo, pdev, 0x1106) ||
  4592. sisfb_find_host_bridge(ivideo, pdev, 0x1022) ||
  4593. sisfb_find_host_bridge(ivideo, pdev, 0x700e) ||
  4594. sisfb_find_host_bridge(ivideo, pdev, 0x10de)) {
  4595. if((v2 & 0x06) == 4)
  4596. v2 ^= 0x06;
  4597. v2 |= 0x08;
  4598. }
  4599. }
  4600. setSISIDXREG(SISCR, 0x5f, 0xf0, v2);
  4601. }
  4602. outSISIDXREG(SISSR, 0x22, v1);
  4603. if(ivideo->revision_id == 2) {
  4604. inSISIDXREG(SISSR, 0x3b, v1);
  4605. inSISIDXREG(SISSR, 0x3a, v2);
  4606. regd = bios[0x90 + 3] | (bios[0x90 + 4] << 8);
  4607. if( (!(v1 & 0x02)) && (v2 & 0x30) && (regd < 0xcf) )
  4608. setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01);
  4609. if((mypdev = SIS_PCI_GET_DEVICE(0x10de, 0x01e0, NULL))) {
  4610. /* TODO: set CR5f &0xf1 | 0x01 for version 6570
  4611. * of nforce 2 ROM
  4612. */
  4613. if(0)
  4614. setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01);
  4615. SIS_PCI_PUT_DEVICE(mypdev);
  4616. }
  4617. }
  4618. v1 = 0x30;
  4619. inSISIDXREG(SISSR, 0x3b, reg);
  4620. inSISIDXREG(SISCR, 0x5f, v2);
  4621. if((!(reg & 0x02)) && (v2 & 0x0e))
  4622. v1 |= 0x08;
  4623. outSISIDXREG(SISSR, 0x27, v1);
  4624. if(bios[0x64] & 0x01) {
  4625. setSISIDXREG(SISCR, 0x5f, 0xf0, bios[0x64]);
  4626. }
  4627. v1 = bios[0x4f7];
  4628. pci_read_config_dword(pdev, 0x50, &regd);
  4629. regd = (regd >> 20) & 0x0f;
  4630. if(regd == 1) {
  4631. v1 &= 0xfc;
  4632. orSISIDXREG(SISCR, 0x5f, 0x08);
  4633. }
  4634. outSISIDXREG(SISCR, 0x48, v1);
  4635. setSISIDXREG(SISCR, 0x47, 0x04, bios[0x4f6] & 0xfb);
  4636. setSISIDXREG(SISCR, 0x49, 0xf0, bios[0x4f8] & 0x0f);
  4637. setSISIDXREG(SISCR, 0x4a, 0x60, bios[0x4f9] & 0x9f);
  4638. setSISIDXREG(SISCR, 0x4b, 0x08, bios[0x4fa] & 0xf7);
  4639. setSISIDXREG(SISCR, 0x4c, 0x80, bios[0x4fb] & 0x7f);
  4640. outSISIDXREG(SISCR, 0x70, bios[0x4fc]);
  4641. setSISIDXREG(SISCR, 0x71, 0xf0, bios[0x4fd] & 0x0f);
  4642. outSISIDXREG(SISCR, 0x74, 0xd0);
  4643. setSISIDXREG(SISCR, 0x74, 0xcf, bios[0x4fe] & 0x30);
  4644. setSISIDXREG(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f);
  4645. setSISIDXREG(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f);
  4646. v1 = bios[0x501];
  4647. if((mypdev = SIS_PCI_GET_DEVICE(0x8086, 0x2530, NULL))) {
  4648. v1 = 0xf0;
  4649. SIS_PCI_PUT_DEVICE(mypdev);
  4650. }
  4651. outSISIDXREG(SISCR, 0x77, v1);
  4652. }
  4653. /* RAM type */
  4654. regb = 0; /* ! */
  4655. v1 = 0xff;
  4656. if(ivideo->haveXGIROM) {
  4657. v1 = bios[0x140 + regb];
  4658. }
  4659. outSISIDXREG(SISCR, 0x6d, v1);
  4660. ptr = cs128;
  4661. if(ivideo->haveXGIROM) {
  4662. ptr = (const u8 *)&bios[0x128];
  4663. }
  4664. for(i = 0, j = 0; i < 3; i++, j += 8) {
  4665. outSISIDXREG(SISCR, 0x68 + i, ptr[j + regb]);
  4666. }
  4667. ptr = cs31a;
  4668. ptr2 = cs33a;
  4669. if(ivideo->haveXGIROM) {
  4670. index = (ivideo->chip == XGI_20) ? 0x31a : 0x3a6;
  4671. ptr = (const u8 *)&bios[index];
  4672. ptr2 = (const u8 *)&bios[index + 0x20];
  4673. }
  4674. for(i = 0; i < 2; i++) {
  4675. if(i == 0) {
  4676. regd = le32_to_cpu(((u32 *)ptr)[regb]);
  4677. rega = 0x6b;
  4678. } else {
  4679. regd = le32_to_cpu(((u32 *)ptr2)[regb]);
  4680. rega = 0x6e;
  4681. }
  4682. reg = 0x00;
  4683. for(j = 0; j < 16; j++) {
  4684. reg &= 0xf3;
  4685. if(regd & 0x01) reg |= 0x04;
  4686. if(regd & 0x02) reg |= 0x08;
  4687. regd >>= 2;
  4688. outSISIDXREG(SISCR, rega, reg);
  4689. inSISIDXREG(SISCR, rega, reg);
  4690. inSISIDXREG(SISCR, rega, reg);
  4691. reg += 0x10;
  4692. }
  4693. }
  4694. andSISIDXREG(SISCR, 0x6e, 0xfc);
  4695. ptr = NULL;
  4696. if(ivideo->haveXGIROM) {
  4697. index = (ivideo->chip == XGI_20) ? 0x35a : 0x3e6;
  4698. ptr = (const u8 *)&bios[index];
  4699. }
  4700. for(i = 0; i < 4; i++) {
  4701. setSISIDXREG(SISCR, 0x6e, 0xfc, i);
  4702. reg = 0x00;
  4703. for(j = 0; j < 2; j++) {
  4704. regd = 0;
  4705. if(ptr) {
  4706. regd = le32_to_cpu(((u32 *)ptr)[regb * 8]);
  4707. ptr += 4;
  4708. }
  4709. /* reg = 0x00; */
  4710. for(k = 0; k < 16; k++) {
  4711. reg &= 0xfc;
  4712. if(regd & 0x01) reg |= 0x01;
  4713. if(regd & 0x02) reg |= 0x02;
  4714. regd >>= 2;
  4715. outSISIDXREG(SISCR, 0x6f, reg);
  4716. inSISIDXREG(SISCR, 0x6f, reg);
  4717. inSISIDXREG(SISCR, 0x6f, reg);
  4718. reg += 0x08;
  4719. }
  4720. }
  4721. }
  4722. ptr = cs148;
  4723. if(ivideo->haveXGIROM) {
  4724. ptr = (const u8 *)&bios[0x148];
  4725. }
  4726. for(i = 0, j = 0; i < 2; i++, j += 8) {
  4727. outSISIDXREG(SISCR, 0x80 + i, ptr[j + regb]);
  4728. }
  4729. andSISIDXREG(SISCR, 0x89, 0x8f);
  4730. ptr = cs45a;
  4731. if(ivideo->haveXGIROM) {
  4732. index = (ivideo->chip == XGI_20) ? 0x45a : 0x4e6;
  4733. ptr = (const u8 *)&bios[index];
  4734. }
  4735. regd = le16_to_cpu(((const u16 *)ptr)[regb]);
  4736. reg = 0x80;
  4737. for(i = 0; i < 5; i++) {
  4738. reg &= 0xfc;
  4739. if(regd & 0x01) reg |= 0x01;
  4740. if(regd & 0x02) reg |= 0x02;
  4741. regd >>= 2;
  4742. outSISIDXREG(SISCR, 0x89, reg);
  4743. inSISIDXREG(SISCR, 0x89, reg);
  4744. inSISIDXREG(SISCR, 0x89, reg);
  4745. reg += 0x10;
  4746. }
  4747. v1 = 0xb5; v2 = 0x20; v3 = 0xf0; v4 = 0x13;
  4748. if(ivideo->haveXGIROM) {
  4749. v1 = bios[0x118 + regb];
  4750. v2 = bios[0xf8 + regb];
  4751. v3 = bios[0x120 + regb];
  4752. v4 = bios[0x1ca];
  4753. }
  4754. outSISIDXREG(SISCR, 0x45, v1 & 0x0f);
  4755. outSISIDXREG(SISCR, 0x99, (v1 >> 4) & 0x07);
  4756. orSISIDXREG(SISCR, 0x40, v1 & 0x80);
  4757. outSISIDXREG(SISCR, 0x41, v2);
  4758. ptr = cs170;
  4759. if(ivideo->haveXGIROM) {
  4760. ptr = (const u8 *)&bios[0x170];
  4761. }
  4762. for(i = 0, j = 0; i < 7; i++, j += 8) {
  4763. outSISIDXREG(SISCR, 0x90 + i, ptr[j + regb]);
  4764. }
  4765. outSISIDXREG(SISCR, 0x59, v3);
  4766. ptr = cs1a8;
  4767. if(ivideo->haveXGIROM) {
  4768. ptr = (const u8 *)&bios[0x1a8];
  4769. }
  4770. for(i = 0, j = 0; i < 3; i++, j += 8) {
  4771. outSISIDXREG(SISCR, 0xc3 + i, ptr[j + regb]);
  4772. }
  4773. ptr = cs100;
  4774. if(ivideo->haveXGIROM) {
  4775. ptr = (const u8 *)&bios[0x100];
  4776. }
  4777. for(i = 0, j = 0; i < 2; i++, j += 8) {
  4778. outSISIDXREG(SISCR, 0x8a + i, ptr[j + regb]);
  4779. }
  4780. outSISIDXREG(SISCR, 0xcf, v4);
  4781. outSISIDXREG(SISCR, 0x83, 0x09);
  4782. outSISIDXREG(SISCR, 0x87, 0x00);
  4783. if(ivideo->chip == XGI_40) {
  4784. if( (ivideo->revision_id == 1) ||
  4785. (ivideo->revision_id == 2) ) {
  4786. outSISIDXREG(SISCR, 0x8c, 0x87);
  4787. }
  4788. }
  4789. outSISIDXREG(SISSR, 0x17, 0x00);
  4790. outSISIDXREG(SISSR, 0x1a, 0x87);
  4791. if(ivideo->chip == XGI_20) {
  4792. outSISIDXREG(SISSR, 0x15, 0x00);
  4793. outSISIDXREG(SISSR, 0x1c, 0x00);
  4794. }
  4795. ramtype = 0x00; v1 = 0x10;
  4796. if(ivideo->haveXGIROM) {
  4797. ramtype = bios[0x62];
  4798. v1 = bios[0x1d2];
  4799. }
  4800. if(!(ramtype & 0x80)) {
  4801. if(ivideo->chip == XGI_20) {
  4802. outSISIDXREG(SISCR, 0x97, v1);
  4803. inSISIDXREG(SISCR, 0x97, reg);
  4804. if(reg & 0x10) {
  4805. ramtype = (reg & 0x01) << 1;
  4806. }
  4807. } else {
  4808. inSISIDXREG(SISSR, 0x39, reg);
  4809. ramtype = reg & 0x02;
  4810. if(!(ramtype)) {
  4811. inSISIDXREG(SISSR, 0x3a, reg);
  4812. ramtype = (reg >> 1) & 0x01;
  4813. }
  4814. }
  4815. }
  4816. ramtype &= 0x07;
  4817. regb = 0; /* ! */
  4818. switch(ramtype) {
  4819. case 0:
  4820. sisfb_post_xgi_setclocks(ivideo, regb);
  4821. if((ivideo->chip == XGI_20) ||
  4822. (ivideo->revision_id == 1) ||
  4823. (ivideo->revision_id == 2)) {
  4824. v1 = cs158[regb]; v2 = cs160[regb]; v3 = cs168[regb];
  4825. if(ivideo->haveXGIROM) {
  4826. v1 = bios[regb + 0x158];
  4827. v2 = bios[regb + 0x160];
  4828. v3 = bios[regb + 0x168];
  4829. }
  4830. outSISIDXREG(SISCR, 0x82, v1);
  4831. outSISIDXREG(SISCR, 0x85, v2);
  4832. outSISIDXREG(SISCR, 0x86, v3);
  4833. } else {
  4834. outSISIDXREG(SISCR, 0x82, 0x88);
  4835. outSISIDXREG(SISCR, 0x86, 0x00);
  4836. inSISIDXREG(SISCR, 0x86, reg);
  4837. outSISIDXREG(SISCR, 0x86, 0x88);
  4838. inSISIDXREG(SISCR, 0x86, reg);
  4839. outSISIDXREG(SISCR, 0x86, bios[regb + 0x168]);
  4840. outSISIDXREG(SISCR, 0x82, 0x77);
  4841. outSISIDXREG(SISCR, 0x85, 0x00);
  4842. inSISIDXREG(SISCR, 0x85, reg);
  4843. outSISIDXREG(SISCR, 0x85, 0x88);
  4844. inSISIDXREG(SISCR, 0x85, reg);
  4845. outSISIDXREG(SISCR, 0x85, bios[regb + 0x160]);
  4846. outSISIDXREG(SISCR, 0x82, bios[regb + 0x158]);
  4847. }
  4848. if(ivideo->chip == XGI_40) {
  4849. outSISIDXREG(SISCR, 0x97, 0x00);
  4850. }
  4851. outSISIDXREG(SISCR, 0x98, 0x01);
  4852. outSISIDXREG(SISCR, 0x9a, 0x02);
  4853. outSISIDXREG(SISSR, 0x18, 0x01);
  4854. if((ivideo->chip == XGI_20) ||
  4855. (ivideo->revision_id == 2)) {
  4856. outSISIDXREG(SISSR, 0x19, 0x40);
  4857. } else {
  4858. outSISIDXREG(SISSR, 0x19, 0x20);
  4859. }
  4860. outSISIDXREG(SISSR, 0x16, 0x00);
  4861. outSISIDXREG(SISSR, 0x16, 0x80);
  4862. if((ivideo->chip == XGI_20) || (bios[0x1cb] != 0x0c)) {
  4863. sisfb_post_xgi_delay(ivideo, 0x43);
  4864. sisfb_post_xgi_delay(ivideo, 0x43);
  4865. sisfb_post_xgi_delay(ivideo, 0x43);
  4866. outSISIDXREG(SISSR, 0x18, 0x00);
  4867. if((ivideo->chip == XGI_20) ||
  4868. (ivideo->revision_id == 2)) {
  4869. outSISIDXREG(SISSR, 0x19, 0x40);
  4870. } else {
  4871. outSISIDXREG(SISSR, 0x19, 0x20);
  4872. }
  4873. } else if((ivideo->chip == XGI_40) && (bios[0x1cb] == 0x0c)) {
  4874. /* outSISIDXREG(SISSR, 0x16, 0x0c); */ /* ? */
  4875. }
  4876. outSISIDXREG(SISSR, 0x16, 0x00);
  4877. outSISIDXREG(SISSR, 0x16, 0x80);
  4878. sisfb_post_xgi_delay(ivideo, 4);
  4879. v1 = 0x31; v2 = 0x03; v3 = 0x83; v4 = 0x03; v5 = 0x83;
  4880. if(ivideo->haveXGIROM) {
  4881. v1 = bios[0xf0];
  4882. index = (ivideo->chip == XGI_20) ? 0x4b2 : 0x53e;
  4883. v2 = bios[index];
  4884. v3 = bios[index + 1];
  4885. v4 = bios[index + 2];
  4886. v5 = bios[index + 3];
  4887. }
  4888. outSISIDXREG(SISSR, 0x18, v1);
  4889. outSISIDXREG(SISSR, 0x19, ((ivideo->chip == XGI_20) ? 0x02 : 0x01));
  4890. outSISIDXREG(SISSR, 0x16, v2);
  4891. outSISIDXREG(SISSR, 0x16, v3);
  4892. sisfb_post_xgi_delay(ivideo, 0x43);
  4893. outSISIDXREG(SISSR, 0x1b, 0x03);
  4894. sisfb_post_xgi_delay(ivideo, 0x22);
  4895. outSISIDXREG(SISSR, 0x18, v1);
  4896. outSISIDXREG(SISSR, 0x19, 0x00);
  4897. outSISIDXREG(SISSR, 0x16, v4);
  4898. outSISIDXREG(SISSR, 0x16, v5);
  4899. outSISIDXREG(SISSR, 0x1b, 0x00);
  4900. break;
  4901. case 1:
  4902. outSISIDXREG(SISCR, 0x82, 0x77);
  4903. outSISIDXREG(SISCR, 0x86, 0x00);
  4904. inSISIDXREG(SISCR, 0x86, reg);
  4905. outSISIDXREG(SISCR, 0x86, 0x88);
  4906. inSISIDXREG(SISCR, 0x86, reg);
  4907. v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb];
  4908. if(ivideo->haveXGIROM) {
  4909. v1 = bios[regb + 0x168];
  4910. v2 = bios[regb + 0x160];
  4911. v3 = bios[regb + 0x158];
  4912. }
  4913. outSISIDXREG(SISCR, 0x86, v1);
  4914. outSISIDXREG(SISCR, 0x82, 0x77);
  4915. outSISIDXREG(SISCR, 0x85, 0x00);
  4916. inSISIDXREG(SISCR, 0x85, reg);
  4917. outSISIDXREG(SISCR, 0x85, 0x88);
  4918. inSISIDXREG(SISCR, 0x85, reg);
  4919. outSISIDXREG(SISCR, 0x85, v2);
  4920. outSISIDXREG(SISCR, 0x82, v3);
  4921. outSISIDXREG(SISCR, 0x98, 0x01);
  4922. outSISIDXREG(SISCR, 0x9a, 0x02);
  4923. outSISIDXREG(SISSR, 0x28, 0x64);
  4924. outSISIDXREG(SISSR, 0x29, 0x63);
  4925. sisfb_post_xgi_delay(ivideo, 15);
  4926. outSISIDXREG(SISSR, 0x18, 0x00);
  4927. outSISIDXREG(SISSR, 0x19, 0x20);
  4928. outSISIDXREG(SISSR, 0x16, 0x00);
  4929. outSISIDXREG(SISSR, 0x16, 0x80);
  4930. outSISIDXREG(SISSR, 0x18, 0xc5);
  4931. outSISIDXREG(SISSR, 0x19, 0x23);
  4932. outSISIDXREG(SISSR, 0x16, 0x00);
  4933. outSISIDXREG(SISSR, 0x16, 0x80);
  4934. sisfb_post_xgi_delay(ivideo, 1);
  4935. outSISIDXREG(SISCR, 0x97,0x11);
  4936. sisfb_post_xgi_setclocks(ivideo, regb);
  4937. sisfb_post_xgi_delay(ivideo, 0x46);
  4938. outSISIDXREG(SISSR, 0x18, 0xc5);
  4939. outSISIDXREG(SISSR, 0x19, 0x23);
  4940. outSISIDXREG(SISSR, 0x16, 0x00);
  4941. outSISIDXREG(SISSR, 0x16, 0x80);
  4942. sisfb_post_xgi_delay(ivideo, 1);
  4943. outSISIDXREG(SISSR, 0x1b, 0x04);
  4944. sisfb_post_xgi_delay(ivideo, 1);
  4945. outSISIDXREG(SISSR, 0x1b, 0x00);
  4946. sisfb_post_xgi_delay(ivideo, 1);
  4947. v1 = 0x31;
  4948. if(ivideo->haveXGIROM) {
  4949. v1 = bios[0xf0];
  4950. }
  4951. outSISIDXREG(SISSR, 0x18, v1);
  4952. outSISIDXREG(SISSR, 0x19, 0x06);
  4953. outSISIDXREG(SISSR, 0x16, 0x04);
  4954. outSISIDXREG(SISSR, 0x16, 0x84);
  4955. sisfb_post_xgi_delay(ivideo, 1);
  4956. break;
  4957. default:
  4958. sisfb_post_xgi_setclocks(ivideo, regb);
  4959. if((ivideo->chip == XGI_40) &&
  4960. ((ivideo->revision_id == 1) ||
  4961. (ivideo->revision_id == 2))) {
  4962. outSISIDXREG(SISCR, 0x82, bios[regb + 0x158]);
  4963. outSISIDXREG(SISCR, 0x85, bios[regb + 0x160]);
  4964. outSISIDXREG(SISCR, 0x86, bios[regb + 0x168]);
  4965. } else {
  4966. outSISIDXREG(SISCR, 0x82, 0x88);
  4967. outSISIDXREG(SISCR, 0x86, 0x00);
  4968. inSISIDXREG(SISCR, 0x86, reg);
  4969. outSISIDXREG(SISCR, 0x86, 0x88);
  4970. outSISIDXREG(SISCR, 0x82, 0x77);
  4971. outSISIDXREG(SISCR, 0x85, 0x00);
  4972. inSISIDXREG(SISCR, 0x85, reg);
  4973. outSISIDXREG(SISCR, 0x85, 0x88);
  4974. inSISIDXREG(SISCR, 0x85, reg);
  4975. v1 = cs160[regb]; v2 = cs158[regb];
  4976. if(ivideo->haveXGIROM) {
  4977. v1 = bios[regb + 0x160];
  4978. v2 = bios[regb + 0x158];
  4979. }
  4980. outSISIDXREG(SISCR, 0x85, v1);
  4981. outSISIDXREG(SISCR, 0x82, v2);
  4982. }
  4983. if(ivideo->chip == XGI_40) {
  4984. outSISIDXREG(SISCR, 0x97, 0x11);
  4985. }
  4986. if((ivideo->chip == XGI_40) && (ivideo->revision_id == 2)) {
  4987. outSISIDXREG(SISCR, 0x98, 0x01);
  4988. } else {
  4989. outSISIDXREG(SISCR, 0x98, 0x03);
  4990. }
  4991. outSISIDXREG(SISCR, 0x9a, 0x02);
  4992. if(ivideo->chip == XGI_40) {
  4993. outSISIDXREG(SISSR, 0x18, 0x01);
  4994. } else {
  4995. outSISIDXREG(SISSR, 0x18, 0x00);
  4996. }
  4997. outSISIDXREG(SISSR, 0x19, 0x40);
  4998. outSISIDXREG(SISSR, 0x16, 0x00);
  4999. outSISIDXREG(SISSR, 0x16, 0x80);
  5000. if((ivideo->chip == XGI_40) && (bios[0x1cb] != 0x0c)) {
  5001. sisfb_post_xgi_delay(ivideo, 0x43);
  5002. sisfb_post_xgi_delay(ivideo, 0x43);
  5003. sisfb_post_xgi_delay(ivideo, 0x43);
  5004. outSISIDXREG(SISSR, 0x18, 0x00);
  5005. outSISIDXREG(SISSR, 0x19, 0x40);
  5006. outSISIDXREG(SISSR, 0x16, 0x00);
  5007. outSISIDXREG(SISSR, 0x16, 0x80);
  5008. }
  5009. sisfb_post_xgi_delay(ivideo, 4);
  5010. v1 = 0x31;
  5011. if(ivideo->haveXGIROM) {
  5012. v1 = bios[0xf0];
  5013. }
  5014. outSISIDXREG(SISSR, 0x18, v1);
  5015. outSISIDXREG(SISSR, 0x19, 0x01);
  5016. if(ivideo->chip == XGI_40) {
  5017. outSISIDXREG(SISSR, 0x16, bios[0x53e]);
  5018. outSISIDXREG(SISSR, 0x16, bios[0x53f]);
  5019. } else {
  5020. outSISIDXREG(SISSR, 0x16, 0x05);
  5021. outSISIDXREG(SISSR, 0x16, 0x85);
  5022. }
  5023. sisfb_post_xgi_delay(ivideo, 0x43);
  5024. if(ivideo->chip == XGI_40) {
  5025. outSISIDXREG(SISSR, 0x1b, 0x01);
  5026. } else {
  5027. outSISIDXREG(SISSR, 0x1b, 0x03);
  5028. }
  5029. sisfb_post_xgi_delay(ivideo, 0x22);
  5030. outSISIDXREG(SISSR, 0x18, v1);
  5031. outSISIDXREG(SISSR, 0x19, 0x00);
  5032. if(ivideo->chip == XGI_40) {
  5033. outSISIDXREG(SISSR, 0x16, bios[0x540]);
  5034. outSISIDXREG(SISSR, 0x16, bios[0x541]);
  5035. } else {
  5036. outSISIDXREG(SISSR, 0x16, 0x05);
  5037. outSISIDXREG(SISSR, 0x16, 0x85);
  5038. }
  5039. outSISIDXREG(SISSR, 0x1b, 0x00);
  5040. }
  5041. regb = 0; /* ! */
  5042. v1 = 0x03;
  5043. if(ivideo->haveXGIROM) {
  5044. v1 = bios[0x110 + regb];
  5045. }
  5046. outSISIDXREG(SISSR, 0x1b, v1);
  5047. /* RAM size */
  5048. v1 = 0x00; v2 = 0x00;
  5049. if(ivideo->haveXGIROM) {
  5050. v1 = bios[0x62];
  5051. v2 = bios[0x63];
  5052. }
  5053. regb = 0; /* ! */
  5054. regd = 1 << regb;
  5055. if((v1 & 0x40) && (v2 & regd) && ivideo->haveXGIROM) {
  5056. outSISIDXREG(SISSR, 0x13, bios[regb + 0xe0]);
  5057. outSISIDXREG(SISSR, 0x14, bios[regb + 0xe0 + 8]);
  5058. } else {
  5059. /* Set default mode, don't clear screen */
  5060. ivideo->SiS_Pr.SiS_UseOEM = FALSE;
  5061. SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
  5062. SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
  5063. ivideo->curFSTN = ivideo->curDSTN = 0;
  5064. ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
  5065. SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
  5066. outSISIDXREG(SISSR, 0x05, 0x86);
  5067. /* Disable read-cache */
  5068. andSISIDXREG(SISSR, 0x21, 0xdf);
  5069. sisfb_post_xgi_ramsize(ivideo);
  5070. /* Enable read-cache */
  5071. orSISIDXREG(SISSR, 0x21, 0x20);
  5072. }
  5073. #if 0
  5074. printk(KERN_DEBUG "-----------------\n");
  5075. for(i = 0; i < 0xff; i++) {
  5076. inSISIDXREG(SISCR, i, reg);
  5077. printk(KERN_DEBUG "CR%02x(%x) = 0x%02x\n", i, SISCR, reg);
  5078. }
  5079. for(i = 0; i < 0x40; i++) {
  5080. inSISIDXREG(SISSR, i, reg);
  5081. printk(KERN_DEBUG "SR%02x(%x) = 0x%02x\n", i, SISSR, reg);
  5082. }
  5083. printk(KERN_DEBUG "-----------------\n");
  5084. #endif
  5085. /* Sense CRT1 */
  5086. if(ivideo->chip == XGI_20) {
  5087. orSISIDXREG(SISCR, 0x32, 0x20);
  5088. } else {
  5089. inSISIDXREG(SISPART4, 0x00, reg);
  5090. if((reg == 1) || (reg == 2)) {
  5091. sisfb_sense_crt1(ivideo);
  5092. } else {
  5093. orSISIDXREG(SISCR, 0x32, 0x20);
  5094. }
  5095. }
  5096. /* Set default mode, don't clear screen */
  5097. ivideo->SiS_Pr.SiS_UseOEM = FALSE;
  5098. SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
  5099. SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
  5100. ivideo->curFSTN = ivideo->curDSTN = 0;
  5101. SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
  5102. outSISIDXREG(SISSR, 0x05, 0x86);
  5103. /* Display off */
  5104. orSISIDXREG(SISSR, 0x01, 0x20);
  5105. /* Save mode number in CR34 */
  5106. outSISIDXREG(SISCR, 0x34, 0x2e);
  5107. /* Let everyone know what the current mode is */
  5108. ivideo->modeprechange = 0x2e;
  5109. if(ivideo->chip == XGI_40) {
  5110. inSISIDXREG(SISCR, 0xca, reg);
  5111. inSISIDXREG(SISCR, 0xcc, v1);
  5112. if((reg & 0x10) && (!(v1 & 0x04))) {
  5113. printk(KERN_ERR
  5114. "sisfb: Please connect power to the card.\n");
  5115. return 0;
  5116. }
  5117. }
  5118. return 1;
  5119. }
  5120. #endif
  5121. static int __devinit
  5122. sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
  5123. {
  5124. struct sisfb_chip_info *chipinfo = &sisfb_chip_info[ent->driver_data];
  5125. struct sis_video_info *ivideo = NULL;
  5126. struct fb_info *sis_fb_info = NULL;
  5127. u16 reg16;
  5128. u8 reg;
  5129. int i, ret;
  5130. if(sisfb_off)
  5131. return -ENXIO;
  5132. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3))
  5133. sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev);
  5134. if(!sis_fb_info)
  5135. return -ENOMEM;
  5136. #else
  5137. sis_fb_info = kmalloc(sizeof(*sis_fb_info) + sizeof(*ivideo), GFP_KERNEL);
  5138. if(!sis_fb_info)
  5139. return -ENOMEM;
  5140. memset(sis_fb_info, 0, sizeof(*sis_fb_info) + sizeof(*ivideo));
  5141. sis_fb_info->par = ((char *)sis_fb_info + sizeof(*sis_fb_info));
  5142. #endif
  5143. ivideo = (struct sis_video_info *)sis_fb_info->par;
  5144. ivideo->memyselfandi = sis_fb_info;
  5145. ivideo->sisfb_id = SISFB_ID;
  5146. if(card_list == NULL) {
  5147. ivideo->cardnumber = 0;
  5148. } else {
  5149. struct sis_video_info *countvideo = card_list;
  5150. ivideo->cardnumber = 1;
  5151. while((countvideo = countvideo->next) != 0)
  5152. ivideo->cardnumber++;
  5153. }
  5154. strncpy(ivideo->myid, chipinfo->chip_name, 30);
  5155. ivideo->warncount = 0;
  5156. ivideo->chip_id = pdev->device;
  5157. ivideo->chip_vendor = pdev->vendor;
  5158. pci_read_config_byte(pdev, PCI_REVISION_ID, &ivideo->revision_id);
  5159. ivideo->SiS_Pr.ChipRevision = ivideo->revision_id;
  5160. pci_read_config_word(pdev, PCI_COMMAND, &reg16);
  5161. ivideo->sisvga_enabled = reg16 & 0x01;
  5162. ivideo->pcibus = pdev->bus->number;
  5163. ivideo->pcislot = PCI_SLOT(pdev->devfn);
  5164. ivideo->pcifunc = PCI_FUNC(pdev->devfn);
  5165. ivideo->subsysvendor = pdev->subsystem_vendor;
  5166. ivideo->subsysdevice = pdev->subsystem_device;
  5167. #ifdef SIS_OLD_CONFIG_COMPAT
  5168. ivideo->ioctl32registered = 0;
  5169. #endif
  5170. #ifndef MODULE
  5171. if(sisfb_mode_idx == -1) {
  5172. sisfb_get_vga_mode_from_kernel();
  5173. }
  5174. #endif
  5175. ivideo->chip = chipinfo->chip;
  5176. ivideo->sisvga_engine = chipinfo->vgaengine;
  5177. ivideo->hwcursor_size = chipinfo->hwcursor_size;
  5178. ivideo->CRT2_write_enable = chipinfo->CRT2_write_enable;
  5179. ivideo->mni = chipinfo->mni;
  5180. ivideo->detectedpdc = 0xff;
  5181. ivideo->detectedpdca = 0xff;
  5182. ivideo->detectedlcda = 0xff;
  5183. ivideo->sisfb_thismonitor.datavalid = FALSE;
  5184. ivideo->current_base = 0;
  5185. ivideo->engineok = 0;
  5186. ivideo->sisfb_was_boot_device = 0;
  5187. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12))
  5188. if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) {
  5189. if(ivideo->sisvga_enabled)
  5190. ivideo->sisfb_was_boot_device = 1;
  5191. else {
  5192. printk(KERN_DEBUG "sisfb: PCI device is disabled, "
  5193. "but marked as boot video device ???\n");
  5194. printk(KERN_DEBUG "sisfb: I will not accept this "
  5195. "as the primary VGA device\n");
  5196. }
  5197. }
  5198. #endif
  5199. ivideo->sisfb_parm_mem = sisfb_parm_mem;
  5200. ivideo->sisfb_accel = sisfb_accel;
  5201. ivideo->sisfb_ypan = sisfb_ypan;
  5202. ivideo->sisfb_max = sisfb_max;
  5203. ivideo->sisfb_userom = sisfb_userom;
  5204. ivideo->sisfb_useoem = sisfb_useoem;
  5205. ivideo->sisfb_mode_idx = sisfb_mode_idx;
  5206. ivideo->sisfb_parm_rate = sisfb_parm_rate;
  5207. ivideo->sisfb_crt1off = sisfb_crt1off;
  5208. ivideo->sisfb_forcecrt1 = sisfb_forcecrt1;
  5209. ivideo->sisfb_crt2type = sisfb_crt2type;
  5210. ivideo->sisfb_crt2flags = sisfb_crt2flags;
  5211. /* pdc(a), scalelcd, special timing, lvdshl handled below */
  5212. ivideo->sisfb_dstn = sisfb_dstn;
  5213. ivideo->sisfb_fstn = sisfb_fstn;
  5214. ivideo->sisfb_tvplug = sisfb_tvplug;
  5215. ivideo->sisfb_tvstd = sisfb_tvstd;
  5216. ivideo->tvxpos = sisfb_tvxposoffset;
  5217. ivideo->tvypos = sisfb_tvyposoffset;
  5218. ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate;
  5219. #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
  5220. ivideo->sisfb_inverse = sisfb_inverse;
  5221. #endif
  5222. ivideo->refresh_rate = 0;
  5223. if(ivideo->sisfb_parm_rate != -1) {
  5224. ivideo->refresh_rate = ivideo->sisfb_parm_rate;
  5225. }
  5226. ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd;
  5227. ivideo->SiS_Pr.CenterScreen = -1;
  5228. ivideo->SiS_Pr.SiS_CustomT = sisfb_specialtiming;
  5229. ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl;
  5230. ivideo->SiS_Pr.SiS_Backup70xx = 0xff;
  5231. ivideo->SiS_Pr.SiS_CHOverScan = -1;
  5232. ivideo->SiS_Pr.SiS_ChSW = FALSE;
  5233. ivideo->SiS_Pr.SiS_UseLCDA = FALSE;
  5234. ivideo->SiS_Pr.HaveEMI = FALSE;
  5235. ivideo->SiS_Pr.HaveEMILCD = FALSE;
  5236. ivideo->SiS_Pr.OverruleEMI = FALSE;
  5237. ivideo->SiS_Pr.SiS_SensibleSR11 = FALSE;
  5238. ivideo->SiS_Pr.SiS_MyCR63 = 0x63;
  5239. ivideo->SiS_Pr.PDC = -1;
  5240. ivideo->SiS_Pr.PDCA = -1;
  5241. ivideo->SiS_Pr.DDCPortMixup = FALSE;
  5242. #ifdef CONFIG_FB_SIS_315
  5243. if(ivideo->chip >= SIS_330) {
  5244. ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
  5245. if(ivideo->chip >= SIS_661) {
  5246. ivideo->SiS_Pr.SiS_SensibleSR11 = TRUE;
  5247. }
  5248. }
  5249. #endif
  5250. memcpy(&ivideo->default_var, &my_default_var, sizeof(my_default_var));
  5251. pci_set_drvdata(pdev, ivideo);
  5252. /* Patch special cases */
  5253. if((ivideo->nbridge = sisfb_get_northbridge(ivideo->chip))) {
  5254. switch(ivideo->nbridge->device) {
  5255. #ifdef CONFIG_FB_SIS_300
  5256. case PCI_DEVICE_ID_SI_730:
  5257. ivideo->chip = SIS_730;
  5258. strcpy(ivideo->myid, "SiS 730");
  5259. break;
  5260. #endif
  5261. #ifdef CONFIG_FB_SIS_315
  5262. case PCI_DEVICE_ID_SI_651:
  5263. /* ivideo->chip is ok */
  5264. strcpy(ivideo->myid, "SiS 651");
  5265. break;
  5266. case PCI_DEVICE_ID_SI_740:
  5267. ivideo->chip = SIS_740;
  5268. strcpy(ivideo->myid, "SiS 740");
  5269. break;
  5270. case PCI_DEVICE_ID_SI_661:
  5271. ivideo->chip = SIS_661;
  5272. strcpy(ivideo->myid, "SiS 661");
  5273. break;
  5274. case PCI_DEVICE_ID_SI_741:
  5275. ivideo->chip = SIS_741;
  5276. strcpy(ivideo->myid, "SiS 741");
  5277. break;
  5278. case PCI_DEVICE_ID_SI_760:
  5279. ivideo->chip = SIS_760;
  5280. strcpy(ivideo->myid, "SiS 760");
  5281. break;
  5282. case PCI_DEVICE_ID_SI_761:
  5283. ivideo->chip = SIS_761;
  5284. strcpy(ivideo->myid, "SiS 761");
  5285. break;
  5286. #endif
  5287. default:
  5288. break;
  5289. }
  5290. }
  5291. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
  5292. strcpy(sis_fb_info->modename, ivideo->myid);
  5293. #endif
  5294. ivideo->SiS_Pr.ChipType = ivideo->chip;
  5295. ivideo->SiS_Pr.ivideo = (void *)ivideo;
  5296. #ifdef CONFIG_FB_SIS_315
  5297. if((ivideo->SiS_Pr.ChipType == SIS_315PRO) ||
  5298. (ivideo->SiS_Pr.ChipType == SIS_315)) {
  5299. ivideo->SiS_Pr.ChipType = SIS_315H;
  5300. }
  5301. #endif
  5302. if(!ivideo->sisvga_enabled) {
  5303. if(pci_enable_device(pdev)) {
  5304. if(ivideo->nbridge) SIS_PCI_PUT_DEVICE(ivideo->nbridge);
  5305. pci_set_drvdata(pdev, NULL);
  5306. kfree(sis_fb_info);
  5307. return -EIO;
  5308. }
  5309. }
  5310. ivideo->video_base = pci_resource_start(pdev, 0);
  5311. ivideo->mmio_base = pci_resource_start(pdev, 1);
  5312. ivideo->mmio_size = pci_resource_len(pdev, 1);
  5313. ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
  5314. ivideo->SiS_Pr.IOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;
  5315. SiSRegInit(&ivideo->SiS_Pr, ivideo->SiS_Pr.IOAddress);
  5316. #ifdef CONFIG_FB_SIS_300
  5317. /* Find PCI systems for Chrontel/GPIO communication setup */
  5318. if(ivideo->chip == SIS_630) {
  5319. i = 0;
  5320. do {
  5321. if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
  5322. mychswtable[i].subsysCard == ivideo->subsysdevice) {
  5323. ivideo->SiS_Pr.SiS_ChSW = TRUE;
  5324. printk(KERN_DEBUG "sisfb: Identified [%s %s] "
  5325. "requiring Chrontel/GPIO setup\n",
  5326. mychswtable[i].vendorName,
  5327. mychswtable[i].cardName);
  5328. ivideo->lpcdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0008, NULL);
  5329. break;
  5330. }
  5331. i++;
  5332. } while(mychswtable[i].subsysVendor != 0);
  5333. }
  5334. #endif
  5335. #ifdef CONFIG_FB_SIS_315
  5336. if((ivideo->chip == SIS_760) && (ivideo->nbridge)) {
  5337. ivideo->lpcdev = SIS_PCI_GET_SLOT(ivideo->nbridge->bus, (2 << 3));
  5338. }
  5339. #endif
  5340. outSISIDXREG(SISSR, 0x05, 0x86);
  5341. if( (!ivideo->sisvga_enabled)
  5342. #if !defined(__i386__) && !defined(__x86_64__)
  5343. || (sisfb_resetcard)
  5344. #endif
  5345. ) {
  5346. for(i = 0x30; i <= 0x3f; i++) {
  5347. outSISIDXREG(SISCR, i, 0x00);
  5348. }
  5349. }
  5350. /* Find out about current video mode */
  5351. ivideo->modeprechange = 0x03;
  5352. inSISIDXREG(SISCR, 0x34, reg);
  5353. if(reg & 0x7f) {
  5354. ivideo->modeprechange = reg & 0x7f;
  5355. } else if(ivideo->sisvga_enabled) {
  5356. #if defined(__i386__) || defined(__x86_64__)
  5357. unsigned char SIS_IOTYPE2 *tt = ioremap(0x400, 0x100);
  5358. if(tt) {
  5359. ivideo->modeprechange = readb(tt + 0x49);
  5360. iounmap(tt);
  5361. }
  5362. #endif
  5363. }
  5364. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
  5365. #ifdef MODULE
  5366. if((reg & 0x80) && (reg != 0xff)) {
  5367. if((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni])
  5368. != 0xFF) {
  5369. printk(KERN_INFO "sisfb: Cannot initialize display mode, "
  5370. "X server is active\n");
  5371. ret = -EBUSY;
  5372. goto error_4;
  5373. }
  5374. }
  5375. #endif
  5376. #endif
  5377. /* Search and copy ROM image */
  5378. ivideo->bios_abase = NULL;
  5379. ivideo->SiS_Pr.VirtualRomBase = NULL;
  5380. ivideo->SiS_Pr.UseROM = FALSE;
  5381. ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = FALSE;
  5382. if(ivideo->sisfb_userom) {
  5383. ivideo->SiS_Pr.VirtualRomBase = sisfb_find_rom(pdev);
  5384. ivideo->bios_abase = ivideo->SiS_Pr.VirtualRomBase;
  5385. ivideo->SiS_Pr.UseROM = (ivideo->SiS_Pr.VirtualRomBase) ? TRUE : FALSE;
  5386. printk(KERN_INFO "sisfb: Video ROM %sfound\n",
  5387. ivideo->SiS_Pr.UseROM ? "" : "not ");
  5388. if((ivideo->SiS_Pr.UseROM) && (ivideo->chip >= XGI_20)) {
  5389. ivideo->SiS_Pr.UseROM = FALSE;
  5390. ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = TRUE;
  5391. if( (ivideo->revision_id == 2) &&
  5392. (!(ivideo->bios_abase[0x1d1] & 0x01)) ) {
  5393. ivideo->SiS_Pr.DDCPortMixup = TRUE;
  5394. }
  5395. }
  5396. } else {
  5397. printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
  5398. }
  5399. /* Find systems for special custom timing */
  5400. if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) {
  5401. sisfb_detect_custom_timing(ivideo);
  5402. }
  5403. /* POST card in case this has not been done by the BIOS */
  5404. if( (!ivideo->sisvga_enabled)
  5405. #if !defined(__i386__) && !defined(__x86_64__)
  5406. || (sisfb_resetcard)
  5407. #endif
  5408. ) {
  5409. #ifdef CONFIG_FB_SIS_300
  5410. if(ivideo->sisvga_engine == SIS_300_VGA) {
  5411. if(ivideo->chip == SIS_300) {
  5412. sisfb_post_sis300(pdev);
  5413. ivideo->sisfb_can_post = 1;
  5414. }
  5415. }
  5416. #endif
  5417. #ifdef CONFIG_FB_SIS_315
  5418. if(ivideo->sisvga_engine == SIS_315_VGA) {
  5419. int result = 1;
  5420. /* if((ivideo->chip == SIS_315H) ||
  5421. (ivideo->chip == SIS_315) ||
  5422. (ivideo->chip == SIS_315PRO) ||
  5423. (ivideo->chip == SIS_330)) {
  5424. sisfb_post_sis315330(pdev);
  5425. } else */ if(ivideo->chip == XGI_20) {
  5426. result = sisfb_post_xgi(pdev);
  5427. ivideo->sisfb_can_post = 1;
  5428. } else if((ivideo->chip == XGI_40) && ivideo->haveXGIROM) {
  5429. result = sisfb_post_xgi(pdev);
  5430. ivideo->sisfb_can_post = 1;
  5431. } else {
  5432. printk(KERN_INFO "sisfb: Card is not "
  5433. "POSTed and sisfb can't do this either.\n");
  5434. }
  5435. if(!result) {
  5436. printk(KERN_ERR "sisfb: Failed to POST card\n");
  5437. ret = -ENODEV;
  5438. goto error_3;
  5439. }
  5440. }
  5441. #endif
  5442. }
  5443. ivideo->sisfb_card_posted = 1;
  5444. /* Find out about RAM size */
  5445. if(sisfb_get_dram_size(ivideo)) {
  5446. printk(KERN_INFO "sisfb: Fatal error: Unable to determine VRAM size.\n");
  5447. ret = -ENODEV;
  5448. goto error_3;
  5449. }
  5450. /* Enable PCI addressing and MMIO */
  5451. if((ivideo->sisfb_mode_idx < 0) ||
  5452. ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
  5453. /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
  5454. orSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
  5455. /* Enable 2D accelerator engine */
  5456. orSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
  5457. }
  5458. if(sisfb_pdc != 0xff) {
  5459. if(ivideo->sisvga_engine == SIS_300_VGA)
  5460. sisfb_pdc &= 0x3c;
  5461. else
  5462. sisfb_pdc &= 0x1f;
  5463. ivideo->SiS_Pr.PDC = sisfb_pdc;
  5464. }
  5465. #ifdef CONFIG_FB_SIS_315
  5466. if(ivideo->sisvga_engine == SIS_315_VGA) {
  5467. if(sisfb_pdca != 0xff)
  5468. ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
  5469. }
  5470. #endif
  5471. if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) {
  5472. printk(KERN_ERR "sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
  5473. (int)(ivideo->video_size >> 20));
  5474. printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n");
  5475. ret = -ENODEV;
  5476. goto error_3;
  5477. }
  5478. if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) {
  5479. printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n");
  5480. ret = -ENODEV;
  5481. goto error_2;
  5482. }
  5483. ivideo->video_vbase = ioremap(ivideo->video_base, ivideo->video_size);
  5484. ivideo->SiS_Pr.VideoMemoryAddress = ivideo->video_vbase;
  5485. if(!ivideo->video_vbase) {
  5486. printk(KERN_ERR "sisfb: Fatal error: Unable to map framebuffer memory\n");
  5487. ret = -ENODEV;
  5488. goto error_1;
  5489. }
  5490. ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size);
  5491. if(!ivideo->mmio_vbase) {
  5492. printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
  5493. ret = -ENODEV;
  5494. error_0: iounmap(ivideo->video_vbase);
  5495. error_1: release_mem_region(ivideo->video_base, ivideo->video_size);
  5496. error_2: release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
  5497. error_3: vfree(ivideo->bios_abase);
  5498. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
  5499. error_4:
  5500. #endif
  5501. if(ivideo->lpcdev)
  5502. SIS_PCI_PUT_DEVICE(ivideo->lpcdev);
  5503. if(ivideo->nbridge)
  5504. SIS_PCI_PUT_DEVICE(ivideo->nbridge);
  5505. pci_set_drvdata(pdev, NULL);
  5506. if(!ivideo->sisvga_enabled)
  5507. pci_disable_device(pdev);
  5508. kfree(sis_fb_info);
  5509. return ret;
  5510. }
  5511. printk(KERN_INFO "sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
  5512. ivideo->video_base, (unsigned long)ivideo->video_vbase, ivideo->video_size / 1024);
  5513. if(ivideo->video_offset) {
  5514. printk(KERN_INFO "sisfb: Viewport offset %ldk\n",
  5515. ivideo->video_offset / 1024);
  5516. }
  5517. printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
  5518. ivideo->mmio_base, (unsigned long)ivideo->mmio_vbase, ivideo->mmio_size / 1024);
  5519. /* Determine the size of the command queue */
  5520. if(ivideo->sisvga_engine == SIS_300_VGA) {
  5521. ivideo->cmdQueueSize = TURBO_QUEUE_AREA_SIZE;
  5522. } else {
  5523. if(ivideo->chip == XGI_20) {
  5524. ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE_Z7;
  5525. } else {
  5526. ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE;
  5527. }
  5528. }
  5529. /* Engines are no longer initialized here; this is
  5530. * now done after the first mode-switch (if the
  5531. * submitted var has its acceleration flags set).
  5532. */
  5533. /* Calculate the base of the (unused) hw cursor */
  5534. ivideo->hwcursor_vbase = ivideo->video_vbase
  5535. + ivideo->video_size
  5536. - ivideo->cmdQueueSize
  5537. - ivideo->hwcursor_size;
  5538. ivideo->caps |= HW_CURSOR_CAP;
  5539. /* Initialize offscreen memory manager */
  5540. if((ivideo->havenoheap = sisfb_heap_init(ivideo))) {
  5541. printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n");
  5542. }
  5543. /* Used for clearing the screen only, therefore respect our mem limit */
  5544. ivideo->SiS_Pr.VideoMemoryAddress += ivideo->video_offset;
  5545. ivideo->SiS_Pr.VideoMemorySize = ivideo->sisfb_mem;
  5546. ivideo->mtrr = -1;
  5547. ivideo->vbflags = 0;
  5548. ivideo->lcddefmodeidx = DEFAULT_LCDMODE;
  5549. ivideo->tvdefmodeidx = DEFAULT_TVMODE;
  5550. ivideo->defmodeidx = DEFAULT_MODE;
  5551. ivideo->newrom = 0;
  5552. if(ivideo->chip < XGI_20) {
  5553. if(ivideo->bios_abase) {
  5554. ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr);
  5555. }
  5556. }
  5557. if((ivideo->sisfb_mode_idx < 0) ||
  5558. ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
  5559. sisfb_sense_crt1(ivideo);
  5560. sisfb_get_VB_type(ivideo);
  5561. if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
  5562. sisfb_detect_VB_connect(ivideo);
  5563. }
  5564. ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
  5565. /* Decide on which CRT2 device to use */
  5566. if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
  5567. if(ivideo->sisfb_crt2type != -1) {
  5568. if((ivideo->sisfb_crt2type == CRT2_LCD) &&
  5569. (ivideo->vbflags & CRT2_LCD)) {
  5570. ivideo->currentvbflags |= CRT2_LCD;
  5571. } else if(ivideo->sisfb_crt2type != CRT2_LCD) {
  5572. ivideo->currentvbflags |= ivideo->sisfb_crt2type;
  5573. }
  5574. } else {
  5575. /* Chrontel 700x TV detection often unreliable, therefore
  5576. * use a different default order on such machines
  5577. */
  5578. if((ivideo->sisvga_engine == SIS_300_VGA) &&
  5579. (ivideo->vbflags2 & VB2_CHRONTEL)) {
  5580. if(ivideo->vbflags & CRT2_LCD)
  5581. ivideo->currentvbflags |= CRT2_LCD;
  5582. else if(ivideo->vbflags & CRT2_TV)
  5583. ivideo->currentvbflags |= CRT2_TV;
  5584. else if(ivideo->vbflags & CRT2_VGA)
  5585. ivideo->currentvbflags |= CRT2_VGA;
  5586. } else {
  5587. if(ivideo->vbflags & CRT2_TV)
  5588. ivideo->currentvbflags |= CRT2_TV;
  5589. else if(ivideo->vbflags & CRT2_LCD)
  5590. ivideo->currentvbflags |= CRT2_LCD;
  5591. else if(ivideo->vbflags & CRT2_VGA)
  5592. ivideo->currentvbflags |= CRT2_VGA;
  5593. }
  5594. }
  5595. }
  5596. if(ivideo->vbflags & CRT2_LCD) {
  5597. sisfb_detect_lcd_type(ivideo);
  5598. }
  5599. sisfb_save_pdc_emi(ivideo);
  5600. if(!ivideo->sisfb_crt1off) {
  5601. sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0);
  5602. } else {
  5603. if((ivideo->vbflags2 & VB2_SISTMDSBRIDGE) &&
  5604. (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
  5605. sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1);
  5606. }
  5607. }
  5608. if(ivideo->sisfb_mode_idx >= 0) {
  5609. int bu = ivideo->sisfb_mode_idx;
  5610. ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
  5611. ivideo->sisfb_mode_idx, ivideo->currentvbflags);
  5612. if(bu != ivideo->sisfb_mode_idx) {
  5613. printk(KERN_ERR "Mode %dx%dx%d failed validation\n",
  5614. sisbios_mode[bu].xres,
  5615. sisbios_mode[bu].yres,
  5616. sisbios_mode[bu].bpp);
  5617. }
  5618. }
  5619. if(ivideo->sisfb_mode_idx < 0) {
  5620. switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
  5621. case CRT2_LCD:
  5622. ivideo->sisfb_mode_idx = ivideo->lcddefmodeidx;
  5623. break;
  5624. case CRT2_TV:
  5625. ivideo->sisfb_mode_idx = ivideo->tvdefmodeidx;
  5626. break;
  5627. default:
  5628. ivideo->sisfb_mode_idx = ivideo->defmodeidx;
  5629. break;
  5630. }
  5631. }
  5632. ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
  5633. if(ivideo->refresh_rate != 0) {
  5634. sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate,
  5635. ivideo->sisfb_mode_idx);
  5636. }
  5637. if(ivideo->rate_idx == 0) {
  5638. ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
  5639. ivideo->refresh_rate = 60;
  5640. }
  5641. if(ivideo->sisfb_thismonitor.datavalid) {
  5642. if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor,
  5643. ivideo->sisfb_mode_idx,
  5644. ivideo->rate_idx,
  5645. ivideo->refresh_rate)) {
  5646. printk(KERN_INFO "sisfb: WARNING: Refresh rate "
  5647. "exceeds monitor specs!\n");
  5648. }
  5649. }
  5650. ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
  5651. ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
  5652. ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
  5653. sisfb_set_vparms(ivideo);
  5654. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
  5655. /* ---------------- For 2.4: Now switch the mode ------------------ */
  5656. printk(KERN_INFO "sisfb: Setting mode %dx%dx%d (%dHz)\n",
  5657. ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
  5658. ivideo->refresh_rate);
  5659. /* Determine whether or not acceleration is to be
  5660. * used. Need to know before pre/post_set_mode()
  5661. */
  5662. ivideo->accel = 0;
  5663. ivideo->default_var.accel_flags &= ~FB_ACCELF_TEXT;
  5664. if(ivideo->sisfb_accel) {
  5665. ivideo->accel = -1;
  5666. ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
  5667. }
  5668. /* Now switch the mode */
  5669. sisfb_pre_setmode(ivideo);
  5670. if(SiSSetMode(&ivideo->SiS_Pr, ivideo->mode_no) == 0) {
  5671. printk(KERN_ERR "sisfb: Fatal error: Setting mode[0x%x] failed\n",
  5672. ivideo->mode_no);
  5673. ret = -EINVAL;
  5674. iounmap(ivideo->mmio_vbase);
  5675. goto error_0;
  5676. }
  5677. outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
  5678. sisfb_post_setmode(ivideo);
  5679. /* Maximize regardless of sisfb_max at startup */
  5680. ivideo->default_var.yres_virtual = 32767;
  5681. /* Force reset of x virtual in crtc_to_var */
  5682. ivideo->default_var.xres_virtual = 0;
  5683. /* Copy mode timing to var */
  5684. sisfb_crtc_to_var(ivideo, &ivideo->default_var);
  5685. /* Find out about screen pitch */
  5686. sisfb_calc_pitch(ivideo, &ivideo->default_var);
  5687. sisfb_set_pitch(ivideo);
  5688. /* Init the accelerator (does nothing currently) */
  5689. sisfb_initaccel(ivideo);
  5690. /* Init some fbinfo entries */
  5691. sis_fb_info->node = -1;
  5692. sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
  5693. sis_fb_info->fbops = &sisfb_ops;
  5694. sis_fb_info->disp = &ivideo->sis_disp;
  5695. sis_fb_info->blank = &sisfb_blank;
  5696. sis_fb_info->switch_con = &sisfb_switch;
  5697. sis_fb_info->updatevar = &sisfb_update_var;
  5698. sis_fb_info->changevar = NULL;
  5699. strcpy(sis_fb_info->fontname, sisfb_fontname);
  5700. sisfb_set_disp(-1, &ivideo->default_var, sis_fb_info);
  5701. #else /* --------- For 2.6: Setup a somewhat sane default var ------------ */
  5702. printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n",
  5703. ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
  5704. ivideo->refresh_rate);
  5705. /* Set up the default var according to chosen default display mode */
  5706. ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width;
  5707. ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height;
  5708. ivideo->default_var.bits_per_pixel = ivideo->video_bpp;
  5709. sisfb_bpp_to_var(ivideo, &ivideo->default_var);
  5710. ivideo->default_var.pixclock = (u32) (1000000000 /
  5711. sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, ivideo->mode_no, ivideo->rate_idx));
  5712. if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, ivideo->mode_no,
  5713. ivideo->rate_idx, &ivideo->default_var)) {
  5714. if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
  5715. ivideo->default_var.pixclock <<= 1;
  5716. }
  5717. }
  5718. if(ivideo->sisfb_ypan) {
  5719. /* Maximize regardless of sisfb_max at startup */
  5720. ivideo->default_var.yres_virtual =
  5721. sisfb_calc_maxyres(ivideo, &ivideo->default_var);
  5722. if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) {
  5723. ivideo->default_var.yres_virtual = ivideo->default_var.yres;
  5724. }
  5725. }
  5726. sisfb_calc_pitch(ivideo, &ivideo->default_var);
  5727. ivideo->accel = 0;
  5728. if(ivideo->sisfb_accel) {
  5729. ivideo->accel = -1;
  5730. #ifdef STUPID_ACCELF_TEXT_SHIT
  5731. ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
  5732. #endif
  5733. }
  5734. sisfb_initaccel(ivideo);
  5735. #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
  5736. sis_fb_info->flags = FBINFO_DEFAULT |
  5737. FBINFO_HWACCEL_YPAN |
  5738. FBINFO_HWACCEL_XPAN |
  5739. FBINFO_HWACCEL_COPYAREA |
  5740. FBINFO_HWACCEL_FILLRECT |
  5741. ((ivideo->accel) ? 0 : FBINFO_HWACCEL_DISABLED);
  5742. #else
  5743. sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
  5744. #endif
  5745. sis_fb_info->var = ivideo->default_var;
  5746. sis_fb_info->fix = ivideo->sisfb_fix;
  5747. sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset;
  5748. sis_fb_info->fbops = &sisfb_ops;
  5749. sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info);
  5750. sis_fb_info->pseudo_palette = ivideo->pseudo_palette;
  5751. fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
  5752. #endif /* 2.6 */
  5753. printk(KERN_DEBUG "sisfb: Initial vbflags 0x%x\n", (int)ivideo->vbflags);
  5754. #ifdef CONFIG_MTRR
  5755. ivideo->mtrr = mtrr_add(ivideo->video_base, ivideo->video_size,
  5756. MTRR_TYPE_WRCOMB, 1);
  5757. if(ivideo->mtrr < 0) {
  5758. printk(KERN_DEBUG "sisfb: Failed to add MTRRs\n");
  5759. }
  5760. #endif
  5761. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
  5762. vc_resize_con(1, 1, 0);
  5763. #endif
  5764. if(register_framebuffer(sis_fb_info) < 0) {
  5765. printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
  5766. ret = -EINVAL;
  5767. iounmap(ivideo->mmio_vbase);
  5768. goto error_0;
  5769. }
  5770. ivideo->registered = 1;
  5771. /* Enlist us */
  5772. ivideo->next = card_list;
  5773. card_list = ivideo;
  5774. #ifdef SIS_OLD_CONFIG_COMPAT
  5775. {
  5776. int ret;
  5777. /* Our ioctls are all "32/64bit compatible" */
  5778. ret = register_ioctl32_conversion(FBIO_ALLOC, NULL);
  5779. ret |= register_ioctl32_conversion(FBIO_FREE, NULL);
  5780. ret |= register_ioctl32_conversion(FBIOGET_VBLANK, NULL);
  5781. ret |= register_ioctl32_conversion(SISFB_GET_INFO_SIZE, NULL);
  5782. ret |= register_ioctl32_conversion(SISFB_GET_INFO, NULL);
  5783. ret |= register_ioctl32_conversion(SISFB_GET_TVPOSOFFSET, NULL);
  5784. ret |= register_ioctl32_conversion(SISFB_SET_TVPOSOFFSET, NULL);
  5785. ret |= register_ioctl32_conversion(SISFB_SET_LOCK, NULL);
  5786. ret |= register_ioctl32_conversion(SISFB_GET_VBRSTATUS, NULL);
  5787. ret |= register_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE, NULL);
  5788. ret |= register_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE, NULL);
  5789. ret |= register_ioctl32_conversion(SISFB_COMMAND, NULL);
  5790. if(ret)
  5791. printk(KERN_ERR
  5792. "sisfb: Error registering ioctl32 translations\n");
  5793. else
  5794. ivideo->ioctl32registered = 1;
  5795. }
  5796. #endif
  5797. printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n",
  5798. ivideo->sisfb_accel ? "enabled" : "disabled",
  5799. ivideo->sisfb_ypan ?
  5800. (ivideo->sisfb_max ? "enabled (auto-max)" :
  5801. "enabled (no auto-max)") :
  5802. "disabled");
  5803. printk(KERN_INFO "fb%d: %s frame buffer device version %d.%d.%d\n",
  5804. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
  5805. GET_FB_IDX(sis_fb_info->node),
  5806. #else
  5807. sis_fb_info->node,
  5808. #endif
  5809. ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
  5810. printk(KERN_INFO "sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
  5811. } /* if mode = "none" */
  5812. return 0;
  5813. }
  5814. /*****************************************************/
  5815. /* PCI DEVICE HANDLING */
  5816. /*****************************************************/
  5817. static void __devexit sisfb_remove(struct pci_dev *pdev)
  5818. {
  5819. struct sis_video_info *ivideo = pci_get_drvdata(pdev);
  5820. struct fb_info *sis_fb_info = ivideo->memyselfandi;
  5821. int registered = ivideo->registered;
  5822. int modechanged = ivideo->modechanged;
  5823. #ifdef SIS_OLD_CONFIG_COMPAT
  5824. if(ivideo->ioctl32registered) {
  5825. int ret;
  5826. ret = unregister_ioctl32_conversion(FBIO_ALLOC);
  5827. ret |= unregister_ioctl32_conversion(FBIO_FREE);
  5828. ret |= unregister_ioctl32_conversion(FBIOGET_VBLANK);
  5829. ret |= unregister_ioctl32_conversion(SISFB_GET_INFO_SIZE);
  5830. ret |= unregister_ioctl32_conversion(SISFB_GET_INFO);
  5831. ret |= unregister_ioctl32_conversion(SISFB_GET_TVPOSOFFSET);
  5832. ret |= unregister_ioctl32_conversion(SISFB_SET_TVPOSOFFSET);
  5833. ret |= unregister_ioctl32_conversion(SISFB_SET_LOCK);
  5834. ret |= unregister_ioctl32_conversion(SISFB_GET_VBRSTATUS);
  5835. ret |= unregister_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE);
  5836. ret |= unregister_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE);
  5837. ret |= unregister_ioctl32_conversion(SISFB_COMMAND);
  5838. if(ret)
  5839. printk(KERN_ERR
  5840. "sisfb: Error unregistering ioctl32 translations\n");
  5841. }
  5842. #endif
  5843. /* Unmap */
  5844. iounmap(ivideo->mmio_vbase);
  5845. iounmap(ivideo->video_vbase);
  5846. /* Release mem regions */
  5847. release_mem_region(ivideo->video_base, ivideo->video_size);
  5848. release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
  5849. vfree(ivideo->bios_abase);
  5850. if(ivideo->lpcdev)
  5851. SIS_PCI_PUT_DEVICE(ivideo->lpcdev);
  5852. if(ivideo->nbridge)
  5853. SIS_PCI_PUT_DEVICE(ivideo->nbridge);
  5854. #ifdef CONFIG_MTRR
  5855. /* Release MTRR region */
  5856. if(ivideo->mtrr >= 0)
  5857. mtrr_del(ivideo->mtrr, ivideo->video_base, ivideo->video_size);
  5858. #endif
  5859. pci_set_drvdata(pdev, NULL);
  5860. /* If device was disabled when starting, disable
  5861. * it when quitting.
  5862. */
  5863. if(!ivideo->sisvga_enabled)
  5864. pci_disable_device(pdev);
  5865. /* Unregister the framebuffer */
  5866. if(ivideo->registered) {
  5867. unregister_framebuffer(sis_fb_info);
  5868. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3))
  5869. framebuffer_release(sis_fb_info);
  5870. #else
  5871. kfree(sis_fb_info);
  5872. #endif
  5873. }
  5874. /* OK, our ivideo is gone for good from here. */
  5875. /* TODO: Restore the initial mode
  5876. * This sounds easy but is as good as impossible
  5877. * on many machines with SiS chip and video bridge
  5878. * since text modes are always set up differently
  5879. * from machine to machine. Depends on the type
  5880. * of integration between chipset and bridge.
  5881. */
  5882. if(registered && modechanged)
  5883. printk(KERN_INFO
  5884. "sisfb: Restoring of text mode not supported yet\n");
  5885. };
  5886. static struct pci_driver sisfb_driver = {
  5887. .name = "sisfb",
  5888. .id_table = sisfb_pci_table,
  5889. .probe = sisfb_probe,
  5890. .remove = __devexit_p(sisfb_remove)
  5891. };
  5892. SISINITSTATIC int __init sisfb_init(void)
  5893. {
  5894. #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
  5895. #ifndef MODULE
  5896. char *options = NULL;
  5897. if(fb_get_options("sisfb", &options))
  5898. return -ENODEV;
  5899. sisfb_setup(options);
  5900. #endif
  5901. #endif
  5902. return pci_register_driver(&sisfb_driver);
  5903. }
  5904. #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
  5905. #ifndef MODULE
  5906. module_init(sisfb_init);
  5907. #endif
  5908. #endif
  5909. /*****************************************************/
  5910. /* MODULE */
  5911. /*****************************************************/
  5912. #ifdef MODULE
  5913. static char *mode = NULL;
  5914. static int vesa = -1;
  5915. static unsigned int rate = 0;
  5916. static unsigned int crt1off = 1;
  5917. static unsigned int mem = 0;
  5918. static char *forcecrt2type = NULL;
  5919. static int forcecrt1 = -1;
  5920. static int pdc = -1;
  5921. static int pdc1 = -1;
  5922. static int noaccel = -1;
  5923. static int noypan = -1;
  5924. static int nomax = -1;
  5925. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
  5926. static int inverse = 0;
  5927. #endif
  5928. static int userom = -1;
  5929. static int useoem = -1;
  5930. static char *tvstandard = NULL;
  5931. static int nocrt2rate = 0;
  5932. static int scalelcd = -1;
  5933. static char *specialtiming = NULL;
  5934. static int lvdshl = -1;
  5935. static int tvxposoffset = 0, tvyposoffset = 0;
  5936. #if !defined(__i386__) && !defined(__x86_64__)
  5937. static int resetcard = 0;
  5938. static int videoram = 0;
  5939. #endif
  5940. static int __init sisfb_init_module(void)
  5941. {
  5942. sisfb_setdefaultparms();
  5943. if(rate)
  5944. sisfb_parm_rate = rate;
  5945. if((scalelcd == 0) || (scalelcd == 1))
  5946. sisfb_scalelcd = scalelcd ^ 1;
  5947. /* Need to check crt2 type first for fstn/dstn */
  5948. if(forcecrt2type)
  5949. sisfb_search_crt2type(forcecrt2type);
  5950. if(tvstandard)
  5951. sisfb_search_tvstd(tvstandard);
  5952. if(mode)
  5953. sisfb_search_mode(mode, FALSE);
  5954. else if(vesa != -1)
  5955. sisfb_search_vesamode(vesa, FALSE);
  5956. sisfb_crt1off = (crt1off == 0) ? 1 : 0;
  5957. sisfb_forcecrt1 = forcecrt1;
  5958. if(forcecrt1 == 1)
  5959. sisfb_crt1off = 0;
  5960. else if(forcecrt1 == 0)
  5961. sisfb_crt1off = 1;
  5962. if(noaccel == 1)
  5963. sisfb_accel = 0;
  5964. else if(noaccel == 0)
  5965. sisfb_accel = 1;
  5966. if(noypan == 1)
  5967. sisfb_ypan = 0;
  5968. else if(noypan == 0)
  5969. sisfb_ypan = 1;
  5970. if(nomax == 1)
  5971. sisfb_max = 0;
  5972. else if(nomax == 0)
  5973. sisfb_max = 1;
  5974. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
  5975. if(inverse) sisfb_inverse = 1;
  5976. #endif
  5977. if(mem)
  5978. sisfb_parm_mem = mem;
  5979. if(userom != -1)
  5980. sisfb_userom = userom;
  5981. if(useoem != -1)
  5982. sisfb_useoem = useoem;
  5983. if(pdc != -1)
  5984. sisfb_pdc = (pdc & 0x7f);
  5985. if(pdc1 != -1)
  5986. sisfb_pdca = (pdc1 & 0x1f);
  5987. sisfb_nocrt2rate = nocrt2rate;
  5988. if(specialtiming)
  5989. sisfb_search_specialtiming(specialtiming);
  5990. if((lvdshl >= 0) && (lvdshl <= 3))
  5991. sisfb_lvdshl = lvdshl;
  5992. sisfb_tvxposoffset = tvxposoffset;
  5993. sisfb_tvyposoffset = tvyposoffset;
  5994. #if !defined(__i386__) && !defined(__x86_64__)
  5995. sisfb_resetcard = (resetcard) ? 1 : 0;
  5996. if(videoram)
  5997. sisfb_videoram = videoram;
  5998. #endif
  5999. return sisfb_init();
  6000. }
  6001. static void __exit sisfb_remove_module(void)
  6002. {
  6003. pci_unregister_driver(&sisfb_driver);
  6004. printk(KERN_DEBUG "sisfb: Module unloaded\n");
  6005. }
  6006. module_init(sisfb_init_module);
  6007. module_exit(sisfb_remove_module);
  6008. MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
  6009. MODULE_LICENSE("GPL");
  6010. MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
  6011. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
  6012. MODULE_PARM(mem, "i");
  6013. MODULE_PARM(noaccel, "i");
  6014. MODULE_PARM(noypan, "i");
  6015. MODULE_PARM(nomax, "i");
  6016. MODULE_PARM(userom, "i");
  6017. MODULE_PARM(useoem, "i");
  6018. MODULE_PARM(mode, "s");
  6019. MODULE_PARM(vesa, "i");
  6020. MODULE_PARM(rate, "i");
  6021. MODULE_PARM(forcecrt1, "i");
  6022. MODULE_PARM(forcecrt2type, "s");
  6023. MODULE_PARM(scalelcd, "i");
  6024. MODULE_PARM(pdc, "i");
  6025. MODULE_PARM(pdc1, "i");
  6026. MODULE_PARM(specialtiming, "s");
  6027. MODULE_PARM(lvdshl, "i");
  6028. MODULE_PARM(tvstandard, "s");
  6029. MODULE_PARM(tvxposoffset, "i");
  6030. MODULE_PARM(tvyposoffset, "i");
  6031. MODULE_PARM(nocrt2rate, "i");
  6032. MODULE_PARM(inverse, "i");
  6033. #if !defined(__i386__) && !defined(__x86_64__)
  6034. MODULE_PARM(resetcard, "i");
  6035. MODULE_PARM(videoram, "i");
  6036. #endif
  6037. #endif
  6038. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
  6039. module_param(mem, int, 0);
  6040. module_param(noaccel, int, 0);
  6041. module_param(noypan, int, 0);
  6042. module_param(nomax, int, 0);
  6043. module_param(userom, int, 0);
  6044. module_param(useoem, int, 0);
  6045. module_param(mode, charp, 0);
  6046. module_param(vesa, int, 0);
  6047. module_param(rate, int, 0);
  6048. module_param(forcecrt1, int, 0);
  6049. module_param(forcecrt2type, charp, 0);
  6050. module_param(scalelcd, int, 0);
  6051. module_param(pdc, int, 0);
  6052. module_param(pdc1, int, 0);
  6053. module_param(specialtiming, charp, 0);
  6054. module_param(lvdshl, int, 0);
  6055. module_param(tvstandard, charp, 0);
  6056. module_param(tvxposoffset, int, 0);
  6057. module_param(tvyposoffset, int, 0);
  6058. module_param(nocrt2rate, int, 0);
  6059. #if !defined(__i386__) && !defined(__x86_64__)
  6060. module_param(resetcard, int, 0);
  6061. module_param(videoram, int, 0);
  6062. #endif
  6063. #endif
  6064. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
  6065. MODULE_PARM_DESC(mem,
  6066. "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
  6067. "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
  6068. "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
  6069. "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
  6070. "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
  6071. "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n"
  6072. "for XFree86 4.x/X.org 6.7 and later.\n");
  6073. #else
  6074. MODULE_PARM_DESC(mem,
  6075. "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
  6076. "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
  6077. "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
  6078. "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
  6079. "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
  6080. "The value is to be specified without 'KB'.\n");
  6081. #endif
  6082. MODULE_PARM_DESC(noaccel,
  6083. "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
  6084. "(default: 0)\n");
  6085. MODULE_PARM_DESC(noypan,
  6086. "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
  6087. "will be performed by redrawing the screen. (default: 0)\n");
  6088. MODULE_PARM_DESC(nomax,
  6089. "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
  6090. "memory for the virtual screen in order to optimize scrolling performance. If\n"
  6091. "this is set to anything other than 0, sisfb will not do this and thereby \n"
  6092. "enable the user to positively specify a virtual Y size of the screen using\n"
  6093. "fbset. (default: 0)\n");
  6094. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
  6095. MODULE_PARM_DESC(mode,
  6096. "\nSelects the desired display mode in the format [X]x[Y]x[Depth], eg.\n"
  6097. "1024x768x16. Other formats supported include XxY-Depth and\n"
  6098. "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
  6099. "number, it will be interpreted as a VESA mode number. (default: none if\n"
  6100. "sisfb is a module; this leaves the console untouched and the driver will\n"
  6101. "only do the video memory management for eg. DRM/DRI; 800x600x8 if sisfb\n"
  6102. "is in the kernel)\n");
  6103. MODULE_PARM_DESC(vesa,
  6104. "\nSelects the desired display mode by VESA defined mode number, eg. 0x117\n"
  6105. "(default: 0x0000 if sisfb is a module; this leaves the console untouched\n"
  6106. "and the driver will only do the video memory management for eg. DRM/DRI;\n"
  6107. "0x0103 if sisfb is in the kernel)\n");
  6108. #endif
  6109. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
  6110. MODULE_PARM_DESC(mode,
  6111. "\nSelects the desired default display mode in the format XxYxDepth,\n"
  6112. "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
  6113. "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
  6114. "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
  6115. MODULE_PARM_DESC(vesa,
  6116. "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
  6117. "0x117 (default: 0x0103)\n");
  6118. #endif
  6119. MODULE_PARM_DESC(rate,
  6120. "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
  6121. "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
  6122. "will be ignored (default: 60)\n");
  6123. MODULE_PARM_DESC(forcecrt1,
  6124. "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
  6125. "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
  6126. "0=CRT1 OFF) (default: [autodetected])\n");
  6127. MODULE_PARM_DESC(forcecrt2type,
  6128. "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
  6129. "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
  6130. "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
  6131. "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
  6132. "be used instead of TV to override the TV detection. Furthermore, on systems\n"
  6133. "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
  6134. "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
  6135. "depends on the very hardware in use. (default: [autodetected])\n");
  6136. MODULE_PARM_DESC(scalelcd,
  6137. "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
  6138. "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
  6139. "show black bars around the image, TMDS panels will probably do the scaling\n"
  6140. "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
  6141. MODULE_PARM_DESC(pdc,
  6142. "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
  6143. "should detect this correctly in most cases; however, sometimes this is not\n"
  6144. "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
  6145. "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
  6146. "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
  6147. "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
  6148. #ifdef CONFIG_FB_SIS_315
  6149. MODULE_PARM_DESC(pdc1,
  6150. "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
  6151. "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
  6152. "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
  6153. "implemented yet.\n");
  6154. #endif
  6155. MODULE_PARM_DESC(specialtiming,
  6156. "\nPlease refer to documentation for more information on this option.\n");
  6157. MODULE_PARM_DESC(lvdshl,
  6158. "\nPlease refer to documentation for more information on this option.\n");
  6159. MODULE_PARM_DESC(tvstandard,
  6160. "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
  6161. "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
  6162. MODULE_PARM_DESC(tvxposoffset,
  6163. "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
  6164. "Default: 0\n");
  6165. MODULE_PARM_DESC(tvyposoffset,
  6166. "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
  6167. "Default: 0\n");
  6168. MODULE_PARM_DESC(nocrt2rate,
  6169. "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
  6170. "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
  6171. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
  6172. MODULE_PARM_DESC(inverse,
  6173. "\nSetting this to anything but 0 should invert the display colors, but this\n"
  6174. "does not seem to work. (default: 0)\n");
  6175. #endif
  6176. #if !defined(__i386__) && !defined(__x86_64__)
  6177. #ifdef CONFIG_FB_SIS_300
  6178. MODULE_PARM_DESC(resetcard,
  6179. "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
  6180. "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
  6181. "currently). Default: 0\n");
  6182. MODULE_PARM_DESC(videoram,
  6183. "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
  6184. "some non-x86 architectures where the memory auto detection fails. Only\n"
  6185. "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
  6186. #endif
  6187. #endif
  6188. #endif /* /MODULE */
  6189. /* _GPL only for new symbols. */
  6190. EXPORT_SYMBOL(sis_malloc);
  6191. EXPORT_SYMBOL(sis_free);
  6192. EXPORT_SYMBOL_GPL(sis_malloc_new);
  6193. EXPORT_SYMBOL_GPL(sis_free_new);