cyblafb.c 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681
  1. /*
  2. * Frame buffer driver for Trident Cyberblade/i1 graphics core
  3. *
  4. * Copyright 2005 Knut Petersen <Knut_Petersen@t-online.de>
  5. *
  6. * CREDITS:
  7. * tridentfb.c by Jani Monoses
  8. * see files above for further credits
  9. *
  10. */
  11. #define CYBLAFB_DEBUG 0
  12. #define CYBLAFB_KD_GRAPHICS_QUIRK 1
  13. #define CYBLAFB_PIXMAPSIZE 8192
  14. #include <linux/config.h>
  15. #include <linux/module.h>
  16. #include <linux/string.h>
  17. #include <linux/fb.h>
  18. #include <linux/init.h>
  19. #include <linux/pci.h>
  20. #include <asm/types.h>
  21. #include <video/cyblafb.h>
  22. #define VERSION "0.62"
  23. struct cyblafb_par {
  24. u32 pseudo_pal[16];
  25. struct fb_ops ops;
  26. };
  27. static struct fb_fix_screeninfo cyblafb_fix __devinitdata = {
  28. .id = "CyBla",
  29. .type = FB_TYPE_PACKED_PIXELS,
  30. .xpanstep = 1,
  31. .ypanstep = 1,
  32. .ywrapstep = 1,
  33. .visual = FB_VISUAL_PSEUDOCOLOR,
  34. .accel = FB_ACCEL_NONE,
  35. };
  36. static char *mode __devinitdata = NULL;
  37. static int bpp __devinitdata = 8;
  38. static int ref __devinitdata = 75;
  39. static int fp __devinitdata;
  40. static int crt __devinitdata;
  41. static int memsize __devinitdata;
  42. static int basestride;
  43. static int vesafb;
  44. static int nativex;
  45. static int center;
  46. static int stretch;
  47. static int pciwb = 1;
  48. static int pcirb = 1;
  49. static int pciwr = 1;
  50. static int pcirr = 1;
  51. static int disabled;
  52. static int verbosity;
  53. static int displaytype;
  54. static void __iomem *io_virt; // iospace virtual memory address
  55. module_param(mode, charp, 0);
  56. module_param(bpp, int, 0);
  57. module_param(ref, int, 0);
  58. module_param(fp, int, 0);
  59. module_param(crt, int, 0);
  60. module_param(nativex, int, 0);
  61. module_param(center, int, 0);
  62. module_param(stretch, int, 0);
  63. module_param(pciwb, int, 0);
  64. module_param(pcirb, int, 0);
  65. module_param(pciwr, int, 0);
  66. module_param(pcirr, int, 0);
  67. module_param(memsize, int, 0);
  68. module_param(verbosity, int, 0);
  69. //=========================================
  70. //
  71. // Well, we have to fix the upper layers.
  72. // Until this has been done, we work around
  73. // the bugs.
  74. //
  75. //=========================================
  76. #if (CYBLAFB_KD_GRAPHICS_QUIRK && CYBLAFB_DEBUG)
  77. if (disabled) { \
  78. printk("********\n");\
  79. dump_stack();\
  80. return val;\
  81. }
  82. #elif CYBLAFB_KD_GRAPHICS_QUIRK
  83. #define KD_GRAPHICS_RETURN(val)\
  84. if (disabled) {\
  85. return val;\
  86. }
  87. #else
  88. #define KD_GRAPHICS_RETURN(val)
  89. #endif
  90. //=========================================
  91. //
  92. // Port access macros for memory mapped io
  93. //
  94. //=========================================
  95. #define out8(r, v) writeb(v, io_virt + r)
  96. #define out32(r, v) writel(v, io_virt + r)
  97. #define in8(r) readb(io_virt + r)
  98. #define in32(r) readl(io_virt + r)
  99. //======================================
  100. //
  101. // Hardware access inline functions
  102. //
  103. //======================================
  104. static inline u8 read3X4(u32 reg)
  105. {
  106. out8(0x3D4, reg);
  107. return in8(0x3D5);
  108. }
  109. static inline u8 read3C4(u32 reg)
  110. {
  111. out8(0x3C4, reg);
  112. return in8(0x3C5);
  113. }
  114. static inline u8 read3CE(u32 reg)
  115. {
  116. out8(0x3CE, reg);
  117. return in8(0x3CF);
  118. }
  119. static inline void write3X4(u32 reg, u8 val)
  120. {
  121. out8(0x3D4, reg);
  122. out8(0x3D5, val);
  123. }
  124. static inline void write3C4(u32 reg, u8 val)
  125. {
  126. out8(0x3C4, reg);
  127. out8(0x3C5, val);
  128. }
  129. static inline void write3CE(u32 reg, u8 val)
  130. {
  131. out8(0x3CE, reg);
  132. out8(0x3CF, val);
  133. }
  134. static inline void write3C0(u32 reg, u8 val)
  135. {
  136. in8(0x3DA); // read to reset index
  137. out8(0x3C0, reg);
  138. out8(0x3C0, val);
  139. }
  140. //=================================================
  141. //
  142. // Enable memory mapped io and unprotect registers
  143. //
  144. //=================================================
  145. static void enable_mmio(void)
  146. {
  147. u8 tmp;
  148. outb(0x0B, 0x3C4);
  149. inb(0x3C5); // Set NEW mode
  150. outb(SR0E, 0x3C4); // write enable a lot of extended ports
  151. outb(0x80, 0x3C5);
  152. outb(SR11, 0x3C4); // write enable those extended ports that
  153. outb(0x87, 0x3C5); // are not affected by SR0E_New
  154. outb(CR1E, 0x3d4); // clear write protect bit for port 0x3c2
  155. tmp = inb(0x3d5) & 0xBF;
  156. outb(CR1E, 0x3d4);
  157. outb(tmp, 0x3d5);
  158. outb(CR39, 0x3D4);
  159. outb(inb(0x3D5) | 0x01, 0x3D5); // Enable mmio
  160. }
  161. //=================================================
  162. //
  163. // Set pixel clock VCLK1
  164. // - multipliers set elswhere
  165. // - freq in units of 0.01 MHz
  166. //
  167. // Hardware bug: SR18 >= 250 is broken for the
  168. // cyberblade/i1
  169. //
  170. //=================================================
  171. static void set_vclk(struct cyblafb_par *par, int freq)
  172. {
  173. u32 m, n, k;
  174. int f, fi, d, di;
  175. u8 lo = 0, hi = 0;
  176. d = 2000;
  177. k = freq >= 10000 ? 0 : freq >= 5000 ? 1 : freq >= 2500 ? 2 : 3;
  178. for (m = 0; m < 64; m++)
  179. for (n = 0; n < 250; n++) {
  180. fi = (int)(((5864727 * (n + 8)) /
  181. ((m + 2) * (1 << k))) >> 12);
  182. if ((di = abs(fi - freq)) < d) {
  183. d = di;
  184. f = fi;
  185. lo = (u8) n;
  186. hi = (u8) ((k << 6) | m);
  187. }
  188. }
  189. write3C4(SR19, hi);
  190. write3C4(SR18, lo);
  191. if (verbosity > 0)
  192. output("pixclock = %d.%02d MHz, k/m/n %x %x %x\n",
  193. freq / 100, freq % 100, (hi & 0xc0) >> 6, hi & 0x3f, lo);
  194. }
  195. //================================================
  196. //
  197. // Cyberblade specific Graphics Engine (GE) setup
  198. //
  199. //================================================
  200. static void cyblafb_setup_GE(int pitch, int bpp)
  201. {
  202. KD_GRAPHICS_RETURN();
  203. switch (bpp) {
  204. case 8:
  205. basestride = ((pitch >> 3) << 20) | (0 << 29);
  206. break;
  207. case 15:
  208. basestride = ((pitch >> 3) << 20) | (5 << 29);
  209. break;
  210. case 16:
  211. basestride = ((pitch >> 3) << 20) | (1 << 29);
  212. break;
  213. case 24:
  214. case 32:
  215. basestride = ((pitch >> 3) << 20) | (2 << 29);
  216. break;
  217. }
  218. write3X4(CR36, 0x90); // reset GE
  219. write3X4(CR36, 0x80); // enable GE
  220. out32(GE24, 1 << 7); // reset all GE pointers by toggling
  221. out32(GE24, 0); // d7 of GE24
  222. write3X4(CR2D, 0x00); // GE Timinigs, no delays
  223. out32(GE6C, 0); // Pattern and Style, p 129, ok
  224. }
  225. //=====================================================================
  226. //
  227. // Cyberblade specific syncing
  228. //
  229. // A timeout might be caused by disabled mmio.
  230. // Cause:
  231. // - bit CR39 & 1 == 0 upon return, X trident driver bug
  232. // - kdm bug (KD_GRAPHICS not set on first switch)
  233. // - kernel design flaw (it believes in the correctness
  234. // of kdm/X
  235. // First we try to sync ignoring that problem, as most of the
  236. // time that will succeed immediately and the enable_mmio()
  237. // would only degrade performance.
  238. //
  239. //=====================================================================
  240. static int cyblafb_sync(struct fb_info *info)
  241. {
  242. u32 status, i = 100000;
  243. KD_GRAPHICS_RETURN(0);
  244. while (((status = in32(GE20)) & 0xFe800000) && i != 0)
  245. i--;
  246. if (i == 0) {
  247. enable_mmio();
  248. i = 1000000;
  249. while (((status = in32(GE20)) & 0xFA800000) && i != 0)
  250. i--;
  251. if (i == 0) {
  252. output("GE Timeout, status: %x\n", status);
  253. if (status & 0x80000000)
  254. output("Bresenham Engine : Busy\n");
  255. if (status & 0x40000000)
  256. output("Setup Engine : Busy\n");
  257. if (status & 0x20000000)
  258. output("SP / DPE : Busy\n");
  259. if (status & 0x10000000)
  260. output("Memory Interface : Busy\n");
  261. if (status & 0x08000000)
  262. output("Com Lst Proc : Busy\n");
  263. if (status & 0x04000000)
  264. output("Block Write : Busy\n");
  265. if (status & 0x02000000)
  266. output("Command Buffer : Full\n");
  267. if (status & 0x01000000)
  268. output("RESERVED : Busy\n");
  269. if (status & 0x00800000)
  270. output("PCI Write Buffer : Busy\n");
  271. cyblafb_setup_GE(info->var.xres,
  272. info->var.bits_per_pixel);
  273. }
  274. }
  275. return 0;
  276. }
  277. //==============================
  278. //
  279. // Cyberblade specific fillrect
  280. //
  281. //==============================
  282. static void cyblafb_fillrect(struct fb_info *info, const struct fb_fillrect *fr)
  283. {
  284. u32 bpp = info->var.bits_per_pixel, col, desty, height;
  285. KD_GRAPHICS_RETURN();
  286. switch (bpp) {
  287. default:
  288. case 8:
  289. col = fr->color;
  290. col |= col << 8;
  291. col |= col << 16;
  292. break;
  293. case 16:
  294. col = ((u32 *) (info->pseudo_palette))[fr->color];
  295. col |= col << 16;
  296. break;
  297. case 32:
  298. col = ((u32 *) (info->pseudo_palette))[fr->color];
  299. break;
  300. }
  301. desty = fr->dy;
  302. height = fr->height;
  303. while (height) {
  304. out32(GEB8, basestride | ((desty * info->var.xres_virtual *
  305. bpp) >> 6));
  306. out32(GE60, col);
  307. out32(GE48, fr->rop ? 0x66 : ROP_S);
  308. out32(GE44, 0x20000000 | 1 << 19 | 1 << 4 | 2 << 2);
  309. out32(GE08, point(fr->dx, 0));
  310. out32(GE0C, point(fr->dx + fr->width - 1,
  311. height > 4096 ? 4095 : height - 1));
  312. if (likely(height <= 4096))
  313. return;
  314. desty += 4096;
  315. height -= 4096;
  316. }
  317. }
  318. //================================================
  319. //
  320. // Cyberblade specific copyarea
  321. //
  322. // This function silently assumes that it never
  323. // will be called with width or height exceeding
  324. // 4096.
  325. //
  326. //================================================
  327. static void cyblafb_copyarea(struct fb_info *info, const struct fb_copyarea *ca)
  328. {
  329. u32 s1, s2, d1, d2, direction;
  330. KD_GRAPHICS_RETURN();
  331. s1 = point(ca->sx, 0);
  332. s2 = point(ca->sx + ca->width - 1, ca->height - 1);
  333. d1 = point(ca->dx, 0);
  334. d2 = point(ca->dx + ca->width - 1, ca->height - 1);
  335. if ((ca->sy > ca->dy) || ((ca->sy == ca->dy) && (ca->sx > ca->dx)))
  336. direction = 0;
  337. else
  338. direction = 2;
  339. out32(GEB8, basestride | ((ca->dy * info->var.xres_virtual *
  340. info->var.bits_per_pixel) >> 6));
  341. out32(GEC8, basestride | ((ca->sy * info->var.xres_virtual *
  342. info->var.bits_per_pixel) >> 6));
  343. out32(GE44, 0xa0000000 | 1 << 19 | 1 << 2 | direction);
  344. out32(GE00, direction ? s2 : s1);
  345. out32(GE04, direction ? s1 : s2);
  346. out32(GE08, direction ? d2 : d1);
  347. out32(GE0C, direction ? d1 : d2);
  348. }
  349. //=======================================================================
  350. //
  351. // Cyberblade specific imageblit
  352. //
  353. // Accelerated for the most usual case, blitting 1 - bit deep
  354. // character images. Everything else is passed to the generic imageblit
  355. // unless it is so insane that it is better to printk an alert.
  356. //
  357. // Hardware bug: _Never_ blit across pixel column 2048, that will lock
  358. // the system. We split those blit requests into three blitting
  359. // operations.
  360. //
  361. //=======================================================================
  362. static void cyblafb_imageblit(struct fb_info *info,
  363. const struct fb_image *image)
  364. {
  365. u32 fgcol, bgcol;
  366. u32 *pd = (u32 *) image->data;
  367. u32 bpp = info->var.bits_per_pixel;
  368. KD_GRAPHICS_RETURN();
  369. // Used only for drawing the penguine (image->depth > 1)
  370. if (image->depth != 1) {
  371. cfb_imageblit(info, image);
  372. return;
  373. }
  374. // That should never happen, but it would be fatal
  375. if (image->width == 0 || image->height == 0) {
  376. output("imageblit: width/height 0 detected\n");
  377. return;
  378. }
  379. if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
  380. info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
  381. fgcol = ((u32 *) (info->pseudo_palette))[image->fg_color];
  382. bgcol = ((u32 *) (info->pseudo_palette))[image->bg_color];
  383. } else {
  384. fgcol = image->fg_color;
  385. bgcol = image->bg_color;
  386. }
  387. switch (bpp) {
  388. case 8:
  389. fgcol |= fgcol << 8;
  390. bgcol |= bgcol << 8;
  391. case 16:
  392. fgcol |= fgcol << 16;
  393. bgcol |= bgcol << 16;
  394. default:
  395. break;
  396. }
  397. out32(GEB8, basestride | ((image->dy * info->var.xres_virtual *
  398. bpp) >> 6));
  399. out32(GE60, fgcol);
  400. out32(GE64, bgcol);
  401. if (!(image->dx < 2048 && (image->dx + image->width - 1) >= 2048)) {
  402. u32 dds = ((image->width + 31) >> 5) * image->height;
  403. out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19);
  404. out32(GE08, point(image->dx, 0));
  405. out32(GE0C, point(image->dx + image->width - 1,
  406. image->height - 1));
  407. while (dds--)
  408. out32(GE9C, *pd++);
  409. } else {
  410. int i, j;
  411. u32 ddstotal = (image->width + 31) >> 5;
  412. u32 ddsleft = (2048 - image->dx + 31) >> 5;
  413. u32 skipleft = ddstotal - ddsleft;
  414. out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19);
  415. out32(GE08, point(image->dx, 0));
  416. out32(GE0C, point(2048 - 1, image->height - 1));
  417. for (i = 0; i < image->height; i++) {
  418. for (j = 0; j < ddsleft; j++)
  419. out32(GE9C, *pd++);
  420. pd += skipleft;
  421. }
  422. if (image->dx % 32) {
  423. out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19);
  424. out32(GE08, point(2048, 0));
  425. if (image->width > ddsleft << 5)
  426. out32(GE0C, point(image->dx + (ddsleft << 5) -
  427. 1, image->height - 1));
  428. else
  429. out32(GE0C, point(image->dx + image->width - 1,
  430. image->height - 1));
  431. pd = ((u32 *) image->data) + ddstotal - skipleft - 1;
  432. for (i = 0; i < image->height; i++) {
  433. out32(GE9C, swab32(swab32(*pd) << ((32 -
  434. (image->dx & 31)) & 31)));
  435. pd += ddstotal;
  436. }
  437. }
  438. if (skipleft) {
  439. out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19);
  440. out32(GE08, point(image->dx + (ddsleft << 5), 0));
  441. out32(GE0C, point(image->dx + image->width - 1,
  442. image->height - 1));
  443. pd = (u32 *) image->data;
  444. for (i = 0; i < image->height; i++) {
  445. pd += ddsleft;
  446. for (j = 0; j < skipleft; j++)
  447. out32(GE9C, *pd++);
  448. }
  449. }
  450. }
  451. }
  452. //==========================================================
  453. //
  454. // Check if video mode is acceptable. We change var->??? if
  455. // video mode is slightly off or return error otherwise.
  456. // info->??? must not be changed!
  457. //
  458. //==========================================================
  459. static int cyblafb_check_var(struct fb_var_screeninfo *var,
  460. struct fb_info *info)
  461. {
  462. int bpp = var->bits_per_pixel;
  463. //
  464. // we try to support 8, 16, 24 and 32 bpp modes,
  465. // default to 8
  466. //
  467. // there is a 24 bpp mode, but for now we change requests to 32 bpp
  468. // (This is what tridentfb does ... will be changed in the future)
  469. //
  470. //
  471. if (bpp % 8 != 0 || bpp < 8 || bpp > 32)
  472. bpp = 8;
  473. if (bpp == 24)
  474. bpp = var->bits_per_pixel = 32;
  475. //
  476. // interlaced modes are broken, fail if one is requested
  477. //
  478. if (var->vmode & FB_VMODE_INTERLACED)
  479. return -EINVAL;
  480. //
  481. // fail if requested resolution is higher than physical
  482. // flatpanel resolution
  483. //
  484. if ((displaytype == DISPLAY_FP) && nativex && var->xres > nativex)
  485. return -EINVAL;
  486. //
  487. // we do not allow vclk to exceed 230 MHz. If the requested
  488. // vclk is too high, we default to 200 MHz
  489. //
  490. if ((bpp == 32 ? 200000000 : 100000000) / var->pixclock > 23000)
  491. var->pixclock = (bpp == 32 ? 200000000 : 100000000) / 20000;
  492. //
  493. // enforce (h|v)sync_len limits
  494. //
  495. var->hsync_len &= ~7;
  496. if(var->hsync_len > 248)
  497. var->hsync_len = 248;
  498. var->vsync_len &= 15;
  499. //
  500. // Enforce horizontal and vertical hardware limits.
  501. // 1600x1200 is mentioned as a maximum, but higher resolutions could
  502. // work with slow refresh, small margins and short sync.
  503. //
  504. var->xres &= ~7;
  505. if (((var->xres + var->left_margin + var->right_margin +
  506. var->hsync_len) > (bpp == 32 ? 2040 : 4088)) ||
  507. ((var->yres + var->upper_margin + var->lower_margin +
  508. var->vsync_len) > 2047))
  509. return -EINVAL;
  510. if ((var->xres > 1600) || (var->yres > 1200))
  511. output("Mode %dx%d exceeds documented limits.\n",
  512. var->xres, var->yres);
  513. //
  514. // try to be smart about (x|y)res_virtual problems.
  515. //
  516. if (var->xres > var->xres_virtual)
  517. var->xres_virtual = var->xres;
  518. if (var->yres > var->yres_virtual)
  519. var->yres_virtual = var->yres;
  520. if (bpp == 8 || bpp == 16) {
  521. if (var->xres_virtual > 4088)
  522. var->xres_virtual = 4088;
  523. } else {
  524. if (var->xres_virtual > 2040)
  525. var->xres_virtual = 2040;
  526. }
  527. var->xres_virtual &= ~7;
  528. while (var->xres_virtual * var->yres_virtual * bpp / 8 >
  529. info->fix.smem_len) {
  530. if (var->yres_virtual > var->yres)
  531. var->yres_virtual--;
  532. else if (var->xres_virtual > var->xres)
  533. var->xres_virtual -= 8;
  534. else
  535. return -EINVAL;
  536. }
  537. switch (bpp) {
  538. case 8:
  539. var->red.offset = 0;
  540. var->green.offset = 0;
  541. var->blue.offset = 0;
  542. var->red.length = 6;
  543. var->green.length = 6;
  544. var->blue.length = 6;
  545. break;
  546. case 16:
  547. var->red.offset = 11;
  548. var->green.offset = 5;
  549. var->blue.offset = 0;
  550. var->red.length = 5;
  551. var->green.length = 6;
  552. var->blue.length = 5;
  553. break;
  554. case 32:
  555. var->red.offset = 16;
  556. var->green.offset = 8;
  557. var->blue.offset = 0;
  558. var->red.length = 8;
  559. var->green.length = 8;
  560. var->blue.length = 8;
  561. break;
  562. default:
  563. return -EINVAL;
  564. }
  565. return 0;
  566. }
  567. //=====================================================================
  568. //
  569. // Pan the display
  570. //
  571. // The datasheets defines crt start address to be 20 bits wide and
  572. // to be programmed to CR0C, CR0D, CR1E and CR27. Actually there is
  573. // CR2B[5] as an undocumented extension bit. Epia BIOS 2.07 does use
  574. // it, so it is also safe to be used here. BTW: datasheet CR0E on page
  575. // 90 really is CR1E, the real CRE is documented on page 72.
  576. //
  577. // BUT:
  578. //
  579. // As of internal version 0.60 we do not use vga panning any longer.
  580. // Vga panning did not allow us the use of all available video memory
  581. // and thus prevented ywrap scrolling. We do use the "right view"
  582. // register now.
  583. //
  584. //
  585. //=====================================================================
  586. static int cyblafb_pan_display(struct fb_var_screeninfo *var,
  587. struct fb_info *info)
  588. {
  589. KD_GRAPHICS_RETURN(0);
  590. info->var.xoffset = var->xoffset;
  591. info->var.yoffset = var->yoffset;
  592. out32(GE10, 0x80000000 | ((var->xoffset + (var->yoffset *
  593. var->xres_virtual)) * var->bits_per_pixel / 32));
  594. return 0;
  595. }
  596. //============================================
  597. //
  598. // This will really help in case of a bug ...
  599. // dump most gaphics core registers.
  600. //
  601. //============================================
  602. static void regdump(struct cyblafb_par *par)
  603. {
  604. int i;
  605. if (verbosity < 2)
  606. return;
  607. printk("\n");
  608. for (i = 0; i <= 0xff; i++) {
  609. outb(i, 0x3d4);
  610. printk("CR%02x=%02x ", i, inb(0x3d5));
  611. if (i % 16 == 15)
  612. printk("\n");
  613. }
  614. outb(0x30, 0x3ce);
  615. outb(inb(0x3cf) | 0x40, 0x3cf);
  616. for (i = 0; i <= 0x1f; i++) {
  617. if (i == 0 || (i > 2 && i < 8) || i == 0x10 || i == 0x11
  618. || i == 0x16) {
  619. outb(i, 0x3d4);
  620. printk("CR%02x=%02x ", i, inb(0x3d5));
  621. } else
  622. printk("------- ");
  623. if (i % 16 == 15)
  624. printk("\n");
  625. }
  626. outb(0x30, 0x3ce);
  627. outb(inb(0x3cf) & 0xbf, 0x3cf);
  628. printk("\n");
  629. for (i = 0; i <= 0x7f; i++) {
  630. outb(i, 0x3ce);
  631. printk("GR%02x=%02x ", i, inb(0x3cf));
  632. if (i % 16 == 15)
  633. printk("\n");
  634. }
  635. printk("\n");
  636. for (i = 0; i <= 0xff; i++) {
  637. outb(i, 0x3c4);
  638. printk("SR%02x=%02x ", i, inb(0x3c5));
  639. if (i % 16 == 15)
  640. printk("\n");
  641. }
  642. printk("\n");
  643. for (i = 0; i <= 0x1F; i++) {
  644. inb(0x3da); // next access is index!
  645. outb(i, 0x3c0);
  646. printk("AR%02x=%02x ", i, inb(0x3c1));
  647. if (i % 16 == 15)
  648. printk("\n");
  649. }
  650. printk("\n");
  651. inb(0x3DA); // reset internal flag to 3c0 index
  652. outb(0x20, 0x3C0); // enable attr
  653. return;
  654. }
  655. //=======================================================================
  656. //
  657. // Save State
  658. //
  659. // This function is called while a switch to KD_TEXT is in progress,
  660. // before any of the other functions are called.
  661. //
  662. //=======================================================================
  663. static void cyblafb_save_state(struct fb_info *info)
  664. {
  665. struct cyblafb_par *par = info->par;
  666. if (verbosity > 0)
  667. output("Switching to KD_TEXT\n");
  668. disabled = 0;
  669. regdump(par);
  670. enable_mmio();
  671. return;
  672. }
  673. //=======================================================================
  674. //
  675. // Restore State
  676. //
  677. // This function is called while a switch to KD_GRAPHICS is in progress,
  678. // We have to turn on vga style panning registers again because the
  679. // trident driver of X does not know about GE10.
  680. //
  681. //=======================================================================
  682. static void cyblafb_restore_state(struct fb_info *info)
  683. {
  684. if (verbosity > 0)
  685. output("Switching to KD_GRAPHICS\n");
  686. out32(GE10, 0);
  687. disabled = 1;
  688. return;
  689. }
  690. //======================================
  691. //
  692. // Set hardware to requested video mode
  693. //
  694. //======================================
  695. static int cyblafb_set_par(struct fb_info *info)
  696. {
  697. struct cyblafb_par *par = info->par;
  698. u32 htotal, hdispend, hsyncstart, hsyncend, hblankstart,
  699. hblankend, preendfetch, vtotal, vdispend, vsyncstart,
  700. vsyncend, vblankstart, vblankend;
  701. struct fb_var_screeninfo *var = &info->var;
  702. int bpp = var->bits_per_pixel;
  703. int i;
  704. KD_GRAPHICS_RETURN(0);
  705. if (verbosity > 0)
  706. output("Switching to new mode: "
  707. "fbset -g %d %d %d %d %d -t %d %d %d %d %d %d %d\n",
  708. var->xres, var->yres, var->xres_virtual,
  709. var->yres_virtual, var->bits_per_pixel, var->pixclock,
  710. var->left_margin, var->right_margin, var->upper_margin,
  711. var->lower_margin, var->hsync_len, var->vsync_len);
  712. htotal = (var->xres + var->left_margin + var->right_margin +
  713. var->hsync_len) / 8 - 5;
  714. hdispend = var->xres / 8 - 1;
  715. hsyncstart = (var->xres + var->right_margin) / 8;
  716. hsyncend = var->hsync_len / 8;
  717. hblankstart = hdispend + 1;
  718. hblankend = htotal + 3; // should be htotal + 5, bios does it this way
  719. preendfetch = ((var->xres >> 3) + 1) * ((bpp + 1) >> 3);
  720. vtotal = var->yres + var->upper_margin + var->lower_margin +
  721. var->vsync_len - 2;
  722. vdispend = var->yres - 1;
  723. vsyncstart = var->yres + var->lower_margin;
  724. vblankstart = var->yres;
  725. vblankend = vtotal; // should be vtotal + 2, but bios does it this way
  726. vsyncend = var->vsync_len;
  727. enable_mmio(); // necessary! ... check X ...
  728. write3X4(CR11, read3X4(CR11) & 0x7F); // unlock cr00 .. cr07
  729. write3CE(GR30, 8);
  730. if ((displaytype == DISPLAY_FP) && var->xres < nativex) {
  731. // stretch or center ?
  732. out8(0x3C2, 0xEB);
  733. write3CE(GR30, read3CE(GR30) | 0x81); // shadow mode on
  734. if (center) {
  735. write3CE(GR52, (read3CE(GR52) & 0x7C) | 0x80);
  736. write3CE(GR53, (read3CE(GR53) & 0x7C) | 0x80);
  737. } else if (stretch) {
  738. write3CE(GR5D, 0);
  739. write3CE(GR52, (read3CE(GR52) & 0x7C) | 1);
  740. write3CE(GR53, (read3CE(GR53) & 0x7C) | 1);
  741. }
  742. } else {
  743. out8(0x3C2, 0x2B);
  744. write3CE(GR30, 8);
  745. }
  746. //
  747. // Setup CRxx regs
  748. //
  749. write3X4(CR00, htotal & 0xFF);
  750. write3X4(CR01, hdispend & 0xFF);
  751. write3X4(CR02, hblankstart & 0xFF);
  752. write3X4(CR03, hblankend & 0x1F);
  753. write3X4(CR04, hsyncstart & 0xFF);
  754. write3X4(CR05, (hsyncend & 0x1F) | ((hblankend & 0x20) << 2));
  755. write3X4(CR06, vtotal & 0xFF);
  756. write3X4(CR07, (vtotal & 0x100) >> 8 |
  757. (vdispend & 0x100) >> 7 |
  758. (vsyncstart & 0x100) >> 6 |
  759. (vblankstart & 0x100) >> 5 |
  760. 0x10 |
  761. (vtotal & 0x200) >> 4 |
  762. (vdispend & 0x200) >> 3 | (vsyncstart & 0x200) >> 2);
  763. write3X4(CR08, 0);
  764. write3X4(CR09, (vblankstart & 0x200) >> 4 | 0x40 | // FIX !!!
  765. ((info->var.vmode & FB_VMODE_DOUBLE) ? 0x80 : 0));
  766. write3X4(CR0A, 0); // Init to some reasonable default
  767. write3X4(CR0B, 0); // Init to some reasonable default
  768. write3X4(CR0C, 0); // Offset 0
  769. write3X4(CR0D, 0); // Offset 0
  770. write3X4(CR0E, 0); // Init to some reasonable default
  771. write3X4(CR0F, 0); // Init to some reasonable default
  772. write3X4(CR10, vsyncstart & 0xFF);
  773. write3X4(CR11, (vsyncend & 0x0F));
  774. write3X4(CR12, vdispend & 0xFF);
  775. write3X4(CR13, ((info->var.xres_virtual * bpp) / (4 * 16)) & 0xFF);
  776. write3X4(CR14, 0x40); // double word mode
  777. write3X4(CR15, vblankstart & 0xFF);
  778. write3X4(CR16, vblankend & 0xFF);
  779. write3X4(CR17, 0xE3);
  780. write3X4(CR18, 0xFF);
  781. // CR19: needed for interlaced modes ... ignore it for now
  782. write3X4(CR1A, 0x07); // Arbitration Control Counter 1
  783. write3X4(CR1B, 0x07); // Arbitration Control Counter 2
  784. write3X4(CR1C, 0x07); // Arbitration Control Counter 3
  785. write3X4(CR1D, 0x00); // Don't know, doesn't hurt ; -)
  786. write3X4(CR1E, (info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80);
  787. // CR1F: do not set, contains BIOS info about memsize
  788. write3X4(CR20, 0x20); // enabe wr buf, disable 16bit planar mode
  789. write3X4(CR21, 0x20); // enable linear memory access
  790. // CR22: RO cpu latch readback
  791. // CR23: ???
  792. // CR24: RO AR flag state
  793. // CR25: RAMDAC rw timing, pclk buffer tristate control ????
  794. // CR26: ???
  795. write3X4(CR27, (vdispend & 0x400) >> 6 |
  796. (vsyncstart & 0x400) >> 5 |
  797. (vblankstart & 0x400) >> 4 |
  798. (vtotal & 0x400) >> 3 |
  799. 0x8);
  800. // CR28: ???
  801. write3X4(CR29, (read3X4(CR29) & 0xCF) | ((((info->var.xres_virtual *
  802. bpp) / (4 * 16)) & 0x300) >> 4));
  803. write3X4(CR2A, read3X4(CR2A) | 0x40);
  804. write3X4(CR2B, (htotal & 0x100) >> 8 |
  805. (hdispend & 0x100) >> 7 |
  806. // (0x00 & 0x100) >> 6 | hinterlace para bit 8 ???
  807. (hsyncstart & 0x100) >> 5 |
  808. (hblankstart & 0x100) >> 4);
  809. // CR2C: ???
  810. // CR2D: initialized in cyblafb_setup_GE()
  811. write3X4(CR2F, 0x92); // conservative, better signal quality
  812. // CR30: reserved
  813. // CR31: reserved
  814. // CR32: reserved
  815. // CR33: reserved
  816. // CR34: disabled in CR36
  817. // CR35: disabled in CR36
  818. // CR36: initialized in cyblafb_setup_GE
  819. // CR37: i2c, ignore for now
  820. write3X4(CR38, (bpp == 8) ? 0x00 : //
  821. (bpp == 16) ? 0x05 : // highcolor
  822. (bpp == 24) ? 0x29 : // packed 24bit truecolor
  823. (bpp == 32) ? 0x09 : 0); // truecolor, 16 bit pixelbus
  824. write3X4(CR39, 0x01 | // MMIO enable
  825. (pcirb ? 0x02 : 0) | // pci read burst enable
  826. (pciwb ? 0x04 : 0)); // pci write burst enable
  827. write3X4(CR55, 0x1F | // pci clocks * 2 for STOP# during 1st data phase
  828. (pcirr ? 0x40 : 0) | // pci read retry enable
  829. (pciwr ? 0x80 : 0)); // pci write retry enable
  830. write3X4(CR56, preendfetch >> 8 < 2 ? (preendfetch >> 8 & 0x01) | 2
  831. : 0);
  832. write3X4(CR57, preendfetch >> 8 < 2 ? preendfetch & 0xff : 0);
  833. write3X4(CR58, 0x82); // Bios does this .... don't know more
  834. //
  835. // Setup SRxx regs
  836. //
  837. write3C4(SR00, 3);
  838. write3C4(SR01, 1); //set char clock 8 dots wide
  839. write3C4(SR02, 0x0F); //enable 4 maps needed in chain4 mode
  840. write3C4(SR03, 0); //no character map select
  841. write3C4(SR04, 0x0E); //memory mode: ext mem, even, chain4
  842. out8(0x3C4, 0x0b);
  843. in8(0x3C5); // Set NEW mode
  844. write3C4(SR0D, 0x00); // test ... check
  845. set_vclk(par, (bpp == 32 ? 200000000 : 100000000)
  846. / info->var.pixclock); //SR18, SR19
  847. //
  848. // Setup GRxx regs
  849. //
  850. write3CE(GR00, 0x00); // test ... check
  851. write3CE(GR01, 0x00); // test ... check
  852. write3CE(GR02, 0x00); // test ... check
  853. write3CE(GR03, 0x00); // test ... check
  854. write3CE(GR04, 0x00); // test ... check
  855. write3CE(GR05, 0x40); // no CGA compat, allow 256 col
  856. write3CE(GR06, 0x05); // graphics mode
  857. write3CE(GR07, 0x0F); // planes?
  858. write3CE(GR08, 0xFF); // test ... check
  859. write3CE(GR0F, (bpp == 32) ? 0x1A : 0x12); // vclk / 2 if 32bpp, chain4
  860. write3CE(GR20, 0xC0); // test ... check
  861. write3CE(GR2F, 0xA0); // PCLK = VCLK, no skew,
  862. //
  863. // Setup ARxx regs
  864. //
  865. for (i = 0; i < 0x10; i++) // set AR00 .. AR0f
  866. write3C0(i, i);
  867. write3C0(AR10, 0x41); // graphics mode and support 256 color modes
  868. write3C0(AR12, 0x0F); // planes
  869. write3C0(AR13, 0); // horizontal pel panning
  870. in8(0x3DA); // reset internal flag to 3c0 index
  871. out8(0x3C0, 0x20); // enable attr
  872. //
  873. // Setup hidden RAMDAC command register
  874. //
  875. in8(0x3C8); // these reads are
  876. in8(0x3C6); // necessary to
  877. in8(0x3C6); // unmask the RAMDAC
  878. in8(0x3C6); // command reg, otherwise
  879. in8(0x3C6); // we would write the pixelmask reg!
  880. out8(0x3C6, (bpp == 8) ? 0x00 : // 256 colors
  881. (bpp == 15) ? 0x10 : //
  882. (bpp == 16) ? 0x30 : // hicolor
  883. (bpp == 24) ? 0xD0 : // truecolor
  884. (bpp == 32) ? 0xD0 : 0); // truecolor
  885. in8(0x3C8);
  886. //
  887. // GR31 is not mentioned in the datasheet
  888. //
  889. if (displaytype == DISPLAY_FP)
  890. write3CE(GR31, (read3CE(GR31) & 0x8F) |
  891. ((info->var.yres > 1024) ? 0x50 :
  892. (info->var.yres > 768) ? 0x30 :
  893. (info->var.yres > 600) ? 0x20 :
  894. (info->var.yres > 480) ? 0x10 : 0));
  895. info->fix.visual = (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR
  896. : FB_VISUAL_TRUECOLOR;
  897. info->fix.line_length = info->var.xres_virtual * (bpp >> 3);
  898. info->cmap.len = (bpp == 8) ? 256 : 16;
  899. //
  900. // init acceleration engine
  901. //
  902. cyblafb_setup_GE(info->var.xres_virtual, info->var.bits_per_pixel);
  903. //
  904. // Set/clear flags to allow proper scroll mode selection.
  905. //
  906. if (var->xres == var->xres_virtual)
  907. info->flags &= ~FBINFO_HWACCEL_XPAN;
  908. else
  909. info->flags |= FBINFO_HWACCEL_XPAN;
  910. if (var->yres == var->yres_virtual)
  911. info->flags &= ~FBINFO_HWACCEL_YPAN;
  912. else
  913. info->flags |= FBINFO_HWACCEL_YPAN;
  914. if (info->fix.smem_len !=
  915. var->xres_virtual * var->yres_virtual * bpp / 8)
  916. info->flags &= ~FBINFO_HWACCEL_YWRAP;
  917. else
  918. info->flags |= FBINFO_HWACCEL_YWRAP;
  919. regdump(par);
  920. return 0;
  921. }
  922. //========================
  923. //
  924. // Set one color register
  925. //
  926. //========================
  927. static int cyblafb_setcolreg(unsigned regno, unsigned red, unsigned green,
  928. unsigned blue, unsigned transp,
  929. struct fb_info *info)
  930. {
  931. int bpp = info->var.bits_per_pixel;
  932. KD_GRAPHICS_RETURN(0);
  933. if (regno >= info->cmap.len)
  934. return 1;
  935. if (bpp == 8) {
  936. out8(0x3C6, 0xFF);
  937. out8(0x3C8, regno);
  938. out8(0x3C9, red >> 10);
  939. out8(0x3C9, green >> 10);
  940. out8(0x3C9, blue >> 10);
  941. } else if (bpp == 16) // RGB 565
  942. ((u32 *) info->pseudo_palette)[regno] =
  943. (red & 0xF800) |
  944. ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
  945. else if (bpp == 32) // ARGB 8888
  946. ((u32 *) info->pseudo_palette)[regno] =
  947. ((transp & 0xFF00) << 16) |
  948. ((red & 0xFF00) << 8) |
  949. ((green & 0xFF00)) | ((blue & 0xFF00) >> 8);
  950. return 0;
  951. }
  952. //==========================================================
  953. //
  954. // Try blanking the screen. For flat panels it does nothing
  955. //
  956. //==========================================================
  957. static int cyblafb_blank(int blank_mode, struct fb_info *info)
  958. {
  959. unsigned char PMCont, DPMSCont;
  960. KD_GRAPHICS_RETURN(0);
  961. if (displaytype == DISPLAY_FP)
  962. return 0;
  963. out8(0x83C8, 0x04); // DPMS Control
  964. PMCont = in8(0x83C6) & 0xFC;
  965. DPMSCont = read3CE(GR23) & 0xFC;
  966. switch (blank_mode) {
  967. case FB_BLANK_UNBLANK: // Screen: On, HSync: On, VSync: On
  968. case FB_BLANK_NORMAL: // Screen: Off, HSync: On, VSync: On
  969. PMCont |= 0x03;
  970. DPMSCont |= 0x00;
  971. break;
  972. case FB_BLANK_HSYNC_SUSPEND: // Screen: Off, HSync: Off, VSync: On
  973. PMCont |= 0x02;
  974. DPMSCont |= 0x01;
  975. break;
  976. case FB_BLANK_VSYNC_SUSPEND: // Screen: Off, HSync: On, VSync: Off
  977. PMCont |= 0x02;
  978. DPMSCont |= 0x02;
  979. break;
  980. case FB_BLANK_POWERDOWN: // Screen: Off, HSync: Off, VSync: Off
  981. PMCont |= 0x00;
  982. DPMSCont |= 0x03;
  983. break;
  984. }
  985. write3CE(GR23, DPMSCont);
  986. out8(0x83C8, 4);
  987. out8(0x83C6, PMCont);
  988. //
  989. // let fbcon do a softblank for us
  990. //
  991. return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
  992. }
  993. static struct fb_ops cyblafb_ops __devinitdata = {
  994. .owner = THIS_MODULE,
  995. .fb_setcolreg = cyblafb_setcolreg,
  996. .fb_pan_display = cyblafb_pan_display,
  997. .fb_blank = cyblafb_blank,
  998. .fb_check_var = cyblafb_check_var,
  999. .fb_set_par = cyblafb_set_par,
  1000. .fb_fillrect = cyblafb_fillrect,
  1001. .fb_copyarea = cyblafb_copyarea,
  1002. .fb_imageblit = cyblafb_imageblit,
  1003. .fb_sync = cyblafb_sync,
  1004. .fb_restore_state = cyblafb_restore_state,
  1005. .fb_save_state = cyblafb_save_state,
  1006. };
  1007. //==========================================================================
  1008. //
  1009. // getstartupmode() decides about the inital video mode
  1010. //
  1011. // There is no reason to use modedb, a lot of video modes there would
  1012. // need altered timings to display correctly. So I decided that it is much
  1013. // better to provide a limited optimized set of modes plus the option of
  1014. // using the mode in effect at startup time (might be selected using the
  1015. // vga=??? paramter). After that the user might use fbset to select any
  1016. // mode he likes, check_var will not try to alter geometry parameters as
  1017. // it would be necessary otherwise.
  1018. //
  1019. //==========================================================================
  1020. static int __devinit getstartupmode(struct fb_info *info)
  1021. {
  1022. u32 htotal, hdispend, hsyncstart, hsyncend, hblankstart, hblankend,
  1023. vtotal, vdispend, vsyncstart, vsyncend, vblankstart, vblankend,
  1024. cr00, cr01, cr02, cr03, cr04, cr05, cr2b,
  1025. cr06, cr07, cr09, cr10, cr11, cr12, cr15, cr16, cr27,
  1026. cr38, sr0d, sr18, sr19, gr0f, fi, pxclkdiv, vclkdiv, tmp, i;
  1027. struct modus {
  1028. int xres; int vxres; int yres; int vyres;
  1029. int bpp; int pxclk;
  1030. int left_margin; int right_margin;
  1031. int upper_margin; int lower_margin;
  1032. int hsync_len; int vsync_len;
  1033. } modedb[5] = {
  1034. {
  1035. 0, 2048, 0, 4096, 0, 0, 0, 0, 0, 0, 0, 0}, {
  1036. 640, 2048, 480, 4096, 0, 0, -40, 24, 17, 0, 216, 3}, {
  1037. 800, 2048, 600, 4096, 0, 0, 96, 24, 14, 0, 136, 11}, {
  1038. 1024, 2048, 768, 4096, 0, 0, 144, 24, 29, 0, 120, 3}, {
  1039. 1280, 2048, 1024, 4096, 0, 0, 232, 16, 39, 0, 160, 3}
  1040. };
  1041. outb(0x00, 0x3d4); cr00 = inb(0x3d5);
  1042. outb(0x01, 0x3d4); cr01 = inb(0x3d5);
  1043. outb(0x02, 0x3d4); cr02 = inb(0x3d5);
  1044. outb(0x03, 0x3d4); cr03 = inb(0x3d5);
  1045. outb(0x04, 0x3d4); cr04 = inb(0x3d5);
  1046. outb(0x05, 0x3d4); cr05 = inb(0x3d5);
  1047. outb(0x06, 0x3d4); cr06 = inb(0x3d5);
  1048. outb(0x07, 0x3d4); cr07 = inb(0x3d5);
  1049. outb(0x09, 0x3d4); cr09 = inb(0x3d5);
  1050. outb(0x10, 0x3d4); cr10 = inb(0x3d5);
  1051. outb(0x11, 0x3d4); cr11 = inb(0x3d5);
  1052. outb(0x12, 0x3d4); cr12 = inb(0x3d5);
  1053. outb(0x15, 0x3d4); cr15 = inb(0x3d5);
  1054. outb(0x16, 0x3d4); cr16 = inb(0x3d5);
  1055. outb(0x27, 0x3d4); cr27 = inb(0x3d5);
  1056. outb(0x2b, 0x3d4); cr2b = inb(0x3d5);
  1057. outb(0x38, 0x3d4); cr38 = inb(0x3d5);
  1058. outb(0x0b, 0x3c4);
  1059. inb(0x3c5);
  1060. outb(0x0d, 0x3c4); sr0d = inb(0x3c5);
  1061. outb(0x18, 0x3c4); sr18 = inb(0x3c5);
  1062. outb(0x19, 0x3c4); sr19 = inb(0x3c5);
  1063. outb(0x0f, 0x3ce); gr0f = inb(0x3cf);
  1064. htotal = cr00 | (cr2b & 0x01) << 8;
  1065. hdispend = cr01 | (cr2b & 0x02) << 7;
  1066. hblankstart = cr02 | (cr2b & 0x10) << 4;
  1067. hblankend = (cr03 & 0x1f) | (cr05 & 0x80) >> 2;
  1068. hsyncstart = cr04 | (cr2b & 0x08) << 5;
  1069. hsyncend = cr05 & 0x1f;
  1070. modedb[0].xres = hblankstart * 8;
  1071. modedb[0].hsync_len = hsyncend * 8;
  1072. modedb[0].right_margin = hsyncstart * 8 - modedb[0].xres;
  1073. modedb[0].left_margin = (htotal + 5) * 8 - modedb[0].xres -
  1074. modedb[0].right_margin - modedb[0].hsync_len;
  1075. vtotal = cr06 | (cr07 & 0x01) << 8 | (cr07 & 0x20) << 4
  1076. | (cr27 & 0x80) << 3;
  1077. vdispend = cr12 | (cr07 & 0x02) << 7 | (cr07 & 0x40) << 3
  1078. | (cr27 & 0x10) << 6;
  1079. vsyncstart = cr10 | (cr07 & 0x04) << 6 | (cr07 & 0x80) << 2
  1080. | (cr27 & 0x20) << 5;
  1081. vsyncend = cr11 & 0x0f;
  1082. vblankstart = cr15 | (cr07 & 0x08) << 5 | (cr09 & 0x20) << 4
  1083. | (cr27 & 0x40) << 4;
  1084. vblankend = cr16;
  1085. modedb[0].yres = vdispend + 1;
  1086. modedb[0].vsync_len = vsyncend;
  1087. modedb[0].lower_margin = vsyncstart - modedb[0].yres;
  1088. modedb[0].upper_margin = vtotal - modedb[0].yres -
  1089. modedb[0].lower_margin - modedb[0].vsync_len + 2;
  1090. tmp = cr38 & 0x3c;
  1091. modedb[0].bpp = tmp == 0 ? 8 : tmp == 4 ? 16 : tmp == 28 ? 24 :
  1092. tmp == 8 ? 32 : 8;
  1093. fi = ((5864727 * (sr18 + 8)) /
  1094. (((sr19 & 0x3f) + 2) * (1 << ((sr19 & 0xc0) >> 6)))) >> 12;
  1095. pxclkdiv = ((gr0f & 0x08) >> 3 | (gr0f & 0x40) >> 5) + 1;
  1096. tmp = sr0d & 0x06;
  1097. vclkdiv = tmp == 0 ? 2 : tmp == 2 ? 4 : tmp == 4 ? 8 : 3; // * 2 !
  1098. modedb[0].pxclk = ((100000000 * pxclkdiv * vclkdiv) >> 1) / fi;
  1099. if (verbosity > 0)
  1100. output("detected startup mode: "
  1101. "fbset -g %d %d %d ??? %d -t %d %d %d %d %d %d %d\n",
  1102. modedb[0].xres, modedb[0].yres, modedb[0].xres,
  1103. modedb[0].bpp, modedb[0].pxclk, modedb[0].left_margin,
  1104. modedb[0].right_margin, modedb[0].upper_margin,
  1105. modedb[0].lower_margin, modedb[0].hsync_len,
  1106. modedb[0].vsync_len);
  1107. //
  1108. // We use this goto target in case of a failed check_var. No, I really
  1109. // do not want to do it in another way!
  1110. //
  1111. tryagain:
  1112. i = (mode == NULL) ? 0 :
  1113. !strncmp(mode, "640x480", 7) ? 1 :
  1114. !strncmp(mode, "800x600", 7) ? 2 :
  1115. !strncmp(mode, "1024x768", 8) ? 3 :
  1116. !strncmp(mode, "1280x1024", 9) ? 4 : 0;
  1117. ref = (ref < 50) ? 50 : (ref > 85) ? 85 : ref;
  1118. if (i == 0) {
  1119. info->var.pixclock = modedb[i].pxclk;
  1120. info->var.bits_per_pixel = modedb[i].bpp;
  1121. } else {
  1122. info->var.pixclock = (100000000 /
  1123. ((modedb[i].left_margin +
  1124. modedb[i].xres +
  1125. modedb[i].right_margin +
  1126. modedb[i].hsync_len) *
  1127. (modedb[i].upper_margin +
  1128. modedb[i].yres +
  1129. modedb[i].lower_margin +
  1130. modedb[i].vsync_len) * ref / 10000));
  1131. info->var.bits_per_pixel = bpp;
  1132. }
  1133. info->var.left_margin = modedb[i].left_margin;
  1134. info->var.right_margin = modedb[i].right_margin;
  1135. info->var.xres = modedb[i].xres;
  1136. if (!(modedb[i].yres == 1280 && modedb[i].bpp == 32))
  1137. info->var.xres_virtual = modedb[i].vxres;
  1138. else
  1139. info->var.xres_virtual = modedb[i].xres;
  1140. info->var.xoffset = 0;
  1141. info->var.hsync_len = modedb[i].hsync_len;
  1142. info->var.upper_margin = modedb[i].upper_margin;
  1143. info->var.yres = modedb[i].yres;
  1144. info->var.yres_virtual = modedb[i].vyres;
  1145. info->var.yoffset = 0;
  1146. info->var.lower_margin = modedb[i].lower_margin;
  1147. info->var.vsync_len = modedb[i].vsync_len;
  1148. info->var.sync = 0;
  1149. info->var.vmode = FB_VMODE_NONINTERLACED;
  1150. if (cyblafb_check_var(&info->var, info)) {
  1151. // 640x480 - 8@75 should really never fail. One case would
  1152. // be fp == 1 and nativex < 640 ... give up then
  1153. if (i == 1 && bpp == 8 && ref == 75) {
  1154. output("Can't find a valid mode :-(\n");
  1155. return -EINVAL;
  1156. }
  1157. // Our detected mode is unlikely to fail. If it does,
  1158. // try 640x480 - 8@75 ...
  1159. if (i == 0) {
  1160. mode = "640x480";
  1161. bpp = 8;
  1162. ref = 75;
  1163. output("Detected mode failed check_var! "
  1164. "Trying 640x480 - 8@75\n");
  1165. goto tryagain;
  1166. }
  1167. // A specified video mode failed for some reason.
  1168. // Try the startup mode first
  1169. output("Specified mode '%s' failed check! "
  1170. "Falling back to startup mode.\n", mode);
  1171. mode = NULL;
  1172. goto tryagain;
  1173. }
  1174. return 0;
  1175. }
  1176. //========================================================
  1177. //
  1178. // Detect activated memory size. Undefined values require
  1179. // memsize parameter.
  1180. //
  1181. //========================================================
  1182. static unsigned int __devinit get_memsize(void)
  1183. {
  1184. unsigned char tmp;
  1185. unsigned int k;
  1186. if (memsize)
  1187. k = memsize * Kb;
  1188. else {
  1189. tmp = read3X4(CR1F) & 0x0F;
  1190. switch (tmp) {
  1191. case 0x03:
  1192. k = 1 * 1024 * 1024;
  1193. break;
  1194. case 0x07:
  1195. k = 2 * 1024 * 1024;
  1196. break;
  1197. case 0x0F:
  1198. k = 4 * 1024 * 1024;
  1199. break;
  1200. case 0x04:
  1201. k = 8 * 1024 * 1024;
  1202. break;
  1203. default:
  1204. k = 1 * 1024 * 1024;
  1205. output("Unknown memory size code %x in CR1F."
  1206. " We default to 1 Mb for now, please"
  1207. " do provide a memsize parameter!\n", tmp);
  1208. }
  1209. }
  1210. if (verbosity > 0)
  1211. output("framebuffer size = %d Kb\n", k / Kb);
  1212. return k;
  1213. }
  1214. //=========================================================
  1215. //
  1216. // Detect if a flat panel monitor connected to the special
  1217. // interface is active. Override is possible by fp and crt
  1218. // parameters.
  1219. //
  1220. //=========================================================
  1221. static unsigned int __devinit get_displaytype(void)
  1222. {
  1223. if (fp)
  1224. return DISPLAY_FP;
  1225. if (crt)
  1226. return DISPLAY_CRT;
  1227. return (read3CE(GR33) & 0x10) ? DISPLAY_FP : DISPLAY_CRT;
  1228. }
  1229. //=====================================
  1230. //
  1231. // Get native resolution of flat panel
  1232. //
  1233. //=====================================
  1234. static int __devinit get_nativex(void)
  1235. {
  1236. int x, y, tmp;
  1237. if (nativex)
  1238. return nativex;
  1239. tmp = (read3CE(GR52) >> 4) & 3;
  1240. switch (tmp) {
  1241. case 0: x = 1280; y = 1024;
  1242. break;
  1243. case 2: x = 1024; y = 768;
  1244. break;
  1245. case 3: x = 800; y = 600;
  1246. break;
  1247. case 4: x = 1400; y = 1050;
  1248. break;
  1249. case 1:
  1250. default:
  1251. x = 640; y = 480;
  1252. break;
  1253. }
  1254. if (verbosity > 0)
  1255. output("%dx%d flat panel found\n", x, y);
  1256. return x;
  1257. }
  1258. static int __devinit cybla_pci_probe(struct pci_dev *dev,
  1259. const struct pci_device_id *id)
  1260. {
  1261. struct fb_info *info;
  1262. struct cyblafb_par *par;
  1263. info = framebuffer_alloc(sizeof(struct cyblafb_par), &dev->dev);
  1264. if (!info)
  1265. goto errout_alloc_info;
  1266. info->pixmap.addr = kzalloc(CYBLAFB_PIXMAPSIZE, GFP_KERNEL);
  1267. if (!info->pixmap.addr) {
  1268. output("allocation of pixmap buffer failed!\n");
  1269. goto errout_alloc_pixmap;
  1270. }
  1271. info->pixmap.size = CYBLAFB_PIXMAPSIZE - 4;
  1272. info->pixmap.buf_align = 4;
  1273. info->pixmap.access_align = 32;
  1274. info->pixmap.flags = FB_PIXMAP_SYSTEM;
  1275. info->pixmap.scan_align = 4;
  1276. par = info->par;
  1277. par->ops = cyblafb_ops;
  1278. info->fix = cyblafb_fix;
  1279. info->fbops = &par->ops;
  1280. info->fix = cyblafb_fix;
  1281. if (pci_enable_device(dev)) {
  1282. output("could not enable device!\n");
  1283. goto errout_enable;
  1284. }
  1285. // might already be requested by vga console or vesafb,
  1286. // so we do care about success
  1287. if (!request_region(0x3c0, 0x20, "cyblafb")) {
  1288. output("region 0x3c0/0x20 already reserved\n");
  1289. vesafb |= 1;
  1290. }
  1291. //
  1292. // Graphics Engine Registers
  1293. //
  1294. if (!request_region(GEBase, 0x100, "cyblafb")) {
  1295. output("region %#x/0x100 already reserved\n", GEBase);
  1296. vesafb |= 2;
  1297. }
  1298. regdump(par);
  1299. enable_mmio();
  1300. // setup MMIO region
  1301. info->fix.mmio_start = pci_resource_start(dev, 1);
  1302. info->fix.mmio_len = 0x20000;
  1303. if (!request_mem_region(info->fix.mmio_start,
  1304. info->fix.mmio_len, "cyblafb")) {
  1305. output("request_mem_region failed for mmio region!\n");
  1306. goto errout_mmio_reqmem;
  1307. }
  1308. io_virt = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
  1309. if (!io_virt) {
  1310. output("ioremap failed for mmio region\n");
  1311. goto errout_mmio_remap;
  1312. }
  1313. // setup framebuffer memory ... might already be requested
  1314. // by vesafb. Not to fail in case of an unsuccessful request
  1315. // is useful if both are loaded.
  1316. info->fix.smem_start = pci_resource_start(dev, 0);
  1317. info->fix.smem_len = get_memsize();
  1318. if (!request_mem_region(info->fix.smem_start,
  1319. info->fix.smem_len, "cyblafb")) {
  1320. output("region %#lx/%#x already reserved\n",
  1321. info->fix.smem_start, info->fix.smem_len);
  1322. vesafb |= 4;
  1323. }
  1324. info->screen_base = ioremap_nocache(info->fix.smem_start,
  1325. info->fix.smem_len);
  1326. if (!info->screen_base) {
  1327. output("ioremap failed for smem region\n");
  1328. goto errout_smem_remap;
  1329. }
  1330. displaytype = get_displaytype();
  1331. if (displaytype == DISPLAY_FP)
  1332. nativex = get_nativex();
  1333. info->flags = FBINFO_DEFAULT
  1334. | FBINFO_HWACCEL_COPYAREA
  1335. | FBINFO_HWACCEL_FILLRECT
  1336. | FBINFO_HWACCEL_IMAGEBLIT
  1337. | FBINFO_READS_FAST
  1338. // | FBINFO_PARTIAL_PAN_OK
  1339. | FBINFO_MISC_ALWAYS_SETPAR;
  1340. info->pseudo_palette = par->pseudo_pal;
  1341. if (getstartupmode(info))
  1342. goto errout_findmode;
  1343. fb_alloc_cmap(&info->cmap, 256, 0);
  1344. if (register_framebuffer(info)) {
  1345. output("Could not register CyBla framebuffer\n");
  1346. goto errout_register;
  1347. }
  1348. pci_set_drvdata(dev, info);
  1349. //
  1350. // normal exit and error paths
  1351. //
  1352. return 0;
  1353. errout_register:
  1354. errout_findmode:
  1355. iounmap(info->screen_base);
  1356. errout_smem_remap:
  1357. if (!(vesafb & 4))
  1358. release_mem_region(info->fix.smem_start, info->fix.smem_len);
  1359. iounmap(io_virt);
  1360. errout_mmio_remap:
  1361. release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
  1362. errout_mmio_reqmem:
  1363. if (!(vesafb & 1))
  1364. release_region(0x3c0, 32);
  1365. errout_enable:
  1366. kfree(info->pixmap.addr);
  1367. errout_alloc_pixmap:
  1368. framebuffer_release(info);
  1369. errout_alloc_info:
  1370. output("CyblaFB version %s aborting init.\n", VERSION);
  1371. return -ENODEV;
  1372. }
  1373. static void __devexit cybla_pci_remove(struct pci_dev *dev)
  1374. {
  1375. struct fb_info *info = pci_get_drvdata(dev);
  1376. unregister_framebuffer(info);
  1377. iounmap(io_virt);
  1378. iounmap(info->screen_base);
  1379. if (!(vesafb & 4))
  1380. release_mem_region(info->fix.smem_start, info->fix.smem_len);
  1381. release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
  1382. fb_dealloc_cmap(&info->cmap);
  1383. if (!(vesafb & 2))
  1384. release_region(GEBase, 0x100);
  1385. if (!(vesafb & 1))
  1386. release_region(0x3c0, 32);
  1387. kfree(info->pixmap.addr);
  1388. framebuffer_release(info);
  1389. output("CyblaFB version %s normal exit.\n", VERSION);
  1390. }
  1391. //
  1392. // List of boards that we are trying to support
  1393. //
  1394. static struct pci_device_id cybla_devices[] = {
  1395. {PCI_VENDOR_ID_TRIDENT, CYBERBLADEi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
  1396. {0,}
  1397. };
  1398. MODULE_DEVICE_TABLE(pci, cybla_devices);
  1399. static struct pci_driver cyblafb_pci_driver = {
  1400. .name = "cyblafb",
  1401. .id_table = cybla_devices,
  1402. .probe = cybla_pci_probe,
  1403. .remove = __devexit_p(cybla_pci_remove)
  1404. };
  1405. //=============================================================
  1406. //
  1407. // kernel command line example:
  1408. //
  1409. // video=cyblafb:1280x1024, bpp=16, ref=50 ...
  1410. //
  1411. // modprobe command line example:
  1412. //
  1413. // modprobe cyblafb mode=1280x1024 bpp=16 ref=50 ...
  1414. //
  1415. //=============================================================
  1416. static int __devinit cyblafb_init(void)
  1417. {
  1418. #ifndef MODULE
  1419. char *options = NULL;
  1420. char *opt;
  1421. if (fb_get_options("cyblafb", &options))
  1422. return -ENODEV;
  1423. if (options && *options)
  1424. while ((opt = strsep(&options, ",")) != NULL) {
  1425. if (!*opt)
  1426. continue;
  1427. else if (!strncmp(opt, "bpp=", 4))
  1428. bpp = simple_strtoul(opt + 4, NULL, 0);
  1429. else if (!strncmp(opt, "ref=", 4))
  1430. ref = simple_strtoul(opt + 4, NULL, 0);
  1431. else if (!strncmp(opt, "fp", 2))
  1432. displaytype = DISPLAY_FP;
  1433. else if (!strncmp(opt, "crt", 3))
  1434. displaytype = DISPLAY_CRT;
  1435. else if (!strncmp(opt, "nativex=", 8))
  1436. nativex = simple_strtoul(opt + 8, NULL, 0);
  1437. else if (!strncmp(opt, "center", 6))
  1438. center = 1;
  1439. else if (!strncmp(opt, "stretch", 7))
  1440. stretch = 1;
  1441. else if (!strncmp(opt, "pciwb=", 6))
  1442. pciwb = simple_strtoul(opt + 6, NULL, 0);
  1443. else if (!strncmp(opt, "pcirb=", 6))
  1444. pcirb = simple_strtoul(opt + 6, NULL, 0);
  1445. else if (!strncmp(opt, "pciwr=", 6))
  1446. pciwr = simple_strtoul(opt + 6, NULL, 0);
  1447. else if (!strncmp(opt, "pcirr=", 6))
  1448. pcirr = simple_strtoul(opt + 6, NULL, 0);
  1449. else if (!strncmp(opt, "memsize=", 8))
  1450. memsize = simple_strtoul(opt + 8, NULL, 0);
  1451. else if (!strncmp(opt, "verbosity=", 10))
  1452. verbosity = simple_strtoul(opt + 10, NULL, 0);
  1453. else
  1454. mode = opt;
  1455. }
  1456. #endif
  1457. output("CyblaFB version %s initializing\n", VERSION);
  1458. return pci_register_driver(&cyblafb_pci_driver);
  1459. }
  1460. static void __exit cyblafb_exit(void)
  1461. {
  1462. pci_unregister_driver(&cyblafb_pci_driver);
  1463. }
  1464. module_init(cyblafb_init);
  1465. module_exit(cyblafb_exit);
  1466. MODULE_AUTHOR("Knut Petersen <knut_petersen@t-online.de>");
  1467. MODULE_DESCRIPTION("Framebuffer driver for Cyberblade/i1 graphics core");
  1468. MODULE_LICENSE("GPL");