1 /* 2 * linux/drivers/video/vga16.c -- VGA 16-color framebuffer driver 3 * 4 * Copyright 1999 Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz> 5 * Based on VGA info at http://www.goodnet.com/~tinara/FreeVGA/home.htm 6 * Based on VESA framebuffer (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de> 7 * 8 * This file is subject to the terms and conditions of the GNU General 9 * Public License. See the file COPYING in the main directory of this 10 * archive for more details. 11 */ 12 13 #include <linux/module.h> 14 #include <linux/kernel.h> 15 #include <linux/errno.h> 16 #include <linux/string.h> 17 #include <linux/mm.h> 18 #include <linux/delay.h> 19 #include <linux/fb.h> 20 #include <linux/ioport.h> 21 #include <linux/init.h> 22 #include <linux/platform_device.h> 23 #include <linux/screen_info.h> 24 25 #include <asm/io.h> 26 #include <video/vga.h> 27 28 #define MODE_SKIP4 1 29 #define MODE_8BPP 2 30 #define MODE_CFB 4 31 #define MODE_TEXT 8 32 33 /* --------------------------------------------------------------------- */ 34 35 /* 36 * card parameters 37 */ 38 39 struct vga16fb_par { 40 /* structure holding original VGA register settings when the 41 screen is blanked */ 42 struct { 43 unsigned char SeqCtrlIndex; /* Sequencer Index reg. */ 44 unsigned char CrtCtrlIndex; /* CRT-Contr. Index reg. */ 45 unsigned char CrtMiscIO; /* Miscellaneous register */ 46 unsigned char HorizontalTotal; /* CRT-Controller:00h */ 47 unsigned char HorizDisplayEnd; /* CRT-Controller:01h */ 48 unsigned char StartHorizRetrace;/* CRT-Controller:04h */ 49 unsigned char EndHorizRetrace; /* CRT-Controller:05h */ 50 unsigned char Overflow; /* CRT-Controller:07h */ 51 unsigned char StartVertRetrace; /* CRT-Controller:10h */ 52 unsigned char EndVertRetrace; /* CRT-Controller:11h */ 53 unsigned char ModeControl; /* CRT-Controller:17h */ 54 unsigned char ClockingMode; /* Seq-Controller:01h */ 55 } vga_state; 56 struct vgastate state; 57 unsigned int ref_count; 58 int palette_blanked, vesa_blanked, mode, isVGA; 59 u8 misc, pel_msk, vss, clkdiv; 60 u8 crtc[VGA_CRT_C]; 61 }; 62 63 /* --------------------------------------------------------------------- */ 64 65 static struct fb_var_screeninfo vga16fb_defined = { 66 .xres = 640, 67 .yres = 480, 68 .xres_virtual = 640, 69 .yres_virtual = 480, 70 .bits_per_pixel = 4, 71 .activate = FB_ACTIVATE_TEST, 72 .height = -1, 73 .width = -1, 74 .pixclock = 39721, 75 .left_margin = 48, 76 .right_margin = 16, 77 .upper_margin = 33, 78 .lower_margin = 10, 79 .hsync_len = 96, 80 .vsync_len = 2, 81 .vmode = FB_VMODE_NONINTERLACED, 82 }; 83 84 /* name should not depend on EGA/VGA */ 85 static const struct fb_fix_screeninfo vga16fb_fix = { 86 .id = "VGA16 VGA", 87 .smem_start = VGA_FB_PHYS_BASE, 88 .smem_len = VGA_FB_PHYS_SIZE, 89 .type = FB_TYPE_VGA_PLANES, 90 .type_aux = FB_AUX_VGA_PLANES_VGA4, 91 .visual = FB_VISUAL_PSEUDOCOLOR, 92 .xpanstep = 8, 93 .ypanstep = 1, 94 .line_length = 640 / 8, 95 .accel = FB_ACCEL_NONE 96 }; 97 98 /* The VGA's weird architecture often requires that we read a byte and 99 write a byte to the same location. It doesn't matter *what* byte 100 we write, however. This is because all the action goes on behind 101 the scenes in the VGA's 32-bit latch register, and reading and writing 102 video memory just invokes latch behavior. 103 104 To avoid race conditions (is this necessary?), reading and writing 105 the memory byte should be done with a single instruction. One 106 suitable instruction is the x86 bitwise OR. The following 107 read-modify-write routine should optimize to one such bitwise 108 OR. */ 109 static inline void rmw(volatile char __iomem *p) 110 { 111 readb(p); 112 writeb(1, p); 113 } 114 115 /* Set the Graphics Mode Register, and return its previous value. 116 Bits 0-1 are write mode, bit 3 is read mode. */ 117 static inline int setmode(int mode) 118 { 119 int oldmode; 120 121 oldmode = vga_io_rgfx(VGA_GFX_MODE); 122 vga_io_w(VGA_GFX_D, mode); 123 return oldmode; 124 } 125 126 /* Select the Bit Mask Register and return its value. */ 127 static inline int selectmask(void) 128 { 129 return vga_io_rgfx(VGA_GFX_BIT_MASK); 130 } 131 132 /* Set the value of the Bit Mask Register. It must already have been 133 selected with selectmask(). */ 134 static inline void setmask(int mask) 135 { 136 vga_io_w(VGA_GFX_D, mask); 137 } 138 139 /* Set the Data Rotate Register and return its old value. 140 Bits 0-2 are rotate count, bits 3-4 are logical operation 141 (0=NOP, 1=AND, 2=OR, 3=XOR). */ 142 static inline int setop(int op) 143 { 144 int oldop; 145 146 oldop = vga_io_rgfx(VGA_GFX_DATA_ROTATE); 147 vga_io_w(VGA_GFX_D, op); 148 return oldop; 149 } 150 151 /* Set the Enable Set/Reset Register and return its old value. 152 The code here always uses value 0xf for this register. */ 153 static inline int setsr(int sr) 154 { 155 int oldsr; 156 157 oldsr = vga_io_rgfx(VGA_GFX_SR_ENABLE); 158 vga_io_w(VGA_GFX_D, sr); 159 return oldsr; 160 } 161 162 /* Set the Set/Reset Register and return its old value. */ 163 static inline int setcolor(int color) 164 { 165 int oldcolor; 166 167 oldcolor = vga_io_rgfx(VGA_GFX_SR_VALUE); 168 vga_io_w(VGA_GFX_D, color); 169 return oldcolor; 170 } 171 172 /* Return the value in the Graphics Address Register. */ 173 static inline int getindex(void) 174 { 175 return vga_io_r(VGA_GFX_I); 176 } 177 178 /* Set the value in the Graphics Address Register. */ 179 static inline void setindex(int index) 180 { 181 vga_io_w(VGA_GFX_I, index); 182 } 183 184 /* Check if the video mode is supported by the driver */ 185 static inline int check_mode_supported(const struct screen_info *si) 186 { 187 /* non-x86 architectures treat orig_video_isVGA as a boolean flag */ 188 #if defined(CONFIG_X86) 189 /* only EGA and VGA in 16 color graphic mode are supported */ 190 if (si->orig_video_isVGA != VIDEO_TYPE_EGAC && 191 si->orig_video_isVGA != VIDEO_TYPE_VGAC) 192 return -ENODEV; 193 194 if (si->orig_video_mode != 0x0D && /* 320x200/4 (EGA) */ 195 si->orig_video_mode != 0x0E && /* 640x200/4 (EGA) */ 196 si->orig_video_mode != 0x10 && /* 640x350/4 (EGA) */ 197 si->orig_video_mode != 0x12) /* 640x480/4 (VGA) */ 198 return -ENODEV; 199 #endif 200 return 0; 201 } 202 203 static void vga16fb_pan_var(struct fb_info *info, 204 struct fb_var_screeninfo *var) 205 { 206 struct vga16fb_par *par = info->par; 207 u32 xoffset, pos; 208 209 xoffset = var->xoffset; 210 if (info->var.bits_per_pixel == 8) { 211 pos = (info->var.xres_virtual * var->yoffset + xoffset) >> 2; 212 } else if (par->mode & MODE_TEXT) { 213 int fh = 16; // FIXME !!! font height. Fugde for now. 214 pos = (info->var.xres_virtual * (var->yoffset / fh) + xoffset) >> 3; 215 } else { 216 if (info->var.nonstd) 217 xoffset--; 218 pos = (info->var.xres_virtual * var->yoffset + xoffset) >> 3; 219 } 220 vga_io_wcrt(VGA_CRTC_START_HI, pos >> 8); 221 vga_io_wcrt(VGA_CRTC_START_LO, pos & 0xFF); 222 /* if we support CFB4, then we must! support xoffset with pixel 223 * granularity if someone supports xoffset in bit resolution */ 224 vga_io_r(VGA_IS1_RC); /* reset flip-flop */ 225 vga_io_w(VGA_ATT_IW, VGA_ATC_PEL); 226 if (info->var.bits_per_pixel == 8) 227 vga_io_w(VGA_ATT_IW, (xoffset & 3) << 1); 228 else 229 vga_io_w(VGA_ATT_IW, xoffset & 7); 230 vga_io_r(VGA_IS1_RC); 231 vga_io_w(VGA_ATT_IW, 0x20); 232 } 233 234 static void vga16fb_update_fix(struct fb_info *info) 235 { 236 if (info->var.bits_per_pixel == 4) { 237 if (info->var.nonstd) { 238 info->fix.type = FB_TYPE_PACKED_PIXELS; 239 info->fix.line_length = info->var.xres_virtual / 2; 240 } else { 241 info->fix.type = FB_TYPE_VGA_PLANES; 242 info->fix.type_aux = FB_AUX_VGA_PLANES_VGA4; 243 info->fix.line_length = info->var.xres_virtual / 8; 244 } 245 } else if (info->var.bits_per_pixel == 0) { 246 info->fix.type = FB_TYPE_TEXT; 247 info->fix.type_aux = FB_AUX_TEXT_CGA; 248 info->fix.line_length = info->var.xres_virtual / 4; 249 } else { /* 8bpp */ 250 if (info->var.nonstd) { 251 info->fix.type = FB_TYPE_VGA_PLANES; 252 info->fix.type_aux = FB_AUX_VGA_PLANES_CFB8; 253 info->fix.line_length = info->var.xres_virtual / 4; 254 } else { 255 info->fix.type = FB_TYPE_PACKED_PIXELS; 256 info->fix.line_length = info->var.xres_virtual; 257 } 258 } 259 } 260 261 static void vga16fb_clock_chip(struct vga16fb_par *par, 262 unsigned int *pixclock, 263 const struct fb_info *info, 264 int mul, int div) 265 { 266 static const struct { 267 u32 pixclock; 268 u8 misc; 269 u8 seq_clock_mode; 270 } *ptr, *best, vgaclocks[] = { 271 { 79442 /* 12.587 */, 0x00, 0x08}, 272 { 70616 /* 14.161 */, 0x04, 0x08}, 273 { 39721 /* 25.175 */, 0x00, 0x00}, 274 { 35308 /* 28.322 */, 0x04, 0x00}, 275 { 0 /* bad */, 0x00, 0x00}}; 276 int err; 277 278 *pixclock = (*pixclock * mul) / div; 279 best = vgaclocks; 280 err = *pixclock - best->pixclock; 281 if (err < 0) err = -err; 282 for (ptr = vgaclocks + 1; ptr->pixclock; ptr++) { 283 int tmp; 284 285 tmp = *pixclock - ptr->pixclock; 286 if (tmp < 0) tmp = -tmp; 287 if (tmp < err) { 288 err = tmp; 289 best = ptr; 290 } 291 } 292 par->misc |= best->misc; 293 par->clkdiv = best->seq_clock_mode; 294 *pixclock = (best->pixclock * div) / mul; 295 } 296 297 #define FAIL(X) return -EINVAL 298 299 static int vga16fb_open(struct fb_info *info, int user) 300 { 301 struct vga16fb_par *par = info->par; 302 303 if (!par->ref_count) { 304 memset(&par->state, 0, sizeof(struct vgastate)); 305 par->state.flags = VGA_SAVE_FONTS | VGA_SAVE_MODE | 306 VGA_SAVE_CMAP; 307 save_vga(&par->state); 308 } 309 par->ref_count++; 310 311 return 0; 312 } 313 314 static int vga16fb_release(struct fb_info *info, int user) 315 { 316 struct vga16fb_par *par = info->par; 317 318 if (!par->ref_count) 319 return -EINVAL; 320 321 if (par->ref_count == 1) 322 restore_vga(&par->state); 323 par->ref_count--; 324 325 return 0; 326 } 327 328 static int vga16fb_check_var(struct fb_var_screeninfo *var, 329 struct fb_info *info) 330 { 331 struct vga16fb_par *par = info->par; 332 u32 xres, right, hslen, left, xtotal; 333 u32 yres, lower, vslen, upper, ytotal; 334 u32 vxres, xoffset, vyres, yoffset; 335 u32 pos; 336 u8 r7, rMode; 337 int shift; 338 int mode; 339 u32 maxmem; 340 341 par->pel_msk = 0xFF; 342 343 if (var->bits_per_pixel == 4) { 344 if (var->nonstd) { 345 if (!par->isVGA) 346 return -EINVAL; 347 shift = 3; 348 mode = MODE_SKIP4 | MODE_CFB; 349 maxmem = 16384; 350 par->pel_msk = 0x0F; 351 } else { 352 shift = 3; 353 mode = 0; 354 maxmem = 65536; 355 } 356 } else if (var->bits_per_pixel == 8) { 357 if (!par->isVGA) 358 return -EINVAL; /* no support on EGA */ 359 shift = 2; 360 if (var->nonstd) { 361 mode = MODE_8BPP | MODE_CFB; 362 maxmem = 65536; 363 } else { 364 mode = MODE_SKIP4 | MODE_8BPP | MODE_CFB; 365 maxmem = 16384; 366 } 367 } else 368 return -EINVAL; 369 370 xres = (var->xres + 7) & ~7; 371 vxres = (var->xres_virtual + 0xF) & ~0xF; 372 xoffset = (var->xoffset + 7) & ~7; 373 left = (var->left_margin + 7) & ~7; 374 right = (var->right_margin + 7) & ~7; 375 hslen = (var->hsync_len + 7) & ~7; 376 377 if (vxres < xres) 378 vxres = xres; 379 if (xres + xoffset > vxres) 380 xoffset = vxres - xres; 381 382 var->xres = xres; 383 var->right_margin = right; 384 var->hsync_len = hslen; 385 var->left_margin = left; 386 var->xres_virtual = vxres; 387 var->xoffset = xoffset; 388 389 xres >>= shift; 390 right >>= shift; 391 hslen >>= shift; 392 left >>= shift; 393 vxres >>= shift; 394 xtotal = xres + right + hslen + left; 395 if (xtotal >= 256) 396 FAIL("xtotal too big"); 397 if (hslen > 32) 398 FAIL("hslen too big"); 399 if (right + hslen + left > 64) 400 FAIL("hblank too big"); 401 par->crtc[VGA_CRTC_H_TOTAL] = xtotal - 5; 402 par->crtc[VGA_CRTC_H_BLANK_START] = xres - 1; 403 par->crtc[VGA_CRTC_H_DISP] = xres - 1; 404 pos = xres + right; 405 par->crtc[VGA_CRTC_H_SYNC_START] = pos; 406 pos += hslen; 407 par->crtc[VGA_CRTC_H_SYNC_END] = pos & 0x1F; 408 pos += left - 2; /* blank_end + 2 <= total + 5 */ 409 par->crtc[VGA_CRTC_H_BLANK_END] = (pos & 0x1F) | 0x80; 410 if (pos & 0x20) 411 par->crtc[VGA_CRTC_H_SYNC_END] |= 0x80; 412 413 yres = var->yres; 414 lower = var->lower_margin; 415 vslen = var->vsync_len; 416 upper = var->upper_margin; 417 vyres = var->yres_virtual; 418 yoffset = var->yoffset; 419 420 if (yres > vyres) 421 vyres = yres; 422 if (vxres * vyres > maxmem) { 423 vyres = maxmem / vxres; 424 if (vyres < yres) 425 return -ENOMEM; 426 } 427 if (yoffset + yres > vyres) 428 yoffset = vyres - yres; 429 var->yres = yres; 430 var->lower_margin = lower; 431 var->vsync_len = vslen; 432 var->upper_margin = upper; 433 var->yres_virtual = vyres; 434 var->yoffset = yoffset; 435 436 if (var->vmode & FB_VMODE_DOUBLE) { 437 yres <<= 1; 438 lower <<= 1; 439 vslen <<= 1; 440 upper <<= 1; 441 } 442 ytotal = yres + lower + vslen + upper; 443 if (ytotal > 1024) { 444 ytotal >>= 1; 445 yres >>= 1; 446 lower >>= 1; 447 vslen >>= 1; 448 upper >>= 1; 449 rMode = 0x04; 450 } else 451 rMode = 0x00; 452 if (ytotal > 1024) 453 FAIL("ytotal too big"); 454 if (vslen > 16) 455 FAIL("vslen too big"); 456 par->crtc[VGA_CRTC_V_TOTAL] = ytotal - 2; 457 r7 = 0x10; /* disable linecompare */ 458 if (ytotal & 0x100) r7 |= 0x01; 459 if (ytotal & 0x200) r7 |= 0x20; 460 par->crtc[VGA_CRTC_PRESET_ROW] = 0; 461 par->crtc[VGA_CRTC_MAX_SCAN] = 0x40; /* 1 scanline, no linecmp */ 462 if (var->vmode & FB_VMODE_DOUBLE) 463 par->crtc[VGA_CRTC_MAX_SCAN] |= 0x80; 464 par->crtc[VGA_CRTC_CURSOR_START] = 0x20; 465 par->crtc[VGA_CRTC_CURSOR_END] = 0x00; 466 if ((mode & (MODE_CFB | MODE_8BPP)) == MODE_CFB) 467 xoffset--; 468 pos = yoffset * vxres + (xoffset >> shift); 469 par->crtc[VGA_CRTC_START_HI] = pos >> 8; 470 par->crtc[VGA_CRTC_START_LO] = pos & 0xFF; 471 par->crtc[VGA_CRTC_CURSOR_HI] = 0x00; 472 par->crtc[VGA_CRTC_CURSOR_LO] = 0x00; 473 pos = yres - 1; 474 par->crtc[VGA_CRTC_V_DISP_END] = pos & 0xFF; 475 par->crtc[VGA_CRTC_V_BLANK_START] = pos & 0xFF; 476 if (pos & 0x100) 477 r7 |= 0x0A; /* 0x02 -> DISP_END, 0x08 -> BLANK_START */ 478 if (pos & 0x200) { 479 r7 |= 0x40; /* 0x40 -> DISP_END */ 480 par->crtc[VGA_CRTC_MAX_SCAN] |= 0x20; /* BLANK_START */ 481 } 482 pos += lower; 483 par->crtc[VGA_CRTC_V_SYNC_START] = pos & 0xFF; 484 if (pos & 0x100) 485 r7 |= 0x04; 486 if (pos & 0x200) 487 r7 |= 0x80; 488 pos += vslen; 489 par->crtc[VGA_CRTC_V_SYNC_END] = (pos & 0x0F) & ~0x10; /* disabled IRQ */ 490 pos += upper - 1; /* blank_end + 1 <= ytotal + 2 */ 491 par->crtc[VGA_CRTC_V_BLANK_END] = pos & 0xFF; /* 0x7F for original VGA, 492 but some SVGA chips requires all 8 bits to set */ 493 if (vxres >= 512) 494 FAIL("vxres too long"); 495 par->crtc[VGA_CRTC_OFFSET] = vxres >> 1; 496 if (mode & MODE_SKIP4) 497 par->crtc[VGA_CRTC_UNDERLINE] = 0x5F; /* 256, cfb8 */ 498 else 499 par->crtc[VGA_CRTC_UNDERLINE] = 0x1F; /* 16, vgap */ 500 par->crtc[VGA_CRTC_MODE] = rMode | ((mode & MODE_TEXT) ? 0xA3 : 0xE3); 501 par->crtc[VGA_CRTC_LINE_COMPARE] = 0xFF; 502 par->crtc[VGA_CRTC_OVERFLOW] = r7; 503 504 par->vss = 0x00; /* 3DA */ 505 506 par->misc = 0xE3; /* enable CPU, ports 0x3Dx, positive sync */ 507 if (var->sync & FB_SYNC_HOR_HIGH_ACT) 508 par->misc &= ~0x40; 509 if (var->sync & FB_SYNC_VERT_HIGH_ACT) 510 par->misc &= ~0x80; 511 512 par->mode = mode; 513 514 if (mode & MODE_8BPP) 515 /* pixel clock == vga clock / 2 */ 516 vga16fb_clock_chip(par, &var->pixclock, info, 1, 2); 517 else 518 /* pixel clock == vga clock */ 519 vga16fb_clock_chip(par, &var->pixclock, info, 1, 1); 520 521 var->red.offset = var->green.offset = var->blue.offset = 522 var->transp.offset = 0; 523 var->red.length = var->green.length = var->blue.length = 524 (par->isVGA) ? 6 : 2; 525 var->transp.length = 0; 526 var->activate = FB_ACTIVATE_NOW; 527 var->height = -1; 528 var->width = -1; 529 var->accel_flags = 0; 530 return 0; 531 } 532 #undef FAIL 533 534 static int vga16fb_set_par(struct fb_info *info) 535 { 536 struct vga16fb_par *par = info->par; 537 u8 gdc[VGA_GFX_C]; 538 u8 seq[VGA_SEQ_C]; 539 u8 atc[VGA_ATT_C]; 540 int fh, i; 541 542 seq[VGA_SEQ_CLOCK_MODE] = 0x01 | par->clkdiv; 543 if (par->mode & MODE_TEXT) 544 seq[VGA_SEQ_PLANE_WRITE] = 0x03; 545 else 546 seq[VGA_SEQ_PLANE_WRITE] = 0x0F; 547 seq[VGA_SEQ_CHARACTER_MAP] = 0x00; 548 if (par->mode & MODE_TEXT) 549 seq[VGA_SEQ_MEMORY_MODE] = 0x03; 550 else if (par->mode & MODE_SKIP4) 551 seq[VGA_SEQ_MEMORY_MODE] = 0x0E; 552 else 553 seq[VGA_SEQ_MEMORY_MODE] = 0x06; 554 555 gdc[VGA_GFX_SR_VALUE] = 0x00; 556 gdc[VGA_GFX_SR_ENABLE] = 0x00; 557 gdc[VGA_GFX_COMPARE_VALUE] = 0x00; 558 gdc[VGA_GFX_DATA_ROTATE] = 0x00; 559 gdc[VGA_GFX_PLANE_READ] = 0; 560 if (par->mode & MODE_TEXT) { 561 gdc[VGA_GFX_MODE] = 0x10; 562 gdc[VGA_GFX_MISC] = 0x06; 563 } else { 564 if (par->mode & MODE_CFB) 565 gdc[VGA_GFX_MODE] = 0x40; 566 else 567 gdc[VGA_GFX_MODE] = 0x00; 568 gdc[VGA_GFX_MISC] = 0x05; 569 } 570 gdc[VGA_GFX_COMPARE_MASK] = 0x0F; 571 gdc[VGA_GFX_BIT_MASK] = 0xFF; 572 573 for (i = 0x00; i < 0x10; i++) 574 atc[i] = i; 575 if (par->mode & MODE_TEXT) 576 atc[VGA_ATC_MODE] = 0x04; 577 else if (par->mode & MODE_8BPP) 578 atc[VGA_ATC_MODE] = 0x41; 579 else 580 atc[VGA_ATC_MODE] = 0x81; 581 atc[VGA_ATC_OVERSCAN] = 0x00; /* 0 for EGA, 0xFF for VGA */ 582 atc[VGA_ATC_PLANE_ENABLE] = 0x0F; 583 if (par->mode & MODE_8BPP) 584 atc[VGA_ATC_PEL] = (info->var.xoffset & 3) << 1; 585 else 586 atc[VGA_ATC_PEL] = info->var.xoffset & 7; 587 atc[VGA_ATC_COLOR_PAGE] = 0x00; 588 589 if (par->mode & MODE_TEXT) { 590 fh = 16; // FIXME !!! Fudge font height. 591 par->crtc[VGA_CRTC_MAX_SCAN] = (par->crtc[VGA_CRTC_MAX_SCAN] 592 & ~0x1F) | (fh - 1); 593 } 594 595 vga_io_w(VGA_MIS_W, vga_io_r(VGA_MIS_R) | 0x01); 596 597 /* Enable graphics register modification */ 598 if (!par->isVGA) { 599 vga_io_w(EGA_GFX_E0, 0x00); 600 vga_io_w(EGA_GFX_E1, 0x01); 601 } 602 603 /* update misc output register */ 604 vga_io_w(VGA_MIS_W, par->misc); 605 606 /* synchronous reset on */ 607 vga_io_wseq(0x00, 0x01); 608 609 if (par->isVGA) 610 vga_io_w(VGA_PEL_MSK, par->pel_msk); 611 612 /* write sequencer registers */ 613 vga_io_wseq(VGA_SEQ_CLOCK_MODE, seq[VGA_SEQ_CLOCK_MODE] | 0x20); 614 for (i = 2; i < VGA_SEQ_C; i++) { 615 vga_io_wseq(i, seq[i]); 616 } 617 618 /* synchronous reset off */ 619 vga_io_wseq(0x00, 0x03); 620 621 /* deprotect CRT registers 0-7 */ 622 vga_io_wcrt(VGA_CRTC_V_SYNC_END, par->crtc[VGA_CRTC_V_SYNC_END]); 623 624 /* write CRT registers */ 625 for (i = 0; i < VGA_CRTC_REGS; i++) { 626 vga_io_wcrt(i, par->crtc[i]); 627 } 628 629 /* write graphics controller registers */ 630 for (i = 0; i < VGA_GFX_C; i++) { 631 vga_io_wgfx(i, gdc[i]); 632 } 633 634 /* write attribute controller registers */ 635 for (i = 0; i < VGA_ATT_C; i++) { 636 vga_io_r(VGA_IS1_RC); /* reset flip-flop */ 637 vga_io_wattr(i, atc[i]); 638 } 639 640 /* Wait for screen to stabilize. */ 641 mdelay(50); 642 643 vga_io_wseq(VGA_SEQ_CLOCK_MODE, seq[VGA_SEQ_CLOCK_MODE]); 644 645 vga_io_r(VGA_IS1_RC); 646 vga_io_w(VGA_ATT_IW, 0x20); 647 648 vga16fb_update_fix(info); 649 return 0; 650 } 651 652 static void ega16_setpalette(int regno, unsigned red, unsigned green, unsigned blue) 653 { 654 static const unsigned char map[] = { 000, 001, 010, 011 }; 655 int val; 656 657 if (regno >= 16) 658 return; 659 val = map[red>>14] | ((map[green>>14]) << 1) | ((map[blue>>14]) << 2); 660 vga_io_r(VGA_IS1_RC); /* ! 0x3BA */ 661 vga_io_wattr(regno, val); 662 vga_io_r(VGA_IS1_RC); /* some clones need it */ 663 vga_io_w(VGA_ATT_IW, 0x20); /* unblank screen */ 664 } 665 666 static void vga16_setpalette(int regno, unsigned red, unsigned green, unsigned blue) 667 { 668 outb(regno, VGA_PEL_IW); 669 outb(red >> 10, VGA_PEL_D); 670 outb(green >> 10, VGA_PEL_D); 671 outb(blue >> 10, VGA_PEL_D); 672 } 673 674 static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green, 675 unsigned blue, unsigned transp, 676 struct fb_info *info) 677 { 678 struct vga16fb_par *par = info->par; 679 int gray; 680 681 /* 682 * Set a single color register. The values supplied are 683 * already rounded down to the hardware's capabilities 684 * (according to the entries in the `var' structure). Return 685 * != 0 for invalid regno. 686 */ 687 688 if (regno >= 256) 689 return 1; 690 691 gray = info->var.grayscale; 692 693 if (gray) { 694 /* gray = 0.30*R + 0.59*G + 0.11*B */ 695 red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; 696 } 697 if (par->isVGA) 698 vga16_setpalette(regno,red,green,blue); 699 else 700 ega16_setpalette(regno,red,green,blue); 701 return 0; 702 } 703 704 static int vga16fb_pan_display(struct fb_var_screeninfo *var, 705 struct fb_info *info) 706 { 707 vga16fb_pan_var(info, var); 708 return 0; 709 } 710 711 /* The following VESA blanking code is taken from vgacon.c. The VGA 712 blanking code was originally by Huang shi chao, and modified by 713 Christoph Rimek (chrimek@toppoint.de) and todd j. derr 714 (tjd@barefoot.org) for Linux. */ 715 716 static void vga_vesa_blank(struct vga16fb_par *par, int mode) 717 { 718 unsigned char SeqCtrlIndex = vga_io_r(VGA_SEQ_I); 719 unsigned char CrtCtrlIndex = vga_io_r(VGA_CRT_IC); 720 721 /* save original values of VGA controller registers */ 722 if(!par->vesa_blanked) { 723 par->vga_state.CrtMiscIO = vga_io_r(VGA_MIS_R); 724 //sti(); 725 726 par->vga_state.HorizontalTotal = vga_io_rcrt(0x00); /* HorizontalTotal */ 727 par->vga_state.HorizDisplayEnd = vga_io_rcrt(0x01); /* HorizDisplayEnd */ 728 par->vga_state.StartHorizRetrace = vga_io_rcrt(0x04); /* StartHorizRetrace */ 729 par->vga_state.EndHorizRetrace = vga_io_rcrt(0x05); /* EndHorizRetrace */ 730 par->vga_state.Overflow = vga_io_rcrt(0x07); /* Overflow */ 731 par->vga_state.StartVertRetrace = vga_io_rcrt(0x10); /* StartVertRetrace */ 732 par->vga_state.EndVertRetrace = vga_io_rcrt(0x11); /* EndVertRetrace */ 733 par->vga_state.ModeControl = vga_io_rcrt(0x17); /* ModeControl */ 734 par->vga_state.ClockingMode = vga_io_rseq(0x01); /* ClockingMode */ 735 } 736 737 /* assure that video is enabled */ 738 /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */ 739 vga_io_wseq(0x01, par->vga_state.ClockingMode | 0x20); 740 741 /* test for vertical retrace in process.... */ 742 if ((par->vga_state.CrtMiscIO & 0x80) == 0x80) 743 vga_io_w(VGA_MIS_W, par->vga_state.CrtMiscIO & 0xef); 744 745 /* 746 * Set <End of vertical retrace> to minimum (0) and 747 * <Start of vertical Retrace> to maximum (incl. overflow) 748 * Result: turn off vertical sync (VSync) pulse. 749 */ 750 if (mode & FB_BLANK_VSYNC_SUSPEND) { 751 vga_io_wcrt(VGA_CRTC_V_SYNC_START, 0xff); 752 vga_io_wcrt(VGA_CRTC_V_SYNC_END, 0x40); 753 /* bits 9,10 of vert. retrace */ 754 vga_io_wcrt(VGA_CRTC_OVERFLOW, par->vga_state.Overflow | 0x84); 755 } 756 757 if (mode & FB_BLANK_HSYNC_SUSPEND) { 758 /* 759 * Set <End of horizontal retrace> to minimum (0) and 760 * <Start of horizontal Retrace> to maximum 761 * Result: turn off horizontal sync (HSync) pulse. 762 */ 763 vga_io_wcrt(VGA_CRTC_H_SYNC_START, 0xff); 764 vga_io_wcrt(VGA_CRTC_H_SYNC_END, 0x00); 765 } 766 767 /* restore both index registers */ 768 outb_p(SeqCtrlIndex, VGA_SEQ_I); 769 outb_p(CrtCtrlIndex, VGA_CRT_IC); 770 } 771 772 static void vga_vesa_unblank(struct vga16fb_par *par) 773 { 774 unsigned char SeqCtrlIndex = vga_io_r(VGA_SEQ_I); 775 unsigned char CrtCtrlIndex = vga_io_r(VGA_CRT_IC); 776 777 /* restore original values of VGA controller registers */ 778 vga_io_w(VGA_MIS_W, par->vga_state.CrtMiscIO); 779 780 /* HorizontalTotal */ 781 vga_io_wcrt(0x00, par->vga_state.HorizontalTotal); 782 /* HorizDisplayEnd */ 783 vga_io_wcrt(0x01, par->vga_state.HorizDisplayEnd); 784 /* StartHorizRetrace */ 785 vga_io_wcrt(0x04, par->vga_state.StartHorizRetrace); 786 /* EndHorizRetrace */ 787 vga_io_wcrt(0x05, par->vga_state.EndHorizRetrace); 788 /* Overflow */ 789 vga_io_wcrt(0x07, par->vga_state.Overflow); 790 /* StartVertRetrace */ 791 vga_io_wcrt(0x10, par->vga_state.StartVertRetrace); 792 /* EndVertRetrace */ 793 vga_io_wcrt(0x11, par->vga_state.EndVertRetrace); 794 /* ModeControl */ 795 vga_io_wcrt(0x17, par->vga_state.ModeControl); 796 /* ClockingMode */ 797 vga_io_wseq(0x01, par->vga_state.ClockingMode); 798 799 /* restore index/control registers */ 800 vga_io_w(VGA_SEQ_I, SeqCtrlIndex); 801 vga_io_w(VGA_CRT_IC, CrtCtrlIndex); 802 } 803 804 static void vga_pal_blank(void) 805 { 806 int i; 807 808 for (i=0; i<16; i++) { 809 outb_p(i, VGA_PEL_IW); 810 outb_p(0, VGA_PEL_D); 811 outb_p(0, VGA_PEL_D); 812 outb_p(0, VGA_PEL_D); 813 } 814 } 815 816 /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */ 817 static int vga16fb_blank(int blank, struct fb_info *info) 818 { 819 struct vga16fb_par *par = info->par; 820 821 switch (blank) { 822 case FB_BLANK_UNBLANK: /* Unblank */ 823 if (par->vesa_blanked) { 824 vga_vesa_unblank(par); 825 par->vesa_blanked = 0; 826 } 827 if (par->palette_blanked) { 828 par->palette_blanked = 0; 829 } 830 break; 831 case FB_BLANK_NORMAL: /* blank */ 832 vga_pal_blank(); 833 par->palette_blanked = 1; 834 break; 835 default: /* VESA blanking */ 836 vga_vesa_blank(par, blank); 837 par->vesa_blanked = 1; 838 break; 839 } 840 return 0; 841 } 842 843 static void vga_8planes_fillrect(struct fb_info *info, const struct fb_fillrect *rect) 844 { 845 u32 dx = rect->dx, width = rect->width; 846 char oldindex = getindex(); 847 char oldmode = setmode(0x40); 848 char oldmask = selectmask(); 849 int line_ofs, height; 850 char oldop, oldsr; 851 char __iomem *where; 852 853 dx /= 4; 854 where = info->screen_base + dx + rect->dy * info->fix.line_length; 855 856 if (rect->rop == ROP_COPY) { 857 oldop = setop(0); 858 oldsr = setsr(0); 859 860 width /= 4; 861 line_ofs = info->fix.line_length - width; 862 setmask(0xff); 863 864 height = rect->height; 865 866 while (height--) { 867 int x; 868 869 /* we can do memset... */ 870 for (x = width; x > 0; --x) { 871 writeb(rect->color, where); 872 where++; 873 } 874 where += line_ofs; 875 } 876 } else { 877 char oldcolor = setcolor(0xf); 878 int y; 879 880 oldop = setop(0x18); 881 oldsr = setsr(0xf); 882 setmask(0x0F); 883 for (y = 0; y < rect->height; y++) { 884 rmw(where); 885 rmw(where+1); 886 where += info->fix.line_length; 887 } 888 setcolor(oldcolor); 889 } 890 setmask(oldmask); 891 setsr(oldsr); 892 setop(oldop); 893 setmode(oldmode); 894 setindex(oldindex); 895 } 896 897 static void vga16fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) 898 { 899 int x, x2, y2, vxres, vyres, width, height, line_ofs; 900 char __iomem *dst; 901 902 vxres = info->var.xres_virtual; 903 vyres = info->var.yres_virtual; 904 905 if (!rect->width || !rect->height || rect->dx > vxres || rect->dy > vyres) 906 return; 907 908 /* We could use hardware clipping but on many cards you get around 909 * hardware clipping by writing to framebuffer directly. */ 910 911 x2 = rect->dx + rect->width; 912 y2 = rect->dy + rect->height; 913 x2 = x2 < vxres ? x2 : vxres; 914 y2 = y2 < vyres ? y2 : vyres; 915 width = x2 - rect->dx; 916 917 switch (info->fix.type) { 918 case FB_TYPE_VGA_PLANES: 919 if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) { 920 921 height = y2 - rect->dy; 922 width = rect->width/8; 923 924 line_ofs = info->fix.line_length - width; 925 dst = info->screen_base + (rect->dx/8) + rect->dy * info->fix.line_length; 926 927 switch (rect->rop) { 928 case ROP_COPY: 929 setmode(0); 930 setop(0); 931 setsr(0xf); 932 setcolor(rect->color); 933 selectmask(); 934 935 setmask(0xff); 936 937 while (height--) { 938 for (x = 0; x < width; x++) { 939 writeb(0, dst); 940 dst++; 941 } 942 dst += line_ofs; 943 } 944 break; 945 case ROP_XOR: 946 setmode(0); 947 setop(0x18); 948 setsr(0xf); 949 setcolor(0xf); 950 selectmask(); 951 952 setmask(0xff); 953 while (height--) { 954 for (x = 0; x < width; x++) { 955 rmw(dst); 956 dst++; 957 } 958 dst += line_ofs; 959 } 960 break; 961 } 962 } else 963 vga_8planes_fillrect(info, rect); 964 break; 965 case FB_TYPE_PACKED_PIXELS: 966 default: 967 cfb_fillrect(info, rect); 968 break; 969 } 970 } 971 972 static void vga_8planes_copyarea(struct fb_info *info, const struct fb_copyarea *area) 973 { 974 char oldindex = getindex(); 975 char oldmode = setmode(0x41); 976 char oldop = setop(0); 977 char oldsr = setsr(0xf); 978 int height, line_ofs, x; 979 u32 sx, dx, width; 980 char __iomem *dest; 981 char __iomem *src; 982 983 height = area->height; 984 985 sx = area->sx / 4; 986 dx = area->dx / 4; 987 width = area->width / 4; 988 989 if (area->dy < area->sy || (area->dy == area->sy && dx < sx)) { 990 line_ofs = info->fix.line_length - width; 991 dest = info->screen_base + dx + area->dy * info->fix.line_length; 992 src = info->screen_base + sx + area->sy * info->fix.line_length; 993 while (height--) { 994 for (x = 0; x < width; x++) { 995 readb(src); 996 writeb(0, dest); 997 src++; 998 dest++; 999 } 1000 src += line_ofs; 1001 dest += line_ofs; 1002 } 1003 } else { 1004 line_ofs = info->fix.line_length - width; 1005 dest = info->screen_base + dx + width + 1006 (area->dy + height - 1) * info->fix.line_length; 1007 src = info->screen_base + sx + width + 1008 (area->sy + height - 1) * info->fix.line_length; 1009 while (height--) { 1010 for (x = 0; x < width; x++) { 1011 --src; 1012 --dest; 1013 readb(src); 1014 writeb(0, dest); 1015 } 1016 src -= line_ofs; 1017 dest -= line_ofs; 1018 } 1019 } 1020 1021 setsr(oldsr); 1022 setop(oldop); 1023 setmode(oldmode); 1024 setindex(oldindex); 1025 } 1026 1027 static void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *area) 1028 { 1029 u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy; 1030 int x, x2, y2, old_dx, old_dy, vxres, vyres; 1031 int height, width, line_ofs; 1032 char __iomem *dst = NULL; 1033 char __iomem *src = NULL; 1034 1035 vxres = info->var.xres_virtual; 1036 vyres = info->var.yres_virtual; 1037 1038 if (area->dx > vxres || area->sx > vxres || area->dy > vyres || 1039 area->sy > vyres) 1040 return; 1041 1042 /* clip the destination */ 1043 old_dx = area->dx; 1044 old_dy = area->dy; 1045 1046 /* 1047 * We could use hardware clipping but on many cards you get around 1048 * hardware clipping by writing to framebuffer directly. 1049 */ 1050 x2 = area->dx + area->width; 1051 y2 = area->dy + area->height; 1052 dx = area->dx > 0 ? area->dx : 0; 1053 dy = area->dy > 0 ? area->dy : 0; 1054 x2 = x2 < vxres ? x2 : vxres; 1055 y2 = y2 < vyres ? y2 : vyres; 1056 width = x2 - dx; 1057 height = y2 - dy; 1058 1059 if (sx + dx < old_dx || sy + dy < old_dy) 1060 return; 1061 1062 /* update sx1,sy1 */ 1063 sx += (dx - old_dx); 1064 sy += (dy - old_dy); 1065 1066 /* the source must be completely inside the virtual screen */ 1067 if (sx + width > vxres || sy + height > vyres) 1068 return; 1069 1070 switch (info->fix.type) { 1071 case FB_TYPE_VGA_PLANES: 1072 if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) { 1073 width = width/8; 1074 line_ofs = info->fix.line_length - width; 1075 1076 setmode(1); 1077 setop(0); 1078 setsr(0xf); 1079 1080 if (dy < sy || (dy == sy && dx < sx)) { 1081 dst = info->screen_base + (dx/8) + dy * info->fix.line_length; 1082 src = info->screen_base + (sx/8) + sy * info->fix.line_length; 1083 while (height--) { 1084 for (x = 0; x < width; x++) { 1085 readb(src); 1086 writeb(0, dst); 1087 dst++; 1088 src++; 1089 } 1090 src += line_ofs; 1091 dst += line_ofs; 1092 } 1093 } else { 1094 dst = info->screen_base + (dx/8) + width + 1095 (dy + height - 1) * info->fix.line_length; 1096 src = info->screen_base + (sx/8) + width + 1097 (sy + height - 1) * info->fix.line_length; 1098 while (height--) { 1099 for (x = 0; x < width; x++) { 1100 dst--; 1101 src--; 1102 readb(src); 1103 writeb(0, dst); 1104 } 1105 src -= line_ofs; 1106 dst -= line_ofs; 1107 } 1108 } 1109 } else 1110 vga_8planes_copyarea(info, area); 1111 break; 1112 case FB_TYPE_PACKED_PIXELS: 1113 default: 1114 cfb_copyarea(info, area); 1115 break; 1116 } 1117 } 1118 1119 #define TRANS_MASK_LOW {0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF} 1120 #define TRANS_MASK_HIGH {0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00, \ 1121 0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00} 1122 1123 #if defined(__LITTLE_ENDIAN) 1124 static const u16 transl_l[] = TRANS_MASK_LOW; 1125 static const u16 transl_h[] = TRANS_MASK_HIGH; 1126 #elif defined(__BIG_ENDIAN) 1127 static const u16 transl_l[] = TRANS_MASK_HIGH; 1128 static const u16 transl_h[] = TRANS_MASK_LOW; 1129 #else 1130 #error "Only __BIG_ENDIAN and __LITTLE_ENDIAN are supported in vga-planes" 1131 #endif 1132 1133 static void vga_8planes_imageblit(struct fb_info *info, const struct fb_image *image) 1134 { 1135 char oldindex = getindex(); 1136 char oldmode = setmode(0x40); 1137 char oldop = setop(0); 1138 char oldsr = setsr(0); 1139 char oldmask = selectmask(); 1140 const unsigned char *cdat = image->data; 1141 u32 dx = image->dx; 1142 char __iomem *where; 1143 int y; 1144 1145 dx /= 4; 1146 where = info->screen_base + dx + image->dy * info->fix.line_length; 1147 1148 setmask(0xff); 1149 writeb(image->bg_color, where); 1150 readb(where); 1151 selectmask(); 1152 setmask(image->fg_color ^ image->bg_color); 1153 setmode(0x42); 1154 setop(0x18); 1155 for (y = 0; y < image->height; y++, where += info->fix.line_length) 1156 writew(transl_h[cdat[y]&0xF] | transl_l[cdat[y] >> 4], where); 1157 setmask(oldmask); 1158 setsr(oldsr); 1159 setop(oldop); 1160 setmode(oldmode); 1161 setindex(oldindex); 1162 } 1163 1164 static void vga_imageblit_expand(struct fb_info *info, const struct fb_image *image) 1165 { 1166 char __iomem *where = info->screen_base + (image->dx/8) + 1167 image->dy * info->fix.line_length; 1168 struct vga16fb_par *par = info->par; 1169 char *cdat = (char *) image->data; 1170 char __iomem *dst; 1171 int x, y; 1172 1173 switch (info->fix.type) { 1174 case FB_TYPE_VGA_PLANES: 1175 if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) { 1176 if (par->isVGA) { 1177 setmode(2); 1178 setop(0); 1179 setsr(0xf); 1180 setcolor(image->fg_color); 1181 selectmask(); 1182 1183 setmask(0xff); 1184 writeb(image->bg_color, where); 1185 rmb(); 1186 readb(where); /* fill latches */ 1187 setmode(3); 1188 wmb(); 1189 for (y = 0; y < image->height; y++) { 1190 dst = where; 1191 for (x = image->width/8; x--;) 1192 writeb(*cdat++, dst++); 1193 where += info->fix.line_length; 1194 } 1195 wmb(); 1196 } else { 1197 setmode(0); 1198 setop(0); 1199 setsr(0xf); 1200 setcolor(image->bg_color); 1201 selectmask(); 1202 1203 setmask(0xff); 1204 for (y = 0; y < image->height; y++) { 1205 dst = where; 1206 for (x=image->width/8; x--;){ 1207 rmw(dst); 1208 setcolor(image->fg_color); 1209 selectmask(); 1210 if (*cdat) { 1211 setmask(*cdat++); 1212 rmw(dst++); 1213 } 1214 } 1215 where += info->fix.line_length; 1216 } 1217 } 1218 } else 1219 vga_8planes_imageblit(info, image); 1220 break; 1221 case FB_TYPE_PACKED_PIXELS: 1222 default: 1223 cfb_imageblit(info, image); 1224 break; 1225 } 1226 } 1227 1228 static void vga_imageblit_color(struct fb_info *info, const struct fb_image *image) 1229 { 1230 /* 1231 * Draw logo 1232 */ 1233 struct vga16fb_par *par = info->par; 1234 char __iomem *where = 1235 info->screen_base + image->dy * info->fix.line_length + 1236 image->dx/8; 1237 const char *cdat = image->data; 1238 char __iomem *dst; 1239 int x, y; 1240 1241 switch (info->fix.type) { 1242 case FB_TYPE_VGA_PLANES: 1243 if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4 && 1244 par->isVGA) { 1245 setsr(0xf); 1246 setop(0); 1247 setmode(0); 1248 1249 for (y = 0; y < image->height; y++) { 1250 for (x = 0; x < image->width; x++) { 1251 dst = where + x/8; 1252 1253 setcolor(*cdat); 1254 selectmask(); 1255 setmask(1 << (7 - (x % 8))); 1256 fb_readb(dst); 1257 fb_writeb(0, dst); 1258 1259 cdat++; 1260 } 1261 where += info->fix.line_length; 1262 } 1263 } 1264 break; 1265 case FB_TYPE_PACKED_PIXELS: 1266 cfb_imageblit(info, image); 1267 break; 1268 default: 1269 break; 1270 } 1271 } 1272 1273 static void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image) 1274 { 1275 if (image->depth == 1) 1276 vga_imageblit_expand(info, image); 1277 else 1278 vga_imageblit_color(info, image); 1279 } 1280 1281 static void vga16fb_destroy(struct fb_info *info) 1282 { 1283 iounmap(info->screen_base); 1284 fb_dealloc_cmap(&info->cmap); 1285 /* XXX unshare VGA regions */ 1286 framebuffer_release(info); 1287 } 1288 1289 static const struct fb_ops vga16fb_ops = { 1290 .owner = THIS_MODULE, 1291 .fb_open = vga16fb_open, 1292 .fb_release = vga16fb_release, 1293 .fb_destroy = vga16fb_destroy, 1294 .fb_check_var = vga16fb_check_var, 1295 .fb_set_par = vga16fb_set_par, 1296 .fb_setcolreg = vga16fb_setcolreg, 1297 .fb_pan_display = vga16fb_pan_display, 1298 .fb_blank = vga16fb_blank, 1299 .fb_fillrect = vga16fb_fillrect, 1300 .fb_copyarea = vga16fb_copyarea, 1301 .fb_imageblit = vga16fb_imageblit, 1302 }; 1303 1304 static int vga16fb_probe(struct platform_device *dev) 1305 { 1306 struct screen_info *si; 1307 struct fb_info *info; 1308 struct vga16fb_par *par; 1309 int i; 1310 int ret = 0; 1311 1312 si = dev_get_platdata(&dev->dev); 1313 if (!si) 1314 return -ENODEV; 1315 1316 ret = check_mode_supported(si); 1317 if (ret) 1318 return ret; 1319 1320 printk(KERN_DEBUG "vga16fb: initializing\n"); 1321 info = framebuffer_alloc(sizeof(struct vga16fb_par), &dev->dev); 1322 1323 if (!info) { 1324 ret = -ENOMEM; 1325 goto err_fb_alloc; 1326 } 1327 info->apertures = alloc_apertures(1); 1328 if (!info->apertures) { 1329 ret = -ENOMEM; 1330 goto err_ioremap; 1331 } 1332 1333 /* XXX share VGA_FB_PHYS_BASE and I/O region with vgacon and others */ 1334 info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS_BASE, 0); 1335 1336 if (!info->screen_base) { 1337 printk(KERN_ERR "vga16fb: unable to map device\n"); 1338 ret = -ENOMEM; 1339 goto err_ioremap; 1340 } 1341 1342 printk(KERN_INFO "vga16fb: mapped to 0x%p\n", info->screen_base); 1343 par = info->par; 1344 1345 #if defined(CONFIG_X86) 1346 par->isVGA = si->orig_video_isVGA == VIDEO_TYPE_VGAC; 1347 #else 1348 /* non-x86 architectures treat orig_video_isVGA as a boolean flag */ 1349 par->isVGA = si->orig_video_isVGA; 1350 #endif 1351 par->palette_blanked = 0; 1352 par->vesa_blanked = 0; 1353 1354 i = par->isVGA? 6 : 2; 1355 1356 vga16fb_defined.red.length = i; 1357 vga16fb_defined.green.length = i; 1358 vga16fb_defined.blue.length = i; 1359 1360 /* name should not depend on EGA/VGA */ 1361 info->fbops = &vga16fb_ops; 1362 info->var = vga16fb_defined; 1363 info->fix = vga16fb_fix; 1364 /* supports rectangles with widths of multiples of 8 */ 1365 info->pixmap.blit_x = 1 << 7 | 1 << 15 | 1 << 23 | 1 << 31; 1366 info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE | 1367 FBINFO_HWACCEL_YPAN; 1368 1369 i = (info->var.bits_per_pixel == 8) ? 256 : 16; 1370 ret = fb_alloc_cmap(&info->cmap, i, 0); 1371 if (ret) { 1372 printk(KERN_ERR "vga16fb: unable to allocate colormap\n"); 1373 ret = -ENOMEM; 1374 goto err_alloc_cmap; 1375 } 1376 1377 if (vga16fb_check_var(&info->var, info)) { 1378 printk(KERN_ERR "vga16fb: unable to validate variable\n"); 1379 ret = -EINVAL; 1380 goto err_check_var; 1381 } 1382 1383 vga16fb_update_fix(info); 1384 1385 info->apertures->ranges[0].base = VGA_FB_PHYS_BASE; 1386 info->apertures->ranges[0].size = VGA_FB_PHYS_SIZE; 1387 1388 if (register_framebuffer(info) < 0) { 1389 printk(KERN_ERR "vga16fb: unable to register framebuffer\n"); 1390 ret = -EINVAL; 1391 goto err_check_var; 1392 } 1393 1394 fb_info(info, "%s frame buffer device\n", info->fix.id); 1395 platform_set_drvdata(dev, info); 1396 1397 return 0; 1398 1399 err_check_var: 1400 fb_dealloc_cmap(&info->cmap); 1401 err_alloc_cmap: 1402 iounmap(info->screen_base); 1403 err_ioremap: 1404 framebuffer_release(info); 1405 err_fb_alloc: 1406 return ret; 1407 } 1408 1409 static int vga16fb_remove(struct platform_device *dev) 1410 { 1411 struct fb_info *info = platform_get_drvdata(dev); 1412 1413 if (info) 1414 unregister_framebuffer(info); 1415 1416 return 0; 1417 } 1418 1419 static const struct platform_device_id vga16fb_driver_id_table[] = { 1420 {"ega-framebuffer", 0}, 1421 {"vga-framebuffer", 0}, 1422 { } 1423 }; 1424 MODULE_DEVICE_TABLE(platform, vga16fb_driver_id_table); 1425 1426 static struct platform_driver vga16fb_driver = { 1427 .probe = vga16fb_probe, 1428 .remove = vga16fb_remove, 1429 .driver = { 1430 .name = "vga16fb", 1431 }, 1432 .id_table = vga16fb_driver_id_table, 1433 }; 1434 1435 module_platform_driver(vga16fb_driver); 1436 1437 MODULE_DESCRIPTION("Legacy VGA framebuffer device driver"); 1438 MODULE_LICENSE("GPL"); 1439