virgefb.c 66 KB

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