1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028 |
- /*
- * SiS 300/305/540/630(S)/730(S)
- * SiS 315(H/PRO)/55x/(M)65x/(M)661(F/M)X/740/741(GX)/330/(M)760
- * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
- *
- * Copyright (C) 2001-2004 Thomas Winischhofer, Vienna, Austria.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the named License,
- * or any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
- *
- * Author: Thomas Winischhofer <thomas@winischhofer.net>
- *
- * Author of (practically wiped) code base:
- * SiS (www.sis.com)
- * Copyright (C) 1999 Silicon Integrated Systems, Inc.
- *
- * See http://www.winischhofer.net/ for more information and updates
- *
- * Originally based on the VBE 2.0 compliant graphic boards framebuffer driver,
- * which is (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
- *
- */
- #include <linux/config.h>
- #include <linux/version.h>
- #include <linux/module.h>
- #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- #include <linux/moduleparam.h>
- #endif
- #include <linux/kernel.h>
- #include <linux/smp_lock.h>
- #include <linux/spinlock.h>
- #include <linux/errno.h>
- #include <linux/string.h>
- #include <linux/mm.h>
- #include <linux/tty.h>
- #include <linux/slab.h>
- #include <linux/delay.h>
- #include <linux/fb.h>
- #include <linux/console.h>
- #include <linux/selection.h>
- #include <linux/smp_lock.h>
- #include <linux/ioport.h>
- #include <linux/init.h>
- #include <linux/pci.h>
- #include <linux/vmalloc.h>
- #include <linux/vt_kern.h>
- #include <linux/capability.h>
- #include <linux/fs.h>
- #include <linux/types.h>
- #include <asm/uaccess.h>
- #include <asm/io.h>
- #ifdef CONFIG_MTRR
- #include <asm/mtrr.h>
- #endif
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- #include <video/fbcon.h>
- #include <video/fbcon-cfb8.h>
- #include <video/fbcon-cfb16.h>
- #include <video/fbcon-cfb24.h>
- #include <video/fbcon-cfb32.h>
- #endif
- #include "sis.h"
- #include "sis_main.h"
- #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3)
- #error "This version of sisfb requires at least 2.6.3"
- #endif
- #endif
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- #ifdef FBCON_HAS_CFB8
- extern struct display_switch fbcon_sis8;
- #endif
- #ifdef FBCON_HAS_CFB16
- extern struct display_switch fbcon_sis16;
- #endif
- #ifdef FBCON_HAS_CFB32
- extern struct display_switch fbcon_sis32;
- #endif
- #endif
- /* ------------------ Internal helper routines ----------------- */
- static void __init
- sisfb_setdefaultparms(void)
- {
- sisfb_off = 0;
- sisfb_parm_mem = 0;
- sisfb_accel = -1;
- sisfb_ypan = -1;
- sisfb_max = -1;
- sisfb_userom = -1;
- sisfb_useoem = -1;
- #ifdef MODULE
- /* Module: "None" for 2.4, default mode for 2.5+ */
- #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- sisfb_mode_idx = -1;
- #else
- sisfb_mode_idx = MODE_INDEX_NONE;
- #endif
- #else
- /* Static: Default mode */
- sisfb_mode_idx = -1;
- #endif
- sisfb_parm_rate = -1;
- sisfb_crt1off = 0;
- sisfb_forcecrt1 = -1;
- sisfb_crt2type = -1;
- sisfb_crt2flags = 0;
- sisfb_pdc = 0xff;
- sisfb_pdca = 0xff;
- sisfb_scalelcd = -1;
- sisfb_specialtiming = CUT_NONE;
- sisfb_lvdshl = -1;
- sisfb_dstn = 0;
- sisfb_fstn = 0;
- sisfb_tvplug = -1;
- sisfb_tvstd = -1;
- sisfb_tvxposoffset = 0;
- sisfb_tvyposoffset = 0;
- sisfb_filter = -1;
- sisfb_nocrt2rate = 0;
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- sisfb_inverse = 0;
- sisfb_fontname[0] = 0;
- #endif
- #if !defined(__i386__) && !defined(__x86_64__)
- sisfb_resetcard = 0;
- sisfb_videoram = 0;
- #endif
- }
- static void __devinit
- sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet)
- {
- int i = 0, j = 0;
- /* BEWARE: We don't know the hardware specs yet and there is no ivideo */
- if(vesamode == 0) {
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- sisfb_mode_idx = MODE_INDEX_NONE;
- #else
- if(!quiet) {
- printk(KERN_ERR "sisfb: Invalid mode. Using default.\n");
- }
- sisfb_mode_idx = DEFAULT_MODE;
- #endif
- return;
- }
- vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
- while(sisbios_mode[i++].mode_no[0] != 0) {
- if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) ||
- (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) {
- if(sisfb_fstn) {
- if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
- sisbios_mode[i-1].mode_no[1] == 0x56 ||
- sisbios_mode[i-1].mode_no[1] == 0x53) continue;
- } else {
- if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
- sisbios_mode[i-1].mode_no[1] == 0x5b) continue;
- }
- sisfb_mode_idx = i - 1;
- j = 1;
- break;
- }
- }
- if((!j) && !quiet) printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
- }
- static void
- sisfb_search_mode(char *name, BOOLEAN quiet)
- {
- int i = 0;
- unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
- char strbuf[16], strbuf1[20];
- char *nameptr = name;
- /* BEWARE: We don't know the hardware specs yet and there is no ivideo */
- if(name == NULL) {
- if(!quiet) {
- printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
- }
- sisfb_mode_idx = DEFAULT_MODE;
- return;
- }
- #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
- if(!quiet) {
- printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
- }
- sisfb_mode_idx = DEFAULT_MODE;
- return;
- }
- #endif
- if(strlen(name) <= 19) {
- strcpy(strbuf1, name);
- for(i=0; i<strlen(strbuf1); i++) {
- if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
- }
- /* This does some fuzzy mode naming detection */
- if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
- if((rate <= 32) || (depth > 32)) {
- j = rate; rate = depth; depth = j;
- }
- sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
- nameptr = strbuf;
- sisfb_parm_rate = rate;
- } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
- sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
- nameptr = strbuf;
- } else {
- xres = 0;
- if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
- sprintf(strbuf, "%ux%ux8", xres, yres);
- nameptr = strbuf;
- } else {
- sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
- return;
- }
- }
- }
- i = 0; j = 0;
- while(sisbios_mode[i].mode_no[0] != 0) {
- if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
- if(sisfb_fstn) {
- if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
- sisbios_mode[i-1].mode_no[1] == 0x56 ||
- sisbios_mode[i-1].mode_no[1] == 0x53) continue;
- } else {
- if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
- sisbios_mode[i-1].mode_no[1] == 0x5b) continue;
- }
- sisfb_mode_idx = i - 1;
- j = 1;
- break;
- }
- }
- if((!j) && !quiet) printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
- }
- #ifndef MODULE
- static void __devinit
- sisfb_get_vga_mode_from_kernel(void)
- {
- #if (defined(__i386__) || defined(__x86_64__)) && defined(CONFIG_VIDEO_SELECT)
- char mymode[32];
- int mydepth = screen_info.lfb_depth;
- if(screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return;
- if( (screen_info.lfb_width >= 320) && (screen_info.lfb_width <= 2048) &&
- (screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) &&
- (mydepth >= 8) && (mydepth <= 32) ) {
- if(mydepth == 24) mydepth = 32;
- sprintf(mymode, "%ux%ux%u", screen_info.lfb_width,
- screen_info.lfb_height,
- mydepth);
- printk(KERN_DEBUG "sisfb: Using vga mode %s pre-set by kernel as default\n", mymode);
- sisfb_search_mode(mymode, TRUE);
- }
- #endif
- return;
- }
- #endif
- static void __init
- sisfb_search_crt2type(const char *name)
- {
- int i = 0;
- /* BEWARE: We don't know the hardware specs yet and there is no ivideo */
- if(name == NULL) return;
- while(sis_crt2type[i].type_no != -1) {
- if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
- sisfb_crt2type = sis_crt2type[i].type_no;
- sisfb_tvplug = sis_crt2type[i].tvplug_no;
- sisfb_crt2flags = sis_crt2type[i].flags;
- break;
- }
- i++;
- }
- sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0;
- sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0;
- if(sisfb_crt2type < 0) {
- printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
- }
- }
- static void __init
- sisfb_search_tvstd(const char *name)
- {
- int i = 0;
- /* BEWARE: We don't know the hardware specs yet and there is no ivideo */
- if(name == NULL) return;
- while(sis_tvtype[i].type_no != -1) {
- if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
- sisfb_tvstd = sis_tvtype[i].type_no;
- break;
- }
- i++;
- }
- }
- static void __init
- sisfb_search_specialtiming(const char *name)
- {
- int i = 0;
- BOOLEAN found = FALSE;
- /* BEWARE: We don't know the hardware specs yet and there is no ivideo */
- if(name == NULL) return;
- if(!strnicmp(name, "none", 4)) {
- sisfb_specialtiming = CUT_FORCENONE;
- printk(KERN_DEBUG "sisfb: Special timing disabled\n");
- } else {
- while(mycustomttable[i].chipID != 0) {
- if(!strnicmp(name,mycustomttable[i].optionName, strlen(mycustomttable[i].optionName))) {
- sisfb_specialtiming = mycustomttable[i].SpecialID;
- found = TRUE;
- printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
- mycustomttable[i].vendorName, mycustomttable[i].cardName,
- mycustomttable[i].optionName);
- break;
- }
- i++;
- }
- if(!found) {
- printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
- printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
- i = 0;
- while(mycustomttable[i].chipID != 0) {
- printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
- mycustomttable[i].optionName,
- mycustomttable[i].vendorName,
- mycustomttable[i].cardName);
- i++;
- }
- }
- }
- }
- static BOOLEAN __devinit
- sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
- {
- int i, j, xres, yres, refresh, index;
- u32 emodes;
- if(buffer[0] != 0x00 || buffer[1] != 0xff ||
- buffer[2] != 0xff || buffer[3] != 0xff ||
- buffer[4] != 0xff || buffer[5] != 0xff ||
- buffer[6] != 0xff || buffer[7] != 0x00) {
- printk(KERN_DEBUG "sisfb: Bad EDID header\n");
- return FALSE;
- }
- if(buffer[0x12] != 0x01) {
- printk(KERN_INFO "sisfb: EDID version %d not supported\n",
- buffer[0x12]);
- return FALSE;
- }
- monitor->feature = buffer[0x18];
- if(!buffer[0x14] & 0x80) {
- if(!(buffer[0x14] & 0x08)) {
- printk(KERN_INFO "sisfb: WARNING: Monitor does not support separate syncs\n");
- }
- }
- if(buffer[0x13] >= 0x01) {
- /* EDID V1 rev 1 and 2: Search for monitor descriptor
- * to extract ranges
- */
- j = 0x36;
- for(i=0; i<4; i++) {
- if(buffer[j] == 0x00 && buffer[j + 1] == 0x00 &&
- buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd &&
- buffer[j + 4] == 0x00) {
- monitor->hmin = buffer[j + 7];
- monitor->hmax = buffer[j + 8];
- monitor->vmin = buffer[j + 5];
- monitor->vmax = buffer[j + 6];
- monitor->dclockmax = buffer[j + 9] * 10 * 1000;
- monitor->datavalid = TRUE;
- break;
- }
- j += 18;
- }
- }
- if(!monitor->datavalid) {
- /* Otherwise: Get a range from the list of supported
- * Estabished Timings. This is not entirely accurate,
- * because fixed frequency monitors are not supported
- * that way.
- */
- monitor->hmin = 65535; monitor->hmax = 0;
- monitor->vmin = 65535; monitor->vmax = 0;
- monitor->dclockmax = 0;
- emodes = buffer[0x23] | (buffer[0x24] << 8) | (buffer[0x25] << 16);
- for(i = 0; i < 13; i++) {
- if(emodes & sisfb_ddcsmodes[i].mask) {
- if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h;
- if(monitor->hmax < sisfb_ddcsmodes[i].h) monitor->hmax = sisfb_ddcsmodes[i].h + 1;
- if(monitor->vmin > sisfb_ddcsmodes[i].v) monitor->vmin = sisfb_ddcsmodes[i].v;
- if(monitor->vmax < sisfb_ddcsmodes[i].v) monitor->vmax = sisfb_ddcsmodes[i].v;
- if(monitor->dclockmax < sisfb_ddcsmodes[i].d) monitor->dclockmax = sisfb_ddcsmodes[i].d;
- }
- }
- index = 0x26;
- for(i = 0; i < 8; i++) {
- xres = (buffer[index] + 31) * 8;
- switch(buffer[index + 1] & 0xc0) {
- case 0xc0: yres = (xres * 9) / 16; break;
- case 0x80: yres = (xres * 4) / 5; break;
- case 0x40: yres = (xres * 3) / 4; break;
- default: yres = xres; break;
- }
- refresh = (buffer[index + 1] & 0x3f) + 60;
- if((xres >= 640) && (yres >= 480)) {
- for(j = 0; j < 8; j++) {
- if((xres == sisfb_ddcfmodes[j].x) &&
- (yres == sisfb_ddcfmodes[j].y) &&
- (refresh == sisfb_ddcfmodes[j].v)) {
- if(monitor->hmin > sisfb_ddcfmodes[j].h) monitor->hmin = sisfb_ddcfmodes[j].h;
- if(monitor->hmax < sisfb_ddcfmodes[j].h) monitor->hmax = sisfb_ddcfmodes[j].h + 1;
- if(monitor->vmin > sisfb_ddcsmodes[j].v) monitor->vmin = sisfb_ddcsmodes[j].v;
- if(monitor->vmax < sisfb_ddcsmodes[j].v) monitor->vmax = sisfb_ddcsmodes[j].v;
- if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[i].d;
- }
- }
- }
- index += 2;
- }
- if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) {
- monitor->datavalid = TRUE;
- }
- }
- return(monitor->datavalid);
- }
- static void __devinit
- sisfb_handle_ddc(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, int crtno)
- {
- USHORT temp, i, realcrtno = crtno;
- u8 buffer[256];
- monitor->datavalid = FALSE;
- if(crtno) {
- if(ivideo->vbflags & CRT2_LCD) realcrtno = 1;
- else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2;
- else return;
- }
- if((ivideo->sisfb_crt1off) && (!crtno)) return;
- temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
- realcrtno, 0, &buffer[0]);
- if((!temp) || (temp == 0xffff)) {
- printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
- return;
- } else {
- printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1);
- printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n",
- crtno + 1,
- (temp & 0x1a) ? "" : "[none of the supported]",
- (temp & 0x02) ? "2 " : "",
- (temp & 0x08) ? "D&P" : "",
- (temp & 0x10) ? "FPDI-2" : "");
- if(temp & 0x02) {
- i = 3; /* Number of retrys */
- do {
- temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
- realcrtno, 1, &buffer[0]);
- } while((temp) && i--);
- if(!temp) {
- if(sisfb_interpret_edid(monitor, &buffer[0])) {
- printk(KERN_INFO "sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
- monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax,
- monitor->dclockmax / 1000);
- } else {
- printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1);
- }
- } else {
- printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1);
- }
- } else {
- printk(KERN_INFO "sisfb: VESA D&P and FPDI-2 not supported yet\n");
- }
- }
- }
- static BOOLEAN
- sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
- int mode_idx, int rate_idx, int rate)
- {
- int htotal, vtotal;
- unsigned int dclock, hsync;
- if(!monitor->datavalid) return TRUE;
- if(mode_idx < 0) return FALSE;
- /* Skip for 320x200, 320x240, 640x400 */
- switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) {
- case 0x59:
- case 0x41:
- case 0x4f:
- case 0x50:
- case 0x56:
- case 0x53:
- case 0x2f:
- case 0x5d:
- case 0x5e:
- return TRUE;
- #ifdef CONFIG_FB_SIS_315
- case 0x5a:
- case 0x5b:
- if(ivideo->sisvga_engine == SIS_315_VGA) return TRUE;
- #endif
- }
- if(rate < (monitor->vmin - 1)) return FALSE;
- if(rate > (monitor->vmax + 1)) return FALSE;
- if(sisfb_gettotalfrommode(&ivideo->SiS_Pr, &ivideo->sishw_ext,
- sisbios_mode[mode_idx].mode_no[ivideo->mni],
- &htotal, &vtotal, rate_idx)) {
- dclock = (htotal * vtotal * rate) / 1000;
- if(dclock > (monitor->dclockmax + 1000)) return FALSE;
- hsync = dclock / htotal;
- if(hsync < (monitor->hmin - 1)) return FALSE;
- if(hsync > (monitor->hmax + 1)) return FALSE;
- } else {
- return FALSE;
- }
- return TRUE;
- }
- static int
- sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
- {
- u16 xres=0, yres, myres;
- #ifdef CONFIG_FB_SIS_300
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- if(!(sisbios_mode[myindex].chipset & MD_SIS300)) return(-1);
- }
- #endif
- #ifdef CONFIG_FB_SIS_315
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- if(!(sisbios_mode[myindex].chipset & MD_SIS315)) return(-1);
- }
- #endif
- myres = sisbios_mode[myindex].yres;
- switch(vbflags & VB_DISPTYPE_DISP2) {
- case CRT2_LCD:
- xres = ivideo->lcdxres; yres = ivideo->lcdyres;
- if(ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) {
- if(sisbios_mode[myindex].xres > xres) return(-1);
- if(myres > yres) return(-1);
- }
- if(vbflags & (VB_LVDS | VB_30xBDH)) {
- if(sisbios_mode[myindex].xres == 320) {
- if((myres == 240) || (myres == 480)) {
- if(!ivideo->sisfb_fstn) {
- if(sisbios_mode[myindex].mode_no[1] == 0x5a ||
- sisbios_mode[myindex].mode_no[1] == 0x5b)
- return(-1);
- } else {
- if(sisbios_mode[myindex].mode_no[1] == 0x50 ||
- sisbios_mode[myindex].mode_no[1] == 0x56 ||
- sisbios_mode[myindex].mode_no[1] == 0x53)
- return(-1);
- }
- }
- }
- }
- if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
- sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn,
- ivideo->SiS_Pr.SiS_CustomT, xres, yres) < 0x14) {
- return(-1);
- }
- break;
- case CRT2_TV:
- if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
- sisbios_mode[myindex].yres, 0) < 0x14) {
- return(-1);
- }
- break;
- case CRT2_VGA:
- if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
- sisbios_mode[myindex].yres, 0) < 0x14) {
- return(-1);
- }
- break;
- }
- return(myindex);
- }
- static u8
- sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx)
- {
- u16 xres, yres;
- int i = 0;
- xres = sisbios_mode[mode_idx].xres;
- yres = sisbios_mode[mode_idx].yres;
- ivideo->rate_idx = 0;
- while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
- if((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) {
- if(sisfb_vrate[i].refresh == rate) {
- ivideo->rate_idx = sisfb_vrate[i].idx;
- break;
- } else if(sisfb_vrate[i].refresh > rate) {
- if((sisfb_vrate[i].refresh - rate) <= 3) {
- DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
- rate, sisfb_vrate[i].refresh);
- ivideo->rate_idx = sisfb_vrate[i].idx;
- ivideo->refresh_rate = sisfb_vrate[i].refresh;
- } else if(((rate - sisfb_vrate[i-1].refresh) <= 2)
- && (sisfb_vrate[i].idx != 1)) {
- DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
- rate, sisfb_vrate[i-1].refresh);
- ivideo->rate_idx = sisfb_vrate[i-1].idx;
- ivideo->refresh_rate = sisfb_vrate[i-1].refresh;
- }
- break;
- } else if((rate - sisfb_vrate[i].refresh) <= 2) {
- DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
- rate, sisfb_vrate[i].refresh);
- ivideo->rate_idx = sisfb_vrate[i].idx;
- break;
- }
- }
- i++;
- }
- if(ivideo->rate_idx > 0) {
- return ivideo->rate_idx;
- } else {
- printk(KERN_INFO "sisfb: Unsupported rate %d for %dx%d\n",
- rate, xres, yres);
- return 0;
- }
- }
- static BOOLEAN
- sisfb_bridgeisslave(struct sis_video_info *ivideo)
- {
- unsigned char P1_00;
- if(!(ivideo->vbflags & VB_VIDEOBRIDGE)) return FALSE;
- inSISIDXREG(SISPART1,0x00,P1_00);
- if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
- ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
- return TRUE;
- } else {
- return FALSE;
- }
- }
- static BOOLEAN
- sisfballowretracecrt1(struct sis_video_info *ivideo)
- {
- u8 temp;
- inSISIDXREG(SISCR,0x17,temp);
- if(!(temp & 0x80)) return FALSE;
- inSISIDXREG(SISSR,0x1f,temp);
- if(temp & 0xc0) return FALSE;
- return TRUE;
- }
- static BOOLEAN
- sisfbcheckvretracecrt1(struct sis_video_info *ivideo)
- {
- if(!sisfballowretracecrt1(ivideo)) return FALSE;
- if(inSISREG(SISINPSTAT) & 0x08) return TRUE;
- else return FALSE;
- }
- static void
- sisfbwaitretracecrt1(struct sis_video_info *ivideo)
- {
- int watchdog;
- if(!sisfballowretracecrt1(ivideo)) return;
- watchdog = 65536;
- while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog);
- watchdog = 65536;
- while((inSISREG(SISINPSTAT) & 0x08) && --watchdog);
- }
- static BOOLEAN
- sisfbcheckvretracecrt2(struct sis_video_info *ivideo)
- {
- unsigned char temp, reg;
- switch(ivideo->sisvga_engine) {
- case SIS_300_VGA: reg = 0x25; break;
- case SIS_315_VGA: reg = 0x30; break;
- default: return FALSE;
- }
- inSISIDXREG(SISPART1, reg, temp);
- if(temp & 0x02) return TRUE;
- else return FALSE;
- }
- static BOOLEAN
- sisfb_CheckVBRetrace(struct sis_video_info *ivideo)
- {
- if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
- if(sisfb_bridgeisslave(ivideo)) {
- return(sisfbcheckvretracecrt1(ivideo));
- } else {
- return(sisfbcheckvretracecrt2(ivideo));
- }
- }
- return(sisfbcheckvretracecrt1(ivideo));
- }
- static u32
- sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount)
- {
- u8 idx, reg1, reg2, reg3, reg4;
- u32 ret = 0;
- (*vcount) = (*hcount) = 0;
- if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) {
- ret |= (FB_VBLANK_HAVE_VSYNC |
- FB_VBLANK_HAVE_HBLANK |
- FB_VBLANK_HAVE_VBLANK |
- FB_VBLANK_HAVE_VCOUNT |
- FB_VBLANK_HAVE_HCOUNT);
- switch(ivideo->sisvga_engine) {
- case SIS_300_VGA: idx = 0x25; break;
- default:
- case SIS_315_VGA: idx = 0x30; break;
- }
- inSISIDXREG(SISPART1,(idx+0),reg1); /* 30 */
- inSISIDXREG(SISPART1,(idx+1),reg2); /* 31 */
- inSISIDXREG(SISPART1,(idx+2),reg3); /* 32 */
- inSISIDXREG(SISPART1,(idx+3),reg4); /* 33 */
- if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
- if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING;
- if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING;
- (*vcount) = reg3 | ((reg4 & 0x70) << 4);
- (*hcount) = reg2 | ((reg4 & 0x0f) << 8);
- } else if(sisfballowretracecrt1(ivideo)) {
- ret |= (FB_VBLANK_HAVE_VSYNC |
- FB_VBLANK_HAVE_VBLANK |
- FB_VBLANK_HAVE_VCOUNT |
- FB_VBLANK_HAVE_HCOUNT);
- reg1 = inSISREG(SISINPSTAT);
- if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
- if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
- inSISIDXREG(SISCR,0x20,reg1);
- inSISIDXREG(SISCR,0x1b,reg1);
- inSISIDXREG(SISCR,0x1c,reg2);
- inSISIDXREG(SISCR,0x1d,reg3);
- (*vcount) = reg2 | ((reg3 & 0x07) << 8);
- (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
- }
- return ret;
- }
- static int
- sisfb_myblank(struct sis_video_info *ivideo, int blank)
- {
- u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
- BOOLEAN backlight = TRUE;
- switch(blank) {
- case FB_BLANK_UNBLANK: /* on */
- sr01 = 0x00;
- sr11 = 0x00;
- sr1f = 0x00;
- cr63 = 0x00;
- p2_0 = 0x20;
- p1_13 = 0x00;
- backlight = TRUE;
- break;
- case FB_BLANK_NORMAL: /* blank */
- sr01 = 0x20;
- sr11 = 0x00;
- sr1f = 0x00;
- cr63 = 0x00;
- p2_0 = 0x20;
- p1_13 = 0x00;
- backlight = TRUE;
- break;
- case FB_BLANK_VSYNC_SUSPEND: /* no vsync */
- sr01 = 0x20;
- sr11 = 0x08;
- sr1f = 0x80;
- cr63 = 0x40;
- p2_0 = 0x40;
- p1_13 = 0x80;
- backlight = FALSE;
- break;
- case FB_BLANK_HSYNC_SUSPEND: /* no hsync */
- sr01 = 0x20;
- sr11 = 0x08;
- sr1f = 0x40;
- cr63 = 0x40;
- p2_0 = 0x80;
- p1_13 = 0x40;
- backlight = FALSE;
- break;
- case FB_BLANK_POWERDOWN: /* off */
- sr01 = 0x20;
- sr11 = 0x08;
- sr1f = 0xc0;
- cr63 = 0x40;
- p2_0 = 0xc0;
- p1_13 = 0xc0;
- backlight = FALSE;
- break;
- default:
- return 1;
- }
- if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) {
- if( (!ivideo->sisfb_thismonitor.datavalid) ||
- ((ivideo->sisfb_thismonitor.datavalid) &&
- (ivideo->sisfb_thismonitor.feature & 0xe0))) {
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
- }
- if(!(sisfb_bridgeisslave(ivideo))) {
- setSISIDXREG(SISSR, 0x01, ~0x20, sr01);
- setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f);
- }
- }
- }
- if(ivideo->currentvbflags & CRT2_LCD) {
- if(ivideo->vbflags & (VB_301LV|VB_302LV|VB_302ELV)) {
- if(backlight) {
- SiS_SiS30xBLOn(&ivideo->SiS_Pr, &ivideo->sishw_ext);
- } else {
- SiS_SiS30xBLOff(&ivideo->SiS_Pr, &ivideo->sishw_ext);
- }
- } else if(ivideo->sisvga_engine == SIS_315_VGA) {
- if(ivideo->vbflags & VB_CHRONTEL) {
- if(backlight) {
- SiS_Chrontel701xBLOn(&ivideo->SiS_Pr,&ivideo->sishw_ext);
- } else {
- SiS_Chrontel701xBLOff(&ivideo->SiS_Pr);
- }
- }
- }
- if(((ivideo->sisvga_engine == SIS_300_VGA) &&
- (ivideo->vbflags & (VB_301|VB_30xBDH|VB_LVDS))) ||
- ((ivideo->sisvga_engine == SIS_315_VGA) &&
- ((ivideo->vbflags & (VB_LVDS | VB_CHRONTEL)) == VB_LVDS))) {
- setSISIDXREG(SISSR, 0x11, ~0x0c, sr11);
- }
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- if((ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) &&
- (!(ivideo->vbflags & VB_30xBDH))) {
- setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13);
- }
- } else if(ivideo->sisvga_engine == SIS_315_VGA) {
- if((ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) &&
- (!(ivideo->vbflags & VB_30xBDH))) {
- setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
- }
- }
- } else if(ivideo->currentvbflags & CRT2_VGA) {
- if(ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) {
- setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
- }
- }
- return(0);
- }
- /* ----------- FBDev related routines for all series ----------- */
- static int
- sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
- {
- return (var->bits_per_pixel == 8) ? 256 : 16;
- }
- static void
- sisfb_set_vparms(struct sis_video_info *ivideo)
- {
- switch(ivideo->video_bpp) {
- case 8:
- ivideo->DstColor = 0x0000;
- ivideo->SiS310_AccelDepth = 0x00000000;
- ivideo->video_cmap_len = 256;
- break;
- case 16:
- ivideo->DstColor = 0x8000;
- ivideo->SiS310_AccelDepth = 0x00010000;
- ivideo->video_cmap_len = 16;
- break;
- case 32:
- ivideo->DstColor = 0xC000;
- ivideo->SiS310_AccelDepth = 0x00020000;
- ivideo->video_cmap_len = 16;
- break;
- default:
- ivideo->video_cmap_len = 16;
- printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp);
- ivideo->accel = 0;
- break;
- }
- }
- static int
- sisfb_calc_maxyres(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
- {
- int maxyres = ivideo->heapstart / (var->xres_virtual * (var->bits_per_pixel >> 3));
- if(maxyres > 32767) maxyres = 32767;
- return maxyres;
- }
- static void
- sisfb_calc_pitch(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
- {
- ivideo->video_linelength = var->xres_virtual * (var->bits_per_pixel >> 3);
- ivideo->scrnpitchCRT1 = ivideo->video_linelength;
- if(!(ivideo->currentvbflags & CRT1_LCDA)) {
- if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
- ivideo->scrnpitchCRT1 <<= 1;
- }
- }
- }
- static void
- sisfb_set_pitch(struct sis_video_info *ivideo)
- {
- BOOLEAN isslavemode = FALSE;
- unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3;
- unsigned short HDisplay2 = ivideo->video_linelength >> 3;
- if(sisfb_bridgeisslave(ivideo)) isslavemode = TRUE;
- /* We need to set pitch for CRT1 if bridge is in slave mode, too */
- if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
- outSISIDXREG(SISCR,0x13,(HDisplay1 & 0xFF));
- setSISIDXREG(SISSR,0x0E,0xF0,(HDisplay1 >> 8));
- }
- /* We must not set the pitch for CRT2 if bridge is in slave mode */
- if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) {
- orSISIDXREG(SISPART1,ivideo->CRT2_write_enable,0x01);
- outSISIDXREG(SISPART1,0x07,(HDisplay2 & 0xFF));
- setSISIDXREG(SISPART1,0x09,0xF0,(HDisplay2 >> 8));
- }
- }
- static void
- sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
- {
- ivideo->video_cmap_len = sisfb_get_cmap_len(var);
- switch(var->bits_per_pixel) {
- case 8:
- var->red.offset = var->green.offset = var->blue.offset = 0;
- var->red.length = var->green.length = var->blue.length = 6;
- break;
- case 16:
- var->red.offset = 11;
- var->red.length = 5;
- var->green.offset = 5;
- var->green.length = 6;
- var->blue.offset = 0;
- var->blue.length = 5;
- var->transp.offset = 0;
- var->transp.length = 0;
- break;
- case 32:
- var->red.offset = 16;
- var->red.length = 8;
- var->green.offset = 8;
- var->green.length = 8;
- var->blue.offset = 0;
- var->blue.length = 8;
- var->transp.offset = 24;
- var->transp.length = 8;
- break;
- }
- }
- static int
- sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- unsigned int htotal = 0, vtotal = 0;
- unsigned int drate = 0, hrate = 0;
- int found_mode = 0;
- int old_mode;
- u32 pixclock;
- htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
- vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
- pixclock = var->pixclock;
- if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
- vtotal += var->yres;
- vtotal <<= 1;
- } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
- vtotal += var->yres;
- vtotal <<= 2;
- } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
- vtotal += var->yres;
- vtotal <<= 1;
- } else vtotal += var->yres;
- if(!(htotal) || !(vtotal)) {
- DPRINTK("sisfb: Invalid 'var' information\n");
- return -EINVAL;
- }
- if(pixclock && htotal && vtotal) {
- drate = 1000000000 / pixclock;
- hrate = (drate * 1000) / htotal;
- ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal);
- } else {
- ivideo->refresh_rate = 60;
- }
- old_mode = ivideo->sisfb_mode_idx;
- ivideo->sisfb_mode_idx = 0;
- while( (sisbios_mode[ivideo->sisfb_mode_idx].mode_no[0] != 0) &&
- (sisbios_mode[ivideo->sisfb_mode_idx].xres <= var->xres) ) {
- if( (sisbios_mode[ivideo->sisfb_mode_idx].xres == var->xres) &&
- (sisbios_mode[ivideo->sisfb_mode_idx].yres == var->yres) &&
- (sisbios_mode[ivideo->sisfb_mode_idx].bpp == var->bits_per_pixel)) {
- ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
- found_mode = 1;
- break;
- }
- ivideo->sisfb_mode_idx++;
- }
- if(found_mode) {
- ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
- ivideo->sisfb_mode_idx, ivideo->currentvbflags);
- } else {
- ivideo->sisfb_mode_idx = -1;
- }
- if(ivideo->sisfb_mode_idx < 0) {
- printk(KERN_ERR "sisfb: Mode %dx%dx%d not supported\n", var->xres,
- var->yres, var->bits_per_pixel);
- ivideo->sisfb_mode_idx = old_mode;
- return -EINVAL;
- }
- if(sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx) == 0) {
- ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
- ivideo->refresh_rate = 60;
- }
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- if(ivideo->sisfb_thismonitor.datavalid) {
- if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, ivideo->sisfb_mode_idx,
- ivideo->rate_idx, ivideo->refresh_rate)) {
- printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
- }
- }
- #endif
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- if(((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) {
- #else
- if(isactive) {
- #endif
- sisfb_pre_setmode(ivideo);
- if(SiSSetMode(&ivideo->SiS_Pr, &ivideo->sishw_ext, ivideo->mode_no) == 0) {
- printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
- return -EINVAL;
- }
- outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
- sisfb_post_setmode(ivideo);
- ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
- ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
- ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
- sisfb_calc_pitch(ivideo, var);
- sisfb_set_pitch(ivideo);
- ivideo->accel = 0;
- #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
- #ifdef STUPID_ACCELF_TEXT_SHIT
- if(var->accel_flags & FB_ACCELF_TEXT) {
- info->flags &= ~FBINFO_HWACCEL_DISABLED;
- } else {
- info->flags |= FBINFO_HWACCEL_DISABLED;
- }
- #endif
- if(!(info->flags & FBINFO_HWACCEL_DISABLED)) ivideo->accel = -1;
- #else
- if(var->accel_flags & FB_ACCELF_TEXT) ivideo->accel = -1;
- #endif
- sisfb_set_vparms(ivideo);
- ivideo->current_width = ivideo->video_width;
- ivideo->current_height = ivideo->video_height;
- ivideo->current_bpp = ivideo->video_bpp;
- ivideo->current_htotal = htotal;
- ivideo->current_vtotal = vtotal;
- ivideo->current_linelength = ivideo->video_linelength;
- ivideo->current_pixclock = var->pixclock;
- ivideo->current_refresh_rate = ivideo->refresh_rate;
- #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate;
- #endif
- }
- return 0;
- }
- static int
- sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
- {
- unsigned int base;
- if(var->xoffset > (var->xres_virtual - var->xres)) {
- return -EINVAL;
- }
- if(var->yoffset > (var->yres_virtual - var->yres)) {
- return -EINVAL;
- }
- base = (var->yoffset * var->xres_virtual) + var->xoffset;
- /* calculate base bpp dep. */
- switch(var->bits_per_pixel) {
- case 32:
- break;
- case 16:
- base >>= 1;
- break;
- case 8:
- default:
- base >>= 2;
- break;
- }
-
- outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
- outSISIDXREG(SISCR, 0x0D, base & 0xFF);
- outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF);
- outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF);
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
- }
- if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
- orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01);
- outSISIDXREG(SISPART1, 0x06, (base & 0xFF));
- outSISIDXREG(SISPART1, 0x05, ((base >> 8) & 0xFF));
- outSISIDXREG(SISPART1, 0x04, ((base >> 16) & 0xFF));
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
- }
- }
- return 0;
- }
- /* ------------ FBDev related routines for 2.4 series ----------- */
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- static void
- sisfb_crtc_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
- {
- u16 VRE, VBE, VRS, VBS, VDE, VT;
- u16 HRE, HBE, HRS, HBS, HDE, HT;
- u8 sr_data, cr_data, cr_data2, cr_data3, mr_data;
- int A, B, C, D, E, F, temp;
- unsigned int hrate, drate, maxyres;
- inSISIDXREG(SISSR, IND_SIS_COLOR_MODE, sr_data);
- if(sr_data & SIS_INTERLACED_MODE)
- var->vmode = FB_VMODE_INTERLACED;
- else
- var->vmode = FB_VMODE_NONINTERLACED;
- switch((sr_data & 0x1C) >> 2) {
- case SIS_8BPP_COLOR_MODE:
- var->bits_per_pixel = 8;
- break;
- case SIS_16BPP_COLOR_MODE:
- var->bits_per_pixel = 16;
- break;
- case SIS_32BPP_COLOR_MODE:
- var->bits_per_pixel = 32;
- break;
- }
- sisfb_bpp_to_var(ivideo, var);
-
- inSISIDXREG(SISSR, 0x0A, sr_data);
- inSISIDXREG(SISCR, 0x06, cr_data);
- inSISIDXREG(SISCR, 0x07, cr_data2);
- VT = (cr_data & 0xFF) |
- ((u16) (cr_data2 & 0x01) << 8) |
- ((u16) (cr_data2 & 0x20) << 4) |
- ((u16) (sr_data & 0x01) << 10);
- A = VT + 2;
- inSISIDXREG(SISCR, 0x12, cr_data);
- VDE = (cr_data & 0xff) |
- ((u16) (cr_data2 & 0x02) << 7) |
- ((u16) (cr_data2 & 0x40) << 3) |
- ((u16) (sr_data & 0x02) << 9);
- E = VDE + 1;
- inSISIDXREG(SISCR, 0x10, cr_data);
- VRS = (cr_data & 0xff) |
- ((u16) (cr_data2 & 0x04) << 6) |
- ((u16) (cr_data2 & 0x80) << 2) |
- ((u16) (sr_data & 0x08) << 7);
- F = VRS + 1 - E;
- inSISIDXREG(SISCR, 0x15, cr_data);
- inSISIDXREG(SISCR, 0x09, cr_data3);
- if(cr_data3 & 0x80) var->vmode = FB_VMODE_DOUBLE;
- VBS = (cr_data & 0xff) |
- ((u16) (cr_data2 & 0x08) << 5) |
- ((u16) (cr_data3 & 0x20) << 4) |
- ((u16) (sr_data & 0x04) << 8);
- inSISIDXREG(SISCR, 0x16, cr_data);
- VBE = (cr_data & 0xff) | ((u16) (sr_data & 0x10) << 4);
- temp = VBE - ((E - 1) & 511);
- B = (temp > 0) ? temp : (temp + 512);
- inSISIDXREG(SISCR, 0x11, cr_data);
- VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
- temp = VRE - ((E + F - 1) & 31);
- C = (temp > 0) ? temp : (temp + 32);
- D = B - F - C;
- var->yres = E;
- var->upper_margin = D;
- var->lower_margin = F;
- var->vsync_len = C;
- if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
- var->yres <<= 1;
- var->upper_margin <<= 1;
- var->lower_margin <<= 1;
- var->vsync_len <<= 1;
- } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
- var->yres >>= 1;
- var->upper_margin >>= 1;
- var->lower_margin >>= 1;
- var->vsync_len >>= 1;
- }
- inSISIDXREG(SISSR, 0x0b, sr_data);
- inSISIDXREG(SISCR, 0x00, cr_data);
- HT = (cr_data & 0xff) | ((u16) (sr_data & 0x03) << 8);
- A = HT + 5;
- inSISIDXREG(SISCR, 0x01, cr_data);
- HDE = (cr_data & 0xff) | ((u16) (sr_data & 0x0C) << 6);
- E = HDE + 1;
- inSISIDXREG(SISCR, 0x04, cr_data);
- HRS = (cr_data & 0xff) | ((u16) (sr_data & 0xC0) << 2);
- F = HRS - E - 3;
- inSISIDXREG(SISCR, 0x02, cr_data);
- HBS = (cr_data & 0xff) | ((u16) (sr_data & 0x30) << 4);
- inSISIDXREG(SISSR, 0x0c, sr_data);
- inSISIDXREG(SISCR, 0x03, cr_data);
- inSISIDXREG(SISCR, 0x05, cr_data2);
- HBE = (cr_data & 0x1f) |
- ((u16) (cr_data2 & 0x80) >> 2) |
- ((u16) (sr_data & 0x03) << 6);
- HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
- temp = HBE - ((E - 1) & 255);
- B = (temp > 0) ? temp : (temp + 256);
- temp = HRE - ((E + F + 3) & 63);
- C = (temp > 0) ? temp : (temp + 64);
- D = B - F - C;
- var->xres = E * 8;
- if(var->xres_virtual < var->xres) {
- var->xres_virtual = var->xres;
- }
- if((var->xres == 320) &&
- (var->yres == 200 || var->yres == 240)) {
- /* Terrible hack, but the correct CRTC data for
- * these modes only produces a black screen...
- */
- var->left_margin = (400 - 376);
- var->right_margin = (328 - 320);
- var->hsync_len = (376 - 328);
- } else {
- var->left_margin = D * 8;
- var->right_margin = F * 8;
- var->hsync_len = C * 8;
- }
- var->activate = FB_ACTIVATE_NOW;
- var->sync = 0;
- mr_data = inSISREG(SISMISCR);
- if(mr_data & 0x80)
- var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
- else
- var->sync |= FB_SYNC_VERT_HIGH_ACT;
- if(mr_data & 0x40)
- var->sync &= ~FB_SYNC_HOR_HIGH_ACT;
- else
- var->sync |= FB_SYNC_HOR_HIGH_ACT;
- VT += 2;
- VT <<= 1;
- HT = (HT + 5) * 8;
- if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
- VT <<= 1;
- }
- hrate = ivideo->refresh_rate * VT / 2;
- drate = (hrate * HT) / 1000;
- var->pixclock = (u32) (1000000000 / drate);
- if(ivideo->sisfb_ypan) {
- maxyres = sisfb_calc_maxyres(ivideo, var);
- if(ivideo->sisfb_max) {
- var->yres_virtual = maxyres;
- } else {
- if(var->yres_virtual > maxyres) {
- var->yres_virtual = maxyres;
- }
- }
- if(var->yres_virtual <= var->yres) {
- var->yres_virtual = var->yres;
- }
- } else {
- var->yres_virtual = var->yres;
- }
- }
- static int
- sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue,
- unsigned *transp, struct fb_info *info)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- if(regno >= ivideo->video_cmap_len) return 1;
- *red = ivideo->sis_palette[regno].red;
- *green = ivideo->sis_palette[regno].green;
- *blue = ivideo->sis_palette[regno].blue;
- *transp = 0;
- return 0;
- }
- static int
- sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
- unsigned transp, struct fb_info *info)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- if(regno >= ivideo->video_cmap_len) return 1;
- ivideo->sis_palette[regno].red = red;
- ivideo->sis_palette[regno].green = green;
- ivideo->sis_palette[regno].blue = blue;
- switch(ivideo->video_bpp) {
- #ifdef FBCON_HAS_CFB8
- case 8:
- outSISREG(SISDACA, regno);
- outSISREG(SISDACD, (red >> 10));
- outSISREG(SISDACD, (green >> 10));
- outSISREG(SISDACD, (blue >> 10));
- if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
- outSISREG(SISDAC2A, regno);
- outSISREG(SISDAC2D, (red >> 8));
- outSISREG(SISDAC2D, (green >> 8));
- outSISREG(SISDAC2D, (blue >> 8));
- }
- break;
- #endif
- #ifdef FBCON_HAS_CFB16
- case 16:
- ivideo->sis_fbcon_cmap.cfb16[regno] =
- ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
- break;
- #endif
- #ifdef FBCON_HAS_CFB32
- case 32:
- red >>= 8;
- green >>= 8;
- blue >>= 8;
- ivideo->sis_fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | (blue);
- break;
- #endif
- }
- return 0;
- }
- static void
- sisfb_set_disp(int con, struct fb_var_screeninfo *var, struct fb_info *info)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- struct display *display;
- struct display_switch *sw;
- struct fb_fix_screeninfo fix;
- long flags;
- display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp;
- sisfb_get_fix(&fix, con, info);
- display->var = *var;
- display->screen_base = (char *)ivideo->video_vbase;
- display->visual = fix.visual;
- display->type = fix.type;
- display->type_aux = fix.type_aux;
- display->ypanstep = fix.ypanstep;
- display->ywrapstep = fix.ywrapstep;
- display->line_length = fix.line_length;
- display->can_soft_blank = 1;
- display->inverse = ivideo->sisfb_inverse;
- display->next_line = fix.line_length;
- save_flags(flags);
- switch(ivideo->video_bpp) {
- #ifdef FBCON_HAS_CFB8
- case 8: sw = ivideo->accel ? &fbcon_sis8 : &fbcon_cfb8;
- break;
- #endif
- #ifdef FBCON_HAS_CFB16
- case 16:sw = ivideo->accel ? &fbcon_sis16 : &fbcon_cfb16;
- display->dispsw_data = &ivideo->sis_fbcon_cmap.cfb16;
- break;
- #endif
- #ifdef FBCON_HAS_CFB32
- case 32:sw = ivideo->accel ? &fbcon_sis32 : &fbcon_cfb32;
- display->dispsw_data = &ivideo->sis_fbcon_cmap.cfb32;
- break;
- #endif
- default:sw = &fbcon_dummy;
- break;
- }
- memcpy(&ivideo->sisfb_sw, sw, sizeof(*sw));
- display->dispsw = &ivideo->sisfb_sw;
- restore_flags(flags);
- if(ivideo->sisfb_ypan) {
- /* display->scrollmode = 0; */
- } else {
- display->scrollmode = SCROLL_YREDRAW;
- ivideo->sisfb_sw.bmove = fbcon_redraw_bmove;
- }
- }
- static void
- sisfb_do_install_cmap(int con, struct fb_info *info)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- if(con != ivideo->currcon) return;
- if(fb_display[con].cmap.len) {
- fb_set_cmap(&fb_display[con].cmap, 1, sisfb_setcolreg, info);
- } else {
- int size = sisfb_get_cmap_len(&fb_display[con].var);
- fb_set_cmap(fb_default_cmap(size), 1, sisfb_setcolreg, info);
- }
- }
- static int
- sisfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- if(con == -1) {
- memcpy(var, &ivideo->default_var, sizeof(struct fb_var_screeninfo));
- } else {
- *var = fb_display[con].var;
- }
- if(ivideo->sisfb_fstn) {
- if(var->xres == 320 && var->yres == 480) var->yres = 240;
- }
- return 0;
- }
- static int
- sisfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- int err;
- fb_display[con].var.activate = FB_ACTIVATE_NOW;
- if(sisfb_do_set_var(var, con == ivideo->currcon, info)) {
- sisfb_crtc_to_var(ivideo, var);
- return -EINVAL;
- }
- sisfb_crtc_to_var(ivideo, var);
- sisfb_set_disp(con, var, info);
- if(info->changevar) {
- (*info->changevar)(con);
- }
- if((err = fb_alloc_cmap(&fb_display[con].cmap, 0, 0))) {
- return err;
- }
- sisfb_do_install_cmap(con, info);
- #if 0 /* Why was this called here? */
- unsigned int cols, rows;
- cols = sisbios_mode[ivideo->sisfb_mode_idx].cols;
- rows = sisbios_mode[ivideo->sisfb_mode_idx].rows;
- vc_resize_con(rows, cols, fb_display[con].conp->vc_num);
- #endif
- return 0;
- }
- static int
- sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- struct display *display;
- display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp;
- if(con == ivideo->currcon) {
- return fb_get_cmap(cmap, kspc, sis_getcolreg, info);
- } else if(display->cmap.len) {
- fb_copy_cmap(&display->cmap, cmap, kspc ? 0 : 2);
- } else {
- int size = sisfb_get_cmap_len(&display->var);
- fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
- }
- return 0;
- }
- static int
- sisfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- struct display *display;
- int err, size;
- display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp;
- size = sisfb_get_cmap_len(&display->var);
- if(display->cmap.len != size) {
- err = fb_alloc_cmap(&display->cmap, size, 0);
- if(err) return err;
- }
-
- if(con == ivideo->currcon) {
- return fb_set_cmap(cmap, kspc, sisfb_setcolreg, info);
- } else {
- fb_copy_cmap(cmap, &display->cmap, kspc ? 0 : 1);
- }
- return 0;
- }
- static int
- sisfb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info* info)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- int err;
- if(var->vmode & FB_VMODE_YWRAP) return -EINVAL;
- if((var->xoffset+fb_display[con].var.xres > fb_display[con].var.xres_virtual) ||
- (var->yoffset+fb_display[con].var.yres > fb_display[con].var.yres_virtual)) {
- return -EINVAL;
- }
- if(con == ivideo->currcon) {
- if((err = sisfb_pan_var(ivideo, var)) < 0) return err;
- }
- fb_display[con].var.xoffset = var->xoffset;
- fb_display[con].var.yoffset = var->yoffset;
- return 0;
- }
- static int
- sisfb_update_var(int con, struct fb_info *info)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- return(sisfb_pan_var(ivideo, &fb_display[con].var));
- }
- static int
- sisfb_switch(int con, struct fb_info *info)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- int cols, rows;
- if(fb_display[ivideo->currcon].cmap.len) {
- fb_get_cmap(&fb_display[ivideo->currcon].cmap, 1, sis_getcolreg, info);
- }
- fb_display[con].var.activate = FB_ACTIVATE_NOW;
- if(!memcmp(&fb_display[con].var, &fb_display[ivideo->currcon].var,
- sizeof(struct fb_var_screeninfo))) {
- ivideo->currcon = con;
- return 1;
- }
- ivideo->currcon = con;
- sisfb_do_set_var(&fb_display[con].var, 1, info);
- sisfb_set_disp(con, &fb_display[con].var, info);
- sisfb_do_install_cmap(con, info);
- cols = sisbios_mode[ivideo->sisfb_mode_idx].cols;
- rows = sisbios_mode[ivideo->sisfb_mode_idx].rows;
- vc_resize_con(rows, cols, fb_display[con].conp->vc_num);
- sisfb_update_var(con, info);
- return 1;
- }
- static void
- sisfb_blank(int blank, struct fb_info *info)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- sisfb_myblank(ivideo, blank);
- }
- #endif
- /* ------------ FBDev related routines for 2.6 series ----------- */
- #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- static int
- sisfb_open(struct fb_info *info, int user)
- {
- return 0;
- }
- static int
- sisfb_release(struct fb_info *info, int user)
- {
- return 0;
- }
- static int
- sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
- unsigned transp, struct fb_info *info)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- if(regno >= sisfb_get_cmap_len(&info->var)) return 1;
- switch(info->var.bits_per_pixel) {
- case 8:
- outSISREG(SISDACA, regno);
- outSISREG(SISDACD, (red >> 10));
- outSISREG(SISDACD, (green >> 10));
- outSISREG(SISDACD, (blue >> 10));
- if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
- outSISREG(SISDAC2A, regno);
- outSISREG(SISDAC2D, (red >> 8));
- outSISREG(SISDAC2D, (green >> 8));
- outSISREG(SISDAC2D, (blue >> 8));
- }
- break;
- case 16:
- ((u32 *)(info->pseudo_palette))[regno] =
- ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
- break;
- case 32:
- red >>= 8;
- green >>= 8;
- blue >>= 8;
- ((u32 *)(info->pseudo_palette))[regno] =
- (red << 16) | (green << 8) | (blue);
- break;
- }
- return 0;
- }
- static int
- sisfb_set_par(struct fb_info *info)
- {
- int err;
- if((err = sisfb_do_set_var(&info->var, 1, info))) {
- return err;
- }
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
- sisfb_get_fix(&info->fix, info->currcon, info);
- #else
- sisfb_get_fix(&info->fix, -1, info);
- #endif
- return 0;
- }
- static int
- sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
- unsigned int drate = 0, hrate = 0, maxyres;
- int found_mode = 0;
- int refresh_rate, search_idx;
- BOOLEAN recalc_clock = FALSE;
- u32 pixclock;
- htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
- vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
- pixclock = var->pixclock;
- if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
- vtotal += var->yres;
- vtotal <<= 1;
- } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
- vtotal += var->yres;
- vtotal <<= 2;
- } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
- vtotal += var->yres;
- vtotal <<= 1;
- } else vtotal += var->yres;
- if(!(htotal) || !(vtotal)) {
- SISFAIL("sisfb: no valid timing data");
- }
- search_idx = 0;
- while( (sisbios_mode[search_idx].mode_no[0] != 0) &&
- (sisbios_mode[search_idx].xres <= var->xres) ) {
- if( (sisbios_mode[search_idx].xres == var->xres) &&
- (sisbios_mode[search_idx].yres == var->yres) &&
- (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) {
- if(sisfb_validate_mode(ivideo, search_idx, ivideo->currentvbflags) > 0) {
- found_mode = 1;
- break;
- }
- }
- search_idx++;
- }
- if(!found_mode) {
- search_idx = 0;
- while(sisbios_mode[search_idx].mode_no[0] != 0) {
- if( (var->xres <= sisbios_mode[search_idx].xres) &&
- (var->yres <= sisbios_mode[search_idx].yres) &&
- (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) {
- if(sisfb_validate_mode(ivideo,search_idx, ivideo->currentvbflags) > 0) {
- found_mode = 1;
- break;
- }
- }
- search_idx++;
- }
- if(found_mode) {
- printk(KERN_DEBUG "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
- var->xres, var->yres, var->bits_per_pixel,
- sisbios_mode[search_idx].xres,
- sisbios_mode[search_idx].yres,
- var->bits_per_pixel);
- var->xres = sisbios_mode[search_idx].xres;
- var->yres = sisbios_mode[search_idx].yres;
- } else {
- printk(KERN_ERR "sisfb: Failed to find supported mode near %dx%dx%d\n",
- var->xres, var->yres, var->bits_per_pixel);
- return -EINVAL;
- }
- }
- if( ((ivideo->vbflags & VB_LVDS) || /* Slave modes on LVDS and 301B-DH */
- ((ivideo->vbflags & VB_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) &&
- (var->bits_per_pixel == 8) ) {
- refresh_rate = 60;
- recalc_clock = TRUE;
- } else if( (ivideo->current_htotal == htotal) && /* x=x & y=y & c=c -> assume depth change */
- (ivideo->current_vtotal == vtotal) &&
- (ivideo->current_pixclock == pixclock) ) {
- drate = 1000000000 / pixclock;
- hrate = (drate * 1000) / htotal;
- refresh_rate = (unsigned int) (hrate * 2 / vtotal);
- } else if( ( (ivideo->current_htotal != htotal) || /* x!=x | y!=y & c=c -> invalid pixclock */
- (ivideo->current_vtotal != vtotal) ) &&
- (ivideo->current_pixclock == var->pixclock) ) {
- if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) {
- refresh_rate = ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];
- } else if(ivideo->sisfb_parm_rate != -1) {
- /* Sic, sisfb_parm_rate - want to know originally desired rate here */
- refresh_rate = ivideo->sisfb_parm_rate;
- } else {
- refresh_rate = 60;
- }
- recalc_clock = TRUE;
- } else if((pixclock) && (htotal) && (vtotal)) {
- drate = 1000000000 / pixclock;
- hrate = (drate * 1000) / htotal;
- refresh_rate = (unsigned int) (hrate * 2 / vtotal);
- } else if(ivideo->current_refresh_rate) {
- refresh_rate = ivideo->current_refresh_rate;
- recalc_clock = TRUE;
- } else {
- refresh_rate = 60;
- recalc_clock = TRUE;
- }
- myrateindex = sisfb_search_refresh_rate(ivideo, refresh_rate, search_idx);
- /* Eventually recalculate timing and clock */
- if(recalc_clock) {
- if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
- var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr,
- &ivideo->sishw_ext,
- sisbios_mode[search_idx].mode_no[ivideo->mni],
- myrateindex));
- sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, &ivideo->sishw_ext,
- sisbios_mode[search_idx].mode_no[ivideo->mni], myrateindex, var);
- if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
- var->pixclock <<= 1;
- }
- }
- if(ivideo->sisfb_thismonitor.datavalid) {
- if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx,
- myrateindex, refresh_rate)) {
- printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
- }
- }
- /* Adapt RGB settings */
- sisfb_bpp_to_var(ivideo, var);
-
- /* Sanity check for offsets */
- if(var->xoffset < 0) var->xoffset = 0;
- if(var->yoffset < 0) var->yoffset = 0;
- if(var->xres > var->xres_virtual) {
- var->xres_virtual = var->xres;
- }
- if(ivideo->sisfb_ypan) {
- maxyres = sisfb_calc_maxyres(ivideo, var);
- if(ivideo->sisfb_max) {
- var->yres_virtual = maxyres;
- } else {
- if(var->yres_virtual > maxyres) {
- var->yres_virtual = maxyres;
- }
- }
- if(var->yres_virtual <= var->yres) {
- var->yres_virtual = var->yres;
- }
- } else {
- if(var->yres != var->yres_virtual) {
- var->yres_virtual = var->yres;
- }
- var->xoffset = 0;
- var->yoffset = 0;
- }
-
- /* Truncate offsets to maximum if too high */
- if(var->xoffset > var->xres_virtual - var->xres) {
- var->xoffset = var->xres_virtual - var->xres - 1;
- }
- if(var->yoffset > var->yres_virtual - var->yres) {
- var->yoffset = var->yres_virtual - var->yres - 1;
- }
-
- /* Set everything else to 0 */
- var->red.msb_right =
- var->green.msb_right =
- var->blue.msb_right =
- var->transp.offset =
- var->transp.length =
- var->transp.msb_right = 0;
- return 0;
- }
- static int
- sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- int err;
- if(var->xoffset > (var->xres_virtual - var->xres)) {
- return -EINVAL;
- }
- if(var->yoffset > (var->yres_virtual - var->yres)) {
- return -EINVAL;
- }
- if(var->vmode & FB_VMODE_YWRAP) return -EINVAL;
- if(var->xoffset + info->var.xres > info->var.xres_virtual ||
- var->yoffset + info->var.yres > info->var.yres_virtual) {
- return -EINVAL;
- }
- if((err = sisfb_pan_var(ivideo, var)) < 0) return err;
- info->var.xoffset = var->xoffset;
- info->var.yoffset = var->yoffset;
- return 0;
- }
- static int
- sisfb_blank(int blank, struct fb_info *info)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- return(sisfb_myblank(ivideo, blank));
- }
- #endif
- /* ----------- FBDev related routines for all series ---------- */
- static int
- sisfb_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg,
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- int con,
- #endif
- struct fb_info *info)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- struct sis_memreq sismemreq;
- struct fb_vblank sisvbblank;
- sisfb_info x;
- u32 gpu32 = 0;
- #ifndef __user
- #define __user
- #endif
- u32 __user *argp = (u32 __user *)arg;
- switch (cmd) {
- case FBIO_ALLOC:
- if(!capable(CAP_SYS_RAWIO)) {
- return -EPERM;
- }
- if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq))) {
- return -EFAULT;
- }
- sis_malloc(&sismemreq);
- if(copy_to_user((void __user *)arg, &sismemreq, sizeof(sismemreq))) {
- sis_free((u32)sismemreq.offset);
- return -EFAULT;
- }
- break;
- case FBIO_FREE:
- if(!capable(CAP_SYS_RAWIO)) {
- return -EPERM;
- }
- if(get_user(gpu32, argp)) {
- return -EFAULT;
- }
- sis_free(gpu32);
- break;
- case FBIOGET_VBLANK:
- sisvbblank.count = 0;
- sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);
- if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank))) {
- return -EFAULT;
- }
- break;
- case SISFB_GET_INFO_SIZE:
- return put_user(sizeof(sisfb_info), argp);
- case SISFB_GET_INFO_OLD:
- if(ivideo->warncount++ < 50) {
- printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");
- }
- case SISFB_GET_INFO: /* For communication with X driver */
- x.sisfb_id = SISFB_ID;
- x.sisfb_version = VER_MAJOR;
- x.sisfb_revision = VER_MINOR;
- x.sisfb_patchlevel = VER_LEVEL;
- x.chip_id = ivideo->chip_id;
- x.memory = ivideo->video_size / 1024;
- x.heapstart = ivideo->heapstart / 1024;
- if(ivideo->modechanged) {
- x.fbvidmode = ivideo->mode_no;
- } else {
- x.fbvidmode = ivideo->modeprechange;
- }
- x.sisfb_caps = ivideo->caps;
- x.sisfb_tqlen = 512; /* yet fixed */
- x.sisfb_pcibus = ivideo->pcibus;
- x.sisfb_pcislot = ivideo->pcislot;
- x.sisfb_pcifunc = ivideo->pcifunc;
- x.sisfb_lcdpdc = ivideo->detectedpdc;
- x.sisfb_lcdpdca = ivideo->detectedpdca;
- x.sisfb_lcda = ivideo->detectedlcda;
- x.sisfb_vbflags = ivideo->vbflags;
- x.sisfb_currentvbflags = ivideo->currentvbflags;
- x.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
- x.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
- x.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
- x.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
- x.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
- x.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
- x.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
- x.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
- x.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
- x.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
- if(copy_to_user((void __user *)arg, &x, sizeof(x))) {
- return -EFAULT;
- }
- break;
- case SISFB_GET_VBRSTATUS_OLD:
- if(ivideo->warncount++ < 50) {
- printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");
- }
- case SISFB_GET_VBRSTATUS:
- if(sisfb_CheckVBRetrace(ivideo)) {
- return put_user((u32)1, argp);
- } else {
- return put_user((u32)0, argp);
- }
- case SISFB_GET_AUTOMAXIMIZE_OLD:
- if(ivideo->warncount++ < 50) {
- printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");
- }
- case SISFB_GET_AUTOMAXIMIZE:
- if(ivideo->sisfb_max) return put_user((u32)1, argp);
- else return put_user((u32)0, argp);
- case SISFB_SET_AUTOMAXIMIZE_OLD:
- if(ivideo->warncount++ < 50) {
- printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");
- }
- case SISFB_SET_AUTOMAXIMIZE:
- if(copy_from_user(&gpu32, argp, sizeof(gpu32))) {
- return -EFAULT;
- }
- ivideo->sisfb_max = (gpu32) ? 1 : 0;
- break;
- case SISFB_SET_TVPOSOFFSET:
- if(copy_from_user(&gpu32, argp, sizeof(gpu32))) {
- return -EFAULT;
- }
- sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32);
- sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32);
- break;
- case SISFB_GET_TVPOSOFFSET:
- return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)),
- argp);
- case SISFB_SET_LOCK:
- if(copy_from_user(&gpu32, argp, sizeof(gpu32))) {
- return -EFAULT;
- }
- ivideo->sisfblocked = (gpu32) ? 1 : 0;
- break;
- default:
- return -ENOIOCTLCMD;
- }
- return 0;
- }
- #ifdef CONFIG_COMPAT
- static long sisfb_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg, struct fb_info *info)
- {
- int ret;
- lock_kernel();
- ret = sisfb_ioctl(NULL, f, cmd, arg, info);
- unlock_kernel();
- return ret;
- }
- #endif
- static int
- sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
- {
- struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
- memset(fix, 0, sizeof(struct fb_fix_screeninfo));
- strcpy(fix->id, ivideo->myid);
- fix->smem_start = ivideo->video_base;
- fix->smem_len = ivideo->sisfb_mem;
- fix->type = FB_TYPE_PACKED_PIXELS;
- fix->type_aux = 0;
- fix->visual = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
- fix->xpanstep = 1;
- fix->ypanstep = (ivideo->sisfb_ypan) ? 1 : 0;
- fix->ywrapstep = 0;
- fix->line_length = ivideo->video_linelength;
- fix->mmio_start = ivideo->mmio_base;
- fix->mmio_len = ivideo->mmio_size;
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- fix->accel = FB_ACCEL_SIS_GLAMOUR;
- } else if((ivideo->chip == SIS_330) || (ivideo->chip == SIS_760)) {
- fix->accel = FB_ACCEL_SIS_XABRE;
- } else {
- fix->accel = FB_ACCEL_SIS_GLAMOUR_2;
- }
- return 0;
- }
- /* ---------------- fb_ops structures ----------------- */
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- static struct fb_ops sisfb_ops = {
- .owner = THIS_MODULE,
- .fb_get_fix = sisfb_get_fix,
- .fb_get_var = sisfb_get_var,
- .fb_set_var = sisfb_set_var,
- .fb_get_cmap = sisfb_get_cmap,
- .fb_set_cmap = sisfb_set_cmap,
- .fb_pan_display = sisfb_pan_display,
- .fb_ioctl = sisfb_ioctl
- };
- #endif
- #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- static struct fb_ops sisfb_ops = {
- .owner = THIS_MODULE,
- .fb_open = sisfb_open,
- .fb_release = sisfb_release,
- .fb_check_var = sisfb_check_var,
- .fb_set_par = sisfb_set_par,
- .fb_setcolreg = sisfb_setcolreg,
- .fb_pan_display = sisfb_pan_display,
- .fb_blank = sisfb_blank,
- .fb_fillrect = fbcon_sis_fillrect,
- .fb_copyarea = fbcon_sis_copyarea,
- .fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
- .fb_sync = fbcon_sis_sync,
- .fb_ioctl = sisfb_ioctl,
- #ifdef CONFIG_COMPAT
- .fb_compat_ioctl = sisfb_compat_ioctl,
- #endif
- };
- #endif
- /* ---------------- Chip generation dependent routines ---------------- */
- static struct pci_dev * sisfb_get_northbridge(int basechipid)
- {
- struct pci_dev *pdev = NULL;
- int nbridgenum, nbridgeidx, i;
- const unsigned short nbridgeids[] = {
- PCI_DEVICE_ID_SI_540, /* for SiS 540 VGA */
- PCI_DEVICE_ID_SI_630, /* for SiS 630/730 VGA */
- PCI_DEVICE_ID_SI_730,
- PCI_DEVICE_ID_SI_550, /* for SiS 550 VGA */
- PCI_DEVICE_ID_SI_650, /* for SiS 650/651/740 VGA */
- PCI_DEVICE_ID_SI_651,
- PCI_DEVICE_ID_SI_740,
- PCI_DEVICE_ID_SI_661, /* for SiS 661/741/660/760 VGA */
- PCI_DEVICE_ID_SI_741,
- PCI_DEVICE_ID_SI_660,
- PCI_DEVICE_ID_SI_760
- };
- switch(basechipid) {
- #ifdef CONFIG_FB_SIS_300
- case SIS_540: nbridgeidx = 0; nbridgenum = 1; break;
- case SIS_630: nbridgeidx = 1; nbridgenum = 2; break;
- #endif
- #ifdef CONFIG_FB_SIS_315
- case SIS_550: nbridgeidx = 3; nbridgenum = 1; break;
- case SIS_650: nbridgeidx = 4; nbridgenum = 3; break;
- case SIS_660: nbridgeidx = 7; nbridgenum = 4; break;
- #endif
- default: return NULL;
- }
- for(i = 0; i < nbridgenum; i++) {
- if((pdev = pci_find_device(PCI_VENDOR_ID_SI, nbridgeids[nbridgeidx+i], NULL))) break;
- }
- return pdev;
- }
- static int __devinit sisfb_get_dram_size(struct sis_video_info *ivideo)
- {
- #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
- u8 reg;
- #endif
- ivideo->video_size = 0;
- switch(ivideo->chip) {
- #ifdef CONFIG_FB_SIS_300
- case SIS_300:
- inSISIDXREG(SISSR, 0x14, reg);
- ivideo->video_size = ((reg & 0x3F) + 1) << 20;
- break;
- case SIS_540:
- case SIS_630:
- case SIS_730:
- if(!ivideo->nbridge) return -1;
- pci_read_config_byte(ivideo->nbridge, 0x63, ®);
- ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21);
- break;
- #endif
- #ifdef CONFIG_FB_SIS_315
- case SIS_315H:
- case SIS_315PRO:
- case SIS_315:
- inSISIDXREG(SISSR, 0x14, reg);
- ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
- switch((reg >> 2) & 0x03) {
- case 0x01:
- case 0x03:
- ivideo->video_size <<= 1;
- break;
- case 0x02:
- ivideo->video_size += (ivideo->video_size/2);
- }
- break;
- case SIS_330:
- inSISIDXREG(SISSR, 0x14, reg);
- ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
- if(reg & 0x0c) ivideo->video_size <<= 1;
- break;
- case SIS_550:
- case SIS_650:
- case SIS_740:
- inSISIDXREG(SISSR, 0x14, reg);
- ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;
- break;
- case SIS_661:
- case SIS_741:
- inSISIDXREG(SISCR, 0x79, reg);
- ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
- break;
- case SIS_660:
- case SIS_760:
- inSISIDXREG(SISCR, 0x79, reg);
- reg = (reg & 0xf0) >> 4;
- if(reg) ivideo->video_size = (1 << reg) << 20;
- inSISIDXREG(SISCR, 0x78, reg);
- reg &= 0x30;
- if(reg) {
- if(reg == 0x10) ivideo->video_size += (32 << 20);
- else ivideo->video_size += (64 << 20);
- }
- break;
- #endif
- default:
- return -1;
- }
- return 0;
- }
- /* -------------- video bridge device detection --------------- */
- static void __devinit sisfb_detect_VB_connect(struct sis_video_info *ivideo)
- {
- u8 cr32, temp;
- #ifdef CONFIG_FB_SIS_300
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- inSISIDXREG(SISSR, 0x17, temp);
- if((temp & 0x0F) && (ivideo->chip != SIS_300)) {
- /* PAL/NTSC is stored on SR16 on such machines */
- if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
- inSISIDXREG(SISSR, 0x16, temp);
- if(temp & 0x20)
- ivideo->vbflags |= TV_PAL;
- else
- ivideo->vbflags |= TV_NTSC;
- }
- }
- }
- #endif
- inSISIDXREG(SISCR, 0x32, cr32);
- if(cr32 & SIS_CRT1) {
- ivideo->sisfb_crt1off = 0;
- } else {
- ivideo->sisfb_crt1off = (cr32 & 0xDF) ? 1 : 0;
- }
- ivideo->vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA);
- if(cr32 & SIS_VB_TV) ivideo->vbflags |= CRT2_TV;
- if(cr32 & SIS_VB_LCD) ivideo->vbflags |= CRT2_LCD;
- if(cr32 & SIS_VB_CRT2) ivideo->vbflags |= CRT2_VGA;
- /* Check given parms for hardware compatibility.
- * (Cannot do this in the search_xx routines since we don't
- * know what hardware we are running on then)
- */
- if(ivideo->chip != SIS_550) {
- ivideo->sisfb_dstn = ivideo->sisfb_fstn = 0;
- }
- if(ivideo->sisfb_tvplug != -1) {
- if( (ivideo->sisvga_engine != SIS_315_VGA) ||
- (!(ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV))) ) {
- if(ivideo->sisfb_tvplug & TV_YPBPR) {
- ivideo->sisfb_tvplug = -1;
- printk(KERN_ERR "sisfb: YPbPr not supported\n");
- }
- }
- }
- if(ivideo->sisfb_tvplug != -1) {
- if( (ivideo->sisvga_engine != SIS_315_VGA) ||
- (!(ivideo->vbflags & (VB_301|VB_301B|VB_302B))) ) {
- if(ivideo->sisfb_tvplug & TV_HIVISION) {
- ivideo->sisfb_tvplug = -1;
- printk(KERN_ERR "sisfb: HiVision not supported\n");
- }
- }
- }
- if(ivideo->sisfb_tvstd != -1) {
- if( (!(ivideo->vbflags & VB_SISBRIDGE)) &&
- (!((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags & VB_CHRONTEL))) ) {
- if(ivideo->sisfb_tvstd & (TV_PALN | TV_PALN | TV_NTSCJ)) {
- ivideo->sisfb_tvstd = -1;
- printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
- }
- }
- }
- /* Detect/set TV plug & type */
- if(ivideo->sisfb_tvplug != -1) {
- ivideo->vbflags |= ivideo->sisfb_tvplug;
- } else {
- if(cr32 & SIS_VB_YPBPR) ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */
- else if(cr32 & SIS_VB_HIVISION) ivideo->vbflags |= TV_HIVISION;
- else if(cr32 & SIS_VB_SCART) ivideo->vbflags |= TV_SCART;
- else {
- if(cr32 & SIS_VB_SVIDEO) ivideo->vbflags |= TV_SVIDEO;
- if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO;
- }
- }
- if(!(ivideo->vbflags & (TV_YPBPR | TV_HIVISION))) {
- if(ivideo->sisfb_tvstd != -1) {
- ivideo->vbflags &= ~(TV_NTSC | TV_PAL | TV_PALM | TV_PALN | TV_NTSCJ);
- ivideo->vbflags |= ivideo->sisfb_tvstd;
- }
- if(ivideo->vbflags & TV_SCART) {
- ivideo->vbflags &= ~(TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ);
- ivideo->vbflags |= TV_PAL;
- }
- if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) {
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- inSISIDXREG(SISSR, 0x38, temp);
- if(temp & 0x01) ivideo->vbflags |= TV_PAL;
- else ivideo->vbflags |= TV_NTSC;
- } else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) {
- inSISIDXREG(SISSR, 0x38, temp);
- if(temp & 0x01) ivideo->vbflags |= TV_PAL;
- else ivideo->vbflags |= TV_NTSC;
- } else {
- inSISIDXREG(SISCR, 0x79, temp);
- if(temp & 0x20) ivideo->vbflags |= TV_PAL;
- else ivideo->vbflags |= TV_NTSC;
- }
- }
- }
- /* Copy forceCRT1 option to CRT1off if option is given */
- if(ivideo->sisfb_forcecrt1 != -1) {
- ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1;
- }
- }
- static void __devinit sisfb_get_VB_type(struct sis_video_info *ivideo)
- {
- char stdstr[] = "sisfb: Detected";
- char bridgestr[] = "video bridge";
- u8 vb_chipid;
- u8 reg;
- inSISIDXREG(SISPART4, 0x00, vb_chipid);
- switch(vb_chipid) {
- case 0x01:
- inSISIDXREG(SISPART4, 0x01, reg);
- if(reg < 0xb0) {
- ivideo->vbflags |= VB_301;
- printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
- } else if(reg < 0xc0) {
- ivideo->vbflags |= VB_301B;
- inSISIDXREG(SISPART4,0x23,reg);
- if(!(reg & 0x02)) {
- ivideo->vbflags |= VB_30xBDH;
- printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
- } else {
- printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
- }
- } else if(reg < 0xd0) {
- ivideo->vbflags |= VB_301C;
- printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
- } else if(reg < 0xe0) {
- ivideo->vbflags |= VB_301LV;
- printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
- } else if(reg <= 0xe1) {
- inSISIDXREG(SISPART4,0x39,reg);
- if(reg == 0xff) {
- ivideo->vbflags |= VB_302LV;
- printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
- } else {
- ivideo->vbflags |= VB_301C;
- printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
- #if 0
- ivideo->vbflags |= VB_302ELV;
- printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
- #endif
- }
- }
- break;
- case 0x02:
- ivideo->vbflags |= VB_302B;
- printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
- break;
- }
- if((!(ivideo->vbflags & VB_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
- inSISIDXREG(SISCR, 0x37, reg);
- reg &= SIS_EXTERNAL_CHIP_MASK;
- reg >>= 1;
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- #ifdef CONFIG_FB_SIS_300
- switch(reg) {
- case SIS_EXTERNAL_CHIP_LVDS:
- ivideo->vbflags |= VB_LVDS;
- break;
- case SIS_EXTERNAL_CHIP_TRUMPION:
- ivideo->vbflags |= VB_TRUMPION;
- break;
- case SIS_EXTERNAL_CHIP_CHRONTEL:
- ivideo->vbflags |= VB_CHRONTEL;
- break;
- case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
- ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);
- break;
- }
- if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 1;
- #endif
- } else if(ivideo->chip < SIS_661) {
- #ifdef CONFIG_FB_SIS_315
- switch (reg) {
- case SIS310_EXTERNAL_CHIP_LVDS:
- ivideo->vbflags |= VB_LVDS;
- break;
- case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
- ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);
- break;
- }
- if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 2;
- #endif
- } else if(ivideo->chip >= SIS_661) {
- #ifdef CONFIG_FB_SIS_315
- inSISIDXREG(SISCR, 0x38, reg);
- reg >>= 5;
- switch(reg) {
- case 0x02:
- ivideo->vbflags |= VB_LVDS;
- break;
- case 0x03:
- ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);
- break;
- case 0x04:
- ivideo->vbflags |= (VB_LVDS | VB_CONEXANT);
- break;
- }
- if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 2;
- #endif
- }
- if(ivideo->vbflags & VB_LVDS) {
- printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
- }
- if(ivideo->vbflags & VB_TRUMPION) {
- printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
- }
- if(ivideo->vbflags & VB_CHRONTEL) {
- printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
- }
- if(ivideo->vbflags & VB_CONEXANT) {
- printk(KERN_INFO "%s Conexant external device\n", stdstr);
- }
- }
- if(ivideo->vbflags & VB_SISBRIDGE) {
- SiS_Sense30x(ivideo);
- } else if(ivideo->vbflags & VB_CHRONTEL) {
- SiS_SenseCh(ivideo);
- }
- }
- /* ------------------ Sensing routines ------------------ */
- static BOOLEAN __devinit sisfb_test_DDC1(struct sis_video_info *ivideo)
- {
- unsigned short old;
- int count = 48;
- old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr);
- do {
- if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
- } while(count--);
- return (count == -1) ? FALSE : TRUE;
- }
- static void __devinit sisfb_sense_crt1(struct sis_video_info *ivideo)
- {
- BOOLEAN mustwait = FALSE;
- u8 sr1F, cr17;
- #ifdef CONFIG_FB_SIS_315
- u8 cr63=0;
- #endif
- u16 temp = 0xffff;
- int i;
- inSISIDXREG(SISSR,0x1F,sr1F);
- orSISIDXREG(SISSR,0x1F,0x04);
- andSISIDXREG(SISSR,0x1F,0x3F);
- if(sr1F & 0xc0) mustwait = TRUE;
- #ifdef CONFIG_FB_SIS_315
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- inSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,cr63);
- cr63 &= 0x40;
- andSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,0xBF);
- }
- #endif
- inSISIDXREG(SISCR,0x17,cr17);
- cr17 &= 0x80;
- if(!cr17) {
- orSISIDXREG(SISCR,0x17,0x80);
- mustwait = TRUE;
- outSISIDXREG(SISSR, 0x00, 0x01);
- outSISIDXREG(SISSR, 0x00, 0x03);
- }
- if(mustwait) {
- for(i=0; i < 10; i++) sisfbwaitretracecrt1(ivideo);
- }
- #ifdef CONFIG_FB_SIS_315
- if(ivideo->chip >= SIS_330) {
- andSISIDXREG(SISCR,0x32,~0x20);
- if(ivideo->chip >= SIS_340) {
- outSISIDXREG(SISCR, 0x57, 0x4a);
- } else {
- outSISIDXREG(SISCR, 0x57, 0x5f);
- }
- orSISIDXREG(SISCR, 0x53, 0x02);
- while((inSISREG(SISINPSTAT)) & 0x01) break;
- while(!((inSISREG(SISINPSTAT)) & 0x01)) break;
- if((inSISREG(SISMISCW)) & 0x10) temp = 1;
- andSISIDXREG(SISCR, 0x53, 0xfd);
- andSISIDXREG(SISCR, 0x57, 0x00);
- }
- #endif
- if(temp == 0xffff) {
- i = 3;
- do {
- temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine, 0, 0, NULL);
- } while(((temp == 0) || (temp == 0xffff)) && i--);
- if((temp == 0) || (temp == 0xffff)) {
- if(sisfb_test_DDC1(ivideo)) temp = 1;
- }
- }
- if((temp) && (temp != 0xffff)) {
- orSISIDXREG(SISCR,0x32,0x20);
- }
- #ifdef CONFIG_FB_SIS_315
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- setSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,0xBF,cr63);
- }
- #endif
- setSISIDXREG(SISCR,0x17,0x7F,cr17);
- outSISIDXREG(SISSR,0x1F,sr1F);
- }
- /* Determine and detect attached devices on SiS30x */
- static int __devinit SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
- {
- int temp, mytest, result, i, j;
- for(j = 0; j < 10; j++) {
- result = 0;
- for(i = 0; i < 3; i++) {
- mytest = test;
- outSISIDXREG(SISPART4,0x11,(type & 0x00ff));
- temp = (type >> 8) | (mytest & 0x00ff);
- setSISIDXREG(SISPART4,0x10,0xe0,temp);
- SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500);
- mytest >>= 8;
- mytest &= 0x7f;
- inSISIDXREG(SISPART4,0x03,temp);
- temp ^= 0x0e;
- temp &= mytest;
- if(temp == mytest) result++;
- #if 1
- outSISIDXREG(SISPART4,0x11,0x00);
- andSISIDXREG(SISPART4,0x10,0xe0);
- SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);
- #endif
- }
- if((result == 0) || (result >= 2)) break;
- }
- return(result);
- }
- static void __devinit SiS_Sense30x(struct sis_video_info *ivideo)
- {
- u8 backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0;
- u16 svhs=0, svhs_c=0;
- u16 cvbs=0, cvbs_c=0;
- u16 vga2=0, vga2_c=0;
- int myflag, result;
- char stdstr[] = "sisfb: Detected";
- char tvstr[] = "TV connected to";
- if(ivideo->vbflags & VB_301) {
- svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
- inSISIDXREG(SISPART4,0x01,myflag);
- if(myflag & 0x04) {
- svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
- }
- } else if(ivideo->vbflags & (VB_301B | VB_302B)) {
- svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190;
- } else if(ivideo->vbflags & (VB_301LV | VB_302LV)) {
- svhs = 0x0200; cvbs = 0x0100;
- } else if(ivideo->vbflags & (VB_301C | VB_302ELV)) {
- svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190;
- } else return;
- vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804;
- if(ivideo->vbflags & (VB_301LV|VB_302LV|VB_302ELV)) {
- svhs_c = 0x0408; cvbs_c = 0x0808;
- }
- biosflag = 2;
- if(ivideo->chip == SIS_300) {
- inSISIDXREG(SISSR,0x3b,myflag);
- if(!(myflag & 0x01)) vga2 = vga2_c = 0;
- }
- inSISIDXREG(SISSR,0x1e,backupSR_1e);
- orSISIDXREG(SISSR,0x1e,0x20);
- inSISIDXREG(SISPART4,0x0d,backupP4_0d);
- if(ivideo->vbflags & VB_301C) {
- setSISIDXREG(SISPART4,0x0d,~0x07,0x01);
- } else {
- orSISIDXREG(SISPART4,0x0d,0x04);
- }
- SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
- inSISIDXREG(SISPART2,0x00,backupP2_00);
- outSISIDXREG(SISPART2,0x00,((backupP2_00 | 0x1c) & 0xfc));
- inSISIDXREG(SISPART2,0x4d,backupP2_4d);
- if(ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV|VB_302ELV)) {
- outSISIDXREG(SISPART2,0x4d,(backupP2_4d & ~0x10));
- }
- if(!(ivideo->vbflags & VB_301C)) {
- SISDoSense(ivideo, 0, 0);
- }
- andSISIDXREG(SISCR, 0x32, ~0x14);
- if(vga2_c || vga2) {
- if(SISDoSense(ivideo, vga2, vga2_c)) {
- if(biosflag & 0x01) {
- printk(KERN_INFO "%s %s SCART output\n", stdstr, tvstr);
- orSISIDXREG(SISCR, 0x32, 0x04);
- } else {
- printk(KERN_INFO "%s secondary VGA connection\n", stdstr);
- orSISIDXREG(SISCR, 0x32, 0x10);
- }
- }
- }
- andSISIDXREG(SISCR, 0x32, 0x3f);
- if(ivideo->vbflags & VB_301C) {
- orSISIDXREG(SISPART4,0x0d,0x04);
- }
- if((ivideo->sisvga_engine == SIS_315_VGA) &&
- (ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV|VB_302ELV))) {
- outSISIDXREG(SISPART2,0x4d,(backupP2_4d | 0x10));
- SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
- if((result = SISDoSense(ivideo, svhs, 0x0604))) {
- if((result = SISDoSense(ivideo, cvbs, 0x0804))) {
- printk(KERN_INFO "%s %s YPbPr component output\n", stdstr, tvstr);
- orSISIDXREG(SISCR,0x32,0x80);
- }
- }
- outSISIDXREG(SISPART2,0x4d,backupP2_4d);
- }
- andSISIDXREG(SISCR, 0x32, ~0x03);
- if(!(ivideo->vbflags & TV_YPBPR)) {
- if((result = SISDoSense(ivideo, svhs, svhs_c))) {
- printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr);
- orSISIDXREG(SISCR, 0x32, 0x02);
- }
- if((biosflag & 0x02) || (!result)) {
- if(SISDoSense(ivideo, cvbs, cvbs_c)) {
- printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr);
- orSISIDXREG(SISCR, 0x32, 0x01);
- }
- }
- }
- SISDoSense(ivideo, 0, 0);
- outSISIDXREG(SISPART2,0x00,backupP2_00);
- outSISIDXREG(SISPART4,0x0d,backupP4_0d);
- outSISIDXREG(SISSR,0x1e,backupSR_1e);
- if(ivideo->vbflags & VB_301C) {
- inSISIDXREG(SISPART2,0x00,biosflag);
- if(biosflag & 0x20) {
- for(myflag = 2; myflag > 0; myflag--) {
- biosflag ^= 0x20;
- outSISIDXREG(SISPART2,0x00,biosflag);
- }
- }
- }
- outSISIDXREG(SISPART2,0x00,backupP2_00);
- }
- /* Determine and detect attached TV's on Chrontel */
- static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
- {
- #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
- u8 temp1, temp2;
- char stdstr[] = "sisfb: Chrontel: Detected TV connected to";
- #endif
- #ifdef CONFIG_FB_SIS_300
- unsigned char test[3];
- int i;
- #endif
- if(ivideo->chip < SIS_315H) {
- #ifdef CONFIG_FB_SIS_300
- ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 1; /* Chrontel 700x */
- SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x9c); /* Set general purpose IO for Chrontel communication */
- SiS_DDC2Delay(&ivideo->SiS_Pr, 1000);
- temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
- /* See Chrontel TB31 for explanation */
- temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
- if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
- SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b0e);
- SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
- }
- temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
- if(temp2 != temp1) temp1 = temp2;
- if((temp1 >= 0x22) && (temp1 <= 0x50)) {
- /* Read power status */
- temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
- if((temp1 & 0x03) != 0x03) {
- /* Power all outputs */
- SiS_SetCH700x(&ivideo->SiS_Pr, 0x0B0E);
- SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
- }
- /* Sense connected TV devices */
- for(i = 0; i < 3; i++) {
- SiS_SetCH700x(&ivideo->SiS_Pr, 0x0110);
- SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
- SiS_SetCH700x(&ivideo->SiS_Pr, 0x0010);
- SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
- temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10);
- if(!(temp1 & 0x08)) test[i] = 0x02;
- else if(!(temp1 & 0x02)) test[i] = 0x01;
- else test[i] = 0;
- SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
- }
- if(test[0] == test[1]) temp1 = test[0];
- else if(test[0] == test[2]) temp1 = test[0];
- else if(test[1] == test[2]) temp1 = test[1];
- else {
- printk(KERN_INFO
- "sisfb: TV detection unreliable - test results varied\n");
- temp1 = test[2];
- }
- if(temp1 == 0x02) {
- printk(KERN_INFO "%s SVIDEO output\n", stdstr);
- ivideo->vbflags |= TV_SVIDEO;
- orSISIDXREG(SISCR, 0x32, 0x02);
- andSISIDXREG(SISCR, 0x32, ~0x05);
- } else if (temp1 == 0x01) {
- printk(KERN_INFO "%s CVBS output\n", stdstr);
- ivideo->vbflags |= TV_AVIDEO;
- orSISIDXREG(SISCR, 0x32, 0x01);
- andSISIDXREG(SISCR, 0x32, ~0x06);
- } else {
- SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x010E,0xF8);
- andSISIDXREG(SISCR, 0x32, ~0x07);
- }
- } else if(temp1 == 0) {
- SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x010E,0xF8);
- andSISIDXREG(SISCR, 0x32, ~0x07);
- }
- /* Set general purpose IO for Chrontel communication */
- SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x00);
- #endif
- } else {
- #ifdef CONFIG_FB_SIS_315
- ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2; /* Chrontel 7019 */
- temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49);
- SiS_SetCH701x(&ivideo->SiS_Pr, 0x2049);
- SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
- temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
- temp2 |= 0x01;
- SiS_SetCH701x(&ivideo->SiS_Pr, (temp2 << 8) | 0x20);
- SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
- temp2 ^= 0x01;
- SiS_SetCH701x(&ivideo->SiS_Pr, (temp2 << 8) | 0x20);
- SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
- temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
- SiS_SetCH701x(&ivideo->SiS_Pr, (temp1 << 8) | 0x49);
- temp1 = 0;
- if(temp2 & 0x02) temp1 |= 0x01;
- if(temp2 & 0x10) temp1 |= 0x01;
- if(temp2 & 0x04) temp1 |= 0x02;
- if( (temp1 & 0x01) && (temp1 & 0x02) ) temp1 = 0x04;
- switch(temp1) {
- case 0x01:
- printk(KERN_INFO "%s CVBS output\n", stdstr);
- ivideo->vbflags |= TV_AVIDEO;
- orSISIDXREG(SISCR, 0x32, 0x01);
- andSISIDXREG(SISCR, 0x32, ~0x06);
- break;
- case 0x02:
- printk(KERN_INFO "%s SVIDEO output\n", stdstr);
- ivideo->vbflags |= TV_SVIDEO;
- orSISIDXREG(SISCR, 0x32, 0x02);
- andSISIDXREG(SISCR, 0x32, ~0x05);
- break;
- case 0x04:
- printk(KERN_INFO "%s SCART output\n", stdstr);
- orSISIDXREG(SISCR, 0x32, 0x04);
- andSISIDXREG(SISCR, 0x32, ~0x03);
- break;
- default:
- andSISIDXREG(SISCR, 0x32, ~0x07);
- }
- #endif
- }
- }
- /* ------------------------ Heap routines -------------------------- */
- static u32 __devinit
- sisfb_getheapstart(struct sis_video_info *ivideo)
- {
- u32 ret = ivideo->sisfb_parm_mem * 1024;
- u32 max = ivideo->video_size - ivideo->hwcursor_size;
- u32 def;
- /* Calculate heap start = end of memory for console
- *
- * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
- * C = console, D = heap, H = HWCursor, Q = cmd-queue
- *
- * Basically given by "mem" parameter
- *
- * maximum = videosize - cmd_queue - hwcursor
- * (results in a heap of size 0)
- * default = SiS 300: depends on videosize
- * SiS 315/330: 32k below max
- */
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- max -= TURBO_QUEUE_AREA_SIZE;
- if(ivideo->video_size > 0x1000000) {
- def = 0xc00000;
- } else if(ivideo->video_size > 0x800000) {
- def = 0x800000;
- } else {
- def = 0x400000;
- }
- } else {
- max -= COMMAND_QUEUE_AREA_SIZE;
- def = max - 0x8000;
- }
- if((!ret) || (ret > max) || (ivideo->cardnumber != 0)) {
- ret = def;
- }
- return ret;
- }
- static int __devinit
- sisfb_heap_init(struct sis_video_info *ivideo)
- {
- SIS_OH *poh;
- ivideo->heapstart = ivideo->sisfb_mem = sisfb_getheapstart(ivideo);
- ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart;
- ivideo->sisfb_heap_end = ivideo->video_vbase + ivideo->video_size;
- /* Initialize command queue (We use MMIO only) */
- #ifdef CONFIG_FB_SIS_315
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- u32 tempq = 0;
- u8 temp = 0;
- ivideo->sisfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
- outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
- outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
- tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT);
- MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
- temp = SIS_CMD_QUEUE_SIZE_512k;
- temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
- outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
- tempq = (u32)(ivideo->video_size - COMMAND_QUEUE_AREA_SIZE);
- MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
- ivideo->caps |= MMIO_CMD_QUEUE_CAP;
- }
- #endif
- #ifdef CONFIG_FB_SIS_300
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- unsigned long tqueue_pos;
- u8 tq_state;
- ivideo->sisfb_heap_end -= TURBO_QUEUE_AREA_SIZE;
- tqueue_pos = (ivideo->video_size - TURBO_QUEUE_AREA_SIZE) / (64 * 1024);
- inSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
- tq_state |= 0xf0;
- tq_state &= 0xfc;
- tq_state |= (u8)(tqueue_pos >> 8);
- outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
- outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
- ivideo->caps |= TURBO_QUEUE_CAP;
- }
- #endif
- /* Reserve memory for the HWCursor */
- ivideo->sisfb_heap_end -= ivideo->hwcursor_size;
- ivideo->hwcursor_vbase = ivideo->sisfb_heap_end;
- ivideo->caps |= HW_CURSOR_CAP;
- ivideo->sisfb_heap_size = ivideo->sisfb_heap_end - ivideo->sisfb_heap_start;
- if(ivideo->cardnumber == 0) {
- printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n",
- (int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024));
- sisfb_heap.vinfo = ivideo;
- sisfb_heap.poha_chain = NULL;
- sisfb_heap.poh_freelist = NULL;
- poh = sisfb_poh_new_node();
- if(poh == NULL) return 1;
- poh->poh_next = &sisfb_heap.oh_free;
- poh->poh_prev = &sisfb_heap.oh_free;
- poh->size = ivideo->sisfb_heap_size;
- poh->offset = ivideo->heapstart;
- sisfb_heap.oh_free.poh_next = poh;
- sisfb_heap.oh_free.poh_prev = poh;
- sisfb_heap.oh_free.size = 0;
- sisfb_heap.max_freesize = poh->size;
- sisfb_heap.oh_used.poh_next = &sisfb_heap.oh_used;
- sisfb_heap.oh_used.poh_prev = &sisfb_heap.oh_used;
- sisfb_heap.oh_used.size = SENTINEL;
- } else {
- printk(KERN_INFO "Skipped heap initialization for secondary cards\n");
- }
- return 0;
- }
- static SIS_OH *
- sisfb_poh_new_node(void)
- {
- int i;
- unsigned long cOhs;
- SIS_OHALLOC *poha;
- SIS_OH *poh;
- if(sisfb_heap.poh_freelist == NULL) {
- poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL);
- if(!poha) return NULL;
- poha->poha_next = sisfb_heap.poha_chain;
- sisfb_heap.poha_chain = poha;
- cOhs = (SIS_OH_ALLOC_SIZE - sizeof(SIS_OHALLOC)) / sizeof(SIS_OH) + 1;
- poh = &poha->aoh[0];
- for(i = cOhs - 1; i != 0; i--) {
- poh->poh_next = poh + 1;
- poh = poh + 1;
- }
- poh->poh_next = NULL;
- sisfb_heap.poh_freelist = &poha->aoh[0];
- }
- poh = sisfb_heap.poh_freelist;
- sisfb_heap.poh_freelist = poh->poh_next;
- return (poh);
- }
- static SIS_OH *
- sisfb_poh_allocate(u32 size)
- {
- SIS_OH *pohThis;
- SIS_OH *pohRoot;
- int bAllocated = 0;
- if(size > sisfb_heap.max_freesize) {
- DPRINTK("sisfb: Can't allocate %dk video memory\n",
- (unsigned int) size / 1024);
- return (NULL);
- }
- pohThis = sisfb_heap.oh_free.poh_next;
- while(pohThis != &sisfb_heap.oh_free) {
- if (size <= pohThis->size) {
- bAllocated = 1;
- break;
- }
- pohThis = pohThis->poh_next;
- }
- if(!bAllocated) {
- DPRINTK("sisfb: Can't allocate %dk video memory\n",
- (unsigned int) size / 1024);
- return (NULL);
- }
- if(size == pohThis->size) {
- pohRoot = pohThis;
- sisfb_delete_node(pohThis);
- } else {
- pohRoot = sisfb_poh_new_node();
- if(pohRoot == NULL) {
- return (NULL);
- }
- pohRoot->offset = pohThis->offset;
- pohRoot->size = size;
- pohThis->offset += size;
- pohThis->size -= size;
- }
- sisfb_heap.max_freesize -= size;
- pohThis = &sisfb_heap.oh_used;
- sisfb_insert_node(pohThis, pohRoot);
- return (pohRoot);
- }
- static void
- sisfb_delete_node(SIS_OH *poh)
- {
- SIS_OH *poh_prev;
- SIS_OH *poh_next;
- poh_prev = poh->poh_prev;
- poh_next = poh->poh_next;
- poh_prev->poh_next = poh_next;
- poh_next->poh_prev = poh_prev;
- }
- static void
- sisfb_insert_node(SIS_OH *pohList, SIS_OH *poh)
- {
- SIS_OH *pohTemp;
- pohTemp = pohList->poh_next;
- pohList->poh_next = poh;
- pohTemp->poh_prev = poh;
- poh->poh_prev = pohList;
- poh->poh_next = pohTemp;
- }
- static SIS_OH *
- sisfb_poh_free(u32 base)
- {
- SIS_OH *pohThis;
- SIS_OH *poh_freed;
- SIS_OH *poh_prev;
- SIS_OH *poh_next;
- u32 ulUpper;
- u32 ulLower;
- int foundNode = 0;
- poh_freed = sisfb_heap.oh_used.poh_next;
- while(poh_freed != &sisfb_heap.oh_used) {
- if(poh_freed->offset == base) {
- foundNode = 1;
- break;
- }
- poh_freed = poh_freed->poh_next;
- }
- if(!foundNode) return(NULL);
- sisfb_heap.max_freesize += poh_freed->size;
- poh_prev = poh_next = NULL;
- ulUpper = poh_freed->offset + poh_freed->size;
- ulLower = poh_freed->offset;
- pohThis = sisfb_heap.oh_free.poh_next;
- while(pohThis != &sisfb_heap.oh_free) {
- if(pohThis->offset == ulUpper) {
- poh_next = pohThis;
- } else if((pohThis->offset + pohThis->size) == ulLower) {
- poh_prev = pohThis;
- }
- pohThis = pohThis->poh_next;
- }
- sisfb_delete_node(poh_freed);
- if(poh_prev && poh_next) {
- poh_prev->size += (poh_freed->size + poh_next->size);
- sisfb_delete_node(poh_next);
- sisfb_free_node(poh_freed);
- sisfb_free_node(poh_next);
- return(poh_prev);
- }
- if(poh_prev) {
- poh_prev->size += poh_freed->size;
- sisfb_free_node(poh_freed);
- return(poh_prev);
- }
- if(poh_next) {
- poh_next->size += poh_freed->size;
- poh_next->offset = poh_freed->offset;
- sisfb_free_node(poh_freed);
- return(poh_next);
- }
- sisfb_insert_node(&sisfb_heap.oh_free, poh_freed);
- return(poh_freed);
- }
- static void
- sisfb_free_node(SIS_OH *poh)
- {
- if(poh == NULL) return;
- poh->poh_next = sisfb_heap.poh_freelist;
- sisfb_heap.poh_freelist = poh;
- }
- void
- sis_malloc(struct sis_memreq *req)
- {
- struct sis_video_info *ivideo = sisfb_heap.vinfo;
- SIS_OH *poh = NULL;
- if((ivideo) && (!ivideo->havenoheap)) {
- poh = sisfb_poh_allocate((u32)req->size);
- }
- if(poh == NULL) {
- req->offset = req->size = 0;
- DPRINTK("sisfb: Video RAM allocation failed\n");
- } else {
- req->offset = poh->offset;
- req->size = poh->size;
- DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
- (poh->offset + ivideo->video_vbase));
- }
- }
- /* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
- void
- sis_free(u32 base)
- {
- struct sis_video_info *ivideo = sisfb_heap.vinfo;
- SIS_OH *poh;
- if((!ivideo) || (ivideo->havenoheap)) return;
- poh = sisfb_poh_free((u32)base);
- if(poh == NULL) {
- DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
- (unsigned int) base);
- }
- }
- /* --------------------- SetMode routines ------------------------- */
- static void
- sisfb_pre_setmode(struct sis_video_info *ivideo)
- {
- u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0;
- int tvregnum = 0;
- ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
- inSISIDXREG(SISCR, 0x31, cr31);
- cr31 &= ~0x60;
- cr31 |= 0x04;
- cr33 = ivideo->rate_idx & 0x0F;
- #ifdef CONFIG_FB_SIS_315
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- if(ivideo->chip >= SIS_661) {
- inSISIDXREG(SISCR, 0x38, cr38);
- cr38 &= ~0x07; /* Clear LCDA/DualEdge and YPbPr bits */
- } else {
- tvregnum = 0x38;
- inSISIDXREG(SISCR, tvregnum, cr38);
- cr38 &= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */
- }
- }
- #endif
- #ifdef CONFIG_FB_SIS_300
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- tvregnum = 0x35;
- inSISIDXREG(SISCR, tvregnum, cr38);
- }
- #endif
- SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
- SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
- switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
- case CRT2_TV:
- cr38 &= ~0xc0; /* Clear PAL-M / PAL-N bits */
- if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV))) {
- #ifdef CONFIG_FB_SIS_315
- if(ivideo->chip >= SIS_661) {
- cr38 |= 0x04;
- if(ivideo->vbflags & TV_YPBPR525P) cr35 |= 0x20;
- else if(ivideo->vbflags & TV_YPBPR750P) cr35 |= 0x40;
- else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60;
- cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
- cr35 &= ~0x01;
- ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
- } else if(ivideo->sisvga_engine == SIS_315_VGA) {
- cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE);
- cr38 |= 0x08;
- if(ivideo->vbflags & TV_YPBPR525P) cr38 |= 0x10;
- else if(ivideo->vbflags & TV_YPBPR750P) cr38 |= 0x20;
- else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30;
- cr31 &= ~0x01;
- ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
- }
- #endif
- } else if((ivideo->vbflags & TV_HIVISION) && (ivideo->vbflags & (VB_301|VB_301B|VB_302B))) {
- if(ivideo->chip >= SIS_661) {
- cr38 |= 0x04;
- cr35 |= 0x60;
- } else {
- cr30 |= 0x80;
- }
- cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
- cr31 |= 0x01;
- cr35 |= 0x01;
- ivideo->currentvbflags |= TV_HIVISION;
- } else if(ivideo->vbflags & TV_SCART) {
- cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE);
- cr31 |= 0x01;
- cr35 |= 0x01;
- ivideo->currentvbflags |= TV_SCART;
- } else {
- if(ivideo->vbflags & TV_SVIDEO) {
- cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE);
- ivideo->currentvbflags |= TV_SVIDEO;
- }
- if(ivideo->vbflags & TV_AVIDEO) {
- cr30 = (SIS_VB_OUTPUT_COMPOSITE | SIS_SIMULTANEOUS_VIEW_ENABLE);
- ivideo->currentvbflags |= TV_AVIDEO;
- }
- }
- cr31 |= SIS_DRIVER_MODE;
- if(ivideo->vbflags & (TV_AVIDEO|TV_SVIDEO)) {
- if(ivideo->vbflags & TV_PAL) {
- cr31 |= 0x01; cr35 |= 0x01;
- ivideo->currentvbflags |= TV_PAL;
- if(ivideo->vbflags & TV_PALM) {
- cr38 |= 0x40; cr35 |= 0x04;
- ivideo->currentvbflags |= TV_PALM;
- } else if(ivideo->vbflags & TV_PALN) {
- cr38 |= 0x80; cr35 |= 0x08;
- ivideo->currentvbflags |= TV_PALN;
- }
- } else {
- cr31 &= ~0x01; cr35 &= ~0x01;
- ivideo->currentvbflags |= TV_NTSC;
- if(ivideo->vbflags & TV_NTSCJ) {
- cr38 |= 0x40; cr35 |= 0x02;
- ivideo->currentvbflags |= TV_NTSCJ;
- }
- }
- }
- break;
- case CRT2_LCD:
- cr30 = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
- cr31 |= SIS_DRIVER_MODE;
- SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn);
- SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->sisfb_fstn);
- break;
- case CRT2_VGA:
- cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
- cr31 |= SIS_DRIVER_MODE;
- if(ivideo->sisfb_nocrt2rate) {
- cr33 |= (sisbios_mode[ivideo->sisfb_mode_idx].rate_idx << 4);
- } else {
- cr33 |= ((ivideo->rate_idx & 0x0F) << 4);
- }
- break;
- default: /* disable CRT2 */
- cr30 = 0x00;
- cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
- }
- outSISIDXREG(SISCR, 0x30, cr30);
- outSISIDXREG(SISCR, 0x33, cr33);
- if(ivideo->chip >= SIS_661) {
- #ifdef CONFIG_FB_SIS_315
- cr31 &= ~0x01; /* Clear PAL flag (now in CR35) */
- setSISIDXREG(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */
- cr38 &= 0x07; /* Use only LCDA and HiVision/YPbPr bits */
- setSISIDXREG(SISCR, 0x38, 0xf8, cr38);
- #endif
- } else if(ivideo->chip != SIS_300) {
- outSISIDXREG(SISCR, tvregnum, cr38);
- }
- outSISIDXREG(SISCR, 0x31, cr31);
- if(ivideo->accel) sisfb_syncaccel(ivideo);
- ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem;
- }
- /* Fix SR11 for 661 and later */
- #ifdef CONFIG_FB_SIS_315
- static void
- sisfb_fixup_SR11(struct sis_video_info *ivideo)
- {
- u8 tmpreg;
- if(ivideo->chip >= SIS_661) {
- inSISIDXREG(SISSR,0x11,tmpreg);
- if(tmpreg & 0x20) {
- inSISIDXREG(SISSR,0x3e,tmpreg);
- tmpreg = (tmpreg + 1) & 0xff;
- outSISIDXREG(SISSR,0x3e,tmpreg);
- inSISIDXREG(SISSR,0x11,tmpreg);
- }
- if(tmpreg & 0xf0) {
- andSISIDXREG(SISSR,0x11,0x0f);
- }
- }
- }
- #endif
- static void sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
- {
- if(val > 32) val = 32;
- if(val < -32) val = -32;
- ivideo->tvxpos = val;
- if(ivideo->sisfblocked) return;
- if(!ivideo->modechanged) return;
- if(ivideo->currentvbflags & CRT2_TV) {
- if(ivideo->vbflags & VB_CHRONTEL) {
- int x = ivideo->tvx;
- switch(ivideo->chronteltype) {
- case 1:
- x += val;
- if(x < 0) x = 0;
- outSISIDXREG(SISSR,0x05,0x86);
- SiS_SetCH700x(&ivideo->SiS_Pr, (((x & 0xff) << 8) | 0x0a));
- SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, (((x & 0x0100) << 1) | 0x08),0xFD);
- break;
- case 2:
- /* Not supported by hardware */
- break;
- }
- } else if(ivideo->vbflags & VB_SISBRIDGE) {
- u8 p2_1f,p2_20,p2_2b,p2_42,p2_43;
- unsigned short temp;
- p2_1f = ivideo->p2_1f;
- p2_20 = ivideo->p2_20;
- p2_2b = ivideo->p2_2b;
- p2_42 = ivideo->p2_42;
- p2_43 = ivideo->p2_43;
- temp = p2_1f | ((p2_20 & 0xf0) << 4);
- temp += (val * 2);
- p2_1f = temp & 0xff;
- p2_20 = (temp & 0xf00) >> 4;
- p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f;
- temp = p2_43 | ((p2_42 & 0xf0) << 4);
- temp += (val * 2);
- p2_43 = temp & 0xff;
- p2_42 = (temp & 0xf00) >> 4;
- outSISIDXREG(SISPART2,0x1f,p2_1f);
- setSISIDXREG(SISPART2,0x20,0x0F,p2_20);
- setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b);
- setSISIDXREG(SISPART2,0x42,0x0F,p2_42);
- outSISIDXREG(SISPART2,0x43,p2_43);
- }
- }
- }
- static void sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
- {
- if(val > 32) val = 32;
- if(val < -32) val = -32;
- ivideo->tvypos = val;
- if(ivideo->sisfblocked) return;
- if(!ivideo->modechanged) return;
- if(ivideo->currentvbflags & CRT2_TV) {
- if(ivideo->vbflags & VB_CHRONTEL) {
- int y = ivideo->tvy;
- switch(ivideo->chronteltype) {
- case 1:
- y -= val;
- if(y < 0) y = 0;
- outSISIDXREG(SISSR,0x05,0x86);
- SiS_SetCH700x(&ivideo->SiS_Pr, (((y & 0xff) << 8) | 0x0b));
- SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, ((y & 0x0100) | 0x08),0xFE);
- break;
- case 2:
- /* Not supported by hardware */
- break;
- }
- } else if(ivideo->vbflags & VB_SISBRIDGE) {
- char p2_01, p2_02;
- val /= 2;
- p2_01 = ivideo->p2_01;
- p2_02 = ivideo->p2_02;
- p2_01 += val;
- p2_02 += val;
- while((p2_01 <= 0) || (p2_02 <= 0)) {
- p2_01 += 2;
- p2_02 += 2;
- }
- outSISIDXREG(SISPART2,0x01,p2_01);
- outSISIDXREG(SISPART2,0x02,p2_02);
- }
- }
- }
- static void
- sisfb_post_setmode(struct sis_video_info *ivideo)
- {
- BOOLEAN crt1isoff = FALSE;
- BOOLEAN doit = TRUE;
- #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
- u8 reg;
- #endif
- #ifdef CONFIG_FB_SIS_315
- u8 reg1;
- #endif
- outSISIDXREG(SISSR,0x05,0x86);
- #ifdef CONFIG_FB_SIS_315
- sisfb_fixup_SR11(ivideo);
- #endif
- /* Now we actually HAVE changed the display mode */
- ivideo->modechanged = 1;
- /* We can't switch off CRT1 if bridge is in slave mode */
- if(ivideo->vbflags & VB_VIDEOBRIDGE) {
- if(sisfb_bridgeisslave(ivideo)) doit = FALSE;
- } else ivideo->sisfb_crt1off = 0;
- #ifdef CONFIG_FB_SIS_300
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- if((ivideo->sisfb_crt1off) && (doit)) {
- crt1isoff = TRUE;
- reg = 0x00;
- } else {
- crt1isoff = FALSE;
- reg = 0x80;
- }
- setSISIDXREG(SISCR, 0x17, 0x7f, reg);
- }
- #endif
- #ifdef CONFIG_FB_SIS_315
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- if((ivideo->sisfb_crt1off) && (doit)) {
- crt1isoff = TRUE;
- reg = 0x40;
- reg1 = 0xc0;
- } else {
- crt1isoff = FALSE;
- reg = 0x00;
- reg1 = 0x00;
- }
- setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
- setSISIDXREG(SISSR, 0x1f, ~0xc0, reg1);
- }
- #endif
- if(crt1isoff) {
- ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1;
- ivideo->currentvbflags |= VB_SINGLE_MODE;
- } else {
- ivideo->currentvbflags |= VB_DISPTYPE_CRT1;
- if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) {
- ivideo->currentvbflags |= VB_MIRROR_MODE;
- } else {
- ivideo->currentvbflags |= VB_SINGLE_MODE;
- }
- }
- andSISIDXREG(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
- if(ivideo->currentvbflags & CRT2_TV) {
- if(ivideo->vbflags & VB_SISBRIDGE) {
- inSISIDXREG(SISPART2,0x1f,ivideo->p2_1f);
- inSISIDXREG(SISPART2,0x20,ivideo->p2_20);
- inSISIDXREG(SISPART2,0x2b,ivideo->p2_2b);
- inSISIDXREG(SISPART2,0x42,ivideo->p2_42);
- inSISIDXREG(SISPART2,0x43,ivideo->p2_43);
- inSISIDXREG(SISPART2,0x01,ivideo->p2_01);
- inSISIDXREG(SISPART2,0x02,ivideo->p2_02);
- } else if(ivideo->vbflags & VB_CHRONTEL) {
- if(ivideo->chronteltype == 1) {
- ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
- ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8);
- ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b);
- ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8);
- }
- }
- }
- if(ivideo->tvxpos) {
- sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos);
- }
- if(ivideo->tvypos) {
- sisfb_set_TVyposoffset(ivideo, ivideo->tvypos);
- }
- if((ivideo->currentvbflags & CRT2_TV) && (ivideo->vbflags & VB_301)) { /* Set filter for SiS301 */
- unsigned char filter_tb = 0;
- switch (ivideo->video_width) {
- case 320:
- filter_tb = (ivideo->vbflags & TV_NTSC) ? 4 : 12;
- break;
- case 640:
- filter_tb = (ivideo->vbflags & TV_NTSC) ? 5 : 13;
- break;
- case 720:
- filter_tb = (ivideo->vbflags & TV_NTSC) ? 6 : 14;
- break;
- case 400:
- case 800:
- filter_tb = (ivideo->vbflags & TV_NTSC) ? 7 : 15;
- break;
- default:
- ivideo->sisfb_filter = -1;
- break;
- }
- orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01);
- if(ivideo->vbflags & TV_NTSC) {
- andSISIDXREG(SISPART2, 0x3a, 0x1f);
- if (ivideo->vbflags & TV_SVIDEO) {
- andSISIDXREG(SISPART2, 0x30, 0xdf);
- } else if (ivideo->vbflags & TV_AVIDEO) {
- orSISIDXREG(SISPART2, 0x30, 0x20);
- switch (ivideo->video_width) {
- case 640:
- outSISIDXREG(SISPART2, 0x35, 0xEB);
- outSISIDXREG(SISPART2, 0x36, 0x04);
- outSISIDXREG(SISPART2, 0x37, 0x25);
- outSISIDXREG(SISPART2, 0x38, 0x18);
- break;
- case 720:
- outSISIDXREG(SISPART2, 0x35, 0xEE);
- outSISIDXREG(SISPART2, 0x36, 0x0C);
- outSISIDXREG(SISPART2, 0x37, 0x22);
- outSISIDXREG(SISPART2, 0x38, 0x08);
- break;
- case 400:
- case 800:
- outSISIDXREG(SISPART2, 0x35, 0xEB);
- outSISIDXREG(SISPART2, 0x36, 0x15);
- outSISIDXREG(SISPART2, 0x37, 0x25);
- outSISIDXREG(SISPART2, 0x38, 0xF6);
- break;
- }
- }
- } else if(ivideo->vbflags & TV_PAL) {
- andSISIDXREG(SISPART2, 0x3A, 0x1F);
- if (ivideo->vbflags & TV_SVIDEO) {
- andSISIDXREG(SISPART2, 0x30, 0xDF);
- } else if (ivideo->vbflags & TV_AVIDEO) {
- orSISIDXREG(SISPART2, 0x30, 0x20);
- switch (ivideo->video_width) {
- case 640:
- outSISIDXREG(SISPART2, 0x35, 0xF1);
- outSISIDXREG(SISPART2, 0x36, 0xF7);
- outSISIDXREG(SISPART2, 0x37, 0x1F);
- outSISIDXREG(SISPART2, 0x38, 0x32);
- break;
- case 720:
- outSISIDXREG(SISPART2, 0x35, 0xF3);
- outSISIDXREG(SISPART2, 0x36, 0x00);
- outSISIDXREG(SISPART2, 0x37, 0x1D);
- outSISIDXREG(SISPART2, 0x38, 0x20);
- break;
- case 400:
- case 800:
- outSISIDXREG(SISPART2, 0x35, 0xFC);
- outSISIDXREG(SISPART2, 0x36, 0xFB);
- outSISIDXREG(SISPART2, 0x37, 0x14);
- outSISIDXREG(SISPART2, 0x38, 0x2A);
- break;
- }
- }
- }
- if((ivideo->sisfb_filter >= 0) && (ivideo->sisfb_filter <= 7)) {
- outSISIDXREG(SISPART2,0x35,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][0]));
- outSISIDXREG(SISPART2,0x36,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][1]));
- outSISIDXREG(SISPART2,0x37,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][2]));
- outSISIDXREG(SISPART2,0x38,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][3]));
- }
-
- }
- }
- #ifndef MODULE
- SISINITSTATIC int __init sisfb_setup(char *options)
- {
- char *this_opt;
-
- sisfb_setdefaultparms();
- printk(KERN_DEBUG "sisfb: Options %s\n", options);
- if(!options || !(*options)) {
- return 0;
- }
- while((this_opt = strsep(&options, ",")) != NULL) {
- if(!(*this_opt)) continue;
- if(!strnicmp(this_opt, "off", 3)) {
- sisfb_off = 1;
- } else if(!strnicmp(this_opt, "forcecrt2type:", 14)) {
- /* Need to check crt2 type first for fstn/dstn */
- sisfb_search_crt2type(this_opt + 14);
- } else if(!strnicmp(this_opt, "tvmode:",7)) {
- sisfb_search_tvstd(this_opt + 7);
- } else if(!strnicmp(this_opt, "tvstandard:",11)) {
- sisfb_search_tvstd(this_opt + 7);
- } else if(!strnicmp(this_opt, "mode:", 5)) {
- sisfb_search_mode(this_opt + 5, FALSE);
- } else if(!strnicmp(this_opt, "vesa:", 5)) {
- sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), FALSE);
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- } else if(!strnicmp(this_opt, "inverse", 7)) {
- sisfb_inverse = 1;
- /* fb_invert_cmaps(); */
- } else if(!strnicmp(this_opt, "font:", 5)) {
- if(strlen(this_opt + 5) < 40) {
- strncpy(sisfb_fontname, this_opt + 5, sizeof(sisfb_fontname) - 1);
- sisfb_fontname[sizeof(sisfb_fontname) - 1] = '\0';
- }
- #endif
- } else if(!strnicmp(this_opt, "rate:", 5)) {
- sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
- } else if(!strnicmp(this_opt, "filter:", 7)) {
- sisfb_filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
- } else if(!strnicmp(this_opt, "forcecrt1:", 10)) {
- sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
- } else if(!strnicmp(this_opt, "mem:",4)) {
- sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
- } else if(!strnicmp(this_opt, "pdc:", 4)) {
- sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
- } else if(!strnicmp(this_opt, "pdc1:", 5)) {
- sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
- } else if(!strnicmp(this_opt, "noaccel", 7)) {
- sisfb_accel = 0;
- } else if(!strnicmp(this_opt, "accel", 5)) {
- sisfb_accel = -1;
- } else if(!strnicmp(this_opt, "noypan", 6)) {
- sisfb_ypan = 0;
- } else if(!strnicmp(this_opt, "ypan", 4)) {
- sisfb_ypan = -1;
- } else if(!strnicmp(this_opt, "nomax", 5)) {
- sisfb_max = 0;
- } else if(!strnicmp(this_opt, "max", 3)) {
- sisfb_max = -1;
- } else if(!strnicmp(this_opt, "userom:", 7)) {
- sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
- } else if(!strnicmp(this_opt, "useoem:", 7)) {
- sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
- } else if(!strnicmp(this_opt, "nocrt2rate", 10)) {
- sisfb_nocrt2rate = 1;
- } else if(!strnicmp(this_opt, "scalelcd:", 9)) {
- unsigned long temp = 2;
- temp = simple_strtoul(this_opt + 9, NULL, 0);
- if((temp == 0) || (temp == 1)) {
- sisfb_scalelcd = temp ^ 1;
- }
- } else if(!strnicmp(this_opt, "tvxposoffset:", 13)) {
- int temp = 0;
- temp = (int)simple_strtol(this_opt + 13, NULL, 0);
- if((temp >= -32) && (temp <= 32)) {
- sisfb_tvxposoffset = temp;
- }
- } else if(!strnicmp(this_opt, "tvyposoffset:", 13)) {
- int temp = 0;
- temp = (int)simple_strtol(this_opt + 13, NULL, 0);
- if((temp >= -32) && (temp <= 32)) {
- sisfb_tvyposoffset = temp;
- }
- } else if(!strnicmp(this_opt, "specialtiming:", 14)) {
- sisfb_search_specialtiming(this_opt + 14);
- } else if(!strnicmp(this_opt, "lvdshl:", 7)) {
- int temp = 4;
- temp = simple_strtoul(this_opt + 7, NULL, 0);
- if((temp >= 0) && (temp <= 3)) {
- sisfb_lvdshl = temp;
- }
- } else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
- sisfb_search_mode(this_opt, TRUE);
- #if !defined(__i386__) && !defined(__x86_64__)
- } else if(!strnicmp(this_opt, "resetcard", 9)) {
- sisfb_resetcard = 1;
- } else if(!strnicmp(this_opt, "videoram:", 9)) {
- sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
- #endif
- } else {
- printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt);
- }
- }
- return 0;
- }
- #endif
- static UCHAR * __devinit sis_find_rom(struct pci_dev *pdev)
- {
- struct sis_video_info *ivideo = pci_get_drvdata(pdev);
- USHORT pciid;
- int romptr;
- UCHAR *myrombase;
- u32 temp;
- SIS_IOTYPE1 *rom_base, *rom;
- if(!(myrombase = vmalloc(65536))) return NULL;
- #if defined(__i386__) || defined(__x86_64__)
- for(temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
- rom_base = ioremap(temp, 0x10000);
- if(!rom_base) continue;
- if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa)) {
- iounmap(rom_base);
- continue;
- }
- romptr = (unsigned short)(readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
- if(romptr > (0x10000 - 8)) {
- iounmap(rom_base);
- continue;
- }
- rom = rom_base + romptr;
- if((readb(rom) != 'P') || (readb(rom + 1) != 'C') ||
- (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R')) {
- iounmap(rom_base);
- continue;
- }
- pciid = readb(rom + 4) | (readb(rom + 5) << 8);
- if(pciid != 0x1039) {
- iounmap(rom_base);
- continue;
- }
- pciid = readb(rom + 6) | (readb(rom + 7) << 8);
- if(pciid == ivideo->chip_id) {
- memcpy_fromio(myrombase, rom_base, 65536);
- iounmap(rom_base);
- return myrombase;
- }
- iounmap(rom_base);
- }
- #else
- pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &temp);
- pci_write_config_dword(pdev, PCI_ROM_ADDRESS,
- (ivideo->video_base & PCI_ROM_ADDRESS_MASK) | PCI_ROM_ADDRESS_ENABLE);
- rom_base = ioremap(ivideo->video_base, 65536);
- if(rom_base) {
- if((readb(rom_base) == 0x55) && (readb(rom_base + 1) == 0xaa)) {
- romptr = (u16)(readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
- if(romptr <= (0x10000 - 8)) {
- rom = rom_base + romptr;
- if((readb(rom) == 'P') && (readb(rom + 1) == 'C') &&
- (readb(rom + 2) == 'I') && (readb(rom + 3) == 'R')) {
- pciid = readb(rom + 4) | (readb(rom + 5) << 8);
- if(pciid == 0x1039) {
- pciid = readb(rom + 6) | (readb(rom + 7) << 8);
- if(pciid == ivideo->chip_id) {
- memcpy_fromio(myrombase, rom_base, 65536);
- iounmap(rom_base);
- pci_write_config_dword(pdev, PCI_ROM_ADDRESS, temp);
- return myrombase;
- }
- }
- }
- }
- }
- iounmap(rom_base);
- }
- pci_write_config_dword(pdev, PCI_ROM_ADDRESS, temp);
- #endif
- vfree(myrombase);
- return NULL;
- }
- #ifdef CONFIG_FB_SIS_300
- static int __devinit
- sisfb_chkbuswidth300(struct pci_dev *pdev, SIS_IOTYPE1 *FBAddress)
- {
- struct sis_video_info *ivideo = pci_get_drvdata(pdev);
- int i, j;
- USHORT temp;
- UCHAR reg;
- andSISIDXREG(SISSR,0x15,0xFB);
- orSISIDXREG(SISSR,0x15,0x04);
- outSISIDXREG(SISSR,0x13,0x00);
- outSISIDXREG(SISSR,0x14,0xBF);
- for(i=0; i<2; i++) {
- temp = 0x1234;
- for(j=0; j<4; j++) {
- writew(temp, FBAddress);
- if(readw(FBAddress) == temp) break;
- orSISIDXREG(SISSR,0x3c,0x01);
- inSISIDXREG(SISSR,0x05,reg);
- inSISIDXREG(SISSR,0x05,reg);
- andSISIDXREG(SISSR,0x3c,0xfe);
- inSISIDXREG(SISSR,0x05,reg);
- inSISIDXREG(SISSR,0x05,reg);
- temp++;
- }
- }
- writel(0x01234567L, FBAddress);
- writel(0x456789ABL, (FBAddress+4));
- writel(0x89ABCDEFL, (FBAddress+8));
- writel(0xCDEF0123L, (FBAddress+12));
- inSISIDXREG(SISSR,0x3b,reg);
- if(reg & 0x01) {
- if(readl((FBAddress+12)) == 0xCDEF0123L) return(4); /* Channel A 128bit */
- }
- if(readl((FBAddress+4)) == 0x456789ABL) return(2); /* Channel B 64bit */
- return(1); /* 32bit */
- }
- static void __devinit
- sisfb_setramsize300(struct pci_dev *pdev)
- {
- struct sis_video_info *ivideo = pci_get_drvdata(pdev);
- SIS_IOTYPE1 *FBAddr = ivideo->video_vbase;
- SIS_IOTYPE1 *Addr;
- USHORT sr13, sr14=0, buswidth, Done, data, TotalCapacity, PhysicalAdrOtherPage=0;
- int PseudoRankCapacity, PseudoTotalCapacity, PseudoAdrPinCount;
- int RankCapacity, AdrPinCount, BankNumHigh, BankNumMid, MB2Bank;
- int PageCapacity, PhysicalAdrHigh, PhysicalAdrHalfPage, i, j, k;
- const USHORT SiS_DRAMType[17][5] = {
- {0x0C,0x0A,0x02,0x40,0x39},
- {0x0D,0x0A,0x01,0x40,0x48},
- {0x0C,0x09,0x02,0x20,0x35},
- {0x0D,0x09,0x01,0x20,0x44},
- {0x0C,0x08,0x02,0x10,0x31},
- {0x0D,0x08,0x01,0x10,0x40},
- {0x0C,0x0A,0x01,0x20,0x34},
- {0x0C,0x09,0x01,0x08,0x32},
- {0x0B,0x08,0x02,0x08,0x21},
- {0x0C,0x08,0x01,0x08,0x30},
- {0x0A,0x08,0x02,0x04,0x11},
- {0x0B,0x0A,0x01,0x10,0x28},
- {0x09,0x08,0x02,0x02,0x01},
- {0x0B,0x09,0x01,0x08,0x24},
- {0x0B,0x08,0x01,0x04,0x20},
- {0x0A,0x08,0x01,0x02,0x10},
- {0x09,0x08,0x01,0x01,0x00}
- };
- buswidth = sisfb_chkbuswidth300(pdev, FBAddr);
- MB2Bank = 16;
- Done = 0;
- for(i = 6; i >= 0; i--) {
- if(Done) break;
- PseudoRankCapacity = 1 << i;
- for(j = 4; j >= 1; j--) {
- if(Done) break;
- PseudoTotalCapacity = PseudoRankCapacity * j;
- PseudoAdrPinCount = 15 - j;
- if(PseudoTotalCapacity <= 64) {
- for(k = 0; k <= 16; k++) {
- if(Done) break;
- RankCapacity = buswidth * SiS_DRAMType[k][3];
- AdrPinCount = SiS_DRAMType[k][2] + SiS_DRAMType[k][0];
- if(RankCapacity == PseudoRankCapacity)
- if(AdrPinCount <= PseudoAdrPinCount) {
- if(j == 3) { /* Rank No */
- BankNumHigh = RankCapacity * MB2Bank * 3 - 1;
- BankNumMid = RankCapacity * MB2Bank * 1 - 1;
- } else {
- BankNumHigh = RankCapacity * MB2Bank * j - 1;
- BankNumMid = RankCapacity * MB2Bank * j / 2 - 1;
- }
- PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
- PhysicalAdrHigh = BankNumHigh;
- PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
- PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
- /* Write data */
- andSISIDXREG(SISSR,0x15,0xFB); /* Test */
- orSISIDXREG(SISSR,0x15,0x04); /* Test */
- TotalCapacity = SiS_DRAMType[k][3] * buswidth;
- sr13 = SiS_DRAMType[k][4];
- if(buswidth == 4) sr14 = (TotalCapacity - 1) | 0x80;
- if(buswidth == 2) sr14 = (TotalCapacity - 1) | 0x40;
- if(buswidth == 1) sr14 = (TotalCapacity - 1) | 0x00;
- outSISIDXREG(SISSR,0x13,sr13);
- outSISIDXREG(SISSR,0x14,sr14);
- Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHigh;
- /* *((USHORT *)(Addr)) = (USHORT)PhysicalAdrHigh; */
- writew(((USHORT)PhysicalAdrHigh), Addr);
- Addr = FBAddr + BankNumMid * 64 * 1024 + PhysicalAdrHigh;
- /* *((USHORT *)(Addr)) = (USHORT)BankNumMid; */
- writew(((USHORT)BankNumMid), Addr);
- Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHalfPage;
- /* *((USHORT *)(Addr)) = (USHORT)PhysicalAdrHalfPage; */
- writew(((USHORT)PhysicalAdrHalfPage), Addr);
- Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrOtherPage;
- /* *((USHORT *)(Addr)) = PhysicalAdrOtherPage; */
- writew(((USHORT)PhysicalAdrOtherPage), Addr);
- /* Read data */
- Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHigh;
- data = readw(Addr); /* *((USHORT *)(Addr)); */
- if(data == PhysicalAdrHigh) Done = 1;
- } /* if */
- } /* for k */
- } /* if */
- } /* for j */
- } /* for i */
- }
- static void __devinit sisfb_post_sis300(struct pci_dev *pdev)
- {
- struct sis_video_info *ivideo = pci_get_drvdata(pdev);
- u8 reg, v1, v2, v3, v4, v5, v6, v7, v8;
- u16 index, rindex, memtype = 0;
- outSISIDXREG(SISSR,0x05,0x86);
- if(ivideo->sishw_ext.UseROM) {
- if(ivideo->sishw_ext.pjVirtualRomBase[0x52] & 0x80) {
- memtype = ivideo->sishw_ext.pjVirtualRomBase[0x52];
- } else {
- inSISIDXREG(SISSR,0x3a,memtype);
- }
- memtype &= 0x07;
- }
- if(ivideo->revision_id <= 0x13) {
- v1 = 0x44; v2 = 0x42; v3 = 0x80;
- v4 = 0x44; v5 = 0x42; v6 = 0x80;
- } else {
- v1 = 0x68; v2 = 0x43; v3 = 0x80; /* Assume 125Mhz MCLK */
- v4 = 0x68; v5 = 0x43; v6 = 0x80; /* Assume 125Mhz ECLK */
- if(ivideo->sishw_ext.UseROM) {
- index = memtype * 5;
- rindex = index + 0x54;
- v1 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- v3 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- rindex = index + 0x7c;
- v4 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- v5 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- v6 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- }
- }
- outSISIDXREG(SISSR,0x28,v1);
- outSISIDXREG(SISSR,0x29,v2);
- outSISIDXREG(SISSR,0x2a,v3);
- outSISIDXREG(SISSR,0x2e,v4);
- outSISIDXREG(SISSR,0x2f,v5);
- outSISIDXREG(SISSR,0x30,v6);
- v1 = 0x10;
- if(ivideo->sishw_ext.UseROM) v1 = ivideo->sishw_ext.pjVirtualRomBase[0xa4];
- outSISIDXREG(SISSR,0x07,v1); /* DAC speed */
- outSISIDXREG(SISSR,0x11,0x0f); /* DDC, power save */
- v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
- v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
- if(ivideo->sishw_ext.UseROM) {
- memtype += 0xa5;
- v1 = ivideo->sishw_ext.pjVirtualRomBase[memtype];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 8];
- v3 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 16];
- v4 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 24];
- v5 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 32];
- v6 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 40];
- v7 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 48];
- v8 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 56];
- }
- if(ivideo->revision_id >= 0x80) v3 &= 0xfd;
- outSISIDXREG(SISSR,0x15,v1); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
- outSISIDXREG(SISSR,0x16,v2);
- outSISIDXREG(SISSR,0x17,v3);
- outSISIDXREG(SISSR,0x18,v4);
- outSISIDXREG(SISSR,0x19,v5);
- outSISIDXREG(SISSR,0x1a,v6);
- outSISIDXREG(SISSR,0x1b,v7);
- outSISIDXREG(SISSR,0x1c,v8); /* ---- */
- andSISIDXREG(SISSR,0x15,0xfb);
- orSISIDXREG(SISSR,0x15,0x04);
- if(ivideo->sishw_ext.UseROM) {
- if(ivideo->sishw_ext.pjVirtualRomBase[0x53] & 0x02) {
- orSISIDXREG(SISSR,0x19,0x20);
- }
- }
- v1 = 0x04; /* DAC pedestal (BIOS 0xe5) */
- if(ivideo->revision_id >= 0x80) v1 |= 0x01;
- outSISIDXREG(SISSR,0x1f,v1);
- outSISIDXREG(SISSR,0x20,0xa0); /* linear & relocated io */
- v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xe8];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[0xe9];
- v3 = ivideo->sishw_ext.pjVirtualRomBase[0xea];
- }
- outSISIDXREG(SISSR,0x23,v1);
- outSISIDXREG(SISSR,0x24,v2);
- outSISIDXREG(SISSR,0x25,v3);
- outSISIDXREG(SISSR,0x21,0x84);
- outSISIDXREG(SISSR,0x22,0x00);
- outSISIDXREG(SISCR,0x37,0x00);
- orSISIDXREG(SISPART1,0x24,0x01); /* unlock crt2 */
- outSISIDXREG(SISPART1,0x00,0x00);
- v1 = 0x40; v2 = 0x11;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xec];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[0xeb];
- }
- outSISIDXREG(SISPART1,0x02,v1);
- if(ivideo->revision_id >= 0x80) v2 &= ~0x01;
- inSISIDXREG(SISPART4,0x00,reg);
- if((reg == 1) || (reg == 2)) {
- outSISIDXREG(SISCR,0x37,0x02);
- outSISIDXREG(SISPART2,0x00,0x1c);
- v4 = 0x00; v5 = 0x00; v6 = 0x10;
- if(ivideo->sishw_ext.UseROM) {
- v4 = ivideo->sishw_ext.pjVirtualRomBase[0xf5];
- v5 = ivideo->sishw_ext.pjVirtualRomBase[0xf6];
- v6 = ivideo->sishw_ext.pjVirtualRomBase[0xf7];
- }
- outSISIDXREG(SISPART4,0x0d,v4);
- outSISIDXREG(SISPART4,0x0e,v5);
- outSISIDXREG(SISPART4,0x10,v6);
- outSISIDXREG(SISPART4,0x0f,0x3f);
- inSISIDXREG(SISPART4,0x01,reg);
- if(reg >= 0xb0) {
- inSISIDXREG(SISPART4,0x23,reg);
- reg &= 0x20;
- reg <<= 1;
- outSISIDXREG(SISPART4,0x23,reg);
- }
- } else {
- v2 &= ~0x10;
- }
- outSISIDXREG(SISSR,0x32,v2);
- andSISIDXREG(SISPART1,0x24,0xfe); /* Lock CRT2 */
- inSISIDXREG(SISSR,0x16,reg);
- reg &= 0xc3;
- outSISIDXREG(SISCR,0x35,reg);
- outSISIDXREG(SISCR,0x83,0x00);
- #if !defined(__i386__) && !defined(__x86_64__)
- if(sisfb_videoram) {
- outSISIDXREG(SISSR,0x13,0x28); /* ? */
- reg = ((sisfb_videoram >> 10) - 1) | 0x40;
- outSISIDXREG(SISSR,0x14,reg);
- } else {
- #endif
- /* Need to map max FB size for finding out about RAM size */
- ivideo->video_vbase = ioremap(ivideo->video_base, 0x4000000);
- if(ivideo->video_vbase) {
- sisfb_setramsize300(pdev);
- iounmap(ivideo->video_vbase);
- } else {
- printk(KERN_DEBUG "sisfb: Failed to map memory for size detection, assuming 8MB\n");
- outSISIDXREG(SISSR,0x13,0x28); /* ? */
- outSISIDXREG(SISSR,0x14,0x47); /* 8MB, 64bit default */
- }
- #if !defined(__i386__) && !defined(__x86_64__)
- }
- #endif
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xe6];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[0xe7];
- } else {
- inSISIDXREG(SISSR,0x3a,reg);
- if((reg & 0x30) == 0x30) {
- v1 = 0x04; /* PCI */
- v2 = 0x92;
- } else {
- v1 = 0x14; /* AGP */
- v2 = 0xb2;
- }
- }
- outSISIDXREG(SISSR,0x21,v1);
- outSISIDXREG(SISSR,0x22,v2);
- }
- #endif
- #ifdef CONFIG_FB_SIS_315
- static void __devinit sisfb_post_sis315330(struct pci_dev *pdev)
- {
- #ifdef YET_TO_BE_DONE
- struct sis_video_info *ivideo = pci_get_drvdata(pdev);
- u8 reg, v1, v2, v3, v4, v5, v6, v7, v8;
- u16 index, rindex, memtype = 0;
- u32 reg1_32, reg2_32, reg3_32;
- int i;
- /* Unlock */
- /* outSISIDXREG(0x3c4,0x05,0x86); */
- outSISIDXREG(SISSR,0x05,0x86);
- /* Enable relocated i/o ports */
- /* setSISIDXREG(0x3c4,0x20,~0x10,0x20); */
- setSISIDXREG(SISSR,0x20,~0x10,0x20);
- /* Clear regs */
- for(i = 0; i < 0x22; i++) {
- outSISIDXREG(SISSR,(0x06 + i),0x00);
- }
- v1 = 0x0d;
- if( is 330) v1 = 0x0b;
- for(i = 0; i < v1; i++) {
- outSISIDXREG(SISSR,(0x31 + i),0x00);
- }
- for(i = 0; i < 0x10; i++) {
- outSISIDXREG(SISCR,(0x30 + i),0x00);
- }
- /* Reset clocks */
- reg = inSISREG(SISMISCR);
- outSISIDXREG(SISSR,0x28,0x81);
- outSISIDXREG(SISSR,0x2A,0x00);
- outSISIDXREG(SISSR,0x29,0xE1);
- outSISREG(SISMISCW,(reg | 0x0c));
- outSISIDXREG(SISSR,0x2B,0x81);
- outSISIDXREG(SISSR,0x2D,0x00);
- outSISIDXREG(SISSR,0x2C,0xE1);
- outSISIDXREG(SISSR,0x2E,0x81);
- outSISIDXREG(SISSR,0x30,0x00);
- outSISIDXREG(SISSR,0x2F,0xE1);
- SiS_DDC2Delay(....);
- outSISREG(SISMISCW,reg);
- /* Get memory type */
- if(ivideo->sishw_ext.UseROM) {
- if(ivideo->sishw_ext.pjVirtualRomBase[0x52] & 0x80)) {
- memtype = ivideo->sishw_ext.pjVirtualRomBase[0x52];
- } else {
- inSISIDXREG(SISSR,0x3a,memtype);
- }
- memtype &= 0x03;
- if( is 330 ) {
- if(memtype <= 1) memtype = 0;
- else {
- inSISIDXREG(SISCR,0x5F,reg);
- reg &= 0x30;
- switch(reg) {
- case 0x00: memtype = 1; break;
- case 0x10: memtype = 3; break;
- case 0x20: memtype = 3; break;
- default: memtype = 2;
- }
- }
- }
- }
- /* Set clocks */
- v1 = 0x3b; v2 = 0x22; v3 = 0x01; /* Assume 143Mhz MCLK */
- v4 = 0x5c; v5 = 0x23; v6 = 0x01; /* Assume 166Mhz ECLK */
- if(ivideo->sishw_ext.UseROM) {
- index = memtype * 5;
- rindex = index + 0x54;
- v1 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- v3 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- rindex = index + 0x68;
- v4 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- v5 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- v6 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
- }
- outSISIDXREG(SISSR,0x28,v1);
- outSISIDXREG(SISSR,0x29,v2);
- outSISIDXREG(SISSR,0x2a,v3);
- if( is 330 ) {
- inSISIDXREG(SISSR,0x3a,reg);
- reg &= 0x03;
- if(reg >= 2) {
- ...
- }
- }
- outSISIDXREG(SISSR,0x2e,v4);
- outSISIDXREG(SISSR,0x2f,v5);
- outSISIDXREG(SISSR,0x30,v6);
- /* End of comp with 330 */
- v1 = 0x18;
- if(ivideo->sishw_ext.UseROM) v1 = ivideo->sishw_ext.pjVirtualRomBase[0x7c];
- outSISIDXREG(SISSR,0x07,v1);
- outSISIDXREG(SISSR,0x11,0x0f);
- v1 = 0x00; v2 = 0x0f; v3 = 0xba; v4 = 0xa9;
- v5 = 0xa0; v6 = 0x00; v7 = 0x30;
- if(ivideo->sishw_ext.UseROM) {
- index = memtype + 0x7d;
- v1 = ivideo->sishw_ext.pjVirtualRomBase[index];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[index + 4];
- v3 = ivideo->sishw_ext.pjVirtualRomBase[index + 8];
- v4 = ivideo->sishw_ext.pjVirtualRomBase[index + 12];
- v5 = ivideo->sishw_ext.pjVirtualRomBase[index + 16];
- v6 = ivideo->sishw_ext.pjVirtualRomBase[index + 20];
- v7 = ivideo->sishw_ext.pjVirtualRomBase[index + 24];
- }
- outSISIDXREG(SISSR,0x15,v1); /* Ram type (assuming 0, BIOS 0x7d step 4) */
- outSISIDXREG(SISSR,0x16,v2);
- outSISIDXREG(SISSR,0x17,v3);
- outSISIDXREG(SISSR,0x18,v4);
- outSISIDXREG(SISSR,0x19,v5);
- outSISIDXREG(SISSR,0x1a,v6);
- outSISIDXREG(SISSR,0x1b,v7);
- outSISIDXREG(SISSR,0x1c,v8); /* ---- */
- v1 = 0x77; v2 = 0x77; v3 = 0x00; v4 = 0x5b; v5 = 0x00;
- if(ivideo->sishw_ext.UseROM) {
- index = memtype + 0xa2;
- v1 = ivideo->sishw_ext.pjVirtualRomBase[index];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[index + 4];
- v3 = ivideo->sishw_ext.pjVirtualRomBase[index + 8];
- v4 = ivideo->sishw_ext.pjVirtualRomBase[index + 12];
- v5 = ivideo->sishw_ext.pjVirtualRomBase[index + 16];
- }
- outSISIDXREG(SISCR,0x40,v1);
- outSISIDXREG(SISCR,0x41,v2);
- outSISIDXREG(SISCR,0x42,v3);
- outSISIDXREG(SISCR,0x43,v4);
- outSISIDXREG(SISCR,0x44,v5);
- if( is 330 ) {
- v1 = 0x;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xBA];
- }
- outSISIDXREG(SISCR,0x59,v1);
- v1 = 0x; v2 = 0x; v3 = 0x; v4 = 0x;
- v5 = 0x; v6 = 0x; v7 = 0x; v8 = 0x;
- if(ivideo->sishw_ext.UseROM) {
- index = memtype + 0xbe;
- v1 = ivideo->sishw_ext.pjVirtualRomBase[index];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[index + 4];
- v3 = ivideo->sishw_ext.pjVirtualRomBase[index + 8];
- v4 = ivideo->sishw_ext.pjVirtualRomBase[index + 12];
- v5 = ivideo->sishw_ext.pjVirtualRomBase[index + 16];
- v6 = ivideo->sishw_ext.pjVirtualRomBase[index + 20];
- v7 = ivideo->sishw_ext.pjVirtualRomBase[index + 24];
- v8 = ivideo->sishw_ext.pjVirtualRomBase[index + 28];
- }
- outSISIDXREG(SISCR,0x68,v1);
- outSISIDXREG(SISCR,0x69,v2);
- outSISIDXREG(SISCR,0x6a,v3);
- outSISIDXREG(SISCR,0x6b,v4);
- outSISIDXREG(SISCR,0x6c,v5);
- outSISIDXREG(SISCR,0x6d,v6);
- outSISIDXREG(SISCR,0x6e,v7);
- outSISIDXREG(SISCR,0x6f,v8);
- v1 = 0x20;
- inSISIDXREG(SISSR,0x3b,reg);
- if(!(reg & 0x04)) {
- inSISIDXREG(SISCR,0x5F,reg);
- reg &= 0x30;
- if(reg) v1 = 0x23;
- }
- outSISIDXREG(SISCR,0x48,v1);
- outSISIDXREG(SISCR,0x4c,0x20);
- xx= xxx();
- if(xx >= 1) {
- v1 = 0x;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xBA];
- }
- outSISIDXREG(SISCR,0x59,v1);
- }
- } else {
- outSISIDXREG(SISCR,0x48,0x23);
- andSISIDXREG(SISSR,0x16,0x0f);
- if(memtype <= 1) {
- orSISIDXREG(SISSR,0x16,0x80);
- } else {
- v1 = 0x0f;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0x81 + memtype];
- }
- if(!(v1 & 0x10)) v2 = 0xc0;
- else v2 = 0xd0;
- orSISIDXREG(SISSR,0x16,v2);
- andSISIDXREG(SISSR,0x16,0x0f);
- if(!(v1 & 0x10)) v2 = 0x80;
- else v2 = 0xA0;
- orSISIDXREG(SISSR,0x16,v2);
- }
- if(memtype >= 2) {
- const u8 sr3cseq1[] = { 0xc0,0xe0,0xf0,0xe0,0xf0,0xa0,0xb0,0xa0,0xb0,0x90,0xd0 };
- const u8 sr3cseq2[] = { 0xc0,0xa0,0xb0,0xa0,0xb0,0xe0,0xf0,0xa0,0xb0,0x90,0xd0 };
- for(i = 0; i < 11; i++) {
- outSISIDXREG(SISSR,0x3c,sr3cseq1[i]);
- }
- outSISIDXREG(SISSR,0x3d,0x00);
- outSISIDXREG(SISSR,0x3d,0x04);
- SiS_DDC2Delay(0x200);
- v1 = inSISIDXREG(SISCR,0xEC);
- v2 = inSISIDXREG(SISCR,0xED);
- reg1_32 = (v2 << 8) | v1;
- outSISIDXREG(SISSR,0x3D,0x00);
- for(i = 0; i < 11; i++) {
- outSISIDXREG(SISSR,0x3c,sr3cseq2[i]);
- }
- outSISIDXREG(SISSR,0x3d,0x00);
- outSISIDXREG(SISSR,0x3d,0x04);
- SiS_DDC2Delay(0x200);
- v1 = inSISIDXREG(SISCR,0xEC);
- v2 = inSISIDXREG(SISCR,0xED);
- reg2_32 = (v2 << 8) | v1;
- outSISIDXREG(SISSR,0x3D,0x00);
- reg3_32 = reg2_32 << 1;
- reg2_32 >>= 1;
- reg3_32 += reg2_32;
- v1 = 0x40;
- if(reg3_32 > reg1_32) v1 = 0x10;
- outSISIDXREG(SISCR,0x59,v1);
- }
- }
- v1 = 0x00;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0x99];
- }
- outSISIDXREG(SISSR,0x1f,v1);
- outSISIDXREG(SISSR,0x20,0x20);
- v1 = 0xf6; v2 = 0x0d; v3 = 0x33;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0x9c];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[0x9d];
- v3 = ivideo->sishw_ext.pjVirtualRomBase[0x9e];
- }
- outSISIDXREG(SISSR,0x23,v1);
- outSISIDXREG(SISSR,0x24,v2);
- outSISIDXREG(SISSR,0x25,v3);
- outSISIDXREG(SISSR,0x21,0x84);
- outSISIDXREG(SISSR,0x22,0x00);
- outSISIDXREG(SISSR,0x27,0x1f);
- v1 = 0x00; v2 = 0x00;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0x9F];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[0xA1];
- }
- outSISIDXREG(SISSR,0x31,v1);
- outSISIDXREG(SISSR,0x33,v2);
- v1 = 0x11;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xA0];
- }
- v2 = inSISIDXREG(SISPART4,0x00);
- if((v2 != 1) && (v2 != 2)) v1 &= 0xef;
- outSISIDXREG(SISSR,0x32,v1);
- /* AGP */
- pci_read_config_long(pdev, 0x50, ®1_32);
- reg1_32 >>= 20;
- reg1_32 &= 0x0f;
- if(reg1_32 == 1) {
- v1 = 0xAA; v2 = 0x33;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xF7];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[0x9E];
- }
- } else {
- v1 = 0x88; v2 = 0x03;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xF8];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[0xF6];
- }
- }
- outSISIDXREG(SISCR,0x49,v1);
- outSISIDXREG(SISSR,0x25,v2);
- v1 = inSISIDXREG(SISPART4,0x00);
- if((v1 == 1) || (v1 == 2)) {
- orSISIDXREG(SISPART1,0x2F,0x01); /* Unlock CRT2 */
- outSISIDXREG(SISPART1,0x00,0x00);
- v1 = 0x00;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xb6];
- }
- outSISIDXREG(SISPART1,0x02,v1);
- outSISIDXREG(SISPART1,0x2E,0x08);
- outSISIDXREG(SISPART2,0x00,0x1c);
- v1 = 0x40; v2 = 0x00; v3 = 0x80;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0xb7];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[0xb8];
- v3 = ivideo->sishw_ext.pjVirtualRomBase[0xbb];
- }
- outSISIDXREG(SISPART4,0x0d,v1);
- outSISIDXREG(SISPART4,0x0e,v2);
- outSISIDXREG(SISPART4,0x10,v3);
- outSISIDXREG(SISPART4,0x0F,0x3F);
- inSISIDXREG(SISPART4,0x01,reg);
- if(reg >= 0xb0) {
- inSISIDXREG(SISPART4,0x23,reg);
- reg &= 0x20;
- reg <<= 1;
- outSISIDXREG(SISPART4,0x23,reg);
- }
- }
- outSISIDXREG(SISCR,0x37,0x02); /* Why? */
- outSISIDXREG(SISCR,0x83,0x00);
- outSISIDXREG(SISCR,0x90,0x00);
- andSISIDXREG(SISSR,0x5B,0xDF);
- outSISIDXREG(SISVID,0x00,0x86);
- outSISIDXREG(SISVID,0x32,0x00);
- outSISIDXREG(SISVID,0x30,0x00);
- outSISIDXREG(SISVID,0x32,0x01);
- outSISIDXREG(SISVID,0x30,0x00);
- orSISIDXREG(SISCR,0x63,0x80);
- /* End of Init1 */
- /* Set Mode 0x2e */
- /* Ramsize */
- orSISIDXREG(SISSR,0x16,0x0f);
- orSISIDXREG(SISSR,0x18,0xA9);
- orSISIDXREG(SISSR,0x19,0xA0);
- orSISIDXREG(SISSR,0x1B,0x30);
- andSISIDXREG(SISSR,0x17,0xF8);
- orSISIDXREG(SISSR,0x19,0x03);
- andSIDIDXREG(SISSR,0x13,0x00);
- /* Need to map max FB size for finding out about RAM size */
- ivideo->video_vbase = ioremap(ivideo->video_base, 0x4000000);
- if(ivideo->video_vbase) {
- /* Find out about bus width */
- if(memtype <= 1) {
- outSISIDXREG(SISSR,0x14,0x02);
- andSISIDXREG(SISSR,0x16,0x0F);
- orSISIDXREG(SISSR,0x16,0x80);
- ...
- } else {
- ...
- }
- /* Find out about size */
- iounmap(ivideo->video_vbase);
- } else {
- printk(KERN_DEBUG "sisfb: Failed to map memory for size detection, assuming 8MB\n");
- outSISIDXREG(SISSR,0x14,0x??); /* 8MB, 64bit default */
- }
- /* AGP (Missing: Checks for VIA and AMD hosts) */
- v1 = 0xA5; v2 = 0xFB;
- if(ivideo->sishw_ext.UseROM) {
- v1 = ivideo->sishw_ext.pjVirtualRomBase[0x9A];
- v2 = ivideo->sishw_ext.pjVirtualRomBase[0x9B];
- }
- outSISIDXREG(SISSR,0x21,v1);
- outSISIDXREG(SISSR,0x22,v2);
- #endif
- return;
- }
- #endif
- static int __devinit sisfb_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
- {
- struct sisfb_chip_info *chipinfo = &sisfb_chip_info[ent->driver_data];
- struct sis_video_info *ivideo = NULL;
- struct fb_info *sis_fb_info = NULL;
- u16 reg16;
- u8 reg;
- int sisvga_enabled = 0, i;
- if(sisfb_off) return -ENXIO;
- #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3))
- sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev);
- if(!sis_fb_info) return -ENOMEM;
- #else
- sis_fb_info = kmalloc(sizeof(*sis_fb_info) + sizeof(*ivideo), GFP_KERNEL);
- if(!sis_fb_info) return -ENOMEM;
- memset(sis_fb_info, 0, sizeof(*sis_fb_info) + sizeof(*ivideo));
- sis_fb_info->par = ((char *)sis_fb_info + sizeof(*sis_fb_info));
- #endif
- ivideo = (struct sis_video_info *)sis_fb_info->par;
- ivideo->memyselfandi = sis_fb_info;
- if(card_list == NULL) {
- ivideo->cardnumber = 0;
- } else {
- struct sis_video_info *countvideo = card_list;
- ivideo->cardnumber = 1;
- while((countvideo = countvideo->next) != NULL) ivideo->cardnumber++;
- }
- strncpy(ivideo->myid, chipinfo->chip_name, 30);
- ivideo->warncount = 0;
- ivideo->chip_id = pdev->device;
- pci_read_config_byte(pdev, PCI_REVISION_ID, &ivideo->revision_id);
- ivideo->sishw_ext.jChipRevision = ivideo->revision_id;
- pci_read_config_word(pdev, PCI_COMMAND, ®16);
- sisvga_enabled = reg16 & 0x01;
- ivideo->pcibus = pdev->bus->number;
- ivideo->pcislot = PCI_SLOT(pdev->devfn);
- ivideo->pcifunc = PCI_FUNC(pdev->devfn);
- ivideo->subsysvendor = pdev->subsystem_vendor;
- ivideo->subsysdevice = pdev->subsystem_device;
- #ifndef MODULE
- if(sisfb_mode_idx == -1) {
- sisfb_get_vga_mode_from_kernel();
- }
- #endif
- ivideo->chip = chipinfo->chip;
- ivideo->sisvga_engine = chipinfo->vgaengine;
- ivideo->hwcursor_size = chipinfo->hwcursor_size;
- ivideo->CRT2_write_enable = chipinfo->CRT2_write_enable;
- ivideo->mni = chipinfo->mni;
- ivideo->detectedpdc = 0xff;
- ivideo->detectedpdca = 0xff;
- ivideo->detectedlcda = 0xff;
- ivideo->sisfb_thismonitor.datavalid = FALSE;
- ivideo->sisfb_parm_mem = sisfb_parm_mem;
- ivideo->sisfb_accel = sisfb_accel;
- ivideo->sisfb_ypan = sisfb_ypan;
- ivideo->sisfb_max = sisfb_max;
- ivideo->sisfb_userom = sisfb_userom;
- ivideo->sisfb_useoem = sisfb_useoem;
- ivideo->sisfb_mode_idx = sisfb_mode_idx;
- ivideo->sisfb_parm_rate = sisfb_parm_rate;
- ivideo->sisfb_crt1off = sisfb_crt1off;
- ivideo->sisfb_forcecrt1 = sisfb_forcecrt1;
- ivideo->sisfb_crt2type = sisfb_crt2type;
- ivideo->sisfb_crt2flags = sisfb_crt2flags;
- /* pdc(a), scalelcd, special timing, lvdshl handled below */
- ivideo->sisfb_dstn = sisfb_dstn;
- ivideo->sisfb_fstn = sisfb_fstn;
- ivideo->sisfb_tvplug = sisfb_tvplug;
- ivideo->sisfb_tvstd = sisfb_tvstd;
- ivideo->tvxpos = sisfb_tvxposoffset;
- ivideo->tvypos = sisfb_tvyposoffset;
- ivideo->sisfb_filter = sisfb_filter;
- ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate;
- #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
- ivideo->sisfb_inverse = sisfb_inverse;
- #endif
- ivideo->refresh_rate = 0;
- if(ivideo->sisfb_parm_rate != -1) {
- ivideo->refresh_rate = ivideo->sisfb_parm_rate;
- }
- ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd;
- ivideo->SiS_Pr.CenterScreen = -1;
- ivideo->SiS_Pr.SiS_CustomT = sisfb_specialtiming;
- ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl;
- ivideo->SiS_Pr.SiS_Backup70xx = 0xff;
- ivideo->SiS_Pr.SiS_CHOverScan = -1;
- ivideo->SiS_Pr.SiS_ChSW = FALSE;
- ivideo->SiS_Pr.SiS_UseLCDA = FALSE;
- ivideo->SiS_Pr.HaveEMI = FALSE;
- ivideo->SiS_Pr.HaveEMILCD = FALSE;
- ivideo->SiS_Pr.OverruleEMI = FALSE;
- ivideo->SiS_Pr.SiS_SensibleSR11 = FALSE;
- ivideo->SiS_Pr.SiS_MyCR63 = 0x63;
- ivideo->SiS_Pr.PDC = -1;
- ivideo->SiS_Pr.PDCA = -1;
- #ifdef CONFIG_FB_SIS_315
- if(ivideo->chip >= SIS_330) {
- ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
- if(ivideo->chip >= SIS_661) {
- ivideo->SiS_Pr.SiS_SensibleSR11 = TRUE;
- }
- }
- #endif
- memcpy(&ivideo->default_var, &my_default_var, sizeof(my_default_var));
- pci_set_drvdata(pdev, ivideo);
- /* Patch special cases */
- if((ivideo->nbridge = sisfb_get_northbridge(ivideo->chip))) {
- switch(ivideo->nbridge->device) {
- #ifdef CONFIG_FB_SIS_300
- case PCI_DEVICE_ID_SI_730:
- ivideo->chip = SIS_730;
- strcpy(ivideo->myid, "SiS 730");
- break;
- #endif
- #ifdef CONFIG_FB_SIS_315
- case PCI_DEVICE_ID_SI_651:
- /* ivideo->chip is ok */
- strcpy(ivideo->myid, "SiS 651");
- break;
- case PCI_DEVICE_ID_SI_740:
- ivideo->chip = SIS_740;
- strcpy(ivideo->myid, "SiS 740");
- break;
- case PCI_DEVICE_ID_SI_661:
- ivideo->chip = SIS_661;
- strcpy(ivideo->myid, "SiS 661");
- break;
- case PCI_DEVICE_ID_SI_741:
- ivideo->chip = SIS_741;
- strcpy(ivideo->myid, "SiS 741");
- break;
- case PCI_DEVICE_ID_SI_760:
- ivideo->chip = SIS_760;
- strcpy(ivideo->myid, "SiS 760");
- break;
- #endif
- }
- }
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- strcpy(sis_fb_info->modename, ivideo->myid);
- #endif
- ivideo->sishw_ext.jChipType = ivideo->chip;
- #ifdef CONFIG_FB_SIS_315
- if((ivideo->sishw_ext.jChipType == SIS_315PRO) ||
- (ivideo->sishw_ext.jChipType == SIS_315)) {
- ivideo->sishw_ext.jChipType = SIS_315H;
- }
- #endif
- ivideo->video_base = pci_resource_start(pdev, 0);
- ivideo->mmio_base = pci_resource_start(pdev, 1);
- ivideo->mmio_size = pci_resource_len(pdev, 1);
- ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
- ivideo->sishw_ext.ulIOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;
- if(!sisvga_enabled) {
- if(pci_enable_device(pdev)) {
- pci_set_drvdata(pdev, NULL);
- kfree(sis_fb_info);
- return -EIO;
- }
- }
- SiSRegInit(&ivideo->SiS_Pr, ivideo->sishw_ext.ulIOAddress);
- #ifdef CONFIG_FB_SIS_300
- /* Find PCI systems for Chrontel/GPIO communication setup */
- if(ivideo->chip == SIS_630) {
- i=0;
- do {
- if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
- mychswtable[i].subsysCard == ivideo->subsysdevice) {
- ivideo->SiS_Pr.SiS_ChSW = TRUE;
- printk(KERN_DEBUG "sisfb: Identified [%s %s] requiring Chrontel/GPIO setup\n",
- mychswtable[i].vendorName, mychswtable[i].cardName);
- break;
- }
- i++;
- } while(mychswtable[i].subsysVendor != 0);
- }
- #endif
- outSISIDXREG(SISSR, 0x05, 0x86);
- if( (!sisvga_enabled)
- #if !defined(__i386__) && !defined(__x86_64__)
- || (sisfb_resetcard)
- #endif
- ) {
- for(i = 0x30; i <= 0x3f; i++) {
- outSISIDXREG(SISCR,i,0x00);
- }
- }
- /* Find out about current video mode */
- ivideo->modeprechange = 0x03;
- inSISIDXREG(SISCR,0x34,reg);
- if(reg & 0x7f) {
- ivideo->modeprechange = reg & 0x7f;
- } else if(sisvga_enabled) {
- #if defined(__i386__) || defined(__x86_64__)
- unsigned char SIS_IOTYPE2 *tt = ioremap(0, 0x1000);
- if(tt) {
- ivideo->modeprechange = readb(tt + 0x449);
- iounmap(tt);
- }
- #endif
- }
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- #ifdef MODULE
- if((reg & 0x80) && (reg != 0xff)) {
- if((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF) {
- printk(KERN_INFO "sisfb: Cannot initialize display mode, X server is active\n");
- pci_set_drvdata(pdev, NULL);
- kfree(sis_fb_info);
- return -EBUSY;
- }
- }
- #endif
- #endif
- ivideo->sishw_ext.bIntegratedMMEnabled = TRUE;
- #ifdef CONFIG_FB_SIS_300
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- if(ivideo->chip != SIS_300) {
- inSISIDXREG(SISSR, 0x1a, reg);
- if(!(reg & 0x10)) {
- ivideo->sishw_ext.bIntegratedMMEnabled = FALSE;
- }
- }
- }
- #endif
- ivideo->bios_abase = NULL;
- if(ivideo->sisfb_userom) {
- ivideo->sishw_ext.pjVirtualRomBase = sis_find_rom(pdev);
- ivideo->bios_abase = ivideo->sishw_ext.pjVirtualRomBase;
- if(ivideo->sishw_ext.pjVirtualRomBase) {
- printk(KERN_INFO "sisfb: Video ROM found and copied\n");
- ivideo->sishw_ext.UseROM = TRUE;
- } else {
- ivideo->sishw_ext.UseROM = FALSE;
- printk(KERN_INFO "sisfb: Video ROM not found\n");
- }
- } else {
- ivideo->sishw_ext.pjVirtualRomBase = NULL;
- ivideo->sishw_ext.UseROM = FALSE;
- printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
- }
- /* Find systems for special custom timing */
- if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) {
- int j;
- unsigned char *biosver = NULL;
- unsigned char *biosdate = NULL;
- BOOLEAN footprint;
- u32 chksum = 0;
- if(ivideo->sishw_ext.UseROM) {
- biosver = ivideo->sishw_ext.pjVirtualRomBase + 0x06;
- biosdate = ivideo->sishw_ext.pjVirtualRomBase + 0x2c;
- for(i=0; i<32768; i++) chksum += ivideo->sishw_ext.pjVirtualRomBase[i];
- }
- i=0;
- do {
- if( (mycustomttable[i].chipID == ivideo->chip) &&
- ((!strlen(mycustomttable[i].biosversion)) ||
- (ivideo->sishw_ext.UseROM &&
- (!strncmp(mycustomttable[i].biosversion, biosver, strlen(mycustomttable[i].biosversion))))) &&
- ((!strlen(mycustomttable[i].biosdate)) ||
- (ivideo->sishw_ext.UseROM &&
- (!strncmp(mycustomttable[i].biosdate, biosdate, strlen(mycustomttable[i].biosdate))))) &&
- ((!mycustomttable[i].bioschksum) ||
- (ivideo->sishw_ext.UseROM &&
- (mycustomttable[i].bioschksum == chksum))) &&
- (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
- (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
- footprint = TRUE;
- for(j = 0; j < 5; j++) {
- if(mycustomttable[i].biosFootprintAddr[j]) {
- if(ivideo->sishw_ext.UseROM) {
- if(ivideo->sishw_ext.pjVirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
- mycustomttable[i].biosFootprintData[j]) {
- footprint = FALSE;
- }
- } else footprint = FALSE;
- }
- }
- if(footprint) {
- ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
- printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
- mycustomttable[i].vendorName,
- mycustomttable[i].cardName);
- printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n",
- mycustomttable[i].optionName);
- break;
- }
- }
- i++;
- } while(mycustomttable[i].chipID);
- }
- #ifdef CONFIG_FB_SIS_300
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- if( (!sisvga_enabled)
- #if !defined(__i386__) && !defined(__x86_64__)
- || (sisfb_resetcard)
- #endif
- ) {
- if(ivideo->chip == SIS_300) {
- sisfb_post_sis300(pdev);
- }
- }
- }
- #endif
- #ifdef CONFIG_FB_SIS_315
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- if( (!sisvga_enabled)
- #if !defined(__i386__) && !defined(__x86_64__)
- || (sisfb_resetcard)
- #endif
- ) {
- if((ivideo->chip == SIS_315H) ||
- (ivideo->chip == SIS_315) ||
- (ivideo->chip == SIS_315PRO) ||
- (ivideo->chip == SIS_330)) {
- sisfb_post_sis315330(pdev);
- }
- }
- }
- #endif
- if(sisfb_get_dram_size(ivideo)) {
- printk(KERN_INFO "sisfb: Fatal error: Unable to determine RAM size.\n");
- if(ivideo->bios_abase) vfree(ivideo->bios_abase);
- pci_set_drvdata(pdev, NULL);
- kfree(sis_fb_info);
- return -ENODEV;
- }
- if((ivideo->sisfb_mode_idx < 0) ||
- ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
- /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
- orSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
- /* Enable 2D accelerator engine */
- orSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
- }
- if(sisfb_pdc != 0xff) {
- if(ivideo->sisvga_engine == SIS_300_VGA) sisfb_pdc &= 0x3c;
- else sisfb_pdc &= 0x1f;
- ivideo->SiS_Pr.PDC = sisfb_pdc;
- }
- #ifdef CONFIG_FB_SIS_315
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- if(sisfb_pdca != 0xff) ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
- }
- #endif
- if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) {
- printk(KERN_ERR "sisfb: Fatal error: Unable to reserve frame buffer memory\n");
- printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n");
- if(ivideo->bios_abase) vfree(ivideo->bios_abase);
- pci_set_drvdata(pdev, NULL);
- kfree(sis_fb_info);
- return -ENODEV;
- }
- if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) {
- printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n");
- release_mem_region(ivideo->video_base, ivideo->video_size);
- if(ivideo->bios_abase) vfree(ivideo->bios_abase);
- pci_set_drvdata(pdev, NULL);
- kfree(sis_fb_info);
- return -ENODEV;
- }
- ivideo->video_vbase = ioremap(ivideo->video_base, ivideo->video_size);
- ivideo->sishw_ext.pjVideoMemoryAddress = ivideo->video_vbase;
- if(!ivideo->video_vbase) {
- printk(KERN_ERR "sisfb: Fatal error: Unable to map frame buffer memory\n");
- release_mem_region(ivideo->video_base, ivideo->video_size);
- release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
- if(ivideo->bios_abase) vfree(ivideo->bios_abase);
- pci_set_drvdata(pdev, NULL);
- kfree(sis_fb_info);
- return -ENODEV;
- }
- ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size);
- if(!ivideo->mmio_vbase) {
- printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
- iounmap(ivideo->video_vbase);
- release_mem_region(ivideo->video_base, ivideo->video_size);
- release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
- if(ivideo->bios_abase) vfree(ivideo->bios_abase);
- pci_set_drvdata(pdev, NULL);
- kfree(sis_fb_info);
- return -ENODEV;
- }
- printk(KERN_INFO "sisfb: Framebuffer at 0x%lx, mapped to 0x%lx, size %ldk\n",
- ivideo->video_base, (ULONG)ivideo->video_vbase, ivideo->video_size / 1024);
- printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
- ivideo->mmio_base, (ULONG)ivideo->mmio_vbase, ivideo->mmio_size / 1024);
- if((ivideo->havenoheap = sisfb_heap_init(ivideo))) {
- printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n");
- }
- /* Used for clearing the screen only, therefore respect our mem limit */
- ivideo->sishw_ext.ulVideoMemorySize = ivideo->sisfb_mem;
- ivideo->mtrr = 0;
- ivideo->vbflags = 0;
- ivideo->lcddefmodeidx = DEFAULT_LCDMODE;
- ivideo->tvdefmodeidx = DEFAULT_TVMODE;
- ivideo->defmodeidx = DEFAULT_MODE;
- ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr, &ivideo->sishw_ext);
- if((ivideo->sisfb_mode_idx < 0) ||
- ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
- sisfb_sense_crt1(ivideo);
- sisfb_get_VB_type(ivideo);
- if(ivideo->vbflags & VB_VIDEOBRIDGE) {
- sisfb_detect_VB_connect(ivideo);
- }
- ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
- if(ivideo->vbflags & VB_VIDEOBRIDGE) {
- if(ivideo->sisfb_crt2type != -1) {
- if((ivideo->sisfb_crt2type == CRT2_LCD) && (ivideo->vbflags & CRT2_LCD)) {
- ivideo->currentvbflags |= CRT2_LCD;
- } else if(ivideo->sisfb_crt2type != CRT2_LCD) {
- ivideo->currentvbflags |= ivideo->sisfb_crt2type;
- }
- } else {
- /* Chrontel 700x TV detection often unreliable, therefore use a
- * different default order on such machines
- */
- if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags & VB_CHRONTEL)) {
- if(ivideo->vbflags & CRT2_LCD) ivideo->currentvbflags |= CRT2_LCD;
- else if(ivideo->vbflags & CRT2_TV) ivideo->currentvbflags |= CRT2_TV;
- else if(ivideo->vbflags & CRT2_VGA) ivideo->currentvbflags |= CRT2_VGA;
- } else {
- if(ivideo->vbflags & CRT2_TV) ivideo->currentvbflags |= CRT2_TV;
- else if(ivideo->vbflags & CRT2_LCD) ivideo->currentvbflags |= CRT2_LCD;
- else if(ivideo->vbflags & CRT2_VGA) ivideo->currentvbflags |= CRT2_VGA;
- }
- }
- }
- if(ivideo->vbflags & CRT2_LCD) {
- inSISIDXREG(SISCR, 0x36, reg);
- reg &= 0x0f;
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- ivideo->CRT2LCDType = sis300paneltype[reg];
- } else if(ivideo->chip >= SIS_661) {
- ivideo->CRT2LCDType = sis661paneltype[reg];
- } else {
- ivideo->CRT2LCDType = sis310paneltype[reg];
- if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
- if((ivideo->CRT2LCDType != LCD_640x480_2) &&
- (ivideo->CRT2LCDType != LCD_640x480_3)) {
- ivideo->CRT2LCDType = LCD_320x480;
- }
- }
- }
- if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
- /* For broken BIOSes: Assume 1024x768, RGB18 */
- ivideo->CRT2LCDType = LCD_1024x768;
- setSISIDXREG(SISCR,0x36,0xf0,0x02);
- setSISIDXREG(SISCR,0x37,0xee,0x01);
- printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
- }
- for(i = 0; i < SIS_LCD_NUMBER; i++) {
- if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) {
- ivideo->lcdxres = sis_lcd_data[i].xres;
- ivideo->lcdyres = sis_lcd_data[i].yres;
- ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
- break;
- }
- }
- if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
- ivideo->lcdxres = 1360; ivideo->lcdyres = 1024; ivideo->lcddefmodeidx = 99;
- } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
- ivideo->lcdxres = 848; ivideo->lcdyres = 480; ivideo->lcddefmodeidx = 47;
- }
- printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n",
- ivideo->lcdxres, ivideo->lcdyres);
- }
- #ifdef CONFIG_FB_SIS_300
- /* Save the current PanelDelayCompensation if the LCD is currently used */
- if(ivideo->sisvga_engine == SIS_300_VGA) {
- if(ivideo->vbflags & (VB_LVDS | VB_30xBDH)) {
- int tmp;
- inSISIDXREG(SISCR,0x30,tmp);
- if(tmp & 0x20) {
- /* Currently on LCD? If yes, read current pdc */
- inSISIDXREG(SISPART1,0x13,ivideo->detectedpdc);
- ivideo->detectedpdc &= 0x3c;
- if(ivideo->SiS_Pr.PDC == -1) {
- /* Let option override detection */
- ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
- }
- printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
- ivideo->detectedpdc);
- }
- if((ivideo->SiS_Pr.PDC != -1) && (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
- printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
- ivideo->SiS_Pr.PDC);
- }
- }
- }
- #endif
- #ifdef CONFIG_FB_SIS_315
- if(ivideo->sisvga_engine == SIS_315_VGA) {
- /* Try to find about LCDA */
- if(ivideo->vbflags & (VB_301C | VB_302B | VB_301LV | VB_302LV | VB_302ELV)) {
- int tmp;
- inSISIDXREG(SISPART1,0x13,tmp);
- if(tmp & 0x04) {
- ivideo->SiS_Pr.SiS_UseLCDA = TRUE;
- ivideo->detectedlcda = 0x03;
- }
- }
- /* Save PDC */
- if(ivideo->vbflags & (VB_301LV | VB_302LV | VB_302ELV)) {
- int tmp;
- inSISIDXREG(SISCR,0x30,tmp);
- if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
- /* Currently on LCD? If yes, read current pdc */
- u8 pdc;
- inSISIDXREG(SISPART1,0x2D,pdc);
- ivideo->detectedpdc = (pdc & 0x0f) << 1;
- ivideo->detectedpdca = (pdc & 0xf0) >> 3;
- inSISIDXREG(SISPART1,0x35,pdc);
- ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
- inSISIDXREG(SISPART1,0x20,pdc);
- ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
- if(ivideo->newrom) {
- /* New ROM invalidates other PDC resp. */
- if(ivideo->detectedlcda != 0xff) {
- ivideo->detectedpdc = 0xff;
- } else {
- ivideo->detectedpdca = 0xff;
- }
- }
- if(ivideo->SiS_Pr.PDC == -1) {
- if(ivideo->detectedpdc != 0xff) {
- ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
- }
- }
- if(ivideo->SiS_Pr.PDCA == -1) {
- if(ivideo->detectedpdca != 0xff) {
- ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
- }
- }
- if(ivideo->detectedpdc != 0xff) {
- printk(KERN_INFO
- "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
- ivideo->detectedpdc);
- }
- if(ivideo->detectedpdca != 0xff) {
- printk(KERN_INFO
- "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
- ivideo->detectedpdca);
- }
- }
- /* Save EMI */
- if(ivideo->vbflags & (VB_302LV | VB_302ELV)) {
- inSISIDXREG(SISPART4,0x30,ivideo->SiS_Pr.EMI_30);
- inSISIDXREG(SISPART4,0x31,ivideo->SiS_Pr.EMI_31);
- inSISIDXREG(SISPART4,0x32,ivideo->SiS_Pr.EMI_32);
- inSISIDXREG(SISPART4,0x33,ivideo->SiS_Pr.EMI_33);
- ivideo->SiS_Pr.HaveEMI = TRUE;
- if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
- ivideo->SiS_Pr.HaveEMILCD = TRUE;
- }
- }
- }
- /* Let user override detected PDCs (all bridges) */
- if(ivideo->vbflags & (VB_301B | VB_301C | VB_301LV | VB_302LV | VB_302ELV)) {
- if((ivideo->SiS_Pr.PDC != -1) && (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
- printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
- ivideo->SiS_Pr.PDC);
- }
- if((ivideo->SiS_Pr.PDCA != -1) && (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
- printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
- ivideo->SiS_Pr.PDCA);
- }
- }
- }
- #endif
- if(!ivideo->sisfb_crt1off) {
- sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0);
- } else {
- if((ivideo->vbflags & (VB_301|VB_301B|VB_301C|VB_302B)) &&
- (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
- sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1);
- }
- }
- if(ivideo->sisfb_mode_idx >= 0) {
- int bu = ivideo->sisfb_mode_idx;
- ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
- ivideo->sisfb_mode_idx, ivideo->currentvbflags);
- if(bu != ivideo->sisfb_mode_idx) {
- printk(KERN_ERR "Mode %dx%dx%d failed validation\n",
- sisbios_mode[bu].xres,
- sisbios_mode[bu].yres,
- sisbios_mode[bu].bpp);
- }
- }
- if(ivideo->sisfb_mode_idx < 0) {
- switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
- case CRT2_LCD:
- ivideo->sisfb_mode_idx = ivideo->lcddefmodeidx;
- break;
- case CRT2_TV:
- ivideo->sisfb_mode_idx = ivideo->tvdefmodeidx;
- break;
- default:
- ivideo->sisfb_mode_idx = ivideo->defmodeidx;
- break;
- }
- }
- ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
- if(ivideo->refresh_rate != 0) {
- sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx);
- }
- if(ivideo->rate_idx == 0) {
- ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
- ivideo->refresh_rate = 60;
- }
- if(ivideo->sisfb_thismonitor.datavalid) {
- if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, ivideo->sisfb_mode_idx,
- ivideo->rate_idx, ivideo->refresh_rate)) {
- printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
- }
- }
- ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
- ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
- ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
- sisfb_set_vparms(ivideo);
-
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- /* ---------------- For 2.4: Now switch the mode ------------------ */
-
- printk(KERN_INFO "sisfb: Mode is %dx%dx%d (%dHz)\n",
- ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
- ivideo->refresh_rate);
- sisfb_pre_setmode(ivideo);
- if(SiSSetMode(&ivideo->SiS_Pr, &ivideo->sishw_ext, ivideo->mode_no) == 0) {
- printk(KERN_ERR "sisfb: Fatal error: Setting mode[0x%x] failed\n",
- ivideo->mode_no);
- iounmap(ivideo->video_vbase);
- iounmap(ivideo->mmio_vbase);
- release_mem_region(ivideo->video_base, ivideo->video_size);
- release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
- if(ivideo->bios_abase) vfree(ivideo->bios_abase);
- pci_set_drvdata(pdev, NULL);
- kfree(sis_fb_info);
- return -EINVAL;
- }
- outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
- sisfb_post_setmode(ivideo);
- /* Maximize regardless of sisfb_max at startup */
- ivideo->default_var.yres_virtual = 32767;
- /* Force reset of x virtual in crtc_to_var */
- ivideo->default_var.xres_virtual = 0;
- sisfb_crtc_to_var(ivideo, &ivideo->default_var);
- sisfb_calc_pitch(ivideo, &ivideo->default_var);
- sisfb_set_pitch(ivideo);
- ivideo->accel = 0;
- if(ivideo->sisfb_accel) {
- ivideo->accel = -1;
- ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
- }
- sisfb_initaccel(ivideo);
-
- sis_fb_info->node = -1;
- sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
- sis_fb_info->fbops = &sisfb_ops;
- sis_fb_info->disp = &ivideo->sis_disp;
- sis_fb_info->blank = &sisfb_blank;
- sis_fb_info->switch_con = &sisfb_switch;
- sis_fb_info->updatevar = &sisfb_update_var;
- sis_fb_info->changevar = NULL;
- strcpy(sis_fb_info->fontname, sisfb_fontname);
- sisfb_set_disp(-1, &ivideo->default_var, sis_fb_info);
- #else /* --------- For 2.6: Setup a somewhat sane default var ------------ */
- printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n",
- ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
- ivideo->refresh_rate);
- ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width;
- ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height;
- ivideo->default_var.bits_per_pixel = ivideo->video_bpp;
- sisfb_bpp_to_var(ivideo, &ivideo->default_var);
-
- ivideo->default_var.pixclock = (u32) (1000000000 /
- sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, &ivideo->sishw_ext,
- ivideo->mode_no, ivideo->rate_idx));
-
- if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, &ivideo->sishw_ext,
- ivideo->mode_no, ivideo->rate_idx, &ivideo->default_var)) {
- if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
- ivideo->default_var.pixclock <<= 1;
- }
- }
- if(ivideo->sisfb_ypan) {
- /* Maximize regardless of sisfb_max at startup */
- ivideo->default_var.yres_virtual = sisfb_calc_maxyres(ivideo, &ivideo->default_var);
- if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) {
- ivideo->default_var.yres_virtual = ivideo->default_var.yres;
- }
- }
- sisfb_calc_pitch(ivideo, &ivideo->default_var);
- ivideo->accel = 0;
- if(ivideo->sisfb_accel) {
- ivideo->accel = -1;
- #ifdef STUPID_ACCELF_TEXT_SHIT
- ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
- #endif
- }
- sisfb_initaccel(ivideo);
- #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
- sis_fb_info->flags = FBINFO_DEFAULT |
- FBINFO_HWACCEL_YPAN |
- FBINFO_HWACCEL_XPAN |
- FBINFO_HWACCEL_COPYAREA |
- FBINFO_HWACCEL_FILLRECT |
- ((ivideo->accel) ? 0 : FBINFO_HWACCEL_DISABLED);
- #else
- sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
- #endif
- sis_fb_info->var = ivideo->default_var;
- sis_fb_info->fix = ivideo->sisfb_fix;
- sis_fb_info->screen_base = ivideo->video_vbase;
- sis_fb_info->fbops = &sisfb_ops;
- sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info);
- sis_fb_info->pseudo_palette = ivideo->pseudo_palette;
-
- fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
- #endif /* 2.6 */
- printk(KERN_DEBUG "sisfb: Initial vbflags 0x%lx\n", (unsigned long)ivideo->vbflags);
- #ifdef CONFIG_MTRR
- ivideo->mtrr = mtrr_add(ivideo->video_base, ivideo->video_size,
- MTRR_TYPE_WRCOMB, 1);
- if(!ivideo->mtrr) {
- printk(KERN_DEBUG "sisfb: Failed to add MTRRs\n");
- }
- #endif
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- vc_resize_con(1, 1, 0);
- #endif
- if(register_framebuffer(sis_fb_info) < 0) {
- printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
- iounmap(ivideo->video_vbase);
- iounmap(ivideo->mmio_vbase);
- release_mem_region(ivideo->video_base, ivideo->video_size);
- release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
- if(ivideo->bios_abase) vfree(ivideo->bios_abase);
- pci_set_drvdata(pdev, NULL);
- kfree(sis_fb_info);
- return -EINVAL;
- }
- ivideo->registered = 1;
- /* Enlist us */
- ivideo->next = card_list;
- card_list = ivideo;
- printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n",
- ivideo->sisfb_accel ? "enabled" : "disabled",
- ivideo->sisfb_ypan ?
- (ivideo->sisfb_max ? "enabled (auto-max)" : "enabled (no auto-max)") : "disabled");
- printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%d\n",
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- GET_FB_IDX(sis_fb_info->node),
- #else
- sis_fb_info->node,
- #endif
- ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
- printk(KERN_INFO "sisfb: (C) 2001-2004 Thomas Winischhofer.\n");
- } /* if mode = "none" */
- return 0;
- }
- /*****************************************************/
- /* PCI DEVICE HANDLING */
- /*****************************************************/
- static void __devexit sisfb_remove(struct pci_dev *pdev)
- {
- struct sis_video_info *ivideo = pci_get_drvdata(pdev);
- struct fb_info *sis_fb_info = ivideo->memyselfandi;
- int registered = ivideo->registered;
- /* Unmap */
- iounmap(ivideo->video_vbase);
- iounmap(ivideo->mmio_vbase);
- vfree(ivideo->bios_abase);
- /* Release mem regions */
- release_mem_region(ivideo->video_base, ivideo->video_size);
- release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
- #ifdef CONFIG_MTRR
- /* Release MTRR region */
- if(ivideo->mtrr) {
- mtrr_del(ivideo->mtrr, ivideo->video_base, ivideo->video_size);
- }
- #endif
- /* Unregister the framebuffer */
- if(ivideo->registered) {
- unregister_framebuffer(sis_fb_info);
- #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3))
- framebuffer_release(sis_fb_info);
- #else
- kfree(sis_fb_info);
- #endif
- }
- pci_set_drvdata(pdev, NULL);
- /* TODO: Restore the initial mode
- * This sounds easy but is as good as impossible
- * on many machines with SiS chip and video bridge
- * since text modes are always set up differently
- * from machine to machine. Depends on the type
- * of integration between chipset and bridge.
- */
- if(registered) {
- printk(KERN_INFO "sisfb: Restoring of text mode not supported yet\n");
- }
- };
- static struct pci_driver sisfb_driver = {
- .name = "sisfb",
- .id_table = sisfb_pci_table,
- .probe = sisfb_probe,
- .remove = __devexit_p(sisfb_remove)
- };
- SISINITSTATIC int __init sisfb_init(void)
- {
- #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
- #ifndef MODULE
- char *options = NULL;
- if(fb_get_options("sisfb", &options))
- return -ENODEV;
- sisfb_setup(options);
- #endif
- #endif
- return(pci_register_driver(&sisfb_driver));
- }
- #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
- #ifndef MODULE
- module_init(sisfb_init);
- #endif
- #endif
- /*****************************************************/
- /* MODULE */
- /*****************************************************/
- #ifdef MODULE
- static char *mode = NULL;
- static int vesa = -1;
- static unsigned int rate = 0;
- static unsigned int crt1off = 1;
- static unsigned int mem = 0;
- static char *forcecrt2type = NULL;
- static int forcecrt1 = -1;
- static int pdc = -1;
- static int pdc1 = -1;
- static int noaccel = -1;
- static int noypan = -1;
- static int nomax = -1;
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- static int inverse = 0;
- #endif
- static int userom = -1;
- static int useoem = -1;
- static char *tvstandard = NULL;
- static int nocrt2rate = 0;
- static int scalelcd = -1;
- static char *specialtiming = NULL;
- static int lvdshl = -1;
- static int tvxposoffset = 0, tvyposoffset = 0;
- static int filter = -1;
- #if !defined(__i386__) && !defined(__x86_64__)
- static int resetcard = 0;
- static int videoram = 0;
- #endif
- MODULE_DESCRIPTION("SiS 300/540/630/730/315/550/65x/661/74x/330/760 framebuffer device driver");
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- MODULE_PARM(mem, "i");
- MODULE_PARM(noaccel, "i");
- MODULE_PARM(noypan, "i");
- MODULE_PARM(nomax, "i");
- MODULE_PARM(userom, "i");
- MODULE_PARM(useoem, "i");
- MODULE_PARM(mode, "s");
- MODULE_PARM(vesa, "i");
- MODULE_PARM(rate, "i");
- MODULE_PARM(forcecrt1, "i");
- MODULE_PARM(forcecrt2type, "s");
- MODULE_PARM(scalelcd, "i");
- MODULE_PARM(pdc, "i");
- MODULE_PARM(pdc1, "i");
- MODULE_PARM(specialtiming, "s");
- MODULE_PARM(lvdshl, "i");
- MODULE_PARM(tvstandard, "s");
- MODULE_PARM(tvxposoffset, "i");
- MODULE_PARM(tvyposoffset, "i");
- MODULE_PARM(filter, "i");
- MODULE_PARM(nocrt2rate, "i");
- MODULE_PARM(inverse, "i");
- #if !defined(__i386__) && !defined(__x86_64__)
- MODULE_PARM(resetcard, "i");
- MODULE_PARM(videoram, "i");
- #endif
- #endif
- #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- module_param(mem, int, 0);
- module_param(noaccel, int, 0);
- module_param(noypan, int, 0);
- module_param(nomax, int, 0);
- module_param(userom, int, 0);
- module_param(useoem, int, 0);
- module_param(mode, charp, 0);
- module_param(vesa, int, 0);
- module_param(rate, int, 0);
- module_param(forcecrt1, int, 0);
- module_param(forcecrt2type, charp, 0);
- module_param(scalelcd, int, 0);
- module_param(pdc, int, 0);
- module_param(pdc1, int, 0);
- module_param(specialtiming, charp, 0);
- module_param(lvdshl, int, 0);
- module_param(tvstandard, charp, 0);
- module_param(tvxposoffset, int, 0);
- module_param(tvyposoffset, int, 0);
- module_param(filter, int, 0);
- module_param(nocrt2rate, int, 0);
- #if !defined(__i386__) && !defined(__x86_64__)
- module_param(resetcard, int, 0);
- module_param(videoram, int, 0);
- #endif
- #endif
- MODULE_PARM_DESC(mem,
- "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
- "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
- "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
- "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
- "otherwise at 12288KB. On 315 and Xabre series, the heap size is 32KB by default.\n"
- "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n"
- "for XFree86 4.x/X.org 6.7 and later.\n");
- MODULE_PARM_DESC(noaccel,
- "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
- "(default: 0)\n");
- MODULE_PARM_DESC(noypan,
- "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
- "will be performed by redrawing the screen. (default: 0)\n");
- MODULE_PARM_DESC(nomax,
- "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
- "memory for the virtual screen in order to optimize scrolling performance. If\n"
- "this is set to anything other than 0, sisfb will not do this and thereby \n"
- "enable the user to positively specify a virtual Y size of the screen using\n"
- "fbset. (default: 0)\n");
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- MODULE_PARM_DESC(mode,
- "\nSelects the desired display mode in the format [X]x[Y]x[Depth], eg.\n"
- "1024x768x16. Other formats supported include XxY-Depth and\n"
- "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
- "number, it will be interpreted as a VESA mode number. (default: none if\n"
- "sisfb is a module; this leaves the console untouched and the driver will\n"
- "only do the video memory management for eg. DRM/DRI; 800x600x8 if sisfb\n"
- "is in the kernel)\n");
- MODULE_PARM_DESC(vesa,
- "\nSelects the desired display mode by VESA defined mode number, eg. 0x117\n"
- "(default: 0x0000 if sisfb is a module; this leaves the console untouched\n"
- "and the driver will only do the video memory management for eg. DRM/DRI;\n"
- "0x0103 if sisfb is in the kernel)\n");
- #endif
- #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- MODULE_PARM_DESC(mode,
- "\nSelects the desired default display mode in the format XxYxDepth,\n"
- "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
- "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
- "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
- MODULE_PARM_DESC(vesa,
- "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
- "0x117 (default: 0x0103)\n");
- #endif
- MODULE_PARM_DESC(rate,
- "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
- "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
- "will be ignored (default: 60)\n");
- MODULE_PARM_DESC(forcecrt1,
- "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
- "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
- "0=CRT1 OFF) (default: [autodetected])\n");
- MODULE_PARM_DESC(forcecrt2type,
- "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
- "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
- "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
- "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
- "be used instead of TV to override the TV detection. Furthermore, on systems\n"
- "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
- "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
- "depends on the very hardware in use. (default: [autodetected])\n");
- MODULE_PARM_DESC(scalelcd,
- "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
- "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
- "show black bars around the image, TMDS panels will probably do the scaling\n"
- "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
- MODULE_PARM_DESC(pdc,
- "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
- "should detect this correctly in most cases; however, sometimes this is not\n"
- "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
- "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n"
- "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n"
- "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
- #ifdef CONFIG_FB_SIS_315
- MODULE_PARM_DESC(pdc1,
- "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n"
- "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
- "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
- "implemented yet.\n");
- #endif
- MODULE_PARM_DESC(specialtiming,
- "\nPlease refer to documentation for more information on this option.\n");
- MODULE_PARM_DESC(lvdshl,
- "\nPlease refer to documentation for more information on this option.\n");
- MODULE_PARM_DESC(tvstandard,
- "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
- "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
- MODULE_PARM_DESC(tvxposoffset,
- "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
- "Default: 0\n");
- MODULE_PARM_DESC(tvyposoffset,
- "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
- "Default: 0\n");
- MODULE_PARM_DESC(filter,
- "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
- "(Possible values 0-7, default: [no filter])\n");
- MODULE_PARM_DESC(nocrt2rate,
- "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
- "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- MODULE_PARM_DESC(inverse,
- "\nSetting this to anything but 0 should invert the display colors, but this\n"
- "does not seem to work. (default: 0)\n");
- #endif
- #if !defined(__i386__) && !defined(__x86_64__)
- #ifdef CONFIG_FB_SIS_300
- MODULE_PARM_DESC(resetcard,
- "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
- "the BIOS did not POST the card (only supported for SiS 300/305 currently).\n"
- "Default: 0\n");
- MODULE_PARM_DESC(videoram,
- "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
- "some non-x86 architectures where the memory auto detection fails. Only\n"
- "relevant if resetcard is set, too. Default: [auto-detect]\n");
- #endif
- #endif
- static int __devinit sisfb_init_module(void)
- {
- sisfb_setdefaultparms();
- if(rate) sisfb_parm_rate = rate;
- if((scalelcd == 0) || (scalelcd == 1)) {
- sisfb_scalelcd = scalelcd ^ 1;
- }
- /* Need to check crt2 type first for fstn/dstn */
- if(forcecrt2type)
- sisfb_search_crt2type(forcecrt2type);
- if(tvstandard)
- sisfb_search_tvstd(tvstandard);
- if(mode)
- sisfb_search_mode(mode, FALSE);
- else if(vesa != -1)
- sisfb_search_vesamode(vesa, FALSE);
- sisfb_crt1off = (crt1off == 0) ? 1 : 0;
- sisfb_forcecrt1 = forcecrt1;
- if(forcecrt1 == 1) sisfb_crt1off = 0;
- else if(forcecrt1 == 0) sisfb_crt1off = 1;
- if(noaccel == 1) sisfb_accel = 0;
- else if(noaccel == 0) sisfb_accel = 1;
- if(noypan == 1) sisfb_ypan = 0;
- else if(noypan == 0) sisfb_ypan = 1;
- if(nomax == 1) sisfb_max = 0;
- else if(nomax == 0) sisfb_max = 1;
-
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- if(inverse) sisfb_inverse = 1;
- #endif
- if(mem) sisfb_parm_mem = mem;
- if(userom != -1) sisfb_userom = userom;
- if(useoem != -1) sisfb_useoem = useoem;
- if(pdc != -1) sisfb_pdc = (pdc & 0x7f);
- if(pdc1 != -1) sisfb_pdca = (pdc1 & 0x1f);
- sisfb_nocrt2rate = nocrt2rate;
- if(specialtiming)
- sisfb_search_specialtiming(specialtiming);
- if((lvdshl >= 0) && (lvdshl <= 3)) sisfb_lvdshl = lvdshl;
- if(filter != -1) sisfb_filter = filter;
- sisfb_tvxposoffset = tvxposoffset;
- sisfb_tvyposoffset = tvyposoffset;
- #if !defined(__i386__) && !defined(__x86_64__)
- sisfb_resetcard = (resetcard) ? 1 : 0;
- if(videoram) sisfb_videoram = videoram;
- #endif
- return(sisfb_init());
- }
- static void __exit sisfb_remove_module(void)
- {
- pci_unregister_driver(&sisfb_driver);
- printk(KERN_DEBUG "sisfb: Module unloaded\n");
- }
- module_init(sisfb_init_module);
- module_exit(sisfb_remove_module);
- #endif /* /MODULE */
- EXPORT_SYMBOL(sis_malloc);
- EXPORT_SYMBOL(sis_free);
|