virgefb.c 66 KB

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