Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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