sgivwfb.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895
  1. /*
  2. * linux/drivers/video/sgivwfb.c -- SGI DBE frame buffer device
  3. *
  4. * Copyright (C) 1999 Silicon Graphics, Inc.
  5. * Jeffrey Newquist, newquist@engr.sgi.som
  6. *
  7. * This file is subject to the terms and conditions of the GNU General Public
  8. * License. See the file COPYING in the main directory of this archive for
  9. * more details.
  10. */
  11. #include <linux/config.h>
  12. #include <linux/module.h>
  13. #include <linux/kernel.h>
  14. #include <linux/mm.h>
  15. #include <linux/errno.h>
  16. #include <linux/delay.h>
  17. #include <linux/fb.h>
  18. #include <linux/init.h>
  19. #include <linux/ioport.h>
  20. #include <linux/platform_device.h>
  21. #include <asm/io.h>
  22. #include <asm/mtrr.h>
  23. #include <setup_arch.h>
  24. #define INCLUDE_TIMING_TABLE_DATA
  25. #define DBE_REG_BASE par->regs
  26. #include <video/sgivw.h>
  27. struct sgivw_par {
  28. struct asregs *regs;
  29. u32 cmap_fifo;
  30. u_long timing_num;
  31. };
  32. #define FLATPANEL_SGI_1600SW 5
  33. /*
  34. * RAM we reserve for the frame buffer. This defines the maximum screen
  35. * size
  36. *
  37. * The default can be overridden if the driver is compiled as a module
  38. */
  39. static int ypan = 0;
  40. static int ywrap = 0;
  41. static int flatpanel_id = -1;
  42. static struct fb_fix_screeninfo sgivwfb_fix __initdata = {
  43. .id = "SGI Vis WS FB",
  44. .type = FB_TYPE_PACKED_PIXELS,
  45. .visual = FB_VISUAL_PSEUDOCOLOR,
  46. .mmio_start = DBE_REG_PHYS,
  47. .mmio_len = DBE_REG_SIZE,
  48. .accel = FB_ACCEL_NONE,
  49. .line_length = 640,
  50. };
  51. static struct fb_var_screeninfo sgivwfb_var __initdata = {
  52. /* 640x480, 8 bpp */
  53. .xres = 640,
  54. .yres = 480,
  55. .xres_virtual = 640,
  56. .yres_virtual = 480,
  57. .bits_per_pixel = 8,
  58. .red = { 0, 8, 0 },
  59. .green = { 0, 8, 0 },
  60. .blue = { 0, 8, 0 },
  61. .height = -1,
  62. .width = -1,
  63. .pixclock = 20000,
  64. .left_margin = 64,
  65. .right_margin = 64,
  66. .upper_margin = 32,
  67. .lower_margin = 32,
  68. .hsync_len = 64,
  69. .vsync_len = 2,
  70. .vmode = FB_VMODE_NONINTERLACED
  71. };
  72. static struct fb_var_screeninfo sgivwfb_var1600sw __initdata = {
  73. /* 1600x1024, 8 bpp */
  74. .xres = 1600,
  75. .yres = 1024,
  76. .xres_virtual = 1600,
  77. .yres_virtual = 1024,
  78. .bits_per_pixel = 8,
  79. .red = { 0, 8, 0 },
  80. .green = { 0, 8, 0 },
  81. .blue = { 0, 8, 0 },
  82. .height = -1,
  83. .width = -1,
  84. .pixclock = 9353,
  85. .left_margin = 20,
  86. .right_margin = 30,
  87. .upper_margin = 37,
  88. .lower_margin = 3,
  89. .hsync_len = 20,
  90. .vsync_len = 3,
  91. .vmode = FB_VMODE_NONINTERLACED
  92. };
  93. /*
  94. * Interface used by the world
  95. */
  96. int sgivwfb_init(void);
  97. static int sgivwfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info);
  98. static int sgivwfb_set_par(struct fb_info *info);
  99. static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green,
  100. u_int blue, u_int transp,
  101. struct fb_info *info);
  102. static int sgivwfb_mmap(struct fb_info *info,
  103. struct vm_area_struct *vma);
  104. static struct fb_ops sgivwfb_ops = {
  105. .owner = THIS_MODULE,
  106. .fb_check_var = sgivwfb_check_var,
  107. .fb_set_par = sgivwfb_set_par,
  108. .fb_setcolreg = sgivwfb_setcolreg,
  109. .fb_fillrect = cfb_fillrect,
  110. .fb_copyarea = cfb_copyarea,
  111. .fb_imageblit = cfb_imageblit,
  112. .fb_mmap = sgivwfb_mmap,
  113. };
  114. /*
  115. * Internal routines
  116. */
  117. static unsigned long bytes_per_pixel(int bpp)
  118. {
  119. switch (bpp) {
  120. case 8:
  121. return 1;
  122. case 16:
  123. return 2;
  124. case 32:
  125. return 4;
  126. default:
  127. printk(KERN_INFO "sgivwfb: unsupported bpp %d\n", bpp);
  128. return 0;
  129. }
  130. }
  131. static unsigned long get_line_length(int xres_virtual, int bpp)
  132. {
  133. return (xres_virtual * bytes_per_pixel(bpp));
  134. }
  135. /*
  136. * Function: dbe_TurnOffDma
  137. * Parameters: (None)
  138. * Description: This should turn off the monitor and dbe. This is used
  139. * when switching between the serial console and the graphics
  140. * console.
  141. */
  142. static void dbe_TurnOffDma(struct sgivw_par *par)
  143. {
  144. unsigned int readVal;
  145. int i;
  146. // Check to see if things are already turned off:
  147. // 1) Check to see if dbe is not using the internal dotclock.
  148. // 2) Check to see if the xy counter in dbe is already off.
  149. DBE_GETREG(ctrlstat, readVal);
  150. if (GET_DBE_FIELD(CTRLSTAT, PCLKSEL, readVal) < 2)
  151. return;
  152. DBE_GETREG(vt_xy, readVal);
  153. if (GET_DBE_FIELD(VT_XY, VT_FREEZE, readVal) == 1)
  154. return;
  155. // Otherwise, turn off dbe
  156. DBE_GETREG(ovr_control, readVal);
  157. SET_DBE_FIELD(OVR_CONTROL, OVR_DMA_ENABLE, readVal, 0);
  158. DBE_SETREG(ovr_control, readVal);
  159. udelay(1000);
  160. DBE_GETREG(frm_control, readVal);
  161. SET_DBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, readVal, 0);
  162. DBE_SETREG(frm_control, readVal);
  163. udelay(1000);
  164. DBE_GETREG(did_control, readVal);
  165. SET_DBE_FIELD(DID_CONTROL, DID_DMA_ENABLE, readVal, 0);
  166. DBE_SETREG(did_control, readVal);
  167. udelay(1000);
  168. // XXX HACK:
  169. //
  170. // This was necessary for GBE--we had to wait through two
  171. // vertical retrace periods before the pixel DMA was
  172. // turned off for sure. I've left this in for now, in
  173. // case dbe needs it.
  174. for (i = 0; i < 10000; i++) {
  175. DBE_GETREG(frm_inhwctrl, readVal);
  176. if (GET_DBE_FIELD(FRM_INHWCTRL, FRM_DMA_ENABLE, readVal) ==
  177. 0)
  178. udelay(10);
  179. else {
  180. DBE_GETREG(ovr_inhwctrl, readVal);
  181. if (GET_DBE_FIELD
  182. (OVR_INHWCTRL, OVR_DMA_ENABLE, readVal) == 0)
  183. udelay(10);
  184. else {
  185. DBE_GETREG(did_inhwctrl, readVal);
  186. if (GET_DBE_FIELD
  187. (DID_INHWCTRL, DID_DMA_ENABLE,
  188. readVal) == 0)
  189. udelay(10);
  190. else
  191. break;
  192. }
  193. }
  194. }
  195. }
  196. /*
  197. * Set the User Defined Part of the Display. Again if par use it to get
  198. * real video mode.
  199. */
  200. static int sgivwfb_check_var(struct fb_var_screeninfo *var,
  201. struct fb_info *info)
  202. {
  203. struct sgivw_par *par = (struct sgivw_par *)info->par;
  204. struct dbe_timing_info *timing;
  205. u_long line_length;
  206. u_long min_mode;
  207. int req_dot;
  208. int test_mode;
  209. /*
  210. * FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
  211. * as FB_VMODE_SMOOTH_XPAN is only used internally
  212. */
  213. if (var->vmode & FB_VMODE_CONUPDATE) {
  214. var->vmode |= FB_VMODE_YWRAP;
  215. var->xoffset = info->var.xoffset;
  216. var->yoffset = info->var.yoffset;
  217. }
  218. /* XXX FIXME - forcing var's */
  219. var->xoffset = 0;
  220. var->yoffset = 0;
  221. /* Limit bpp to 8, 16, and 32 */
  222. if (var->bits_per_pixel <= 8)
  223. var->bits_per_pixel = 8;
  224. else if (var->bits_per_pixel <= 16)
  225. var->bits_per_pixel = 16;
  226. else if (var->bits_per_pixel <= 32)
  227. var->bits_per_pixel = 32;
  228. else
  229. return -EINVAL;
  230. var->grayscale = 0; /* No grayscale for now */
  231. /* determine valid resolution and timing */
  232. for (min_mode = 0; min_mode < DBE_VT_SIZE; min_mode++) {
  233. if (dbeVTimings[min_mode].width >= var->xres &&
  234. dbeVTimings[min_mode].height >= var->yres)
  235. break;
  236. }
  237. if (min_mode == DBE_VT_SIZE)
  238. return -EINVAL; /* Resolution to high */
  239. /* XXX FIXME - should try to pick best refresh rate */
  240. /* for now, pick closest dot-clock within 3MHz */
  241. req_dot = PICOS2KHZ(var->pixclock);
  242. printk(KERN_INFO "sgivwfb: requested pixclock=%d ps (%d KHz)\n",
  243. var->pixclock, req_dot);
  244. test_mode = min_mode;
  245. while (dbeVTimings[min_mode].width == dbeVTimings[test_mode].width) {
  246. if (dbeVTimings[test_mode].cfreq + 3000 > req_dot)
  247. break;
  248. test_mode++;
  249. }
  250. if (dbeVTimings[min_mode].width != dbeVTimings[test_mode].width)
  251. test_mode--;
  252. min_mode = test_mode;
  253. timing = &dbeVTimings[min_mode];
  254. printk(KERN_INFO "sgivwfb: granted dot-clock=%d KHz\n", timing->cfreq);
  255. /* Adjust virtual resolution, if necessary */
  256. if (var->xres > var->xres_virtual || (!ywrap && !ypan))
  257. var->xres_virtual = var->xres;
  258. if (var->yres > var->yres_virtual || (!ywrap && !ypan))
  259. var->yres_virtual = var->yres;
  260. /*
  261. * Memory limit
  262. */
  263. line_length = get_line_length(var->xres_virtual, var->bits_per_pixel);
  264. if (line_length * var->yres_virtual > sgivwfb_mem_size)
  265. return -ENOMEM; /* Virtual resolution to high */
  266. info->fix.line_length = line_length;
  267. switch (var->bits_per_pixel) {
  268. case 8:
  269. var->red.offset = 0;
  270. var->red.length = 8;
  271. var->green.offset = 0;
  272. var->green.length = 8;
  273. var->blue.offset = 0;
  274. var->blue.length = 8;
  275. var->transp.offset = 0;
  276. var->transp.length = 0;
  277. break;
  278. case 16: /* RGBA 5551 */
  279. var->red.offset = 11;
  280. var->red.length = 5;
  281. var->green.offset = 6;
  282. var->green.length = 5;
  283. var->blue.offset = 1;
  284. var->blue.length = 5;
  285. var->transp.offset = 0;
  286. var->transp.length = 0;
  287. break;
  288. case 32: /* RGB 8888 */
  289. var->red.offset = 0;
  290. var->red.length = 8;
  291. var->green.offset = 8;
  292. var->green.length = 8;
  293. var->blue.offset = 16;
  294. var->blue.length = 8;
  295. var->transp.offset = 24;
  296. var->transp.length = 8;
  297. break;
  298. }
  299. var->red.msb_right = 0;
  300. var->green.msb_right = 0;
  301. var->blue.msb_right = 0;
  302. var->transp.msb_right = 0;
  303. /* set video timing information */
  304. var->pixclock = KHZ2PICOS(timing->cfreq);
  305. var->left_margin = timing->htotal - timing->hsync_end;
  306. var->right_margin = timing->hsync_start - timing->width;
  307. var->upper_margin = timing->vtotal - timing->vsync_end;
  308. var->lower_margin = timing->vsync_start - timing->height;
  309. var->hsync_len = timing->hsync_end - timing->hsync_start;
  310. var->vsync_len = timing->vsync_end - timing->vsync_start;
  311. /* Ouch. This breaks the rules but timing_num is only important if you
  312. * change a video mode */
  313. par->timing_num = min_mode;
  314. printk(KERN_INFO "sgivwfb: new video mode xres=%d yres=%d bpp=%d\n",
  315. var->xres, var->yres, var->bits_per_pixel);
  316. printk(KERN_INFO " vxres=%d vyres=%d\n", var->xres_virtual,
  317. var->yres_virtual);
  318. return 0;
  319. }
  320. /*
  321. * Setup flatpanel related registers.
  322. */
  323. static void sgivwfb_setup_flatpanel(struct sgivw_par *par, struct dbe_timing_info *currentTiming)
  324. {
  325. int fp_wid, fp_hgt, fp_vbs, fp_vbe;
  326. u32 outputVal = 0;
  327. SET_DBE_FIELD(VT_FLAGS, HDRV_INVERT, outputVal,
  328. (currentTiming->flags & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1);
  329. SET_DBE_FIELD(VT_FLAGS, VDRV_INVERT, outputVal,
  330. (currentTiming->flags & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1);
  331. DBE_SETREG(vt_flags, outputVal);
  332. /* Turn on the flat panel */
  333. switch (flatpanel_id) {
  334. case FLATPANEL_SGI_1600SW:
  335. fp_wid = 1600;
  336. fp_hgt = 1024;
  337. fp_vbs = 0;
  338. fp_vbe = 1600;
  339. currentTiming->pll_m = 4;
  340. currentTiming->pll_n = 1;
  341. currentTiming->pll_p = 0;
  342. break;
  343. default:
  344. fp_wid = fp_hgt = fp_vbs = fp_vbe = 0xfff;
  345. }
  346. outputVal = 0;
  347. SET_DBE_FIELD(FP_DE, FP_DE_ON, outputVal, fp_vbs);
  348. SET_DBE_FIELD(FP_DE, FP_DE_OFF, outputVal, fp_vbe);
  349. DBE_SETREG(fp_de, outputVal);
  350. outputVal = 0;
  351. SET_DBE_FIELD(FP_HDRV, FP_HDRV_OFF, outputVal, fp_wid);
  352. DBE_SETREG(fp_hdrv, outputVal);
  353. outputVal = 0;
  354. SET_DBE_FIELD(FP_VDRV, FP_VDRV_ON, outputVal, 1);
  355. SET_DBE_FIELD(FP_VDRV, FP_VDRV_OFF, outputVal, fp_hgt + 1);
  356. DBE_SETREG(fp_vdrv, outputVal);
  357. }
  358. /*
  359. * Set the hardware according to 'par'.
  360. */
  361. static int sgivwfb_set_par(struct fb_info *info)
  362. {
  363. struct sgivw_par *par = info->par;
  364. int i, j, htmp, temp;
  365. u32 readVal, outputVal;
  366. int wholeTilesX, maxPixelsPerTileX;
  367. int frmWrite1, frmWrite2, frmWrite3b;
  368. struct dbe_timing_info *currentTiming; /* Current Video Timing */
  369. int xpmax, ypmax; // Monitor resolution
  370. int bytesPerPixel; // Bytes per pixel
  371. currentTiming = &dbeVTimings[par->timing_num];
  372. bytesPerPixel = bytes_per_pixel(info->var.bits_per_pixel);
  373. xpmax = currentTiming->width;
  374. ypmax = currentTiming->height;
  375. /* dbe_InitGraphicsBase(); */
  376. /* Turn on dotclock PLL */
  377. DBE_SETREG(ctrlstat, 0x20000000);
  378. dbe_TurnOffDma(par);
  379. /* dbe_CalculateScreenParams(); */
  380. maxPixelsPerTileX = 512 / bytesPerPixel;
  381. wholeTilesX = xpmax / maxPixelsPerTileX;
  382. if (wholeTilesX * maxPixelsPerTileX < xpmax)
  383. wholeTilesX++;
  384. printk(KERN_DEBUG "sgivwfb: pixPerTile=%d wholeTilesX=%d\n",
  385. maxPixelsPerTileX, wholeTilesX);
  386. /* dbe_InitGammaMap(); */
  387. udelay(10);
  388. for (i = 0; i < 256; i++) {
  389. DBE_ISETREG(gmap, i, (i << 24) | (i << 16) | (i << 8));
  390. }
  391. /* dbe_TurnOn(); */
  392. DBE_GETREG(vt_xy, readVal);
  393. if (GET_DBE_FIELD(VT_XY, VT_FREEZE, readVal) == 1) {
  394. DBE_SETREG(vt_xy, 0x00000000);
  395. udelay(1);
  396. } else
  397. dbe_TurnOffDma(par);
  398. /* dbe_Initdbe(); */
  399. for (i = 0; i < 256; i++) {
  400. for (j = 0; j < 100; j++) {
  401. DBE_GETREG(cm_fifo, readVal);
  402. if (readVal != 0x00000000)
  403. break;
  404. else
  405. udelay(10);
  406. }
  407. // DBE_ISETREG(cmap, i, 0x00000000);
  408. DBE_ISETREG(cmap, i, (i << 8) | (i << 16) | (i << 24));
  409. }
  410. /* dbe_InitFramebuffer(); */
  411. frmWrite1 = 0;
  412. SET_DBE_FIELD(FRM_SIZE_TILE, FRM_WIDTH_TILE, frmWrite1,
  413. wholeTilesX);
  414. SET_DBE_FIELD(FRM_SIZE_TILE, FRM_RHS, frmWrite1, 0);
  415. switch (bytesPerPixel) {
  416. case 1:
  417. SET_DBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, frmWrite1,
  418. DBE_FRM_DEPTH_8);
  419. break;
  420. case 2:
  421. SET_DBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, frmWrite1,
  422. DBE_FRM_DEPTH_16);
  423. break;
  424. case 4:
  425. SET_DBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, frmWrite1,
  426. DBE_FRM_DEPTH_32);
  427. break;
  428. }
  429. frmWrite2 = 0;
  430. SET_DBE_FIELD(FRM_SIZE_PIXEL, FB_HEIGHT_PIX, frmWrite2, ypmax);
  431. // Tell dbe about the framebuffer location and type
  432. // XXX What format is the FRM_TILE_PTR?? 64K aligned address?
  433. frmWrite3b = 0;
  434. SET_DBE_FIELD(FRM_CONTROL, FRM_TILE_PTR, frmWrite3b,
  435. sgivwfb_mem_phys >> 9);
  436. SET_DBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, frmWrite3b, 1);
  437. SET_DBE_FIELD(FRM_CONTROL, FRM_LINEAR, frmWrite3b, 1);
  438. /* Initialize DIDs */
  439. outputVal = 0;
  440. switch (bytesPerPixel) {
  441. case 1:
  442. SET_DBE_FIELD(WID, TYP, outputVal, DBE_CMODE_I8);
  443. break;
  444. case 2:
  445. SET_DBE_FIELD(WID, TYP, outputVal, DBE_CMODE_RGBA5);
  446. break;
  447. case 4:
  448. SET_DBE_FIELD(WID, TYP, outputVal, DBE_CMODE_RGB8);
  449. break;
  450. }
  451. SET_DBE_FIELD(WID, BUF, outputVal, DBE_BMODE_BOTH);
  452. for (i = 0; i < 32; i++) {
  453. DBE_ISETREG(mode_regs, i, outputVal);
  454. }
  455. /* dbe_InitTiming(); */
  456. DBE_SETREG(vt_intr01, 0xffffffff);
  457. DBE_SETREG(vt_intr23, 0xffffffff);
  458. DBE_GETREG(dotclock, readVal);
  459. DBE_SETREG(dotclock, readVal & 0xffff);
  460. DBE_SETREG(vt_xymax, 0x00000000);
  461. outputVal = 0;
  462. SET_DBE_FIELD(VT_VSYNC, VT_VSYNC_ON, outputVal,
  463. currentTiming->vsync_start);
  464. SET_DBE_FIELD(VT_VSYNC, VT_VSYNC_OFF, outputVal,
  465. currentTiming->vsync_end);
  466. DBE_SETREG(vt_vsync, outputVal);
  467. outputVal = 0;
  468. SET_DBE_FIELD(VT_HSYNC, VT_HSYNC_ON, outputVal,
  469. currentTiming->hsync_start);
  470. SET_DBE_FIELD(VT_HSYNC, VT_HSYNC_OFF, outputVal,
  471. currentTiming->hsync_end);
  472. DBE_SETREG(vt_hsync, outputVal);
  473. outputVal = 0;
  474. SET_DBE_FIELD(VT_VBLANK, VT_VBLANK_ON, outputVal,
  475. currentTiming->vblank_start);
  476. SET_DBE_FIELD(VT_VBLANK, VT_VBLANK_OFF, outputVal,
  477. currentTiming->vblank_end);
  478. DBE_SETREG(vt_vblank, outputVal);
  479. outputVal = 0;
  480. SET_DBE_FIELD(VT_HBLANK, VT_HBLANK_ON, outputVal,
  481. currentTiming->hblank_start);
  482. SET_DBE_FIELD(VT_HBLANK, VT_HBLANK_OFF, outputVal,
  483. currentTiming->hblank_end - 3);
  484. DBE_SETREG(vt_hblank, outputVal);
  485. outputVal = 0;
  486. SET_DBE_FIELD(VT_VCMAP, VT_VCMAP_ON, outputVal,
  487. currentTiming->vblank_start);
  488. SET_DBE_FIELD(VT_VCMAP, VT_VCMAP_OFF, outputVal,
  489. currentTiming->vblank_end);
  490. DBE_SETREG(vt_vcmap, outputVal);
  491. outputVal = 0;
  492. SET_DBE_FIELD(VT_HCMAP, VT_HCMAP_ON, outputVal,
  493. currentTiming->hblank_start);
  494. SET_DBE_FIELD(VT_HCMAP, VT_HCMAP_OFF, outputVal,
  495. currentTiming->hblank_end - 3);
  496. DBE_SETREG(vt_hcmap, outputVal);
  497. if (flatpanel_id != -1)
  498. sgivwfb_setup_flatpanel(par, currentTiming);
  499. outputVal = 0;
  500. temp = currentTiming->vblank_start - currentTiming->vblank_end - 1;
  501. if (temp > 0)
  502. temp = -temp;
  503. SET_DBE_FIELD(DID_START_XY, DID_STARTY, outputVal, (u32) temp);
  504. if (currentTiming->hblank_end >= 20)
  505. SET_DBE_FIELD(DID_START_XY, DID_STARTX, outputVal,
  506. currentTiming->hblank_end - 20);
  507. else
  508. SET_DBE_FIELD(DID_START_XY, DID_STARTX, outputVal,
  509. currentTiming->htotal - (20 -
  510. currentTiming->
  511. hblank_end));
  512. DBE_SETREG(did_start_xy, outputVal);
  513. outputVal = 0;
  514. SET_DBE_FIELD(CRS_START_XY, CRS_STARTY, outputVal,
  515. (u32) (temp + 1));
  516. if (currentTiming->hblank_end >= DBE_CRS_MAGIC)
  517. SET_DBE_FIELD(CRS_START_XY, CRS_STARTX, outputVal,
  518. currentTiming->hblank_end - DBE_CRS_MAGIC);
  519. else
  520. SET_DBE_FIELD(CRS_START_XY, CRS_STARTX, outputVal,
  521. currentTiming->htotal - (DBE_CRS_MAGIC -
  522. currentTiming->
  523. hblank_end));
  524. DBE_SETREG(crs_start_xy, outputVal);
  525. outputVal = 0;
  526. SET_DBE_FIELD(VC_START_XY, VC_STARTY, outputVal, (u32) temp);
  527. SET_DBE_FIELD(VC_START_XY, VC_STARTX, outputVal,
  528. currentTiming->hblank_end - 4);
  529. DBE_SETREG(vc_start_xy, outputVal);
  530. DBE_SETREG(frm_size_tile, frmWrite1);
  531. DBE_SETREG(frm_size_pixel, frmWrite2);
  532. outputVal = 0;
  533. SET_DBE_FIELD(DOTCLK, M, outputVal, currentTiming->pll_m - 1);
  534. SET_DBE_FIELD(DOTCLK, N, outputVal, currentTiming->pll_n - 1);
  535. SET_DBE_FIELD(DOTCLK, P, outputVal, currentTiming->pll_p);
  536. SET_DBE_FIELD(DOTCLK, RUN, outputVal, 1);
  537. DBE_SETREG(dotclock, outputVal);
  538. udelay(11 * 1000);
  539. DBE_SETREG(vt_vpixen, 0xffffff);
  540. DBE_SETREG(vt_hpixen, 0xffffff);
  541. outputVal = 0;
  542. SET_DBE_FIELD(VT_XYMAX, VT_MAXX, outputVal, currentTiming->htotal);
  543. SET_DBE_FIELD(VT_XYMAX, VT_MAXY, outputVal, currentTiming->vtotal);
  544. DBE_SETREG(vt_xymax, outputVal);
  545. outputVal = frmWrite1;
  546. SET_DBE_FIELD(FRM_SIZE_TILE, FRM_FIFO_RESET, outputVal, 1);
  547. DBE_SETREG(frm_size_tile, outputVal);
  548. DBE_SETREG(frm_size_tile, frmWrite1);
  549. outputVal = 0;
  550. SET_DBE_FIELD(OVR_WIDTH_TILE, OVR_FIFO_RESET, outputVal, 1);
  551. DBE_SETREG(ovr_width_tile, outputVal);
  552. DBE_SETREG(ovr_width_tile, 0);
  553. DBE_SETREG(frm_control, frmWrite3b);
  554. DBE_SETREG(did_control, 0);
  555. // Wait for dbe to take frame settings
  556. for (i = 0; i < 100000; i++) {
  557. DBE_GETREG(frm_inhwctrl, readVal);
  558. if (GET_DBE_FIELD(FRM_INHWCTRL, FRM_DMA_ENABLE, readVal) !=
  559. 0)
  560. break;
  561. else
  562. udelay(1);
  563. }
  564. if (i == 100000)
  565. printk(KERN_INFO
  566. "sgivwfb: timeout waiting for frame DMA enable.\n");
  567. outputVal = 0;
  568. htmp = currentTiming->hblank_end - 19;
  569. if (htmp < 0)
  570. htmp += currentTiming->htotal; /* allow blank to wrap around */
  571. SET_DBE_FIELD(VT_HPIXEN, VT_HPIXEN_ON, outputVal, htmp);
  572. SET_DBE_FIELD(VT_HPIXEN, VT_HPIXEN_OFF, outputVal,
  573. ((htmp + currentTiming->width -
  574. 2) % currentTiming->htotal));
  575. DBE_SETREG(vt_hpixen, outputVal);
  576. outputVal = 0;
  577. SET_DBE_FIELD(VT_VPIXEN, VT_VPIXEN_OFF, outputVal,
  578. currentTiming->vblank_start);
  579. SET_DBE_FIELD(VT_VPIXEN, VT_VPIXEN_ON, outputVal,
  580. currentTiming->vblank_end);
  581. DBE_SETREG(vt_vpixen, outputVal);
  582. // Turn off mouse cursor
  583. par->regs->crs_ctl = 0;
  584. // XXX What's this section for??
  585. DBE_GETREG(ctrlstat, readVal);
  586. readVal &= 0x02000000;
  587. if (readVal != 0) {
  588. DBE_SETREG(ctrlstat, 0x30000000);
  589. }
  590. return 0;
  591. }
  592. /*
  593. * Set a single color register. The values supplied are already
  594. * rounded down to the hardware's capabilities (according to the
  595. * entries in the var structure). Return != 0 for invalid regno.
  596. */
  597. static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green,
  598. u_int blue, u_int transp,
  599. struct fb_info *info)
  600. {
  601. struct sgivw_par *par = (struct sgivw_par *) info->par;
  602. if (regno > 255)
  603. return 1;
  604. red >>= 8;
  605. green >>= 8;
  606. blue >>= 8;
  607. /* wait for the color map FIFO to have a free entry */
  608. while (par->cmap_fifo == 0)
  609. par->cmap_fifo = par->regs->cm_fifo;
  610. par->regs->cmap[regno] = (red << 24) | (green << 16) | (blue << 8);
  611. par->cmap_fifo--; /* assume FIFO is filling up */
  612. return 0;
  613. }
  614. static int sgivwfb_mmap(struct fb_info *info,
  615. struct vm_area_struct *vma)
  616. {
  617. unsigned long size = vma->vm_end - vma->vm_start;
  618. unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
  619. if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
  620. return -EINVAL;
  621. if (offset + size > sgivwfb_mem_size)
  622. return -EINVAL;
  623. offset += sgivwfb_mem_phys;
  624. pgprot_val(vma->vm_page_prot) =
  625. pgprot_val(vma->vm_page_prot) | _PAGE_PCD;
  626. vma->vm_flags |= VM_IO;
  627. if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT,
  628. size, vma->vm_page_prot))
  629. return -EAGAIN;
  630. printk(KERN_DEBUG "sgivwfb: mmap framebuffer P(%lx)->V(%lx)\n",
  631. offset, vma->vm_start);
  632. return 0;
  633. }
  634. int __init sgivwfb_setup(char *options)
  635. {
  636. char *this_opt;
  637. if (!options || !*options)
  638. return 0;
  639. while ((this_opt = strsep(&options, ",")) != NULL) {
  640. if (!strncmp(this_opt, "monitor:", 8)) {
  641. if (!strncmp(this_opt + 8, "crt", 3))
  642. flatpanel_id = -1;
  643. else if (!strncmp(this_opt + 8, "1600sw", 6))
  644. flatpanel_id = FLATPANEL_SGI_1600SW;
  645. }
  646. }
  647. return 0;
  648. }
  649. /*
  650. * Initialisation
  651. */
  652. static int __init sgivwfb_probe(struct platform_device *dev)
  653. {
  654. struct sgivw_par *par;
  655. struct fb_info *info;
  656. char *monitor;
  657. info = framebuffer_alloc(sizeof(struct sgivw_par) + sizeof(u32) * 256, &dev->dev);
  658. if (!info)
  659. return -ENOMEM;
  660. par = info->par;
  661. if (!request_mem_region(DBE_REG_PHYS, DBE_REG_SIZE, "sgivwfb")) {
  662. printk(KERN_ERR "sgivwfb: couldn't reserve mmio region\n");
  663. framebuffer_release(info);
  664. return -EBUSY;
  665. }
  666. par->regs = (struct asregs *) ioremap_nocache(DBE_REG_PHYS, DBE_REG_SIZE);
  667. if (!par->regs) {
  668. printk(KERN_ERR "sgivwfb: couldn't ioremap registers\n");
  669. goto fail_ioremap_regs;
  670. }
  671. mtrr_add(sgivwfb_mem_phys, sgivwfb_mem_size, MTRR_TYPE_WRCOMB, 1);
  672. sgivwfb_fix.smem_start = sgivwfb_mem_phys;
  673. sgivwfb_fix.smem_len = sgivwfb_mem_size;
  674. sgivwfb_fix.ywrapstep = ywrap;
  675. sgivwfb_fix.ypanstep = ypan;
  676. info->fix = sgivwfb_fix;
  677. switch (flatpanel_id) {
  678. case FLATPANEL_SGI_1600SW:
  679. info->var = sgivwfb_var1600sw;
  680. monitor = "SGI 1600SW flatpanel";
  681. break;
  682. default:
  683. info->var = sgivwfb_var;
  684. monitor = "CRT";
  685. }
  686. printk(KERN_INFO "sgivwfb: %s monitor selected\n", monitor);
  687. info->fbops = &sgivwfb_ops;
  688. info->pseudo_palette = (void *) (par + 1);
  689. info->flags = FBINFO_DEFAULT;
  690. info->screen_base = ioremap_nocache((unsigned long) sgivwfb_mem_phys, sgivwfb_mem_size);
  691. if (!info->screen_base) {
  692. printk(KERN_ERR "sgivwfb: couldn't ioremap screen_base\n");
  693. goto fail_ioremap_fbmem;
  694. }
  695. if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
  696. goto fail_color_map;
  697. if (register_framebuffer(info) < 0) {
  698. printk(KERN_ERR "sgivwfb: couldn't register framebuffer\n");
  699. goto fail_register_framebuffer;
  700. }
  701. platform_set_drvdata(dev, info);
  702. printk(KERN_INFO "fb%d: SGI DBE frame buffer device, using %ldK of video memory at %#lx\n",
  703. info->node, sgivwfb_mem_size >> 10, sgivwfb_mem_phys);
  704. return 0;
  705. fail_register_framebuffer:
  706. fb_dealloc_cmap(&info->cmap);
  707. fail_color_map:
  708. iounmap((char *) info->screen_base);
  709. fail_ioremap_fbmem:
  710. iounmap(par->regs);
  711. fail_ioremap_regs:
  712. release_mem_region(DBE_REG_PHYS, DBE_REG_SIZE);
  713. framebuffer_release(info);
  714. return -ENXIO;
  715. }
  716. static int sgivwfb_remove(struct platform_device *dev)
  717. {
  718. struct fb_info *info = platform_get_drvdata(dev);
  719. if (info) {
  720. struct sgivw_par *par = info->par;
  721. unregister_framebuffer(info);
  722. dbe_TurnOffDma(par);
  723. iounmap(par->regs);
  724. iounmap(info->screen_base);
  725. release_mem_region(DBE_REG_PHYS, DBE_REG_SIZE);
  726. }
  727. return 0;
  728. }
  729. static struct platform_driver sgivwfb_driver = {
  730. .probe = sgivwfb_probe,
  731. .remove = sgivwfb_remove,
  732. .driver = {
  733. .name = "sgivwfb",
  734. },
  735. };
  736. static struct platform_device *sgivwfb_device;
  737. int __init sgivwfb_init(void)
  738. {
  739. int ret;
  740. #ifndef MODULE
  741. char *option = NULL;
  742. if (fb_get_options("sgivwfb", &option))
  743. return -ENODEV;
  744. sgivwfb_setup(option);
  745. #endif
  746. ret = platform_driver_register(&sgivwfb_driver);
  747. if (!ret) {
  748. sgivwfb_device = platform_device_alloc("sgivwfb", 0);
  749. if (sgivwfb_device) {
  750. ret = platform_device_add(sgivwfb_device);
  751. } else
  752. ret = -ENOMEM;
  753. if (ret) {
  754. platform_driver_unregister(&sgivwfb_driver);
  755. platform_device_put(sgivwfb_device);
  756. }
  757. }
  758. return ret;
  759. }
  760. module_init(sgivwfb_init);
  761. #ifdef MODULE
  762. MODULE_LICENSE("GPL");
  763. static void __exit sgivwfb_exit(void)
  764. {
  765. platform_device_unregister(sgivwfb_device);
  766. platform_driver_unregister(&sgivwfb_driver);
  767. }
  768. module_exit(sgivwfb_exit);
  769. #endif /* MODULE */