virgefb.c 66 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526
  1. /*
  2. * linux/drivers/video/virgefb.c -- CyberVision64/3D frame buffer device
  3. *
  4. * Copyright (C) 1997 André Heynatz
  5. *
  6. *
  7. * This file is based on the CyberVision frame buffer device (cyberfb.c):
  8. *
  9. * Copyright (C) 1996 Martin Apel
  10. * Geert Uytterhoeven
  11. *
  12. * Zorro II additions :
  13. *
  14. * Copyright (C) 1998-2000 Christian T. Steigies
  15. *
  16. * Initialization additions :
  17. *
  18. * Copyright (C) 1998-2000 Ken Tyler
  19. *
  20. * Parts of the Initialization code are based on Cyberfb.c by Allan Bair,
  21. * and on the NetBSD CyberVision64 frame buffer driver by Michael Teske who gave
  22. * permission for its use.
  23. *
  24. * Many thanks to Frank Mariak for his assistance with ZORRO 2 access and other
  25. * mysteries.
  26. *
  27. *
  28. *
  29. * This file is subject to the terms and conditions of the GNU General Public
  30. * License. See the file COPYING in the main directory of this archive
  31. * for more details.
  32. */
  33. #undef VIRGEFBDEBUG
  34. #undef VIRGEFBDUMP
  35. #include <linux/module.h>
  36. #include <linux/kernel.h>
  37. #include <linux/errno.h>
  38. #include <linux/string.h>
  39. #include <linux/mm.h>
  40. #include <linux/slab.h>
  41. #include <linux/delay.h>
  42. #include <linux/zorro.h>
  43. #include <linux/fb.h>
  44. #include <linux/init.h>
  45. #include <asm/uaccess.h>
  46. #include <asm/system.h>
  47. #include <asm/amigahw.h>
  48. #include <asm/io.h>
  49. #include <asm/irq.h>
  50. #include <video/fbcon.h>
  51. #include <video/fbcon-cfb8.h>
  52. #include <video/fbcon-cfb16.h>
  53. #include <video/fbcon-cfb32.h>
  54. #include "virgefb.h"
  55. #ifdef VIRGEFBDEBUG
  56. #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
  57. #else
  58. #define DPRINTK(fmt, args...)
  59. #endif
  60. #ifdef VIRGEFBDUMP
  61. static void cv64_dump(void);
  62. #define DUMP cv64_dump()
  63. #else
  64. #define DUMP
  65. #endif
  66. /*
  67. * Macros for register access and zorro control
  68. */
  69. static inline void mb_inline(void) { mb(); } /* for use in comma expressions */
  70. /* Set zorro 2 map */
  71. #define SelectIO \
  72. mb(); \
  73. if (on_zorro2) { \
  74. (*(volatile u16 *)((u8 *)(vcode_switch_base + 0x04)) = 0x01); \
  75. mb(); \
  76. }
  77. #define SelectMMIO \
  78. mb(); \
  79. if (on_zorro2) { \
  80. (*(volatile u16 *)((u8 *)(vcode_switch_base + 0x04)) = 0x02); \
  81. mb(); \
  82. }
  83. #define SelectCFG \
  84. mb(); \
  85. if (on_zorro2) { \
  86. (*(volatile u16 *)((u8 *)(vcode_switch_base + 0x04)) = 0x03); \
  87. mb(); \
  88. }
  89. /* Set pass through, 0 = amiga, !=0 = cv64/3d */
  90. #define SetVSwitch(x) \
  91. mb(); \
  92. (*(volatile u16 *)((u8 *)(vcode_switch_base)) = \
  93. (u16)(x ? 0 : 1)); \
  94. mb();
  95. /* Zorro2 endian 'aperture' */
  96. #define ENDIAN_BYTE 2
  97. #define ENDIAN_WORD 1
  98. #define ENDIAN_LONG 0
  99. #define Select_Zorro2_FrameBuffer(x) \
  100. do { \
  101. if (on_zorro2) { \
  102. mb(); \
  103. (*(volatile u16 *)((u8 *)(vcode_switch_base + 0x08)) = \
  104. (x * 0x40)); \
  105. mb(); \
  106. } \
  107. } while (0)
  108. /* SetPortVal - only used for interrupt enable (not yet implemented) */
  109. #if 0
  110. #define SetPortVal(x) \
  111. mb(); \
  112. (*(volatile u16 *)((u8 *)(vcode_switch_base + 0x0c)) = \
  113. (u16)x); \
  114. mb();
  115. #endif
  116. /* IO access */
  117. #define byte_access_io(x) (((x) & 0x3ffc) | (((x) & 3)^3) | (((x) & 3) <<14))
  118. #define byte_access_mmio(x) (((x) & 0xfffc) | (((x) & 3)^3))
  119. /* Write 8 bit VGA register - used once for chip wakeup */
  120. #define wb_vgaio(reg, dat) \
  121. SelectIO; \
  122. (*(volatile u8 *)(vgaio_regs + ((u32)byte_access_io(reg) & 0xffff)) = \
  123. (dat & 0xff)); \
  124. SelectMMIO;
  125. /* Read 8 bit VGA register - only used in dump (SelectIO not needed on read ?) */
  126. #ifdef VIRGEFBDUMP
  127. #define rb_vgaio(reg) \
  128. ({ \
  129. u8 __zzyzx; \
  130. SelectIO; \
  131. __zzyzx = (*(volatile u8 *)((vgaio_regs)+(u32)byte_access_io(reg))); \
  132. SelectMMIO; \
  133. __zzyzx; \
  134. })
  135. #endif
  136. /* MMIO access */
  137. /* Read 8 bit MMIO register */
  138. #define rb_mmio(reg) \
  139. (mb_inline(), \
  140. (*(volatile u8 *)(mmio_regs + 0x8000 + (u32)byte_access_mmio(reg))))
  141. /* Write 8 bit MMIO register */
  142. #define wb_mmio(reg,dat) \
  143. mb(); \
  144. (*(volatile u8 *)(mmio_regs + 0x8000 + (byte_access_mmio((reg) & 0xffff))) = \
  145. (dat & 0xff)); \
  146. mb();
  147. /* Read 32 bit MMIO register */
  148. #define rl_mmio(reg) \
  149. (mb_inline(), \
  150. (*((volatile u32 *)((u8 *)((mmio_regs + (on_zorro2 ? 0x20000 : 0)) + (reg))))))
  151. /* Write 32 bit MMIO register */
  152. #define wl_mmio(reg,dat) \
  153. mb(); \
  154. ((*(volatile u32 *)((u8 *)((mmio_regs + (on_zorro2 ? 0x20000 : 0)) + (reg)))) = \
  155. (u32)(dat)); \
  156. mb();
  157. /* Write to virge graphics register */
  158. #define wgfx(reg, dat) do { wb_mmio(GCT_ADDRESS, (reg)); wb_mmio(GCT_ADDRESS_W, (dat)); } while (0)
  159. /* Write to virge sequencer register */
  160. #define wseq(reg, dat) do { wb_mmio(SEQ_ADDRESS, (reg)); wb_mmio(SEQ_ADDRESS_W, (dat)); } while (0)
  161. /* Write to virge CRT controller register */
  162. #define wcrt(reg, dat) do { wb_mmio(CRT_ADDRESS, (reg)); wb_mmio(CRT_ADDRESS_W, (dat)); } while (0)
  163. /* Write to virge attribute register */
  164. #define watr(reg, dat) \
  165. do { \
  166. volatile unsigned char watr_tmp; \
  167. watr_tmp = rb_mmio(ACT_ADDRESS_RESET); \
  168. wb_mmio(ACT_ADDRESS_W, (reg)); \
  169. wb_mmio(ACT_ADDRESS_W, (dat)); \
  170. udelay(10); \
  171. } while (0)
  172. /* end of macros */
  173. struct virgefb_par {
  174. struct fb_var_screeninfo var;
  175. __u32 type;
  176. __u32 type_aux;
  177. __u32 visual;
  178. __u32 line_length;
  179. };
  180. static struct virgefb_par current_par;
  181. static int current_par_valid = 0;
  182. static struct display disp;
  183. static struct fb_info fb_info;
  184. static union {
  185. #ifdef FBCON_HAS_CFB16
  186. u16 cfb16[16];
  187. #endif
  188. #ifdef FBCON_HAS_CFB32
  189. u32 cfb32[16];
  190. #endif
  191. } fbcon_cmap;
  192. /*
  193. * Switch for Chipset Independency
  194. */
  195. static struct fb_hwswitch {
  196. /* Initialisation */
  197. int (*init)(void);
  198. /* Display Control */
  199. int (*encode_fix)(struct fb_fix_screeninfo *fix, struct virgefb_par *par);
  200. int (*decode_var)(struct fb_var_screeninfo *var, struct virgefb_par *par);
  201. int (*encode_var)(struct fb_var_screeninfo *var, struct virgefb_par *par);
  202. int (*getcolreg)(u_int regno, u_int *red, u_int *green, u_int *blue,
  203. u_int *transp, struct fb_info *info);
  204. void (*blank)(int blank);
  205. } *fbhw;
  206. static unsigned char blit_maybe_busy = 0;
  207. /*
  208. * Frame Buffer Name
  209. */
  210. static char virgefb_name[16] = "CyberVision/3D";
  211. /*
  212. * CyberVision64/3d Graphics Board
  213. */
  214. static unsigned char virgefb_colour_table [256][3];
  215. static unsigned long v_ram;
  216. static unsigned long v_ram_size;
  217. static volatile unsigned char *mmio_regs;
  218. static volatile unsigned char *vgaio_regs;
  219. static unsigned long v_ram_phys;
  220. static unsigned long mmio_regs_phys;
  221. static unsigned long vcode_switch_base;
  222. static unsigned char on_zorro2;
  223. /*
  224. * Offsets from start of video ram to appropriate ZIII aperture
  225. */
  226. #ifdef FBCON_HAS_CFB8
  227. #define CYBMEM_OFFSET_8 0x800000 /* BGRX */
  228. #endif
  229. #ifdef FBCON_HAS_CFB16
  230. #define CYBMEM_OFFSET_16 0x400000 /* GBXR */
  231. #endif
  232. #ifdef FBCON_HAS_CFB32
  233. #define CYBMEM_OFFSET_32 0x000000 /* XRGB */
  234. #endif
  235. /*
  236. * MEMCLOCK was 32MHz, 64MHz works, 72MHz doesn't (on my board)
  237. */
  238. #define MEMCLOCK 50000000
  239. /*
  240. * Predefined Video Modes
  241. */
  242. static struct {
  243. const char *name;
  244. struct fb_var_screeninfo var;
  245. } virgefb_predefined[] __initdata = {
  246. #ifdef FBCON_HAS_CFB8
  247. {
  248. "640x480-8", { /* Cybervision 8 bpp */
  249. 640, 480, 640, 480, 0, 0, 8, 0,
  250. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  251. 0, 0, -1, -1, FB_ACCELF_TEXT, 31250, 160, 136, 82, 61, 88, 2,
  252. 0, FB_VMODE_NONINTERLACED
  253. }
  254. }, {
  255. "768x576-8", { /* Cybervision 8 bpp */
  256. 768, 576, 768, 576, 0, 0, 8, 0,
  257. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  258. 0, 0, -1, -1, FB_ACCELF_TEXT, 29411, 144, 112, 32, 15, 64, 2,
  259. 0, FB_VMODE_NONINTERLACED
  260. }
  261. }, {
  262. "800x600-8", { /* Cybervision 8 bpp */
  263. 800, 600, 800, 600, 0, 0, 8, 0,
  264. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  265. 0, 0, -1, -1, FB_ACCELF_TEXT, 28571, 168, 104, 22, 1, 48, 2,
  266. 0, FB_VMODE_NONINTERLACED
  267. }
  268. }, {
  269. #if 0
  270. "1024x768-8", { /* Cybervision 8 bpp */
  271. 1024, 768, 1024, 768, 0, 0, 8, 0,
  272. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  273. 0, 0, -1, -1, FB_ACCELF_TEXT, 20833, 272, 168, 39, 2, 72, 1,
  274. 0, FB_VMODE_NONINTERLACED
  275. }
  276. #else
  277. "1024x768-8", {
  278. 1024, 768, 1024, 768, 0, 0, 8, 0,
  279. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  280. #if 0
  281. 0, 0, -1, -1, FB_ACCELF_TEXT, 12500, 184, 40, 40, 2, 96, 1,
  282. FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
  283. }
  284. #else
  285. 0, 0, -1, -1, FB_ACCELF_TEXT, 12699, 176, 16, 28, 1, 96, 3,
  286. FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
  287. }
  288. #endif
  289. #endif
  290. }, {
  291. "1152x886-8", { /* Cybervision 8 bpp */
  292. 1152, 886, 1152, 886, 0, 0, 8, 0,
  293. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  294. 0, 0, -1, -1, FB_ACCELF_TEXT, 19230, 280, 168, 45, 1, 64, 10,
  295. 0, FB_VMODE_NONINTERLACED
  296. }
  297. }, {
  298. "1280x1024-8", { /* Cybervision 8 bpp */
  299. 1280, 1024, 1280, 1024, 0, 0, 8, 0,
  300. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  301. #if 0
  302. 0, 0, -1, -1, FB_ACCELF_TEXT, 17857, 232, 232, 71, 15, 176, 12,
  303. }
  304. #else
  305. 0, 0, -1, -1, FB_ACCELF_TEXT, 7414, 232, 64, 38, 1, 112, 3,
  306. FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
  307. }
  308. #endif
  309. }, {
  310. "1600x1200-8", { /* Cybervision 8 bpp */
  311. 1600, 1200, 1600, 1200, 0, 0, 8, 0,
  312. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  313. #if 0
  314. 0, 0, -1, -1, FB_ACCELF_TEXT, 13698, 336, 224, 77, 15, 176, 12,
  315. 0, FB_VMODE_NONINTERLACED
  316. }
  317. #else
  318. 0, 0, -1, -1, FB_ACCELF_TEXT, 6411, 256, 32, 52, 10, 160, 8,
  319. FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
  320. }
  321. #endif
  322. },
  323. #endif
  324. #ifdef FBCON_HAS_CFB16
  325. {
  326. "640x480-16", { /* Cybervision 16 bpp */
  327. 640, 480, 640, 480, 0, 0, 16, 0,
  328. {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
  329. 0, 0, -1, -1, FB_ACCELF_TEXT, 31250, 152, 144, 82, 61, 88, 2,
  330. 0, FB_VMODE_NONINTERLACED
  331. }
  332. }, {
  333. "768x576-16", { /* Cybervision 16 bpp */
  334. 768, 576, 768, 576, 0, 0, 16, 0,
  335. {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
  336. 0, 0, -1, -1, FB_ACCELF_TEXT, 29411, 144, 112, 32, 15, 64, 2,
  337. 0, FB_VMODE_NONINTERLACED
  338. }
  339. }, {
  340. "800x600-16", { /* Cybervision 16 bpp */
  341. 800, 600, 800, 600, 0, 0, 16, 0,
  342. {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
  343. 0, 0, -1, -1, FB_ACCELF_TEXT, 28571, 168, 104, 22, 1, 48, 2,
  344. 0, FB_VMODE_NONINTERLACED
  345. }
  346. }, {
  347. #if 0
  348. "1024x768-16", { /* Cybervision 16 bpp */
  349. 1024, 768, 1024, 768, 0, 0, 16, 0,
  350. {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
  351. 0, 0, -1, -1, FB_ACCELF_TEXT, 20833, 272, 168, 39, 2, 72, 1,
  352. 0, FB_VMODE_NONINTERLACED
  353. }
  354. #else
  355. "1024x768-16", {
  356. 1024, 768, 1024, 768, 0, 0, 16, 0,
  357. {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
  358. 0, 0, -1, -1, FB_ACCELF_TEXT, 12500, 184, 40, 40, 2, 96, 1,
  359. FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
  360. }
  361. #endif
  362. }, {
  363. "1152x886-16", { /* Cybervision 16 bpp */
  364. 1152, 886, 1152, 886, 0, 0, 16, 0,
  365. {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
  366. 0, 0, -1, -1, FB_ACCELF_TEXT, 19230, 280, 168, 45, 1, 64, 10,
  367. 0, FB_VMODE_NONINTERLACED
  368. }
  369. }, {
  370. "1280x1024-16", { /* Cybervision 16 bpp */
  371. 1280, 1024, 1280, 1024, 0, 0, 16, 0,
  372. {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
  373. 0, 0, -1, -1, FB_ACCELF_TEXT, 17857, 232, 232, 71, 15, 176, 12,
  374. 0, FB_VMODE_NONINTERLACED
  375. }
  376. }, {
  377. "1600x1200-16", { /* Cybervision 16 bpp */
  378. 1600, 1200, 1600, 1200, 0, 0, 16, 0,
  379. {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
  380. 0, 0, -1, -1, FB_ACCELF_TEXT, 13698, 336, 224, 77, 15, 176, 12,
  381. 0, FB_VMODE_NONINTERLACED
  382. }
  383. },
  384. #endif
  385. #ifdef FBCON_HAS_CFB32
  386. {
  387. "640x480-32", { /* Cybervision 32 bpp */
  388. 640, 480, 640, 480, 0, 0, 32, 0,
  389. {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
  390. 0, 0, -1, -1, FB_ACCELF_TEXT, 31250, 160, 136, 82, 61, 88, 2,
  391. 0, FB_VMODE_NONINTERLACED
  392. }
  393. }, {
  394. "768x576-32", { /* Cybervision 32 bpp */
  395. 768, 576, 768, 576, 0, 0, 32, 0,
  396. {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
  397. 0, 0, -1, -1, FB_ACCELF_TEXT, 29411, 144, 112, 32, 15, 64, 2,
  398. 0, FB_VMODE_NONINTERLACED
  399. }
  400. }, {
  401. "800x600-32", { /* Cybervision 32 bpp */
  402. 800, 600, 800, 600, 0, 0, 32, 0,
  403. {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
  404. 0, 0, -1, -1, FB_ACCELF_TEXT, 28571, 168, 104, 22, 1, 48, 2,
  405. 0, FB_VMODE_NONINTERLACED
  406. }
  407. }, {
  408. "1024x768-32", { /* Cybervision 32 bpp */
  409. 1024, 768, 1024, 768, 0, 0, 32, 0,
  410. {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
  411. 0, 0, -1, -1, FB_ACCELF_TEXT, 20833, 272, 168, 39, 2, 72, 1,
  412. 0, FB_VMODE_NONINTERLACED
  413. }
  414. }, {
  415. "1152x886-32", { /* Cybervision 32 bpp */
  416. 1152, 886, 1152, 886, 0, 0, 32, 0,
  417. {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
  418. 0, 0, -1, -1, FB_ACCELF_TEXT, 19230, 280, 168, 45, 1, 64, 10,
  419. 0, FB_VMODE_NONINTERLACED
  420. }
  421. }, {
  422. "1280x1024-32", { /* Cybervision 32 bpp */
  423. 1280, 1024, 1280, 1024, 0, 0, 32, 0,
  424. {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
  425. 0, 0, -1, -1, FB_ACCELF_TEXT, 17857, 232, 232, 71, 15, 176, 12,
  426. 0, FB_VMODE_NONINTERLACED
  427. }
  428. }, {
  429. "1600x1200-32", { /* Cybervision 32 bpp */
  430. 1600, 1200, 1600, 1200, 0, 0, 32, 0,
  431. {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
  432. 0, 0, -1, -1, FB_ACCELF_TEXT, 13698, 336, 224, 77, 15, 176, 12,
  433. 0, FB_VMODE_NONINTERLACED
  434. }
  435. },
  436. #endif
  437. /* interlaced modes */
  438. #ifdef FBCON_HAS_CFB8
  439. {
  440. "1024x768-8i", { /* Cybervision 8 bpp */
  441. 1024, 768, 1024, 768, 0, 0, 8, 0,
  442. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  443. 0, 0, -1, -1, FB_ACCELF_TEXT, 20833, 272, 168, 39, 2, 72, 1,
  444. 0, FB_VMODE_INTERLACED
  445. }
  446. }, {
  447. "1280x1024-8i", { /* Cybervision 8 bpp */
  448. 1280, 1024, 1280, 1024, 0, 0, 8, 0,
  449. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  450. 0, 0, -1, -1, FB_ACCELF_TEXT, 17857, 232, 232, 71, 15, 176, 12,
  451. 0, FB_VMODE_INTERLACED
  452. }
  453. }, {
  454. "1600x1200-8i", { /* Cybervision 8 bpp */
  455. 1600, 1200, 1600, 1200, 0, 0, 8, 0,
  456. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  457. 0, 0, -1, -1, FB_ACCELF_TEXT, 13698, 336, 224, 77, 15, 176, 12,
  458. 0, FB_VMODE_INTERLACED
  459. }
  460. },
  461. #endif
  462. #ifdef FBCON_HAS_CFB16
  463. {
  464. "1024x768-16i", { /* Cybervision 16 bpp */
  465. 1024, 768, 1024, 768, 0, 0, 16, 0,
  466. {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
  467. 0, 0, -1, -1, FB_ACCELF_TEXT, 20833, 272, 168, 39, 2, 72, 1,
  468. 0, FB_VMODE_INTERLACED
  469. }
  470. }, {
  471. "1280x1024-16i", { /* Cybervision 16 bpp */
  472. 1280, 1024, 1280, 1024, 0, 0, 16, 0,
  473. {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
  474. 0, 0, -1, -1, FB_ACCELF_TEXT, 17857, 232, 232, 71, 15, 176, 12,
  475. 0, FB_VMODE_INTERLACED
  476. }
  477. }, {
  478. "1600x1200-16i", { /* Cybervision 16 bpp */
  479. 1600, 1200, 1600, 1200, 0, 0, 16, 0,
  480. {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
  481. 0, 0, -1, -1, FB_ACCELF_TEXT, 13698, 336, 224, 77, 15, 176, 12,
  482. 0, FB_VMODE_INTERLACED
  483. }
  484. },
  485. #endif
  486. #ifdef FBCON_HAS_CFB32
  487. {
  488. "1024x768-32i", { /* Cybervision 32 bpp */
  489. 1024, 768, 1024, 768, 0, 0, 32, 0,
  490. {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
  491. 0, 0, -1, -1, FB_ACCELF_TEXT, 22222, 216, 144, 39, 2, 72, 1,
  492. 0, FB_VMODE_INTERLACED
  493. }
  494. }, {
  495. "1280x1024-32i", { /* Cybervision 32 bpp */
  496. 1280, 1024, 1280, 1024, 0, 0, 32, 0,
  497. {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {23, 0, 0},
  498. 0, 0, -1, -1, FB_ACCELF_TEXT, 17857, 232, 232, 71, 15, 176, 12,
  499. 0, FB_VMODE_INTERLACED
  500. }
  501. }, {
  502. "1600x1200-32i", { /* Cybervision 32 bpp */
  503. 1600, 1200, 1600, 1200, 0, 0, 32, 0,
  504. {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
  505. 0, 0, -1, -1, FB_ACCELF_TEXT, 13698, 336, 224, 77, 15, 176, 12,
  506. 0, FB_VMODE_INTERLACED
  507. }
  508. },
  509. #endif
  510. /* doublescan modes */
  511. #ifdef FBCON_HAS_CFB8
  512. {
  513. "320x240-8d", { /* Cybervision 8 bpp */
  514. 320, 240, 320, 240, 0, 0, 8, 0,
  515. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  516. 0, 0, -1, -1, FB_ACCELF_TEXT, 59259, 80, 80, 45, 26, 32, 1,
  517. 0, FB_VMODE_DOUBLE
  518. }
  519. },
  520. #endif
  521. #ifdef FBCON_HAS_CFB16
  522. {
  523. "320x240-16d", { /* Cybervision 16 bpp */
  524. 320, 240, 320, 240, 0, 0, 16, 0,
  525. {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
  526. 0, 0, -1, -1, FB_ACCELF_TEXT, 59259, 80, 80, 45, 26, 32, 1,
  527. 0, FB_VMODE_DOUBLE
  528. }
  529. },
  530. #endif
  531. #ifdef FBCON_HAS_CFB32
  532. {
  533. "320x240-32d", { /* Cybervision 32 bpp */
  534. 320, 240, 320, 240, 0, 0, 32, 0,
  535. {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
  536. 0, 0, -1, -1, FB_ACCELF_TEXT, 59259, 80, 80, 45, 26, 32, 1,
  537. 0, FB_VMODE_DOUBLE
  538. }
  539. },
  540. #endif
  541. };
  542. #define NUM_TOTAL_MODES ARRAY_SIZE(virgefb_predefined)
  543. /*
  544. * Default to 800x600 for video=virge8:, virge16: or virge32:
  545. */
  546. #ifdef FBCON_HAS_CFB8
  547. #define VIRGE8_DEFMODE (2)
  548. #endif
  549. #ifdef FBCON_HAS_CFB16
  550. #define VIRGE16_DEFMODE (9)
  551. #endif
  552. #ifdef FBCON_HAS_CFB32
  553. #define VIRGE32_DEFMODE (16)
  554. #endif
  555. static struct fb_var_screeninfo virgefb_default;
  556. static int virgefb_inverse = 0;
  557. /*
  558. * Interface used by the world
  559. */
  560. int virgefb_setup(char*);
  561. static int virgefb_get_fix(struct fb_fix_screeninfo *fix, int con,
  562. struct fb_info *info);
  563. static int virgefb_get_var(struct fb_var_screeninfo *var, int con,
  564. struct fb_info *info);
  565. static int virgefb_set_var(struct fb_var_screeninfo *var, int con,
  566. struct fb_info *info);
  567. static int virgefb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
  568. struct fb_info *info);
  569. static int virgefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  570. u_int transp, struct fb_info *info);
  571. static int virgefb_blank(int blank, struct fb_info *info);
  572. /*
  573. * Interface to the low level console driver
  574. */
  575. int virgefb_init(void);
  576. static int virgefb_switch(int con, struct fb_info *info);
  577. static int virgefb_updatevar(int con, struct fb_info *info);
  578. /*
  579. * Text console acceleration
  580. */
  581. #ifdef FBCON_HAS_CFB8
  582. static struct display_switch fbcon_virge8;
  583. #endif
  584. #ifdef FBCON_HAS_CFB16
  585. static struct display_switch fbcon_virge16;
  586. #endif
  587. #ifdef FBCON_HAS_CFB32
  588. static struct display_switch fbcon_virge32;
  589. #endif
  590. /*
  591. * Hardware Specific Routines
  592. */
  593. static int virge_init(void);
  594. static int virgefb_encode_fix(struct fb_fix_screeninfo *fix,
  595. struct virgefb_par *par);
  596. static int virgefb_decode_var(struct fb_var_screeninfo *var,
  597. struct virgefb_par *par);
  598. static int virgefb_encode_var(struct fb_var_screeninfo *var,
  599. struct virgefb_par *par);
  600. static int virgefb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
  601. u_int *transp, struct fb_info *info);
  602. static void virgefb_gfx_on_off(int blank);
  603. static inline void virgefb_wait_for_idle(void);
  604. static void virgefb_BitBLT(u_short curx, u_short cury, u_short destx, u_short desty,
  605. u_short width, u_short height, u_short stride, u_short depth);
  606. static void virgefb_RectFill(u_short x, u_short y, u_short width, u_short height,
  607. u_short color, u_short stride, u_short depth);
  608. /*
  609. * Internal routines
  610. */
  611. static void virgefb_get_par(struct virgefb_par *par);
  612. static void virgefb_set_par(struct virgefb_par *par);
  613. static int virgefb_do_fb_set_var(struct fb_var_screeninfo *var, int isactive);
  614. static void virgefb_set_disp(int con, struct fb_info *info);
  615. static int virgefb_get_video_mode(const char *name);
  616. static void virgefb_set_video(struct fb_var_screeninfo *var);
  617. /*
  618. * Additions for Initialization
  619. */
  620. static void virgefb_load_video_mode(struct fb_var_screeninfo *video_mode);
  621. static int cv3d_has_4mb(void);
  622. static unsigned short virgefb_compute_clock(unsigned long freq);
  623. static inline unsigned char rattr(short);
  624. static inline unsigned char rseq(short);
  625. static inline unsigned char rcrt(short);
  626. static inline unsigned char rgfx(short);
  627. static inline void gfx_on_off(int toggle);
  628. static void virgefb_pci_init(void);
  629. /* -------------------- Hardware specific routines ------------------------- */
  630. /*
  631. * Functions for register access
  632. */
  633. /* Read attribute controller register */
  634. static inline unsigned char rattr(short idx)
  635. {
  636. volatile unsigned char rattr_tmp;
  637. rattr_tmp = rb_mmio(ACT_ADDRESS_RESET);
  638. wb_mmio(ACT_ADDRESS_W, idx);
  639. return (rb_mmio(ACT_ADDRESS_R));
  640. }
  641. /* Read sequencer register */
  642. static inline unsigned char rseq(short idx)
  643. {
  644. wb_mmio(SEQ_ADDRESS, idx);
  645. return (rb_mmio(SEQ_ADDRESS_R));
  646. }
  647. /* Read CRT controller register */
  648. static inline unsigned char rcrt(short idx)
  649. {
  650. wb_mmio(CRT_ADDRESS, idx);
  651. return (rb_mmio(CRT_ADDRESS_R));
  652. }
  653. /* Read graphics controller register */
  654. static inline unsigned char rgfx(short idx)
  655. {
  656. wb_mmio(GCT_ADDRESS, idx);
  657. return (rb_mmio(GCT_ADDRESS_R));
  658. }
  659. /*
  660. * Initialization
  661. */
  662. /* PCI init */
  663. void virgefb_pci_init(void) {
  664. DPRINTK("ENTER\n");
  665. SelectCFG;
  666. if (on_zorro2) {
  667. *((short *)(vgaio_regs + 0x00000010)) = 0;
  668. *((long *)(vgaio_regs + 0x00000004)) = 0x02000003;
  669. } else {
  670. *((short *)(vgaio_regs + 0x000e0010)) = 0;
  671. *((long *)(vgaio_regs + 0x000e0004)) = 0x02000003;
  672. }
  673. /* SelectIO is in wb_vgaio macro */
  674. wb_vgaio(SREG_VIDEO_SUBS_ENABLE, 0x01);
  675. /* SelectMMIO is in wb_vgaio macro */
  676. DPRINTK("EXIT\n");
  677. return;
  678. }
  679. /*
  680. * Initalize all mode independent regs, find mem size and clear mem
  681. */
  682. static int virge_init(void)
  683. {
  684. int i;
  685. unsigned char tmp;
  686. DPRINTK("ENTER\n");
  687. virgefb_pci_init();
  688. wb_mmio(GREG_MISC_OUTPUT_W, 0x07); /* colour, ram enable, clk sel */
  689. wseq(SEQ_ID_UNLOCK_EXT, 0x06); /* unlock extensions */
  690. tmp = rb_mmio(GREG_MISC_OUTPUT_R);
  691. wcrt(CRT_ID_REGISTER_LOCK_1, 0x48); /* unlock CR2D to CR3F */
  692. wcrt(CRT_ID_BACKWAD_COMP_1, 0x00); /* irq disable */
  693. wcrt(CRT_ID_REGISTER_LOCK_2, 0xa5); /* unlock CR40 to CRFF and more */
  694. wcrt(CRT_ID_REGISTER_LOCK,0x00); /* unlock h and v timing */
  695. wcrt(CRT_ID_SYSTEM_CONFIG, 0x01); /* unlock enhanced programming registers */
  696. wb_mmio(GREG_FEATURE_CONTROL_W, 0x00);
  697. wcrt(CRT_ID_EXT_MISC_CNTL, 0x00); /* b2 = 0 to allow VDAC mmio access */
  698. #if 0
  699. /* write strap options ... ? */
  700. wcrt(CRT_ID_CONFIG_1, 0x08);
  701. wcrt(CRT_ID_CONFIG_2, 0xff); /* 0x0x2 bit needs to be set ?? */
  702. wcrt(CRT_ID_CONFIG_3, 0x0f);
  703. wcrt(CRT_ID_CONFIG_4, 0x1a);
  704. #endif
  705. wcrt(CRT_ID_EXT_MISC_CNTL_1, 0x82); /* PCI DE and software reset S3D engine */
  706. /* EXT_MISC_CNTL_1, CR66 bit 0 should be the same as bit 0 MR_ADVANCED_FUNCTION_CONTROL - check */
  707. wl_mmio(MR_ADVANCED_FUNCTION_CONTROL, 0x00000011); /* enhanced mode, linear addressing */
  708. /* crtc registers */
  709. wcrt(CRT_ID_PRESET_ROW_SCAN, 0x00);
  710. /* Disable h/w cursor */
  711. wcrt(CRT_ID_CURSOR_START, 0x00);
  712. wcrt(CRT_ID_CURSOR_END, 0x00);
  713. wcrt(CRT_ID_START_ADDR_HIGH, 0x00);
  714. wcrt(CRT_ID_START_ADDR_LOW, 0x00);
  715. wcrt(CRT_ID_CURSOR_LOC_HIGH, 0x00);
  716. wcrt(CRT_ID_CURSOR_LOC_LOW, 0x00);
  717. wcrt(CRT_ID_EXT_MODE, 0x00);
  718. wcrt(CRT_ID_HWGC_MODE, 0x00);
  719. wcrt(CRT_ID_HWGC_ORIGIN_X_HI, 0x00);
  720. wcrt(CRT_ID_HWGC_ORIGIN_X_LO, 0x00);
  721. wcrt(CRT_ID_HWGC_ORIGIN_Y_HI, 0x00);
  722. wcrt(CRT_ID_HWGC_ORIGIN_Y_LO, 0x00);
  723. i = rcrt(CRT_ID_HWGC_MODE);
  724. wcrt(CRT_ID_HWGC_FG_STACK, 0x00);
  725. wcrt(CRT_ID_HWGC_FG_STACK, 0x00);
  726. wcrt(CRT_ID_HWGC_FG_STACK, 0x00);
  727. wcrt(CRT_ID_HWGC_BG_STACK, 0x00);
  728. wcrt(CRT_ID_HWGC_BG_STACK, 0x00);
  729. wcrt(CRT_ID_HWGC_BG_STACK, 0x00);
  730. wcrt(CRT_ID_HWGC_START_AD_HI, 0x00);
  731. wcrt(CRT_ID_HWGC_START_AD_LO, 0x00);
  732. wcrt(CRT_ID_HWGC_DSTART_X, 0x00);
  733. wcrt(CRT_ID_HWGC_DSTART_Y, 0x00);
  734. wcrt(CRT_ID_UNDERLINE_LOC, 0x00);
  735. wcrt(CRT_ID_MODE_CONTROL, 0xe3);
  736. wcrt(CRT_ID_BACKWAD_COMP_2, 0x22); /* blank bdr bit 5 blanking only on 8 bit */
  737. wcrt(CRT_ID_EX_SYNC_1, 0x00);
  738. /* memory */
  739. wcrt(CRT_ID_EXT_SYS_CNTL_3, 0x00);
  740. wcrt(CRT_ID_MEMORY_CONF, 0x08); /* config enhanced map */
  741. wcrt(CRT_ID_EXT_MEM_CNTL_1, 0x08); /* MMIO Select (0x0c works as well)*/
  742. wcrt(CRT_ID_EXT_MEM_CNTL_2, 0x02); /* why 02 big endian 00 works ? */
  743. wcrt(CRT_ID_EXT_MEM_CNTL_4, 0x9f); /* config big endian - 0x00 ? */
  744. wcrt(CRT_ID_LAW_POS_HI, 0x00);
  745. wcrt(CRT_ID_LAW_POS_LO, 0x00);
  746. wcrt(CRT_ID_EXT_MISC_CNTL_1, 0x81);
  747. wcrt(CRT_ID_MISC_1, 0x90); /* must follow CRT_ID_EXT_MISC_CNTL_1 */
  748. wcrt(CRT_ID_LAW_CNTL, 0x13); /* force 4 Meg for test */
  749. if (cv3d_has_4mb()) {
  750. v_ram_size = 0x00400000;
  751. wcrt(CRT_ID_LAW_CNTL, 0x13); /* 4 MB */
  752. } else {
  753. v_ram_size = 0x00200000;
  754. wcrt(CRT_ID_LAW_CNTL, 0x12); /* 2 MB */
  755. }
  756. if (on_zorro2)
  757. v_ram_size -= 0x60000; /* we need some space for the registers */
  758. wcrt(CRT_ID_EXT_SYS_CNTL_4, 0x00);
  759. wcrt(CRT_ID_EXT_DAC_CNTL, 0x00); /* 0x10 for X11 cursor mode */
  760. /* sequencer registers */
  761. wseq(SEQ_ID_CLOCKING_MODE, 0x01); /* 8 dot clock */
  762. wseq(SEQ_ID_MAP_MASK, 0xff);
  763. wseq(SEQ_ID_CHAR_MAP_SELECT, 0x00);
  764. wseq(SEQ_ID_MEMORY_MODE, 0x02);
  765. wseq(SEQ_ID_RAMDAC_CNTL, 0x00);
  766. wseq(SEQ_ID_SIGNAL_SELECT, 0x00);
  767. wseq(SEQ_ID_EXT_SEQ_REG9, 0x00); /* MMIO and PIO reg access enabled */
  768. wseq(SEQ_ID_EXT_MISC_SEQ, 0x00);
  769. wseq(SEQ_ID_CLKSYN_CNTL_1, 0x00);
  770. wseq(SEQ_ID_EXT_SEQ, 0x00);
  771. /* graphic registers */
  772. wgfx(GCT_ID_SET_RESET, 0x00);
  773. wgfx(GCT_ID_ENABLE_SET_RESET, 0x00);
  774. wgfx(GCT_ID_COLOR_COMPARE, 0x00);
  775. wgfx(GCT_ID_DATA_ROTATE, 0x00);
  776. wgfx(GCT_ID_READ_MAP_SELECT, 0x00);
  777. wgfx(GCT_ID_GRAPHICS_MODE, 0x40);
  778. wgfx(GCT_ID_MISC, 0x01);
  779. wgfx(GCT_ID_COLOR_XCARE, 0x0f);
  780. wgfx(GCT_ID_BITMASK, 0xff);
  781. /* attribute registers */
  782. for(i = 0; i <= 15; i++)
  783. watr(ACT_ID_PALETTE0 + i, i);
  784. watr(ACT_ID_ATTR_MODE_CNTL, 0x41);
  785. watr(ACT_ID_OVERSCAN_COLOR, 0xff);
  786. watr(ACT_ID_COLOR_PLANE_ENA, 0x0f);
  787. watr(ACT_ID_HOR_PEL_PANNING, 0x00);
  788. watr(ACT_ID_COLOR_SELECT, 0x00);
  789. wb_mmio(VDAC_MASK, 0xff);
  790. /* init local cmap as greyscale levels */
  791. for (i = 0; i < 256; i++) {
  792. virgefb_colour_table [i][0] = i;
  793. virgefb_colour_table [i][1] = i;
  794. virgefb_colour_table [i][2] = i;
  795. }
  796. /* clear framebuffer memory */
  797. memset((char*)v_ram, 0x00, v_ram_size);
  798. DPRINTK("EXIT\n");
  799. return 0;
  800. }
  801. /*
  802. * This function should fill in the `fix' structure based on the
  803. * values in the `par' structure.
  804. */
  805. static int virgefb_encode_fix(struct fb_fix_screeninfo *fix,
  806. struct virgefb_par *par)
  807. {
  808. DPRINTK("ENTER set video phys addr\n");
  809. memset(fix, 0, sizeof(struct fb_fix_screeninfo));
  810. strcpy(fix->id, virgefb_name);
  811. if (on_zorro2)
  812. fix->smem_start = v_ram_phys;
  813. switch (par->var.bits_per_pixel) {
  814. #ifdef FBCON_HAS_CFB8
  815. case 8:
  816. if (on_zorro2)
  817. Select_Zorro2_FrameBuffer(ENDIAN_BYTE);
  818. else
  819. fix->smem_start = (v_ram_phys + CYBMEM_OFFSET_8);
  820. break;
  821. #endif
  822. #ifdef FBCON_HAS_CFB16
  823. case 16:
  824. if (on_zorro2)
  825. Select_Zorro2_FrameBuffer(ENDIAN_WORD);
  826. else
  827. fix->smem_start = (v_ram_phys + CYBMEM_OFFSET_16);
  828. break;
  829. #endif
  830. #ifdef FBCON_HAS_CFB32
  831. case 32:
  832. if (on_zorro2)
  833. Select_Zorro2_FrameBuffer(ENDIAN_LONG);
  834. else
  835. fix->smem_start = (v_ram_phys + CYBMEM_OFFSET_32);
  836. break;
  837. #endif
  838. }
  839. fix->smem_len = v_ram_size;
  840. fix->mmio_start = mmio_regs_phys;
  841. fix->mmio_len = 0x10000; /* TODO: verify this for the CV64/3D */
  842. fix->type = FB_TYPE_PACKED_PIXELS;
  843. fix->type_aux = 0;
  844. if (par->var.bits_per_pixel == 8)
  845. fix->visual = FB_VISUAL_PSEUDOCOLOR;
  846. else
  847. fix->visual = FB_VISUAL_TRUECOLOR;
  848. fix->xpanstep = 0;
  849. fix->ypanstep = 0;
  850. fix->ywrapstep = 0;
  851. fix->line_length = par->var.xres_virtual*par->var.bits_per_pixel/8;
  852. fix->accel = FB_ACCEL_S3_VIRGE;
  853. DPRINTK("EXIT v_ram_phys = 0x%8.8lx\n", (unsigned long)fix->smem_start);
  854. return 0;
  855. }
  856. /*
  857. * Fill the `par' structure based on the values in `var'.
  858. * TODO: Verify and adjust values, return -EINVAL if bad.
  859. */
  860. static int virgefb_decode_var(struct fb_var_screeninfo *var,
  861. struct virgefb_par *par)
  862. {
  863. DPRINTK("ENTER\n");
  864. par->var.xres = var->xres;
  865. par->var.yres = var->yres;
  866. par->var.xres_virtual = var->xres_virtual;
  867. par->var.yres_virtual = var->yres_virtual;
  868. /* roundup and validate */
  869. par->var.xres = (par->var.xres+7) & ~7;
  870. par->var.xres_virtual = (par->var.xres_virtual+7) & ~7;
  871. if (par->var.xres_virtual < par->var.xres)
  872. par->var.xres_virtual = par->var.xres;
  873. if (par->var.yres_virtual < par->var.yres)
  874. par->var.yres_virtual = par->var.yres;
  875. par->var.xoffset = var->xoffset;
  876. par->var.yoffset = var->yoffset;
  877. par->var.bits_per_pixel = var->bits_per_pixel;
  878. if (par->var.bits_per_pixel <= 8)
  879. par->var.bits_per_pixel = 8;
  880. else if (par->var.bits_per_pixel <= 16)
  881. par->var.bits_per_pixel = 16;
  882. else
  883. par->var.bits_per_pixel = 32;
  884. #ifndef FBCON_HAS_CFB32
  885. if (par->var.bits_per_pixel == 32)
  886. par->var.bits_per_pixel = 16;
  887. #endif
  888. #ifndef FBCON_HAS_CFB16
  889. if (par->var.bits_per_pixel == 16)
  890. par->var.bits_per_pixel = 8;
  891. #endif
  892. par->var.grayscale = var->grayscale;
  893. par->var.red = var->red;
  894. par->var.green = var->green;
  895. par->var.blue = var->blue;
  896. par->var.transp = var->transp;
  897. par->var.nonstd = var->nonstd;
  898. par->var.activate = var->activate;
  899. par->var.height = var->height;
  900. par->var.width = var->width;
  901. if (var->accel_flags & FB_ACCELF_TEXT) {
  902. par->var.accel_flags = FB_ACCELF_TEXT;
  903. } else {
  904. par->var.accel_flags = 0;
  905. }
  906. par->var.pixclock = var->pixclock;
  907. par->var.left_margin = var->left_margin;
  908. par->var.right_margin = var->right_margin;
  909. par->var.upper_margin = var->upper_margin;
  910. par->var.lower_margin = var->lower_margin;
  911. par->var.hsync_len = var->hsync_len;
  912. par->var.vsync_len = var->vsync_len;
  913. par->var.sync = var->sync;
  914. par->var.vmode = var->vmode;
  915. DPRINTK("EXIT\n");
  916. return 0;
  917. }
  918. /*
  919. * Fill the `var' structure based on the values in `par' and maybe
  920. * other values read out of the hardware.
  921. */
  922. static int virgefb_encode_var(struct fb_var_screeninfo *var,
  923. struct virgefb_par *par)
  924. {
  925. DPRINTK("ENTER\n");
  926. memset(var, 0, sizeof(struct fb_var_screeninfo)); /* need this ? */
  927. var->xres = par->var.xres;
  928. var->yres = par->var.yres;
  929. var->xres_virtual = par->var.xres_virtual;
  930. var->yres_virtual = par->var.yres_virtual;
  931. var->xoffset = par->var.xoffset;
  932. var->yoffset = par->var.yoffset;
  933. var->bits_per_pixel = par->var.bits_per_pixel;
  934. var->grayscale = par->var.grayscale;
  935. var->red = par->var.red;
  936. var->green = par->var.green;
  937. var->blue = par->var.blue;
  938. var->transp = par->var.transp;
  939. var->nonstd = par->var.nonstd;
  940. var->activate = par->var.activate;
  941. var->height = par->var.height;
  942. var->width = par->var.width;
  943. var->accel_flags = par->var.accel_flags;
  944. var->pixclock = par->var.pixclock;
  945. var->left_margin = par->var.left_margin;
  946. var->right_margin = par->var.right_margin;
  947. var->upper_margin = par->var.upper_margin;
  948. var->lower_margin = par->var.lower_margin;
  949. var->hsync_len = par->var.hsync_len;
  950. var->vsync_len = par->var.vsync_len;
  951. var->sync = par->var.sync;
  952. var->vmode = par->var.vmode;
  953. DPRINTK("EXIT\n");
  954. return 0;
  955. }
  956. /*
  957. * Set a single color register. The values supplied are already
  958. * rounded down to the hardware's capabilities (according to the
  959. * entries in the var structure). Return != 0 for invalid regno.
  960. */
  961. static int virgefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  962. u_int transp, struct fb_info *info)
  963. {
  964. DPRINTK("ENTER\n");
  965. if (((current_par.var.bits_per_pixel==8) && (regno>255)) ||
  966. ((current_par.var.bits_per_pixel!=8) && (regno>15))) {
  967. DPRINTK("EXIT\n");
  968. return 1;
  969. }
  970. if (((current_par.var.bits_per_pixel==8) && (regno<256)) ||
  971. ((current_par.var.bits_per_pixel!=8) && (regno<16))) {
  972. virgefb_colour_table [regno][0] = red >> 10;
  973. virgefb_colour_table [regno][1] = green >> 10;
  974. virgefb_colour_table [regno][2] = blue >> 10;
  975. }
  976. switch (current_par.var.bits_per_pixel) {
  977. #ifdef FBCON_HAS_CFB8
  978. case 8:
  979. wb_mmio(VDAC_ADDRESS_W, (unsigned char)regno);
  980. wb_mmio(VDAC_DATA, ((unsigned char)(red >> 10)));
  981. wb_mmio(VDAC_DATA, ((unsigned char)(green >> 10)));
  982. wb_mmio(VDAC_DATA, ((unsigned char)(blue >> 10)));
  983. break;
  984. #endif
  985. #ifdef FBCON_HAS_CFB16
  986. case 16:
  987. fbcon_cmap.cfb16[regno] =
  988. ((red & 0xf800) |
  989. ((green & 0xfc00) >> 5) |
  990. ((blue & 0xf800) >> 11));
  991. break;
  992. #endif
  993. #ifdef FBCON_HAS_CFB32
  994. case 32:
  995. fbcon_cmap.cfb32[regno] =
  996. /* transp = 0's or 1's ? */
  997. (((red & 0xff00) << 8) |
  998. ((green & 0xff00) >> 0) |
  999. ((blue & 0xff00) >> 8));
  1000. break;
  1001. #endif
  1002. }
  1003. DPRINTK("EXIT\n");
  1004. return 0;
  1005. }
  1006. /*
  1007. * Read a single color register and split it into
  1008. * colors/transparent. Return != 0 for invalid regno.
  1009. */
  1010. static int virgefb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
  1011. u_int *transp, struct fb_info *info)
  1012. {
  1013. int t;
  1014. DPRINTK("ENTER\n");
  1015. if (regno > 255) {
  1016. DPRINTK("EXIT\n");
  1017. return 1;
  1018. }
  1019. if (((current_par.var.bits_per_pixel==8) && (regno<256)) ||
  1020. ((current_par.var.bits_per_pixel!=8) && (regno<16))) {
  1021. t = virgefb_colour_table [regno][0];
  1022. *red = (t<<10) | (t<<4) | (t>>2);
  1023. t = virgefb_colour_table [regno][1];
  1024. *green = (t<<10) | (t<<4) | (t>>2);
  1025. t = virgefb_colour_table [regno][2];
  1026. *blue = (t<<10) | (t<<4) | (t>>2);
  1027. }
  1028. *transp = 0;
  1029. DPRINTK("EXIT\n");
  1030. return 0;
  1031. }
  1032. /*
  1033. * (Un)Blank the screen
  1034. */
  1035. static void virgefb_gfx_on_off(int blank)
  1036. {
  1037. DPRINTK("ENTER\n");
  1038. gfx_on_off(blank);
  1039. DPRINTK("EXIT\n");
  1040. }
  1041. /*
  1042. * CV3D low-level support
  1043. */
  1044. static inline void wait_3d_fifo_slots(int n) /* WaitQueue */
  1045. {
  1046. do {
  1047. mb();
  1048. } while (((rl_mmio(MR_SUBSYSTEM_STATUS_R) >> 8) & 0x1f) < (n + 2));
  1049. }
  1050. static inline void virgefb_wait_for_idle(void) /* WaitIdle */
  1051. {
  1052. while(!(rl_mmio(MR_SUBSYSTEM_STATUS_R) & 0x2000)) ;
  1053. blit_maybe_busy = 0;
  1054. }
  1055. /*
  1056. * BitBLT - Through the Plane
  1057. */
  1058. static void virgefb_BitBLT(u_short curx, u_short cury, u_short destx, u_short desty,
  1059. u_short width, u_short height, u_short stride, u_short depth)
  1060. {
  1061. unsigned int blitcmd = S3V_BITBLT | S3V_DRAW | S3V_BLT_COPY;
  1062. switch (depth) {
  1063. #ifdef FBCON_HAS_CFB8
  1064. case 8 :
  1065. blitcmd |= S3V_DST_8BPP;
  1066. break;
  1067. #endif
  1068. #ifdef FBCON_HAS_CFB16
  1069. case 16 :
  1070. blitcmd |= S3V_DST_16BPP;
  1071. break;
  1072. #endif
  1073. #ifdef FBCON_HAS_CFB32
  1074. case 32 :
  1075. /* 32 bit uses 2 by 16 bit values, see fbcon_virge32_bmove */
  1076. blitcmd |= S3V_DST_16BPP;
  1077. break;
  1078. #endif
  1079. }
  1080. /* Set drawing direction */
  1081. /* -Y, X maj, -X (default) */
  1082. if (curx > destx) {
  1083. blitcmd |= (1 << 25); /* Drawing direction +X */
  1084. } else {
  1085. curx += (width - 1);
  1086. destx += (width - 1);
  1087. }
  1088. if (cury > desty) {
  1089. blitcmd |= (1 << 26); /* Drawing direction +Y */
  1090. } else {
  1091. cury += (height - 1);
  1092. desty += (height - 1);
  1093. }
  1094. wait_3d_fifo_slots(8); /* wait on fifo slots for 8 writes */
  1095. if (blit_maybe_busy)
  1096. virgefb_wait_for_idle();
  1097. blit_maybe_busy = 1;
  1098. wl_mmio(BLT_PATTERN_COLOR, 1); /* pattern fb color */
  1099. wl_mmio(BLT_MONO_PATTERN_0, ~0);
  1100. wl_mmio(BLT_MONO_PATTERN_1, ~0);
  1101. wl_mmio(BLT_SIZE_X_Y, ((width << 16) | height));
  1102. wl_mmio(BLT_SRC_X_Y, ((curx << 16) | cury));
  1103. wl_mmio(BLT_DEST_X_Y, ((destx << 16) | desty));
  1104. wl_mmio(BLT_SRC_DEST_STRIDE, (((stride << 16) | stride) /* & 0x0ff80ff8 */)); /* why is this needed now ? */
  1105. wl_mmio(BLT_COMMAND_SET, blitcmd);
  1106. }
  1107. /*
  1108. * Rectangle Fill Solid
  1109. */
  1110. static void virgefb_RectFill(u_short x, u_short y, u_short width, u_short height,
  1111. u_short color, u_short stride, u_short depth)
  1112. {
  1113. unsigned int blitcmd = S3V_RECTFILL | S3V_DRAW |
  1114. S3V_BLT_CLEAR | S3V_MONO_PAT | (1 << 26) | (1 << 25);
  1115. switch (depth) {
  1116. #ifdef FBCON_HAS_CFB8
  1117. case 8 :
  1118. blitcmd |= S3V_DST_8BPP;
  1119. break;
  1120. #endif
  1121. #ifdef FBCON_HAS_CFB16
  1122. case 16 :
  1123. blitcmd |= S3V_DST_16BPP;
  1124. break;
  1125. #endif
  1126. #ifdef FBCON_HAS_CFB32
  1127. case 32 :
  1128. /* 32 bit uses 2 times 16 bit values, see fbcon_virge32_clear */
  1129. blitcmd |= S3V_DST_16BPP;
  1130. break;
  1131. #endif
  1132. }
  1133. wait_3d_fifo_slots(5); /* wait on fifo slots for 5 writes */
  1134. if (blit_maybe_busy)
  1135. virgefb_wait_for_idle();
  1136. blit_maybe_busy = 1;
  1137. wl_mmio(BLT_PATTERN_COLOR, (color & 0xff));
  1138. wl_mmio(BLT_SIZE_X_Y, ((width << 16) | height));
  1139. wl_mmio(BLT_DEST_X_Y, ((x << 16) | y));
  1140. wl_mmio(BLT_SRC_DEST_STRIDE, (((stride << 16) | stride) /* & 0x0ff80ff8 */));
  1141. wl_mmio(BLT_COMMAND_SET, blitcmd);
  1142. }
  1143. /*
  1144. * Move cursor to x, y
  1145. */
  1146. #if 0
  1147. static void virgefb_move_cursor(u_short x, u_short y)
  1148. {
  1149. DPRINTK("Yuck .... MoveCursor on a 3D\n");
  1150. return 0;
  1151. }
  1152. #endif
  1153. /* -------------------- Interfaces to hardware functions -------------------- */
  1154. static struct fb_hwswitch virgefb_hw_switch = {
  1155. .init = virge_init,
  1156. .encode_fix = virgefb_encode_fix,
  1157. .decode_var = virgefb_decode_var,
  1158. .encode_var = virgefb_encode_var,
  1159. .getcolreg = virgefb_getcolreg,
  1160. .blank = virgefb_gfx_on_off
  1161. };
  1162. /* -------------------- Generic routines ------------------------------------ */
  1163. /*
  1164. * Fill the hardware's `par' structure.
  1165. */
  1166. static void virgefb_get_par(struct virgefb_par *par)
  1167. {
  1168. DPRINTK("ENTER\n");
  1169. if (current_par_valid) {
  1170. *par = current_par;
  1171. } else {
  1172. fbhw->decode_var(&virgefb_default, par);
  1173. }
  1174. DPRINTK("EXIT\n");
  1175. }
  1176. static void virgefb_set_par(struct virgefb_par *par)
  1177. {
  1178. DPRINTK("ENTER\n");
  1179. current_par = *par;
  1180. current_par_valid = 1;
  1181. DPRINTK("EXIT\n");
  1182. }
  1183. static void virgefb_set_video(struct fb_var_screeninfo *var)
  1184. {
  1185. /* Set clipping rectangle to current screen size */
  1186. unsigned int clip;
  1187. DPRINTK("ENTER\n");
  1188. wait_3d_fifo_slots(4);
  1189. clip = ((0 << 16) | (var->xres - 1));
  1190. wl_mmio(BLT_CLIP_LEFT_RIGHT, clip);
  1191. clip = ((0 << 16) | (var->yres - 1));
  1192. wl_mmio(BLT_CLIP_TOP_BOTTOM, clip);
  1193. wl_mmio(BLT_SRC_BASE, 0); /* seems we need to clear these two */
  1194. wl_mmio(BLT_DEST_BASE, 0);
  1195. /* Load the video mode defined by the 'var' data */
  1196. virgefb_load_video_mode(var);
  1197. DPRINTK("EXIT\n");
  1198. }
  1199. /*
  1200. Merge these two functions, Geert's suggestion.
  1201. static int virgefb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info);
  1202. static int virgefb_do_fb_set_var(struct fb_var_screeninfo *var, int isactive);
  1203. */
  1204. static int virgefb_do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
  1205. {
  1206. int err, activate;
  1207. struct virgefb_par par;
  1208. DPRINTK("ENTER\n");
  1209. if ((err = fbhw->decode_var(var, &par))) {
  1210. DPRINTK("EXIT\n");
  1211. return (err);
  1212. }
  1213. activate = var->activate;
  1214. if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
  1215. virgefb_set_par(&par);
  1216. fbhw->encode_var(var, &par);
  1217. var->activate = activate;
  1218. if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
  1219. virgefb_set_video(var);
  1220. DPRINTK("EXIT\n");
  1221. return 0;
  1222. }
  1223. /*
  1224. * Get the Fixed Part of the Display
  1225. */
  1226. static int virgefb_get_fix(struct fb_fix_screeninfo *fix, int con,
  1227. struct fb_info *info)
  1228. {
  1229. struct virgefb_par par;
  1230. int error = 0;
  1231. DPRINTK("ENTER\n");
  1232. if (con == -1)
  1233. virgefb_get_par(&par);
  1234. else
  1235. error = fbhw->decode_var(&fb_display[con].var, &par);
  1236. if (!error)
  1237. error = fbhw->encode_fix(fix, &par);
  1238. DPRINTK("EXIT\n");
  1239. return(error);
  1240. }
  1241. /*
  1242. * Get the User Defined Part of the Display
  1243. */
  1244. static int virgefb_get_var(struct fb_var_screeninfo *var, int con,
  1245. struct fb_info *info)
  1246. {
  1247. struct virgefb_par par;
  1248. int error = 0;
  1249. DPRINTK("ENTER\n");
  1250. if (con == -1) {
  1251. virgefb_get_par(&par);
  1252. error = fbhw->encode_var(var, &par);
  1253. disp.var = *var; /* ++Andre: don't know if this is the right place */
  1254. } else {
  1255. *var = fb_display[con].var;
  1256. }
  1257. DPRINTK("EXIT\n");
  1258. return(error);
  1259. }
  1260. static void virgefb_set_disp(int con, struct fb_info *info)
  1261. {
  1262. struct fb_fix_screeninfo fix;
  1263. struct display *display;
  1264. DPRINTK("ENTER\n");
  1265. if (con >= 0)
  1266. display = &fb_display[con];
  1267. else
  1268. display = &disp; /* used during initialization */
  1269. virgefb_get_fix(&fix, con, info);
  1270. if (con == -1)
  1271. con = 0;
  1272. if(on_zorro2) {
  1273. info->screen_base = (char*)v_ram;
  1274. } else {
  1275. switch (display->var.bits_per_pixel) {
  1276. #ifdef FBCON_HAS_CFB8
  1277. case 8:
  1278. info->screen_base = (char*)(v_ram + CYBMEM_OFFSET_8);
  1279. break;
  1280. #endif
  1281. #ifdef FBCON_HAS_CFB16
  1282. case 16:
  1283. info->screen_base = (char*)(v_ram + CYBMEM_OFFSET_16);
  1284. break;
  1285. #endif
  1286. #ifdef FBCON_HAS_CFB32
  1287. case 32:
  1288. info->screen_base = (char*)(v_ram + CYBMEM_OFFSET_32);
  1289. break;
  1290. #endif
  1291. }
  1292. }
  1293. display->visual = fix.visual;
  1294. display->type = fix.type;
  1295. display->type_aux = fix.type_aux;
  1296. display->ypanstep = fix.ypanstep;
  1297. display->ywrapstep = fix.ywrapstep;
  1298. display->can_soft_blank = 1;
  1299. display->inverse = virgefb_inverse;
  1300. display->line_length = display->var.xres_virtual*
  1301. display->var.bits_per_pixel/8;
  1302. switch (display->var.bits_per_pixel) {
  1303. #ifdef FBCON_HAS_CFB8
  1304. case 8:
  1305. if (display->var.accel_flags & FB_ACCELF_TEXT) {
  1306. display->dispsw = &fbcon_virge8;
  1307. #warning FIXME: We should reinit the graphics engine here
  1308. } else
  1309. display->dispsw = &fbcon_cfb8;
  1310. break;
  1311. #endif
  1312. #ifdef FBCON_HAS_CFB16
  1313. case 16:
  1314. if (display->var.accel_flags & FB_ACCELF_TEXT) {
  1315. display->dispsw = &fbcon_virge16;
  1316. } else
  1317. display->dispsw = &fbcon_cfb16;
  1318. display->dispsw_data = &fbcon_cmap.cfb16;
  1319. break;
  1320. #endif
  1321. #ifdef FBCON_HAS_CFB32
  1322. case 32:
  1323. if (display->var.accel_flags & FB_ACCELF_TEXT) {
  1324. display->dispsw = &fbcon_virge32;
  1325. } else
  1326. display->dispsw = &fbcon_cfb32;
  1327. display->dispsw_data = &fbcon_cmap.cfb32;
  1328. break;
  1329. #endif
  1330. default:
  1331. display->dispsw = &fbcon_dummy;
  1332. break;
  1333. }
  1334. DPRINTK("EXIT v_ram virt = 0x%8.8lx\n",(unsigned long)display->screen_base);
  1335. }
  1336. /*
  1337. * Set the User Defined Part of the Display
  1338. */
  1339. static int virgefb_set_var(struct fb_var_screeninfo *var, int con,
  1340. struct fb_info *info)
  1341. {
  1342. int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel;
  1343. DPRINTK("ENTER\n");
  1344. if ((err = virgefb_do_fb_set_var(var, con == info->currcon))) {
  1345. DPRINTK("EXIT\n");
  1346. return(err);
  1347. }
  1348. if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
  1349. oldxres = fb_display[con].var.xres;
  1350. oldyres = fb_display[con].var.yres;
  1351. oldvxres = fb_display[con].var.xres_virtual;
  1352. oldvyres = fb_display[con].var.yres_virtual;
  1353. oldbpp = fb_display[con].var.bits_per_pixel;
  1354. oldaccel = fb_display[con].var.accel_flags;
  1355. fb_display[con].var = *var;
  1356. if (oldxres != var->xres || oldyres != var->yres ||
  1357. oldvxres != var->xres_virtual ||
  1358. oldvyres != var->yres_virtual ||
  1359. oldbpp != var->bits_per_pixel ||
  1360. oldaccel != var->accel_flags) {
  1361. virgefb_set_disp(con, info);
  1362. if (fb_info.changevar)
  1363. (*fb_info.changevar)(con);
  1364. fb_alloc_cmap(&fb_display[con].cmap, 0, 0);
  1365. do_install_cmap(con, info);
  1366. }
  1367. }
  1368. var->activate = 0;
  1369. DPRINTK("EXIT\n");
  1370. return 0;
  1371. }
  1372. /*
  1373. * Get the Colormap
  1374. */
  1375. static int virgefb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
  1376. struct fb_info *info)
  1377. {
  1378. DPRINTK("ENTER\n");
  1379. if (con == info->currcon) { /* current console? */
  1380. DPRINTK("EXIT - console is current console, fb_get_cmap\n");
  1381. return(fb_get_cmap(cmap, kspc, fbhw->getcolreg, info));
  1382. } else if (fb_display[con].cmap.len) { /* non default colormap? */
  1383. DPRINTK("Use console cmap\n");
  1384. fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
  1385. } else {
  1386. DPRINTK("Use default cmap\n");
  1387. fb_copy_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel==8 ? 256 : 16),
  1388. cmap, kspc ? 0 : 2);
  1389. }
  1390. DPRINTK("EXIT\n");
  1391. return 0;
  1392. }
  1393. static struct fb_ops virgefb_ops = {
  1394. .owner = THIS_MODULE,
  1395. .fb_get_fix = virgefb_get_fix,
  1396. .fb_get_var = virgefb_get_var,
  1397. .fb_set_var = virgefb_set_var,
  1398. .fb_get_cmap = virgefb_get_cmap,
  1399. .fb_set_cmap = gen_set_cmap,
  1400. .fb_setcolreg = virgefb_setcolreg,
  1401. .fb_blank = virgefb_blank,
  1402. };
  1403. int __init virgefb_setup(char *options)
  1404. {
  1405. char *this_opt;
  1406. fb_info.fontname[0] = '\0';
  1407. DPRINTK("ENTER\n");
  1408. if (!options || !*options) {
  1409. DPRINTK("EXIT\n");
  1410. return 0;
  1411. }
  1412. while ((this_opt = strsep(&options, ",")) != NULL) {
  1413. if (!*this_opt)
  1414. continue;
  1415. if (!strcmp(this_opt, "inverse")) {
  1416. virgefb_inverse = 1;
  1417. fb_invert_cmaps();
  1418. } else if (!strncmp(this_opt, "font:", 5))
  1419. strcpy(fb_info.fontname, this_opt+5);
  1420. #ifdef FBCON_HAS_CFB8
  1421. else if (!strcmp (this_opt, "virge8")){
  1422. virgefb_default = virgefb_predefined[VIRGE8_DEFMODE].var;
  1423. }
  1424. #endif
  1425. #ifdef FBCON_HAS_CFB16
  1426. else if (!strcmp (this_opt, "virge16")){
  1427. virgefb_default = virgefb_predefined[VIRGE16_DEFMODE].var;
  1428. }
  1429. #endif
  1430. #ifdef FBCON_HAS_CFB32
  1431. else if (!strcmp (this_opt, "virge32")){
  1432. virgefb_default = virgefb_predefined[VIRGE32_DEFMODE].var;
  1433. }
  1434. #endif
  1435. else
  1436. virgefb_get_video_mode(this_opt);
  1437. }
  1438. printk(KERN_INFO "mode : xres=%d, yres=%d, bpp=%d\n", virgefb_default.xres,
  1439. virgefb_default.yres, virgefb_default.bits_per_pixel);
  1440. DPRINTK("EXIT\n");
  1441. return 0;
  1442. }
  1443. /*
  1444. * Get a Video Mode
  1445. */
  1446. static int __init virgefb_get_video_mode(const char *name)
  1447. {
  1448. int i;
  1449. DPRINTK("ENTER\n");
  1450. for (i = 0; i < NUM_TOTAL_MODES; i++) {
  1451. if (!strcmp(name, virgefb_predefined[i].name)) {
  1452. virgefb_default = virgefb_predefined[i].var;
  1453. DPRINTK("EXIT\n");
  1454. return(i);
  1455. }
  1456. }
  1457. /* ++Andre: set virgefb default mode */
  1458. /* prefer 16 bit depth, 8 if no 16, if no 8 or 16 use 32 */
  1459. #ifdef FBCON_HAS_CFB32
  1460. virgefb_default = virgefb_predefined[VIRGE32_DEFMODE].var;
  1461. #endif
  1462. #ifdef FBCON_HAS_CFB8
  1463. virgefb_default = virgefb_predefined[VIRGE8_DEFMODE].var;
  1464. #endif
  1465. #ifdef FBCON_HAS_CFB16
  1466. virgefb_default = virgefb_predefined[VIRGE16_DEFMODE].var;
  1467. #endif
  1468. DPRINTK("EXIT\n");
  1469. return 0;
  1470. }
  1471. /*
  1472. * Initialization
  1473. */
  1474. int __init virgefb_init(void)
  1475. {
  1476. struct virgefb_par par;
  1477. unsigned long board_addr, board_size;
  1478. struct zorro_dev *z = NULL;
  1479. DPRINTK("ENTER\n");
  1480. z = zorro_find_device(ZORRO_PROD_PHASE5_CYBERVISION64_3D, NULL);
  1481. if (!z)
  1482. return -ENODEV;
  1483. board_addr = z->resource.start;
  1484. if (board_addr < 0x01000000) {
  1485. /* board running in Z2 space. This includes the video memory
  1486. as well as the S3 register set */
  1487. on_zorro2 = 1;
  1488. board_size = 0x00400000;
  1489. if (!request_mem_region(board_addr, board_size, "S3 ViRGE"))
  1490. return -ENOMEM;
  1491. v_ram_phys = board_addr;
  1492. v_ram = ZTWO_VADDR(v_ram_phys);
  1493. mmio_regs_phys = (unsigned long)(board_addr + 0x003c0000);
  1494. vgaio_regs = (unsigned char *) ZTWO_VADDR(board_addr + 0x003c0000);
  1495. mmio_regs = (unsigned char *)ZTWO_VADDR(mmio_regs_phys);
  1496. vcode_switch_base = (unsigned long) ZTWO_VADDR(board_addr + 0x003a0000);
  1497. printk(KERN_INFO "CV3D detected running in Z2 mode.\n");
  1498. } else {
  1499. /* board running in Z3 space. Separate video memory (3 apertures)
  1500. and S3 register set */
  1501. on_zorro2 = 0;
  1502. board_size = 0x01000000;
  1503. if (!request_mem_region(board_addr, board_size, "S3 ViRGE"))
  1504. return -ENOMEM;
  1505. v_ram_phys = board_addr + 0x04000000;
  1506. v_ram = (unsigned long)ioremap(v_ram_phys, 0x01000000);
  1507. mmio_regs_phys = board_addr + 0x05000000;
  1508. vgaio_regs = (unsigned char *)ioremap(board_addr +0x0c000000, 0x00100000); /* includes PCI regs */
  1509. mmio_regs = ioremap(mmio_regs_phys, 0x00010000);
  1510. vcode_switch_base = (unsigned long)ioremap(board_addr + 0x08000000, 0x1000);
  1511. printk(KERN_INFO "CV3D detected running in Z3 mode\n");
  1512. }
  1513. #if defined (VIRGEFBDEBUG)
  1514. DPRINTK("board_addr : 0x%8.8lx\n",board_addr);
  1515. DPRINTK("board_size : 0x%8.8lx\n",board_size);
  1516. DPRINTK("mmio_regs_phy : 0x%8.8lx\n",mmio_regs_phys);
  1517. DPRINTK("v_ram_phys : 0x%8.8lx\n",v_ram_phys);
  1518. DPRINTK("vgaio_regs : 0x%8.8lx\n",(unsigned long)vgaio_regs);
  1519. DPRINTK("mmio_regs : 0x%8.8lx\n",(unsigned long)mmio_regs);
  1520. DPRINTK("v_ram : 0x%8.8lx\n",v_ram);
  1521. DPRINTK("vcode sw base : 0x%8.8lx\n",vcode_switch_base);
  1522. #endif
  1523. fbhw = &virgefb_hw_switch;
  1524. strcpy(fb_info.modename, virgefb_name);
  1525. fb_info.changevar = NULL;
  1526. fb_info.fbops = &virgefb_ops;
  1527. fb_info.disp = &disp;
  1528. fb_info.currcon = -1;
  1529. fb_info.switch_con = &virgefb_switch;
  1530. fb_info.updatevar = &virgefb_updatevar;
  1531. fb_info.flags = FBINFO_FLAG_DEFAULT;
  1532. fbhw->init();
  1533. fbhw->decode_var(&virgefb_default, &par);
  1534. fbhw->encode_var(&virgefb_default, &par);
  1535. virgefb_do_fb_set_var(&virgefb_default, 1);
  1536. virgefb_get_var(&fb_display[0].var, -1, &fb_info);
  1537. virgefb_set_disp(-1, &fb_info);
  1538. do_install_cmap(0, &fb_info);
  1539. if (register_framebuffer(&fb_info) < 0) {
  1540. #warning release resources
  1541. printk(KERN_ERR "virgefb.c: register_framebuffer failed\n");
  1542. DPRINTK("EXIT\n");
  1543. goto out_unmap;
  1544. }
  1545. printk(KERN_INFO "fb%d: %s frame buffer device, using %ldK of video memory\n",
  1546. fb_info.node, fb_info.modename, v_ram_size>>10);
  1547. /* TODO: This driver cannot be unloaded yet */
  1548. DPRINTK("EXIT\n");
  1549. return 0;
  1550. out_unmap:
  1551. if (board_addr >= 0x01000000) {
  1552. if (v_ram)
  1553. iounmap((void*)v_ram);
  1554. if (vgaio_regs)
  1555. iounmap(vgaio_regs);
  1556. if (mmio_regs)
  1557. iounmap(mmio_regs);
  1558. if (vcode_switch_base)
  1559. iounmap((void*)vcode_switch_base);
  1560. v_ram = vcode_switch_base = 0;
  1561. vgaio_regs = mmio_regs = NULL;
  1562. }
  1563. return -EINVAL;
  1564. }
  1565. static int virgefb_switch(int con, struct fb_info *info)
  1566. {
  1567. DPRINTK("ENTER\n");
  1568. /* Do we have to save the colormap? */
  1569. if (fb_display[info->currcon].cmap.len)
  1570. fb_get_cmap(&fb_display[info->currcon].cmap, 1,
  1571. fbhw->getcolreg, info);
  1572. virgefb_do_fb_set_var(&fb_display[con].var, 1);
  1573. info->currcon = con;
  1574. /* Install new colormap */
  1575. do_install_cmap(con, info);
  1576. DPRINTK("EXIT\n");
  1577. return 0;
  1578. }
  1579. /*
  1580. * Update the `var' structure (called by fbcon.c)
  1581. *
  1582. * This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
  1583. * Since it's called by a kernel driver, no range checking is done.
  1584. */
  1585. static int virgefb_updatevar(int con, struct fb_info *info)
  1586. {
  1587. DPRINTK("ENTER\n");
  1588. return 0;
  1589. DPRINTK("EXIT\n");
  1590. }
  1591. /*
  1592. * Blank the display.
  1593. */
  1594. static int virgefb_blank(int blank, struct fb_info *info)
  1595. {
  1596. DPRINTK("ENTER\n");
  1597. fbhw->blank(blank);
  1598. DPRINTK("EXIT\n");
  1599. return 0;
  1600. }
  1601. /*
  1602. * Text console acceleration
  1603. */
  1604. #ifdef FBCON_HAS_CFB8
  1605. static void fbcon_virge8_bmove(struct display *p, int sy, int sx, int dy,
  1606. int dx, int height, int width)
  1607. {
  1608. sx *= 8; dx *= 8; width *= 8;
  1609. virgefb_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
  1610. (u_short)(dy*fontheight(p)), (u_short)width,
  1611. (u_short)(height*fontheight(p)), (u_short)p->next_line, 8);
  1612. }
  1613. static void fbcon_virge8_clear(struct vc_data *conp, struct display *p, int sy,
  1614. int sx, int height, int width)
  1615. {
  1616. unsigned char bg;
  1617. sx *= 8; width *= 8;
  1618. bg = attr_bgcol_ec(p,conp);
  1619. virgefb_RectFill((u_short)sx, (u_short)(sy*fontheight(p)),
  1620. (u_short)width, (u_short)(height*fontheight(p)),
  1621. (u_short)bg, (u_short)p->next_line, 8);
  1622. }
  1623. static void fbcon_virge8_putc(struct vc_data *conp, struct display *p, int c, int yy,
  1624. int xx)
  1625. {
  1626. if (blit_maybe_busy)
  1627. virgefb_wait_for_idle();
  1628. fbcon_cfb8_putc(conp, p, c, yy, xx);
  1629. }
  1630. static void fbcon_virge8_putcs(struct vc_data *conp, struct display *p,
  1631. const unsigned short *s, int count, int yy, int xx)
  1632. {
  1633. if (blit_maybe_busy)
  1634. virgefb_wait_for_idle();
  1635. fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
  1636. }
  1637. static void fbcon_virge8_revc(struct display *p, int xx, int yy)
  1638. {
  1639. if (blit_maybe_busy)
  1640. virgefb_wait_for_idle();
  1641. fbcon_cfb8_revc(p, xx, yy);
  1642. }
  1643. static void fbcon_virge8_clear_margins(struct vc_data *conp, struct display *p,
  1644. int bottom_only)
  1645. {
  1646. if (blit_maybe_busy)
  1647. virgefb_wait_for_idle();
  1648. fbcon_cfb8_clear_margins(conp, p, bottom_only);
  1649. }
  1650. static struct display_switch fbcon_virge8 = {
  1651. .setup = fbcon_cfb8_setup,
  1652. .bmove = fbcon_virge8_bmove,
  1653. .clear = fbcon_virge8_clear,
  1654. .putc = fbcon_virge8_putc,
  1655. .putcs = fbcon_virge8_putcs,
  1656. .revc = fbcon_virge8_revc,
  1657. .clear_margins = fbcon_virge8_clear_margins,
  1658. .fontwidthmask = FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
  1659. };
  1660. #endif
  1661. #ifdef FBCON_HAS_CFB16
  1662. static void fbcon_virge16_bmove(struct display *p, int sy, int sx, int dy,
  1663. int dx, int height, int width)
  1664. {
  1665. sx *= 8; dx *= 8; width *= 8;
  1666. virgefb_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
  1667. (u_short)(dy*fontheight(p)), (u_short)width,
  1668. (u_short)(height*fontheight(p)), (u_short)p->next_line, 16);
  1669. }
  1670. static void fbcon_virge16_clear(struct vc_data *conp, struct display *p, int sy,
  1671. int sx, int height, int width)
  1672. {
  1673. unsigned char bg;
  1674. sx *= 8; width *= 8;
  1675. bg = attr_bgcol_ec(p,conp);
  1676. virgefb_RectFill((u_short)sx, (u_short)(sy*fontheight(p)),
  1677. (u_short)width, (u_short)(height*fontheight(p)),
  1678. (u_short)bg, (u_short)p->next_line, 16);
  1679. }
  1680. static void fbcon_virge16_putc(struct vc_data *conp, struct display *p, int c, int yy,
  1681. int xx)
  1682. {
  1683. if (blit_maybe_busy)
  1684. virgefb_wait_for_idle();
  1685. fbcon_cfb16_putc(conp, p, c, yy, xx);
  1686. }
  1687. static void fbcon_virge16_putcs(struct vc_data *conp, struct display *p,
  1688. const unsigned short *s, int count, int yy, int xx)
  1689. {
  1690. if (blit_maybe_busy)
  1691. virgefb_wait_for_idle();
  1692. fbcon_cfb16_putcs(conp, p, s, count, yy, xx);
  1693. }
  1694. static void fbcon_virge16_revc(struct display *p, int xx, int yy)
  1695. {
  1696. if (blit_maybe_busy)
  1697. virgefb_wait_for_idle();
  1698. fbcon_cfb16_revc(p, xx, yy);
  1699. }
  1700. static void fbcon_virge16_clear_margins(struct vc_data *conp, struct display *p,
  1701. int bottom_only)
  1702. {
  1703. if (blit_maybe_busy)
  1704. virgefb_wait_for_idle();
  1705. fbcon_cfb16_clear_margins(conp, p, bottom_only);
  1706. }
  1707. static struct display_switch fbcon_virge16 = {
  1708. .setup = fbcon_cfb16_setup,
  1709. .bmove = fbcon_virge16_bmove,
  1710. .clear = fbcon_virge16_clear,
  1711. .putc = fbcon_virge16_putc,
  1712. .putcs = fbcon_virge16_putcs,
  1713. .revc = fbcon_virge16_revc,
  1714. .clear_margins = fbcon_virge16_clear_margins,
  1715. .fontwidthmask = FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
  1716. };
  1717. #endif
  1718. #ifdef FBCON_HAS_CFB32
  1719. static void fbcon_virge32_bmove(struct display *p, int sy, int sx, int dy,
  1720. int dx, int height, int width)
  1721. {
  1722. sx *= 16; dx *= 16; width *= 16; /* doubled these values to do 32 bit blit */
  1723. virgefb_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
  1724. (u_short)(dy*fontheight(p)), (u_short)width,
  1725. (u_short)(height*fontheight(p)), (u_short)p->next_line, 16);
  1726. }
  1727. static void fbcon_virge32_clear(struct vc_data *conp, struct display *p, int sy,
  1728. int sx, int height, int width)
  1729. {
  1730. unsigned char bg;
  1731. sx *= 16; width *= 16; /* doubled these values to do 32 bit blit */
  1732. bg = attr_bgcol_ec(p,conp);
  1733. virgefb_RectFill((u_short)sx, (u_short)(sy*fontheight(p)),
  1734. (u_short)width, (u_short)(height*fontheight(p)),
  1735. (u_short)bg, (u_short)p->next_line, 16);
  1736. }
  1737. static void fbcon_virge32_putc(struct vc_data *conp, struct display *p, int c, int yy,
  1738. int xx)
  1739. {
  1740. if (blit_maybe_busy)
  1741. virgefb_wait_for_idle();
  1742. fbcon_cfb32_putc(conp, p, c, yy, xx);
  1743. }
  1744. static void fbcon_virge32_putcs(struct vc_data *conp, struct display *p,
  1745. const unsigned short *s, int count, int yy, int xx)
  1746. {
  1747. if (blit_maybe_busy)
  1748. virgefb_wait_for_idle();
  1749. fbcon_cfb32_putcs(conp, p, s, count, yy, xx);
  1750. }
  1751. static void fbcon_virge32_revc(struct display *p, int xx, int yy)
  1752. {
  1753. if (blit_maybe_busy)
  1754. virgefb_wait_for_idle();
  1755. fbcon_cfb32_revc(p, xx, yy);
  1756. }
  1757. static void fbcon_virge32_clear_margins(struct vc_data *conp, struct display *p,
  1758. int bottom_only)
  1759. {
  1760. if (blit_maybe_busy)
  1761. virgefb_wait_for_idle();
  1762. fbcon_cfb32_clear_margins(conp, p, bottom_only);
  1763. }
  1764. static struct display_switch fbcon_virge32 = {
  1765. .setup = fbcon_cfb32_setup,
  1766. .bmove = fbcon_virge32_bmove,
  1767. .clear = fbcon_virge32_clear,
  1768. .putc = fbcon_virge32_putc,
  1769. .putcs = fbcon_virge32_putcs,
  1770. .revc = fbcon_virge32_revc,
  1771. .clear_margins = fbcon_virge32_clear_margins,
  1772. .fontwidthmask = FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
  1773. };
  1774. #endif
  1775. #ifdef MODULE
  1776. MODULE_LICENSE("GPL");
  1777. int init_module(void)
  1778. {
  1779. return virgefb_init();
  1780. }
  1781. #endif /* MODULE */
  1782. static int cv3d_has_4mb(void)
  1783. {
  1784. /* cyberfb version didn't work, neither does this (not reliably)
  1785. forced to return 4MB */
  1786. #if 0
  1787. volatile unsigned long *t0, *t2;
  1788. #endif
  1789. DPRINTK("ENTER\n");
  1790. #if 0
  1791. /* write patterns in memory and test if they can be read */
  1792. t0 = (volatile unsigned long *)v_ram;
  1793. t2 = (volatile unsigned long *)(v_ram + 0x00200000);
  1794. *t0 = 0x87654321;
  1795. *t2 = 0x12345678;
  1796. if (*t0 != 0x87654321) {
  1797. /* read of first location failed */
  1798. DPRINTK("EXIT - 0MB !\n");
  1799. return 0;
  1800. }
  1801. if (*t2 == 0x87654321) {
  1802. /* should read 0x12345678 if 4MB */
  1803. DPRINTK("EXIT - 2MB(a) \n");
  1804. return 0;
  1805. }
  1806. if (*t2 != 0x12345678) {
  1807. /* upper 2MB read back match failed */
  1808. DPRINTK("EXIT - 2MB(b)\n");
  1809. return 0;
  1810. }
  1811. /* may have 4MB */
  1812. *t2 = 0xAAAAAAAA;
  1813. if(*t2 != 0xAAAAAAAA) {
  1814. /* upper 2MB read back match failed */
  1815. DPRINTK("EXIT - 2MB(c)\n");
  1816. return 0;
  1817. }
  1818. *t2 = 0x55555555;
  1819. if(*t2 != 0x55555555) {
  1820. /* upper 2MB read back match failed */
  1821. DPRINTK("EXIT - 2MB(d)\n");
  1822. return 0;
  1823. }
  1824. #endif
  1825. DPRINTK("EXIT - 4MB\n");
  1826. return 1;
  1827. }
  1828. /*
  1829. * Computes M, N, and R pll params for freq arg.
  1830. * Returns 16 bits - hi 0MMMMMM lo 0RRNNNNN
  1831. */
  1832. #define REFCLOCK 14318000
  1833. static unsigned short virgefb_compute_clock(unsigned long freq)
  1834. {
  1835. unsigned char m, n, r, rpwr;
  1836. unsigned long diff, ftry, save = ~0UL;
  1837. unsigned short mnr;
  1838. DPRINTK("ENTER\n");
  1839. for (r = 0, rpwr = 1 ; r < 4 ; r++, rpwr *= 2) {
  1840. if ((135000000 <= (rpwr * freq)) && ((rpwr * freq) <= 270000000)) {
  1841. for (n = 1 ; n < 32 ; n++) {
  1842. m = ((freq * (n + 2) * rpwr)/REFCLOCK) - 2;
  1843. if (m == 0 || m >127)
  1844. break;
  1845. ftry = ((REFCLOCK / (n + 2)) * (m + 2)) / rpwr;
  1846. if (ftry > freq)
  1847. diff = ftry - freq;
  1848. else
  1849. diff = freq - ftry;
  1850. if (diff < save) {
  1851. save = diff;
  1852. mnr = (m << 8) | (r<<5) | (n & 0x7f);
  1853. }
  1854. }
  1855. }
  1856. }
  1857. if (save == ~0UL)
  1858. printk("Can't compute clock PLL values for %ld Hz clock\n", freq);
  1859. DPRINTK("EXIT\n");
  1860. return(mnr);
  1861. }
  1862. static void virgefb_load_video_mode(struct fb_var_screeninfo *video_mode)
  1863. {
  1864. unsigned char lace, dblscan, tmp;
  1865. unsigned short mnr;
  1866. unsigned short HT, HDE, HBS, HBW, HSS, HSW;
  1867. unsigned short VT, VDE, VBS, VBW, VSS, VSW;
  1868. unsigned short SCO;
  1869. int cr11;
  1870. int cr67;
  1871. int hmul;
  1872. int xres, xres_virtual, hfront, hsync, hback;
  1873. int yres, vfront, vsync, vback;
  1874. int bpp;
  1875. int i;
  1876. long freq;
  1877. DPRINTK("ENTER : %dx%d-%d\n",video_mode->xres, video_mode->yres,
  1878. video_mode->bits_per_pixel);
  1879. bpp = video_mode->bits_per_pixel;
  1880. xres = video_mode->xres;
  1881. xres_virtual = video_mode->xres_virtual;
  1882. hfront = video_mode->right_margin;
  1883. hsync = video_mode->hsync_len;
  1884. hback = video_mode->left_margin;
  1885. lace = 0;
  1886. dblscan = 0;
  1887. if (video_mode->vmode & FB_VMODE_DOUBLE) {
  1888. yres = video_mode->yres * 2;
  1889. vfront = video_mode->lower_margin * 2;
  1890. vsync = video_mode->vsync_len * 2;
  1891. vback = video_mode->upper_margin * 2;
  1892. dblscan = 1;
  1893. } else if (video_mode->vmode & FB_VMODE_INTERLACED) {
  1894. yres = (video_mode->yres + 1) / 2;
  1895. vfront = (video_mode->lower_margin + 1) / 2;
  1896. vsync = (video_mode->vsync_len + 1) / 2;
  1897. vback = (video_mode->upper_margin + 1) / 2;
  1898. lace = 1;
  1899. } else {
  1900. yres = video_mode->yres;
  1901. vfront = video_mode->lower_margin;
  1902. vsync = video_mode->vsync_len;
  1903. vback = video_mode->upper_margin;
  1904. }
  1905. switch (bpp) {
  1906. case 8:
  1907. video_mode->red.offset = 0;
  1908. video_mode->green.offset = 0;
  1909. video_mode->blue.offset = 0;
  1910. video_mode->transp.offset = 0;
  1911. video_mode->red.length = 8;
  1912. video_mode->green.length = 8;
  1913. video_mode->blue.length = 8;
  1914. video_mode->transp.length = 0;
  1915. hmul = 1;
  1916. cr67 = 0x00;
  1917. SCO = xres_virtual / 8;
  1918. break;
  1919. case 16:
  1920. video_mode->red.offset = 11;
  1921. video_mode->green.offset = 5;
  1922. video_mode->blue.offset = 0;
  1923. video_mode->transp.offset = 0;
  1924. video_mode->red.length = 5;
  1925. video_mode->green.length = 6;
  1926. video_mode->blue.length = 5;
  1927. video_mode->transp.length = 0;
  1928. hmul = 2;
  1929. cr67 = 0x50;
  1930. SCO = xres_virtual / 4;
  1931. break;
  1932. case 32:
  1933. video_mode->red.offset = 16;
  1934. video_mode->green.offset = 8;
  1935. video_mode->blue.offset = 0;
  1936. video_mode->transp.offset = 24;
  1937. video_mode->red.length = 8;
  1938. video_mode->green.length = 8;
  1939. video_mode->blue.length = 8;
  1940. video_mode->transp.length = 8;
  1941. hmul = 1;
  1942. cr67 = 0xd0;
  1943. SCO = xres_virtual / 2;
  1944. break;
  1945. }
  1946. HT = (((xres + hfront + hsync + hback) / 8) * hmul) - 5;
  1947. HDE = ((xres / 8) * hmul) - 1;
  1948. HBS = (xres / 8) * hmul;
  1949. HSS = ((xres + hfront) / 8) * hmul;
  1950. HSW = (hsync / 8) * hmul;
  1951. HBW = (((hfront + hsync + hback) / 8) * hmul) - 2;
  1952. VT = yres + vfront + vsync + vback - 2;
  1953. VDE = yres - 1;
  1954. VBS = yres - 1;
  1955. VSS = yres + vfront;
  1956. VSW = vsync;
  1957. VBW = vfront + vsync + vback - 2;
  1958. #ifdef VIRGEFBDEBUG
  1959. DPRINTK("HDE : 0x%4.4x, %4.4d\n", HDE, HDE);
  1960. DPRINTK("HBS : 0x%4.4x, %4.4d\n", HBS, HBS);
  1961. DPRINTK("HSS : 0x%4.4x, %4.4d\n", HSS, HSS);
  1962. DPRINTK("HSW : 0x%4.4x, %4.4d\n", HSW, HSW);
  1963. DPRINTK("HBW : 0x%4.4x, %4.4d\n", HBW, HBW);
  1964. DPRINTK("HSS + HSW : 0x%4.4x, %4.4d\n", HSS+HSW, HSS+HSW);
  1965. DPRINTK("HBS + HBW : 0x%4.4x, %4.4d\n", HBS+HBW, HBS+HBW);
  1966. DPRINTK("HT : 0x%4.4x, %4.4d\n", HT, HT);
  1967. DPRINTK("VDE : 0x%4.4x, %4.4d\n", VDE, VDE);
  1968. DPRINTK("VBS : 0x%4.4x, %4.4d\n", VBS, VBS);
  1969. DPRINTK("VSS : 0x%4.4x, %4.4d\n", VSS, VSS);
  1970. DPRINTK("VSW : 0x%4.4x, %4.4d\n", VSW, VSW);
  1971. DPRINTK("VBW : 0x%4.4x, %4.4d\n", VBW, VBW);
  1972. DPRINTK("VT : 0x%4.4x, %4.4d\n", VT, VT);
  1973. #endif
  1974. /* turn gfx off, don't mess up the display */
  1975. gfx_on_off(1);
  1976. /* H and V sync polarity */
  1977. tmp = rb_mmio(GREG_MISC_OUTPUT_R) & 0x2f; /* colour, ram enable, clk sr12/s13 sel */
  1978. if (!(video_mode->sync & FB_SYNC_HOR_HIGH_ACT))
  1979. tmp |= 0x40; /* neg H sync polarity */
  1980. if (!(video_mode->sync & FB_SYNC_VERT_HIGH_ACT))
  1981. tmp |= 0x80; /* neg V sync polarity */
  1982. tmp |= 0x0c; /* clk from sr12/sr13 */
  1983. wb_mmio(GREG_MISC_OUTPUT_W, tmp);
  1984. /* clocks */
  1985. wseq(SEQ_ID_BUS_REQ_CNTL, 0xc0); /* 2 clk mem wr and /RAS1 */
  1986. wseq(SEQ_ID_CLKSYN_CNTL_2, 0x80); /* b7 is 2 mem clk wr */
  1987. mnr = virgefb_compute_clock(MEMCLOCK);
  1988. DPRINTK("mem clock %d, m %d, n %d, r %d.\n", MEMCLOCK, ((mnr>>8)&0x7f), (mnr&0x1f), ((mnr >> 5)&0x03));
  1989. wseq(SEQ_ID_MCLK_LO, (mnr & 0x7f));
  1990. wseq(SEQ_ID_MCLK_HI, ((mnr & 0x7f00) >> 8));
  1991. freq = (1000000000 / video_mode->pixclock) * 1000; /* pixclock is in ps ... convert to Hz */
  1992. mnr = virgefb_compute_clock(freq);
  1993. DPRINTK("dot clock %ld, m %d, n %d, r %d.\n", freq, ((mnr>>8)&0x7f), (mnr&0x1f), ((mnr>>5)&0x03));
  1994. wseq(SEQ_ID_DCLK_LO, (mnr & 0x7f));
  1995. wseq(SEQ_ID_DCLK_HI, ((mnr & 0x7f00) >> 8));
  1996. wseq(SEQ_ID_CLKSYN_CNTL_2, 0xa0);
  1997. wseq(SEQ_ID_CLKSYN_CNTL_2, 0x80);
  1998. udelay(100);
  1999. /* load display parameters into board */
  2000. /* not sure about sync and blanking extensions bits in cr5d and cr5 */
  2001. wcrt(CRT_ID_EXT_HOR_OVF, /* 0x5d */
  2002. ((HT & 0x100) ? 0x01 : 0x00) |
  2003. ((HDE & 0x100) ? 0x02 : 0x00) |
  2004. ((HBS & 0x100) ? 0x04 : 0x00) |
  2005. /* (((HBS + HBW) & 0x40) ? 0x08 : 0x00) | */
  2006. ((HSS & 0x100) ? 0x10 : 0x00) |
  2007. /* (((HSS + HSW) & 0x20) ? 0x20 : 0x00) | */
  2008. ((HSW >= 0x20) ? 0x20 : 0x00) |
  2009. (((HT-5) & 0x100) ? 0x40 : 0x00));
  2010. wcrt(CRT_ID_EXT_VER_OVF, /* 0x5e */
  2011. ((VT & 0x400) ? 0x01 : 0x00) |
  2012. ((VDE & 0x400) ? 0x02 : 0x00) |
  2013. ((VBS & 0x400) ? 0x04 : 0x00) |
  2014. ((VSS & 0x400) ? 0x10 : 0x00) |
  2015. 0x40); /* line compare */
  2016. wcrt(CRT_ID_START_VER_RETR, VSS);
  2017. cr11 = rcrt(CRT_ID_END_VER_RETR) | 0x20; /* vert interrupt flag */
  2018. wcrt(CRT_ID_END_VER_RETR, ((cr11 & 0x20) | ((VSS + VSW) & 0x0f))); /* keeps vert irq enable state, also has unlock bit cr0 to 7 */
  2019. wcrt(CRT_ID_VER_DISP_ENA_END, VDE);
  2020. wcrt(CRT_ID_START_VER_BLANK, VBS);
  2021. wcrt(CRT_ID_END_VER_BLANK, VBS + VBW); /* might be +/- 1 out */
  2022. wcrt(CRT_ID_HOR_TOTAL, HT);
  2023. wcrt(CRT_ID_DISPLAY_FIFO, HT - 5);
  2024. wcrt(CRT_ID_BACKWAD_COMP_3, 0x10); /* enable display fifo */
  2025. wcrt(CRT_ID_HOR_DISP_ENA_END, HDE);
  2026. wcrt(CRT_ID_START_HOR_BLANK , HBS);
  2027. wcrt(CRT_ID_END_HOR_BLANK, (HBS + HBW) & 0x1f);
  2028. wcrt(CRT_ID_START_HOR_RETR, HSS);
  2029. wcrt(CRT_ID_END_HOR_RETR, /* cr5 */
  2030. ((HSS + HSW) & 0x1f) |
  2031. (((HBS + HBW) & 0x20) ? 0x80 : 0x00));
  2032. wcrt(CRT_ID_VER_TOTAL, VT);
  2033. wcrt(CRT_ID_OVERFLOW,
  2034. ((VT & 0x100) ? 0x01 : 0x00) |
  2035. ((VDE & 0x100) ? 0x02 : 0x00) |
  2036. ((VSS & 0x100) ? 0x04 : 0x00) |
  2037. ((VBS & 0x100) ? 0x08 : 0x00) |
  2038. 0x10 |
  2039. ((VT & 0x200) ? 0x20 : 0x00) |
  2040. ((VDE & 0x200) ? 0x40 : 0x00) |
  2041. ((VSS & 0x200) ? 0x80 : 0x00));
  2042. wcrt(CRT_ID_MAX_SCAN_LINE,
  2043. (dblscan ? 0x80 : 0x00) |
  2044. 0x40 |
  2045. ((VBS & 0x200) ? 0x20 : 0x00));
  2046. wcrt(CRT_ID_LINE_COMPARE, 0xff);
  2047. wcrt(CRT_ID_LACE_RETR_START, HT / 2); /* (HT-5)/2 ? */
  2048. wcrt(CRT_ID_LACE_CONTROL, (lace ? 0x20 : 0x00));
  2049. wcrt(CRT_ID_SCREEN_OFFSET, SCO);
  2050. wcrt(CRT_ID_EXT_SYS_CNTL_2, (SCO >> 4) & 0x30 );
  2051. /* wait for vert sync before cr67 update */
  2052. for (i=0; i < 10000; i++) {
  2053. udelay(10);
  2054. mb();
  2055. if (rb_mmio(GREG_INPUT_STATUS1_R) & 0x08)
  2056. break;
  2057. }
  2058. wl_mmio(0x8200, 0x0000c000); /* fifo control (0x00110400 ?) */
  2059. wcrt(CRT_ID_EXT_MISC_CNTL_2, cr67);
  2060. /* enable video */
  2061. tmp = rb_mmio(ACT_ADDRESS_RESET);
  2062. wb_mmio(ACT_ADDRESS_W, ((bpp == 8) ? 0x20 : 0x00)); /* set b5, ENB PLT in attr idx reg) */
  2063. tmp = rb_mmio(ACT_ADDRESS_RESET);
  2064. /* turn gfx on again */
  2065. gfx_on_off(0);
  2066. /* pass-through */
  2067. SetVSwitch(1); /* cv3d */
  2068. DUMP;
  2069. DPRINTK("EXIT\n");
  2070. }
  2071. static inline void gfx_on_off(int toggle)
  2072. {
  2073. unsigned char tmp;
  2074. DPRINTK("ENTER gfx %s\n", (toggle ? "off" : "on"));
  2075. toggle = (toggle & 0x01) << 5;
  2076. tmp = rseq(SEQ_ID_CLOCKING_MODE) & (~(0x01 << 5));
  2077. wseq(SEQ_ID_CLOCKING_MODE, tmp | toggle);
  2078. DPRINTK("EXIT\n");
  2079. }
  2080. #if defined (VIRGEFBDUMP)
  2081. /*
  2082. * Dump board registers
  2083. */
  2084. static void cv64_dump(void)
  2085. {
  2086. int i;
  2087. u8 c, b;
  2088. u16 w;
  2089. u32 l;
  2090. /* crt, seq, gfx and atr regs */
  2091. SelectMMIO;
  2092. printk("\n");
  2093. for (i = 0; i <= 0x6f; i++) {
  2094. wb_mmio(CRT_ADDRESS, i);
  2095. printk("crt idx : 0x%2.2x : 0x%2.2x\n", i, rb_mmio(CRT_ADDRESS_R));
  2096. }
  2097. for (i = 0; i <= 0x1c; i++) {
  2098. wb_mmio(SEQ_ADDRESS, i);
  2099. printk("seq idx : 0x%2.2x : 0x%2.2x\n", i, rb_mmio(SEQ_ADDRESS_R));
  2100. }
  2101. for (i = 0; i <= 8; i++) {
  2102. wb_mmio(GCT_ADDRESS, i);
  2103. printk("gfx idx : 0x%2.2x : 0x%2.2x\n", i, rb_mmio(GCT_ADDRESS_R));
  2104. }
  2105. for (i = 0; i <= 0x14; i++) {
  2106. c = rb_mmio(ACT_ADDRESS_RESET);
  2107. wb_mmio(ACT_ADDRESS_W, i);
  2108. printk("atr idx : 0x%2.2x : 0x%2.2x\n", i, rb_mmio(ACT_ADDRESS_R));
  2109. }
  2110. /* re-enable video access to palette */
  2111. c = rb_mmio(ACT_ADDRESS_RESET);
  2112. udelay(10);
  2113. wb_mmio(ACT_ADDRESS_W, 0x20);
  2114. c = rb_mmio(ACT_ADDRESS_RESET);
  2115. udelay(10);
  2116. /* general regs */
  2117. printk("0x3cc(w 0x3c2) : 0x%2.2x\n", rb_mmio(0x3cc)); /* GREG_MISC_OUTPUT READ */
  2118. printk("0x3c2(-------) : 0x%2.2x\n", rb_mmio(0x3c2)); /* GREG_INPUT_STATUS 0 READ */
  2119. printk("0x3c3(w 0x3c3) : 0x%2.2x\n", rb_vgaio(0x3c3)); /* GREG_VIDEO_SUBS_ENABLE */
  2120. printk("0x3ca(w 0x3da) : 0x%2.2x\n", rb_vgaio(0x3ca)); /* GREG_FEATURE_CONTROL read */
  2121. printk("0x3da(-------) : 0x%2.2x\n", rb_mmio(0x3da)); /* GREG_INPUT_STATUS 1 READ */
  2122. /* engine regs */
  2123. for (i = 0x8180; i <= 0x8200; i = i + 4)
  2124. printk("0x%8.8x : 0x%8.8x\n", i, rl_mmio(i));
  2125. i = 0x8504;
  2126. printk("0x%8.8x : 0x%8.8x\n", i, rl_mmio(i));
  2127. i = 0x850c;
  2128. printk("0x%8.8x : 0x%8.8x\n", i, rl_mmio(i));
  2129. for (i = 0xa4d4; i <= 0xa50c; i = i + 4)
  2130. printk("0x%8.8x : 0x%8.8x\n", i, rl_mmio(i));
  2131. /* PCI regs */
  2132. SelectCFG;
  2133. for (c = 0; c < 0x08; c = c + 2) {
  2134. w = (*((u16 *)((u32)(vgaio_regs + c + (on_zorro2 ? 0 : 0x000e0000)) ^ 2)));
  2135. printk("pci 0x%2.2x : 0x%4.4x\n", c, w);
  2136. }
  2137. c = 8;
  2138. l = (*((u32 *)((u32)(vgaio_regs + c + (on_zorro2 ? 0 : 0x000e0000)))));
  2139. printk("pci 0x%2.2x : 0x%8.8x\n", c, l);
  2140. c = 0x0d;
  2141. b = (*((u8 *)((u32)(vgaio_regs + c + (on_zorro2 ? 0 : 0x000e0000)) ^ 3)));
  2142. printk("pci 0x%2.2x : 0x%2.2x\n", c, b);
  2143. c = 0x10;
  2144. l = (*((u32 *)((u32)(vgaio_regs + c + (on_zorro2 ? 0 : 0x000e0000)))));
  2145. printk("pci 0x%2.2x : 0x%8.8x\n", c, l);
  2146. c = 0x30;
  2147. l = (*((u32 *)((u32)(vgaio_regs + c + (on_zorro2 ? 0 : 0x000e0000)))));
  2148. printk("pci 0x%2.2x : 0x%8.8x\n", c, l);
  2149. c = 0x3c;
  2150. b = (*((u8 *)((u32)(vgaio_regs + c + (on_zorro2 ? 0 : 0x000e0000)) ^ 3)));
  2151. printk("pci 0x%2.2x : 0x%2.2x\n", c, b);
  2152. c = 0x3d;
  2153. b = (*((u8 *)((u32)(vgaio_regs + c + (on_zorro2 ? 0 : 0x000e0000)) ^ 3)));
  2154. printk("pci 0x%2.2x : 0x%2.2x\n", c, b);
  2155. c = 0x3e;
  2156. w = (*((u16 *)((u32)(vgaio_regs + c + (on_zorro2 ? 0 : 0x000e0000)) ^ 2)));
  2157. printk("pci 0x%2.2x : 0x%4.4x\n", c, w);
  2158. SelectMMIO;
  2159. }
  2160. #endif