sis_main.c 174 KB

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