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.12-rc2 789 lines 22 kB view raw
1/* 2 * linux/drivers/video/S3Triofb.c -- Open Firmware based frame buffer device 3 * 4 * Copyright (C) 1997 Peter De Schrijver 5 * 6 * This driver is partly based on the PowerMac console driver: 7 * 8 * Copyright (C) 1996 Paul Mackerras 9 * 10 * and on the Open Firmware based frame buffer device: 11 * 12 * Copyright (C) 1997 Geert Uytterhoeven 13 * 14 * This file is subject to the terms and conditions of the GNU General Public 15 * License. See the file COPYING in the main directory of this archive for 16 * more details. 17 */ 18 19/* 20 Bugs : + OF dependencies should be removed. 21 + This driver should be merged with the CyberVision driver. The 22 CyberVision is a Zorro III implementation of the S3Trio64 chip. 23 24*/ 25 26#include <linux/config.h> 27#include <linux/kernel.h> 28#include <linux/module.h> 29#include <linux/errno.h> 30#include <linux/string.h> 31#include <linux/mm.h> 32#include <linux/tty.h> 33#include <linux/slab.h> 34#include <linux/vmalloc.h> 35#include <linux/delay.h> 36#include <linux/interrupt.h> 37#include <linux/fb.h> 38#include <linux/init.h> 39#include <linux/selection.h> 40#include <asm/io.h> 41#include <asm/prom.h> 42#include <asm/pci-bridge.h> 43#include <linux/pci.h> 44 45#include <video/fbcon.h> 46#include <video/fbcon-cfb8.h> 47#include <video/s3blit.h> 48 49 50#define mem_in8(addr) in_8((void *)(addr)) 51#define mem_in16(addr) in_le16((void *)(addr)) 52#define mem_in32(addr) in_le32((void *)(addr)) 53 54#define mem_out8(val, addr) out_8((void *)(addr), val) 55#define mem_out16(val, addr) out_le16((void *)(addr), val) 56#define mem_out32(val, addr) out_le32((void *)(addr), val) 57 58#define IO_OUT16VAL(v, r) (((v) << 8) | (r)) 59 60static struct display disp; 61static struct fb_info fb_info; 62static struct { u_char red, green, blue, pad; } palette[256]; 63static char s3trio_name[16] = "S3Trio "; 64static char *s3trio_base; 65 66static struct fb_fix_screeninfo fb_fix; 67static struct fb_var_screeninfo fb_var = { 0, }; 68 69 70 /* 71 * Interface used by the world 72 */ 73 74static void __init s3triofb_of_init(struct device_node *dp); 75static int s3trio_get_fix(struct fb_fix_screeninfo *fix, int con, 76 struct fb_info *info); 77static int s3trio_get_var(struct fb_var_screeninfo *var, int con, 78 struct fb_info *info); 79static int s3trio_set_var(struct fb_var_screeninfo *var, int con, 80 struct fb_info *info); 81static int s3trio_get_cmap(struct fb_cmap *cmap, int kspc, int con, 82 struct fb_info *info); 83static int s3trio_setcolreg(u_int regno, u_int red, u_int green, u_int blue, 84 u_int transp, struct fb_info *info); 85static int s3trio_pan_display(struct fb_var_screeninfo *var, int con, 86 struct fb_info *info); 87static void s3triofb_blank(int blank, struct fb_info *info); 88 89 /* 90 * Interface to the low level console driver 91 */ 92 93int s3triofb_init(void); 94static int s3triofbcon_switch(int con, struct fb_info *info); 95static int s3triofbcon_updatevar(int con, struct fb_info *info); 96 97 /* 98 * Text console acceleration 99 */ 100 101#ifdef FBCON_HAS_CFB8 102static struct display_switch fbcon_trio8; 103#endif 104 105 /* 106 * Accelerated Functions used by the low level console driver 107 */ 108 109static void Trio_WaitQueue(u_short fifo); 110static void Trio_WaitBlit(void); 111static void Trio_BitBLT(u_short curx, u_short cury, u_short destx, 112 u_short desty, u_short width, u_short height, 113 u_short mode); 114static void Trio_RectFill(u_short x, u_short y, u_short width, u_short height, 115 u_short mode, u_short color); 116static void Trio_MoveCursor(u_short x, u_short y); 117 118 119 /* 120 * Internal routines 121 */ 122 123static int s3trio_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, 124 u_int *transp, struct fb_info *info); 125 126static struct fb_ops s3trio_ops = { 127 .owner = THIS_MODULE, 128 .fb_get_fix = s3trio_get_fix, 129 .fb_get_var = s3trio_get_var, 130 .fb_set_var = s3trio_set_var, 131 .fb_get_cmap = s3trio_get_cmap, 132 .fb_set_cmap = gen_set_cmap, 133 .fb_setcolreg = s3trio_setcolreg, 134 .fb_pan_display =s3trio_pan_display, 135 .fb_blank = s3triofb_blank, 136}; 137 138 /* 139 * Get the Fixed Part of the Display 140 */ 141 142static int s3trio_get_fix(struct fb_fix_screeninfo *fix, int con, 143 struct fb_info *info) 144{ 145 memcpy(fix, &fb_fix, sizeof(fb_fix)); 146 return 0; 147} 148 149 150 /* 151 * Get the User Defined Part of the Display 152 */ 153 154static int s3trio_get_var(struct fb_var_screeninfo *var, int con, 155 struct fb_info *info) 156{ 157 memcpy(var, &fb_var, sizeof(fb_var)); 158 return 0; 159} 160 161 162 /* 163 * Set the User Defined Part of the Display 164 */ 165 166static int s3trio_set_var(struct fb_var_screeninfo *var, int con, 167 struct fb_info *info) 168{ 169 if (var->xres > fb_var.xres || var->yres > fb_var.yres || 170 var->bits_per_pixel > fb_var.bits_per_pixel ) 171 /* || var->nonstd || var->vmode != FB_VMODE_NONINTERLACED) */ 172 return -EINVAL; 173 if (var->xres_virtual > fb_var.xres_virtual) { 174 outw(IO_OUT16VAL((var->xres_virtual /8) & 0xff, 0x13), 0x3d4); 175 outw(IO_OUT16VAL(((var->xres_virtual /8 ) & 0x300) >> 3, 0x51), 0x3d4); 176 fb_var.xres_virtual = var->xres_virtual; 177 fb_fix.line_length = var->xres_virtual; 178 } 179 fb_var.yres_virtual = var->yres_virtual; 180 memcpy(var, &fb_var, sizeof(fb_var)); 181 return 0; 182} 183 184 185 /* 186 * Pan or Wrap the Display 187 * 188 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag 189 */ 190 191static int s3trio_pan_display(struct fb_var_screeninfo *var, int con, 192 struct fb_info *info) 193{ 194 unsigned int base; 195 196 if (var->xoffset > (var->xres_virtual - var->xres)) 197 return -EINVAL; 198 if (var->yoffset > (var->yres_virtual - var->yres)) 199 return -EINVAL; 200 201 fb_var.xoffset = var->xoffset; 202 fb_var.yoffset = var->yoffset; 203 204 base = var->yoffset * fb_fix.line_length + var->xoffset; 205 206 outw(IO_OUT16VAL((base >> 8) & 0xff, 0x0c),0x03D4); 207 outw(IO_OUT16VAL(base & 0xff, 0x0d),0x03D4); 208 outw(IO_OUT16VAL((base >> 16) & 0xf, 0x69),0x03D4); 209 return 0; 210} 211 212 213 /* 214 * Get the Colormap 215 */ 216 217static int s3trio_get_cmap(struct fb_cmap *cmap, int kspc, int con, 218 struct fb_info *info) 219{ 220 if (con == info->currcon) /* current console? */ 221 return fb_get_cmap(cmap, kspc, s3trio_getcolreg, info); 222 else if (fb_display[con].cmap.len) /* non default colormap? */ 223 fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); 224 else 225 fb_copy_cmap(fb_default_cmap(1 << fb_display[con].var.bits_per_pixel), 226 cmap, kspc ? 0 : 2); 227 return 0; 228} 229 230int __init s3triofb_init(void) 231{ 232 struct device_node *dp; 233 234 dp = find_devices("S3Trio"); 235 if (dp != 0) 236 s3triofb_of_init(dp); 237 return 0; 238} 239 240void __init s3trio_resetaccel(void){ 241 242 243#define EC01_ENH_ENB 0x0005 244#define EC01_LAW_ENB 0x0010 245#define EC01_MMIO_ENB 0x0020 246 247#define EC00_RESET 0x8000 248#define EC00_ENABLE 0x4000 249#define MF_MULT_MISC 0xE000 250#define SRC_FOREGROUND 0x0020 251#define SRC_BACKGROUND 0x0000 252#define MIX_SRC 0x0007 253#define MF_T_CLIP 0x1000 254#define MF_L_CLIP 0x2000 255#define MF_B_CLIP 0x3000 256#define MF_R_CLIP 0x4000 257#define MF_PIX_CONTROL 0xA000 258#define MFA_SRC_FOREGR_MIX 0x0000 259#define MF_PIX_CONTROL 0xA000 260 261 outw(EC00_RESET, 0x42e8); 262 inw( 0x42e8); 263 outw(EC00_ENABLE, 0x42e8); 264 inw( 0x42e8); 265 outw(EC01_ENH_ENB | EC01_LAW_ENB, 266 0x4ae8); 267 outw(MF_MULT_MISC, 0xbee8); /* 16 bit I/O registers */ 268 269 /* Now set some basic accelerator registers */ 270 Trio_WaitQueue(0x0400); 271 outw(SRC_FOREGROUND | MIX_SRC, 0xbae8); 272 outw(SRC_BACKGROUND | MIX_SRC, 0xb6e8);/* direct color*/ 273 outw(MF_T_CLIP | 0, 0xbee8 ); /* clip virtual area */ 274 outw(MF_L_CLIP | 0, 0xbee8 ); 275 outw(MF_R_CLIP | (640 - 1), 0xbee8); 276 outw(MF_B_CLIP | (480 - 1), 0xbee8); 277 Trio_WaitQueue(0x0400); 278 outw(0xffff, 0xaae8); /* Enable all planes */ 279 outw(0xffff, 0xaae8); /* Enable all planes */ 280 outw( MF_PIX_CONTROL | MFA_SRC_FOREGR_MIX, 0xbee8); 281} 282 283int __init s3trio_init(struct device_node *dp){ 284 285 u_char bus, dev; 286 unsigned int t32; 287 unsigned short cmd; 288 289 pci_device_loc(dp,&bus,&dev); 290 pcibios_read_config_dword(bus, dev, PCI_VENDOR_ID, &t32); 291 if(t32 == (PCI_DEVICE_ID_S3_TRIO << 16) + PCI_VENDOR_ID_S3) { 292 pcibios_read_config_dword(bus, dev, PCI_BASE_ADDRESS_0, &t32); 293 pcibios_read_config_dword(bus, dev, PCI_BASE_ADDRESS_1, &t32); 294 pcibios_read_config_word(bus, dev, PCI_COMMAND,&cmd); 295 296 pcibios_write_config_word(bus, dev, PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY); 297 298 pcibios_write_config_dword(bus, dev, PCI_BASE_ADDRESS_0,0xffffffff); 299 pcibios_read_config_dword(bus, dev, PCI_BASE_ADDRESS_0, &t32); 300 301/* This is a gross hack as OF only maps enough memory for the framebuffer and 302 we want to use MMIO too. We should find out which chunk of address space 303 we can use here */ 304 pcibios_write_config_dword(bus,dev,PCI_BASE_ADDRESS_0,0xc6000000); 305 306 /* unlock s3 */ 307 308 outb(0x01, 0x3C3); 309 310 outb(inb(0x03CC) | 1, 0x3c2); 311 312 outw(IO_OUT16VAL(0x48, 0x38),0x03D4); 313 outw(IO_OUT16VAL(0xA0, 0x39),0x03D4); 314 outb(0x33,0x3d4); 315 outw(IO_OUT16VAL((inb(0x3d5) & ~(0x2 | 0x10 | 0x40)) | 316 0x20, 0x33), 0x3d4); 317 318 outw(IO_OUT16VAL(0x6, 0x8), 0x3c4); 319 320 /* switch to MMIO only mode */ 321 322 outb(0x58, 0x3d4); 323 outw(IO_OUT16VAL(inb(0x3d5) | 3 | 0x10, 0x58), 0x3d4); 324 outw(IO_OUT16VAL(8, 0x53), 0x3d4); 325 326 /* switch off I/O accesses */ 327 328#if 0 329 pcibios_write_config_word(bus, dev, PCI_COMMAND, 330 PCI_COMMAND_IO | PCI_COMMAND_MEMORY); 331#endif 332 return 1; 333 } 334 335 return 0; 336} 337 338 339 /* 340 * Initialisation 341 * We heavily rely on OF for the moment. This needs fixing. 342 */ 343 344static void __init s3triofb_of_init(struct device_node *dp) 345{ 346 int i, *pp, len; 347 unsigned long address, size; 348 u_long *CursorBase; 349 350 strncat(s3trio_name, dp->name, sizeof(s3trio_name)); 351 s3trio_name[sizeof(s3trio_name)-1] = '\0'; 352 strcpy(fb_fix.id, s3trio_name); 353 354 if((pp = (int *)get_property(dp, "vendor-id", &len)) != NULL 355 && *pp!=PCI_VENDOR_ID_S3) { 356 printk("%s: can't find S3 Trio board\n", dp->full_name); 357 return; 358 } 359 360 if((pp = (int *)get_property(dp, "device-id", &len)) != NULL 361 && *pp!=PCI_DEVICE_ID_S3_TRIO) { 362 printk("%s: can't find S3 Trio board\n", dp->full_name); 363 return; 364 } 365 366 if ((pp = (int *)get_property(dp, "depth", &len)) != NULL 367 && len == sizeof(int) && *pp != 8) { 368 printk("%s: can't use depth = %d\n", dp->full_name, *pp); 369 return; 370 } 371 if ((pp = (int *)get_property(dp, "width", &len)) != NULL 372 && len == sizeof(int)) 373 fb_var.xres = fb_var.xres_virtual = *pp; 374 if ((pp = (int *)get_property(dp, "height", &len)) != NULL 375 && len == sizeof(int)) 376 fb_var.yres = fb_var.yres_virtual = *pp; 377 if ((pp = (int *)get_property(dp, "linebytes", &len)) != NULL 378 && len == sizeof(int)) 379 fb_fix.line_length = *pp; 380 else 381 fb_fix.line_length = fb_var.xres_virtual; 382 fb_fix.smem_len = fb_fix.line_length*fb_var.yres; 383 384 address = 0xc6000000; 385 size = 64*1024*1024; 386 if (!request_mem_region(address, size, "S3triofb")) 387 return; 388 389 s3trio_init(dp); 390 s3trio_base = ioremap(address, size); 391 fb_fix.smem_start = address; 392 fb_fix.type = FB_TYPE_PACKED_PIXELS; 393 fb_fix.type_aux = 0; 394 fb_fix.accel = FB_ACCEL_S3_TRIO64; 395 fb_fix.mmio_start = address+0x1000000; 396 fb_fix.mmio_len = 0x1000000; 397 398 fb_fix.xpanstep = 1; 399 fb_fix.ypanstep = 1; 400 401 s3trio_resetaccel(); 402 403 mem_out8(0x30, s3trio_base+0x1008000 + 0x03D4); 404 mem_out8(0x2d, s3trio_base+0x1008000 + 0x03D4); 405 mem_out8(0x2e, s3trio_base+0x1008000 + 0x03D4); 406 407 mem_out8(0x50, s3trio_base+0x1008000 + 0x03D4); 408 409 /* disable HW cursor */ 410 411 mem_out8(0x39, s3trio_base+0x1008000 + 0x03D4); 412 mem_out8(0xa0, s3trio_base+0x1008000 + 0x03D5); 413 414 mem_out8(0x45, s3trio_base+0x1008000 + 0x03D4); 415 mem_out8(0, s3trio_base+0x1008000 + 0x03D5); 416 417 mem_out8(0x4e, s3trio_base+0x1008000 + 0x03D4); 418 mem_out8(0, s3trio_base+0x1008000 + 0x03D5); 419 420 mem_out8(0x4f, s3trio_base+0x1008000 + 0x03D4); 421 mem_out8(0, s3trio_base+0x1008000 + 0x03D5); 422 423 /* init HW cursor */ 424 425 CursorBase = (u_long *)(s3trio_base + 2*1024*1024 - 0x400); 426 for (i = 0; i < 8; i++) { 427 *(CursorBase +(i*4)) = 0xffffff00; 428 *(CursorBase+1+(i*4)) = 0xffff0000; 429 *(CursorBase+2+(i*4)) = 0xffff0000; 430 *(CursorBase+3+(i*4)) = 0xffff0000; 431 } 432 for (i = 8; i < 64; i++) { 433 *(CursorBase +(i*4)) = 0xffff0000; 434 *(CursorBase+1+(i*4)) = 0xffff0000; 435 *(CursorBase+2+(i*4)) = 0xffff0000; 436 *(CursorBase+3+(i*4)) = 0xffff0000; 437 } 438 439 440 mem_out8(0x4c, s3trio_base+0x1008000 + 0x03D4); 441 mem_out8(((2*1024 - 1)&0xf00)>>8, s3trio_base+0x1008000 + 0x03D5); 442 443 mem_out8(0x4d, s3trio_base+0x1008000 + 0x03D4); 444 mem_out8((2*1024 - 1) & 0xff, s3trio_base+0x1008000 + 0x03D5); 445 446 mem_out8(0x45, s3trio_base+0x1008000 + 0x03D4); 447 mem_in8(s3trio_base+0x1008000 + 0x03D4); 448 449 mem_out8(0x4a, s3trio_base+0x1008000 + 0x03D4); 450 mem_out8(0x80, s3trio_base+0x1008000 + 0x03D5); 451 mem_out8(0x80, s3trio_base+0x1008000 + 0x03D5); 452 mem_out8(0x80, s3trio_base+0x1008000 + 0x03D5); 453 454 mem_out8(0x4b, s3trio_base+0x1008000 + 0x03D4); 455 mem_out8(0x00, s3trio_base+0x1008000 + 0x03D5); 456 mem_out8(0x00, s3trio_base+0x1008000 + 0x03D5); 457 mem_out8(0x00, s3trio_base+0x1008000 + 0x03D5); 458 459 mem_out8(0x45, s3trio_base+0x1008000 + 0x03D4); 460 mem_out8(0, s3trio_base+0x1008000 + 0x03D5); 461 462 /* setup default color table */ 463 464 for(i = 0; i < 16; i++) { 465 int j = color_table[i]; 466 palette[i].red=default_red[j]; 467 palette[i].green=default_grn[j]; 468 palette[i].blue=default_blu[j]; 469 } 470 471 s3trio_setcolreg(255, 56, 100, 160, 0, NULL /* not used */); 472 s3trio_setcolreg(254, 0, 0, 0, 0, NULL /* not used */); 473 memset((char *)s3trio_base, 0, 640*480); 474 475#if 0 476 Trio_RectFill(0, 0, 90, 90, 7, 1); 477#endif 478 479 fb_fix.visual = FB_VISUAL_PSEUDOCOLOR ; 480 fb_var.xoffset = fb_var.yoffset = 0; 481 fb_var.bits_per_pixel = 8; 482 fb_var.grayscale = 0; 483 fb_var.red.offset = fb_var.green.offset = fb_var.blue.offset = 0; 484 fb_var.red.length = fb_var.green.length = fb_var.blue.length = 8; 485 fb_var.red.msb_right = fb_var.green.msb_right = fb_var.blue.msb_right = 0; 486 fb_var.transp.offset = fb_var.transp.length = fb_var.transp.msb_right = 0; 487 fb_var.nonstd = 0; 488 fb_var.activate = 0; 489 fb_var.height = fb_var.width = -1; 490 fb_var.accel_flags = FB_ACCELF_TEXT; 491#warning FIXME: always obey fb_var.accel_flags 492 fb_var.pixclock = 1; 493 fb_var.left_margin = fb_var.right_margin = 0; 494 fb_var.upper_margin = fb_var.lower_margin = 0; 495 fb_var.hsync_len = fb_var.vsync_len = 0; 496 fb_var.sync = 0; 497 fb_var.vmode = FB_VMODE_NONINTERLACED; 498 499 disp.var = fb_var; 500 disp.cmap.start = 0; 501 disp.cmap.len = 0; 502 disp.cmap.red = disp.cmap.green = disp.cmap.blue = disp.cmap.transp = NULL; 503 disp.visual = fb_fix.visual; 504 disp.type = fb_fix.type; 505 disp.type_aux = fb_fix.type_aux; 506 disp.ypanstep = 0; 507 disp.ywrapstep = 0; 508 disp.line_length = fb_fix.line_length; 509 disp.can_soft_blank = 1; 510 disp.inverse = 0; 511#ifdef FBCON_HAS_CFB8 512 if (fb_var.accel_flags & FB_ACCELF_TEXT) 513 disp.dispsw = &fbcon_trio8; 514 else 515 disp.dispsw = &fbcon_cfb8; 516#else 517 disp.dispsw = &fbcon_dummy; 518#endif 519 disp.scrollmode = fb_var.accel_flags & FB_ACCELF_TEXT ? 0 : SCROLL_YREDRAW; 520 521 strcpy(fb_info.modename, "Trio64 "); 522 strncat(fb_info.modename, dp->full_name, sizeof(fb_info.modename)); 523 fb_info.currcon = -1; 524 fb_info.fbops = &s3trio_ops; 525 fb_info.screen_base = s3trio_base; 526#if 0 527 fb_info.fbvar_num = 1; 528 fb_info.fbvar = &fb_var; 529#endif 530 fb_info.disp = &disp; 531 fb_info.fontname[0] = '\0'; 532 fb_info.changevar = NULL; 533 fb_info.switch_con = &s3triofbcon_switch; 534 fb_info.updatevar = &s3triofbcon_updatevar; 535#if 0 536 fb_info.setcmap = &s3triofbcon_setcmap; 537#endif 538 539 fb_info.flags = FBINFO_FLAG_DEFAULT; 540 if (register_framebuffer(&fb_info) < 0) 541 return; 542 543 printk("fb%d: S3 Trio frame buffer device on %s\n", 544 fb_info.node, dp->full_name); 545} 546 547 548static int s3triofbcon_switch(int con, struct fb_info *info) 549{ 550 /* Do we have to save the colormap? */ 551 if (fb_display[info->currcon].cmap.len) 552 fb_get_cmap(&fb_display[info->currcon].cmap, 1, s3trio_getcolreg, info); 553 554 info->currcon = con; 555 /* Install new colormap */ 556 do_install_cmap(con,info); 557 return 0; 558} 559 560 /* 561 * Update the `var' structure (called by fbcon.c) 562 */ 563 564static int s3triofbcon_updatevar(int con, struct fb_info *info) 565{ 566 /* Nothing */ 567 return 0; 568} 569 570 /* 571 * Blank the display. 572 */ 573 574static int s3triofb_blank(int blank, struct fb_info *info) 575{ 576 unsigned char x; 577 578 mem_out8(0x1, s3trio_base+0x1008000 + 0x03c4); 579 x = mem_in8(s3trio_base+0x1008000 + 0x03c5); 580 mem_out8((x & (~0x20)) | (blank << 5), s3trio_base+0x1008000 + 0x03c5); 581 return 0; 582} 583 584 /* 585 * Read a single color register and split it into 586 * colors/transparent. Return != 0 for invalid regno. 587 */ 588 589static int s3trio_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, 590 u_int *transp, struct fb_info *info) 591{ 592 if (regno > 255) 593 return 1; 594 *red = (palette[regno].red << 8) | palette[regno].red; 595 *green = (palette[regno].green << 8) | palette[regno].green; 596 *blue = (palette[regno].blue << 8) | palette[regno].blue; 597 *transp = 0; 598 return 0; 599} 600 601 602 /* 603 * Set a single color register. Return != 0 for invalid regno. 604 */ 605 606static int s3trio_setcolreg(u_int regno, u_int red, u_int green, u_int blue, 607 u_int transp, struct fb_info *info) 608{ 609 if (regno > 255) 610 return 1; 611 612 red >>= 8; 613 green >>= 8; 614 blue >>= 8; 615 palette[regno].red = red; 616 palette[regno].green = green; 617 palette[regno].blue = blue; 618 619 mem_out8(regno,s3trio_base+0x1008000 + 0x3c8); 620 mem_out8((red & 0xff) >> 2,s3trio_base+0x1008000 + 0x3c9); 621 mem_out8((green & 0xff) >> 2,s3trio_base+0x1008000 + 0x3c9); 622 mem_out8((blue & 0xff) >> 2,s3trio_base+0x1008000 + 0x3c9); 623 624 return 0; 625} 626 627static void Trio_WaitQueue(u_short fifo) { 628 629 u_short status; 630 631 do 632 { 633 status = mem_in16(s3trio_base + 0x1000000 + 0x9AE8); 634 } while (!(status & fifo)); 635 636} 637 638static void Trio_WaitBlit(void) { 639 640 u_short status; 641 642 do 643 { 644 status = mem_in16(s3trio_base + 0x1000000 + 0x9AE8); 645 } while (status & 0x200); 646 647} 648 649static void Trio_BitBLT(u_short curx, u_short cury, u_short destx, 650 u_short desty, u_short width, u_short height, 651 u_short mode) { 652 653 u_short blitcmd = 0xc011; 654 655 /* Set drawing direction */ 656 /* -Y, X maj, -X (default) */ 657 658 if (curx > destx) 659 blitcmd |= 0x0020; /* Drawing direction +X */ 660 else { 661 curx += (width - 1); 662 destx += (width - 1); 663 } 664 665 if (cury > desty) 666 blitcmd |= 0x0080; /* Drawing direction +Y */ 667 else { 668 cury += (height - 1); 669 desty += (height - 1); 670 } 671 672 Trio_WaitQueue(0x0400); 673 674 outw(0xa000, 0xBEE8); 675 outw(0x60 | mode, 0xBAE8); 676 677 outw(curx, 0x86E8); 678 outw(cury, 0x82E8); 679 680 outw(destx, 0x8EE8); 681 outw(desty, 0x8AE8); 682 683 outw(height - 1, 0xBEE8); 684 outw(width - 1, 0x96E8); 685 686 outw(blitcmd, 0x9AE8); 687 688} 689 690static void Trio_RectFill(u_short x, u_short y, u_short width, u_short height, 691 u_short mode, u_short color) { 692 693 u_short blitcmd = 0x40b1; 694 695 Trio_WaitQueue(0x0400); 696 697 outw(0xa000, 0xBEE8); 698 outw((0x20 | mode), 0xBAE8); 699 outw(0xe000, 0xBEE8); 700 outw(color, 0xA6E8); 701 outw(x, 0x86E8); 702 outw(y, 0x82E8); 703 outw((height - 1), 0xBEE8); 704 outw((width - 1), 0x96E8); 705 outw(blitcmd, 0x9AE8); 706 707} 708 709 710static void Trio_MoveCursor(u_short x, u_short y) { 711 712 mem_out8(0x39, s3trio_base + 0x1008000 + 0x3d4); 713 mem_out8(0xa0, s3trio_base + 0x1008000 + 0x3d5); 714 715 mem_out8(0x46, s3trio_base + 0x1008000 + 0x3d4); 716 mem_out8((x & 0x0700) >> 8, s3trio_base + 0x1008000 + 0x3d5); 717 mem_out8(0x47, s3trio_base + 0x1008000 + 0x3d4); 718 mem_out8(x & 0x00ff, s3trio_base + 0x1008000 + 0x3d5); 719 720 mem_out8(0x48, s3trio_base + 0x1008000 + 0x3d4); 721 mem_out8((y & 0x0700) >> 8, s3trio_base + 0x1008000 + 0x3d5); 722 mem_out8(0x49, s3trio_base + 0x1008000 + 0x3d4); 723 mem_out8(y & 0x00ff, s3trio_base + 0x1008000 + 0x3d5); 724 725} 726 727 728 /* 729 * Text console acceleration 730 */ 731 732#ifdef FBCON_HAS_CFB8 733static void fbcon_trio8_bmove(struct display *p, int sy, int sx, int dy, 734 int dx, int height, int width) 735{ 736 sx *= 8; dx *= 8; width *= 8; 737 Trio_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx, 738 (u_short)(dy*fontheight(p)), (u_short)width, 739 (u_short)(height*fontheight(p)), (u_short)S3_NEW); 740} 741 742static void fbcon_trio8_clear(struct vc_data *conp, struct display *p, int sy, 743 int sx, int height, int width) 744{ 745 unsigned char bg; 746 747 sx *= 8; width *= 8; 748 bg = attr_bgcol_ec(p,conp); 749 Trio_RectFill((u_short)sx, 750 (u_short)(sy*fontheight(p)), 751 (u_short)width, 752 (u_short)(height*fontheight(p)), 753 (u_short)S3_NEW, 754 (u_short)bg); 755} 756 757static void fbcon_trio8_putc(struct vc_data *conp, struct display *p, int c, 758 int yy, int xx) 759{ 760 Trio_WaitBlit(); 761 fbcon_cfb8_putc(conp, p, c, yy, xx); 762} 763 764static void fbcon_trio8_putcs(struct vc_data *conp, struct display *p, 765 const unsigned short *s, int count, int yy, int xx) 766{ 767 Trio_WaitBlit(); 768 fbcon_cfb8_putcs(conp, p, s, count, yy, xx); 769} 770 771static void fbcon_trio8_revc(struct display *p, int xx, int yy) 772{ 773 Trio_WaitBlit(); 774 fbcon_cfb8_revc(p, xx, yy); 775} 776 777static struct display_switch fbcon_trio8 = { 778 .setup = fbcon_cfb8_setup, 779 .bmove = fbcon_trio8_bmove, 780 .clear = fbcon_trio8_clear, 781 .putc = fbcon_trio8_putc, 782 .putcs = fbcon_trio8_putcs, 783 .revc = fbcon_trio8_revc, 784 .clear_margins = fbcon_cfb8_clear_margins, 785 .fontwidthmask = FONTWIDTH(8) 786}; 787#endif 788 789MODULE_LICENSE("GPL");