1/* Copyright (c) 2005 Advanced Micro Devices, Inc. 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining a copy 4 * of this software and associated documentation files (the "Software"), to 5 * deal in the Software without restriction, including without limitation the 6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7 * sell copies of the Software, and to permit persons to whom the Software is 8 * furnished to do so, subject to the following conditions: 9 * 10 * The above copyright notice and this permission notice shall be included in 11 * all copies or substantial portions of the Software. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19 * IN THE SOFTWARE. 20 * 21 * Neither the name of the Advanced Micro Devices, Inc. nor the names of its 22 * contributors may be used to endorse or promote products derived from this 23 * software without specific prior written permission. 24 * */ 25 26/* 27 * This file contains routines to set modes using the VGA registers. 28 * Since this file is for the first generation graphics unit, it interfaces 29 * to SoftVGA registers. It works for both VSA1 and VSA2. 30 * */ 31 32/* SoftVGA Extended CRTC register indices and bit definitions */ 33 34#define CRTC_EXTENDED_REGISTER_LOCK 0x30 35#define CRTC_MODE_SWITCH_CONTROL 0x3F 36 37/* BIT DEFINITIONS */ 38 39#define CRTC_BIT_16BPP 0x01 40#define CRTC_BIT_555 0x02 41 42/* LOCAL ROUTINE DEFINITIONS */ 43 44int gu1_detect_vsa2(void); 45 46/*---------------------------------*/ 47/* MODE TABLES FOR VGA REGISTERS */ 48/*---------------------------------*/ 49 50/* FOR SoftVGA, the CRTC_EXTENDED_ADDRESS_CONTROL (0x43) is always equal to 51 * 0x03 for a packed linear frame buffer organization. The 52 * CRTC_EXTENDED_DAC_CONTROL (0x4B) is always equal to 0x03 to work with 53 * older versions of VSA1 (that needed to specify 8 or 16 bit bus to an 54 * external RAMDAC. This is not used in VSA2. The clock frequency is 55 * specified in register 0x4D if clock control (0x4C) is set to 0x80. 56 * Higher resolutions (1280x1024) use the CRTC_EXTENDED_VERTICAL_TIMING 57 * register (index 0x41). 58 */ 59 60gfx_vga_struct gfx_vga_modes[] = { 61/*--------------------------------------------------------------------------*/ 62 { 63 640, 480, 60, /* 640x480 */ 64 25, /* 25 MHz clock = 60 Hz refresh rate */ 65 0xE3, /* miscOutput register */ 66 { 67 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E, 68 /* standard CRTC */ 69 0x80, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 70 0xEA, 0x0C, 0xDF, 0x50, 0x00, 0xE7, 0x04, 0xE3, 0xFF}, 71 { 72 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 73 /* extended CRTC */ 74 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00} 75 }, 76/*--------------------------------------------------------------------------*/ 77 { 78 640, 480, 72, /* 640x480 */ 79 29, /* 29 MHz clock = 72 Hz refresh rate */ 80 0xE3, /* miscOutput register */ 81 { 82 0x63, 0x4f, 0x50, 0x86, 0x55, 0x99, 0x06, 0x3e, 83 /* standard CRTC */ 84 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 85 0xe9, 0x0c, 0xdf, 0x00, 0x00, 0xe7, 0x00, 0xe3, 0xff}, 86 { 87 0x6D, 0x00, 0x00, 0x03, 0x00, 0x01, 0x01, 0x00, 88 /* extended CRTC */ 89 0x00, 0x00, 0x01, 0x08, 0x80, 0x1F, 0x00, 0x4B} 90 }, 91/*--------------------------------------------------------------------------*/ 92 { 93 640, 480, 75, /* 640x480 */ 94 31, 95 /* 31.5 MHz clock = 75 Hz refresh rate */ 96 0xE3, /* miscOutput register */ 97 { 98 0x64, 0x4F, 0x4F, 0x88, 0x54, 0x9B, 0xF2, 0x1F, 99 /* standard CRTC */ 100 0x80, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 101 0xE1, 0x04, 0xDF, 0x50, 0x00, 0xDF, 0xF3, 0xE3, 0xFF}, 102 { 103 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 104 /* extended CRTC */ 105 0x00, 0x00, 0x00, 0x03, 0x80, 0x1F, 0x00, 0x00} 106 }, 107/*--------------------------------------------------------------------------*/ 108 { 109 800, 600, 60, /* 800x600 */ 110 40, /* 40 MHz clock = 60 Hz refresh rate */ 111 0x23, /* miscOutput register */ 112 { 113 0x7F, 0x63, 0x64, 0x82, 0x6B, 0x1B, 0x72, 0xF0, 114 /* standard CRTC */ 115 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 116 0x59, 0x0D, 0x57, 0x64, 0x00, 0x57, 0x73, 0xE3, 0xFF}, 117 { 118 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 119 /* extended CRTC */ 120 0x00, 0x00, 0x00, 0x03, 0x80, 0x28, 0x00, 0x00} 121 }, 122/*--------------------------------------------------------------------------*/ 123 { 124 800, 600, 72, /* 800x600 */ 125 47, /* 47 MHz clock = 72 Hz refresh rate */ 126 0x2B, /* miscOutput register */ 127 { 128 0x7D, 0x63, 0x63, 0x81, 0x6D, 0x1B, 0x98, 0xF0, 129 /* standard CRTC */ 130 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 131 0x7D, 0x03, 0x57, 0x00, 0x00, 0x57, 0x9A, 0xE3, 0xFF}, 132 { 133 0x6F, 0x00, 0x00, 0x03, 0x00, 0x01, 0x01, 0x00, 134 /* extended CRTC */ 135 0x00, 0x00, 0x01, 0x08, 0x80, 0x32, 0x00, 0x4B} 136 }, 137/*--------------------------------------------------------------------------*/ 138 { 139 800, 600, 75, /* 800x600 */ 140 49, 141 /* 49.5 MHz clock = 75 Hz refresh rate */ 142 0x23, /* miscOutput register */ 143 { 144 0x7F, 0x63, 0x63, 0x83, 0x68, 0x11, 0x6F, 0xF0, 145 /* standard CRTC */ 146 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 147 0x59, 0x1C, 0x57, 0x64, 0x00, 0x57, 0x70, 0xE3, 0xFF}, 148 { 149 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 150 /* extended CRTC */ 151 0x00, 0x00, 0x00, 0x03, 0x80, 0x31, 0x00, 0x00} 152 }, 153/*--------------------------------------------------------------------------*/ 154 { 155 1024, 768, 60, /* 1024x768 */ 156 65, /* 65 MHz clock = 60 Hz refresh rate */ 157 0xE3, /* miscOutput register */ 158 { 159 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, 0x24, 0xF5, 160 /* standard CRTC */ 161 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 162 0x04, 0x0A, 0xFF, 0x80, 0x00, 0xFF, 0x25, 0xE3, 0xFF}, 163 { 164 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 165 /* extended CRTC */ 166 0x00, 0x00, 0x00, 0x03, 0x80, 0x41, 0x00, 0x00} 167 }, 168/*--------------------------------------------------------------------------*/ 169 { 170 1024, 768, 70, /* 1024x768 */ 171 76, /* 76 MHz clock = 70 Hz refresh rate */ 172 0x2B, /* miscOutput register */ 173 { 174 0xA1, 0x7F, 0x7F, 0x85, 0x85, 0x95, 0x24, 0xF5, 175 /* standard CRTC */ 176 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 177 0x03, 0x09, 0xFF, 0x00, 0x00, 0xFF, 0x26, 0xE3, 0xFF}, 178 { 179 0x62, 0x00, 0x00, 0x03, 0x00, 0x01, 0x01, 0x00, 180 /* extended CRTC */ 181 0x00, 0x00, 0x01, 0x02, 0x80, 0x4B, 0x00, 0x4B} 182 }, 183/*--------------------------------------------------------------------------*/ 184 { 185 1024, 768, 75, /* 1024x768 */ 186 79, /* 79 MHz clock = 75 Hz refresh rate */ 187 0xE3, /* miscOutput register */ 188 { 189 0x9F, 0x7F, 0x7F, 0x83, 0x84, 0x8F, 0x1E, 0xF5, 190 /* standard CRTC */ 191 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 192 0x01, 0x04, 0xFF, 0x80, 0x00, 0xFF, 0x1F, 0xE3, 0xFF}, 193 { 194 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 195 /* extended CRTC */ 196 0x00, 0x00, 0x00, 0x03, 0x80, 0x4F, 0x00, 0x00} 197 }, 198/*--------------------------------------------------------------------------*/ 199 { 200 1280, 1024, 60, /* 1280x1024 */ 201 108, 202 /* 108 MHz clock = 60 Hz refresh rate */ 203 0x23, /* miscOutput register */ 204 { 205 0xCF, 0x9F, 0xA0, 0x92, 0xAA, 0x19, 0x28, 0x52, 206 /* standard CRTC */ 207 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 208 0x01, 0x04, 0xFF, 0xA0, 0x00, 0x00, 0x29, 0xE3, 0xFF}, 209 { 210 0x00, 0x51, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 211 /* extended CRTC */ 212 0x00, 0x00, 0x00, 0x03, 0x80, 0x6C, 0x00, 0x00} 213 }, 214/*--------------------------------------------------------------------------*/ 215 { 216 1280, 1024, 75, /* 1280x1024 */ 217 135, 218 /* 135 MHz clock = 75 Hz refresh rate */ 219 0x23, /* miscOutput register */ 220 { 221 0xCE, 0x9F, 0x9F, 0x92, 0xA4, 0x15, 0x28, 0x52, 222 /* standard CRTC */ 223 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 224 0x01, 0x04, 0xFF, 0xA0, 0x00, 0x00, 0x29, 0xE3, 0xFF}, 225 { 226 0x00, 0x51, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 227 /* extended CRTC */ 228 0x00, 0x00, 0x00, 0x03, 0x80, 0x87, 0x00, 0x00} 229 }, 230/*--------------------------------------------------------------------------*/ 231 { 232 1280, 1024, 85, /* 1280x1024 */ 233 159, 234 /* 159 MHz clock = 85 Hz refresh rate */ 235 0x2B, /* miscOutput register */ 236 { 237 0xD3, 0x9F, 0xA0, 0x98, 0xA8, 0x9C, 0x2E, 0x5A, 238 /* standard CRTC */ 239 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 240 0x01, 0x04, 0xFF, 0x00, 0x00, 0xFF, 0x30, 0xE3, 0xFF}, 241 { 242 0x6B, 0x41, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 243 /* extended CRTC */ 244 0x00, 0x00, 0x01, 0x00, 0x80, 0x9D, 0x00, 0x4B} 245 }, 246/*--------------------------------------------------------------------------*/ 247}; 248 249#define GFX_VGA_MODES sizeof(gfx_vga_modes)/sizeof(gfx_vga_struct) 250 251/*---------------------------------------------------------------------------- 252 * gfx_get_softvga_active 253 * 254 * This returns the active status of SoftVGA 255 *---------------------------------------------------------------------------- 256 */ 257int 258gfx_get_softvga_active(void) 259{ 260 unsigned short crtcindex, crtcdata; 261 262 if (gu1_detect_vsa2()) 263 return (gfx_get_vsa2_softvga_enable()); 264 265 crtcindex = (INB(0x3CC) & 0x01) ? 0x3D4 : 0x3B4; 266 crtcdata = crtcindex + 1; 267 268 OUTB(crtcindex, CRTC_MODE_SWITCH_CONTROL); 269 return (INB(crtcdata) & 0x1); 270} 271 272/*---------------------------------------------------------------------------- 273 * gfx_vga_test_pci 274 * 275 * This routine looks for the VGA PCI header. It checks to see that bit 1 276 * of the command register is writable to know that SoftVGA is trapping 277 * the PCI config cuscles. If SoftVGA is not emulating the header, the 278 * hardware will still respond with the proper device ID, etc. 279 * 280 * We need to know that SoftVGA is really there so that we can set the 281 * command register and have the proper effect (enable trapping of VGA). 282 * Otherwise, if we enable VGA via the PCI header, trapping really won't be 283 * enabled and the VGA register writes will go out to the external card. 284 *---------------------------------------------------------------------------- 285 */ 286int 287gfx_vga_test_pci(void) 288{ 289 int softvga = 1; 290 unsigned long value; 291 292 value = gfx_pci_config_read(0x80009400); 293 if ((value & 0x0000FFFF) != 0x1078) 294 softvga = 0; 295 else { 296 value = gfx_pci_config_read(0x80009404); 297 gfx_pci_config_write(0x80009404, value | 0x02); 298 if (!(gfx_pci_config_read(0x80009404) & 0x02)) 299 softvga = 0; 300 gfx_pci_config_write(0x80009404, value); 301 } 302 return (softvga); 303} 304 305/*---------------------------------------------------------------------------- 306 * gfx_vga_get_pci_command 307 * 308 * This routine returns the value of the PCI command register. 309 *---------------------------------------------------------------------------- 310 */ 311unsigned char 312gfx_vga_get_pci_command(void) 313{ 314 unsigned long value; 315 316 value = gfx_pci_config_read(0x80009404); 317 return ((unsigned char) value); 318} 319 320/*---------------------------------------------------------------------------- 321 * gfx_vga_set_pci_command 322 * 323 * This routine writes the value of the PCI command register. It is used 324 * to enable or disable SoftVGA. 325 * 326 * Bit 0: Enable VGA IO 327 * Bit 1: Enable VGA memory 328 *---------------------------------------------------------------------------- 329 */ 330int 331gfx_vga_set_pci_command(unsigned char command) 332{ 333 unsigned long value; 334 335 value = gfx_pci_config_read(0x80009404) & 0xFFFFFF00; 336 value |= (unsigned long) command; 337 gfx_pci_config_write(0x80009404, value); 338 return (GFX_STATUS_OK); 339} 340 341/*---------------------------------------------------------------------------- 342 * gfx_vga_seq_reset 343 * 344 * This routine enables or disables SoftVGA. It is used to make SoftVGA 345 * "be quiet" and not interfere with any of the direct hardware access from 346 * Durango. For VSA1, the sequencer is reset to stop text redraws. VSA2 may 347 * provide a better way to have SoftVGA sit in the background. 348 *---------------------------------------------------------------------------- 349 */ 350int 351gfx_vga_seq_reset(int reset) 352{ 353 OUTB(0x3C4, 0); 354 OUTB(0x3C5, (unsigned char) (reset ? 0x00 : 0x03)); 355 return (GFX_STATUS_OK); 356} 357 358/*---------------------------------------------------------------------------- 359 * gfx_vga_set_graphics_bits 360 * 361 * This routine sets the standard VGA sequencer, graphics controller, and 362 * attribute registers to appropriate values for a graphics mode (packed, 363 * 8 BPP or greater). This is also known as "VESA" modes. The timings for 364 * a particular mode are handled by the CRTC registers, which are set by 365 * the "gfx_vga_restore" routine. Most OSs that use VGA to set modes save 366 * and restore the standard VGA registers themselves, which is why these 367 * registers are not part of the save/restore paradigm. 368 *---------------------------------------------------------------------------- 369 */ 370int 371gfx_vga_set_graphics_bits(void) 372{ 373 /* SET GRAPHICS BIT IN GRAPHICS CONTROLLER REG 0x06 */ 374 375 OUTB(0x3CE, 0x06); 376 OUTB(0x3CF, 0x01); 377 378 /* SET GRAPHICS BIT IN ATTRIBUTE CONTROLLER REG 0x10 */ 379 380 INB(0x3BA); /* Reset flip-flop */ 381 INB(0x3DA); 382 OUTB(0x3C0, 0x10); 383 OUTB(0x3C0, 0x01); 384 return (GFX_STATUS_OK); 385} 386 387/*---------------------------------------------------------------------------- 388 * gfx_vga_mode 389 * 390 * This routine searches the VGA mode table for a match of the specified 391 * mode and then fills in the VGA structure with the associated VGA register 392 * values. The "gfx_vga_restore" routine can then be called to actually 393 * set the mode. 394 *---------------------------------------------------------------------------- 395 */ 396int 397gfx_vga_mode(gfx_vga_struct * vga, int xres, int yres, int bpp, int hz) 398{ 399 unsigned int i; 400 unsigned short pitch; 401 402 for (i = 0; i < GFX_VGA_MODES; i++) { 403 if ((gfx_vga_modes[i].xsize == xres) && 404 (gfx_vga_modes[i].ysize == yres) && (gfx_vga_modes[i].hz == hz)) { 405 /* COPY ENTIRE STRUCTURE FROM THE TABLE */ 406 407 *vga = gfx_vga_modes[i]; 408 409 /* SET PITCH TO 1K OR 2K */ 410 /* CRTC_EXTENDED_OFFSET index is 0x45, so offset = 0x05 */ 411 412 pitch = (unsigned short) xres; 413 if (bpp > 8) 414 pitch <<= 1; 415 if (pitch <= 1024) 416 pitch = 1024 >> 3; 417 else 418 pitch = 2048 >> 3; 419 vga->stdCRTCregs[0x13] = (unsigned char) pitch; 420 vga->extCRTCregs[0x05] = (unsigned char) ((pitch >> 8) & 0x03); 421 422 /* SET PROPER COLOR DEPTH VALUE */ 423 /* CRTC_EXTENDED_COLOR_CONTROL index is 0x46, so offset = 0x06 */ 424 425 switch (bpp) { 426 case 15: 427 vga->extCRTCregs[0x06] = CRTC_BIT_16BPP | CRTC_BIT_555; 428 break; 429 case 16: 430 vga->extCRTCregs[0x06] = CRTC_BIT_16BPP; 431 break; 432 default: 433 vga->extCRTCregs[0x06] = 0; 434 break; 435 } 436 return (GFX_STATUS_OK); 437 } 438 } 439 return (GFX_STATUS_UNSUPPORTED); 440} 441 442/*---------------------------------------------------------------------------- 443 * gfx_vga_pitch 444 * 445 * This routine updates the VGA regisers in the specified VGA structure for 446 * the specified pitch. It does not program the hardware. 447 *---------------------------------------------------------------------------- 448 */ 449int 450gfx_vga_pitch(gfx_vga_struct * vga, unsigned short pitch) 451{ 452 pitch >>= 3; 453 vga->stdCRTCregs[0x13] = (unsigned char) pitch; 454 vga->extCRTCregs[0x05] = (unsigned char) ((pitch >> 8) & 0x03); 455 return (0); 456} 457 458/*---------------------------------------------------------------------------- 459 * gfx_vga_save 460 * 461 * This routine saves the state of the VGA registers into the specified 462 * structure. Flags indicate what portions of the register state need to 463 * be saved. 464 *---------------------------------------------------------------------------- 465 */ 466int 467gfx_vga_save(gfx_vga_struct * vga, int flags) 468{ 469 int i; 470 unsigned short crtcindex, crtcdata; 471 472 crtcindex = (INB(0x3CC) & 0x01) ? 0x3D4 : 0x3B4; 473 crtcdata = crtcindex + 1; 474 475 /* CHECK MISCELLANEOUS OUTPUT FLAG */ 476 477 if (flags & GFX_VGA_FLAG_MISC_OUTPUT) { 478 /* SAVE MISCCELLANEOUS OUTPUT REGISTER */ 479 480 vga->miscOutput = INB(0x3CC); 481 } 482 483 /* CHECK STANDARD CRTC FLAG */ 484 485 if (flags & GFX_VGA_FLAG_STD_CRTC) { 486 /* SAVE STANDARD CRTC REGISTERS */ 487 488 for (i = 0; i < GFX_STD_CRTC_REGS; i++) { 489 OUTB(crtcindex, (unsigned char) i); 490 vga->stdCRTCregs[i] = INB(crtcdata); 491 } 492 } 493 494 /* CHECK EXTENDED CRTC FLAG */ 495 496 if (flags & GFX_VGA_FLAG_EXT_CRTC) { 497 /* SAVE EXTENDED CRTC REGISTERS */ 498 499 for (i = 0; i < GFX_EXT_CRTC_REGS; i++) { 500 OUTB(crtcindex, (unsigned char) (0x40 + i)); 501 vga->extCRTCregs[i] = INB(crtcdata); 502 } 503 } 504 return (0); 505} 506 507/*---------------------------------------------------------------------------- 508 * gfx_vga_clear_extended 509 * 510 * This routine clears the extended SoftVGA register values to have SoftVGA 511 * behave like standard VGA. 512 *---------------------------------------------------------------------------- 513 */ 514void 515gfx_vga_clear_extended(void) 516{ 517 int i; 518 unsigned short crtcindex, crtcdata; 519 520 crtcindex = (INB(0x3CC) & 0x01) ? 0x3D4 : 0x3B4; 521 crtcdata = crtcindex + 1; 522 523 OUTB(crtcindex, 0x30); 524 OUTB(crtcdata, 0x57); 525 OUTB(crtcdata, 0x4C); 526 for (i = 0x40; i <= 0x4F; i++) { 527 OUTB(crtcindex, (unsigned char) i); 528 OUTB(crtcdata, 0); 529 } 530 OUTB(crtcindex, 0x30); 531 OUTB(crtcdata, 0x00); 532} 533 534/*---------------------------------------------------------------------------- 535 * gfx_vga_restore 536 * 537 * This routine restores the state of the VGA registers from the specified 538 * structure. Flags indicate what portions of the register state need to 539 * be saved. 540 *---------------------------------------------------------------------------- 541 */ 542int 543gfx_vga_restore(gfx_vga_struct * vga, int flags) 544{ 545 int i; 546 unsigned short crtcindex, crtcdata; 547 548 crtcindex = (INB(0x3CC) & 0x01) ? 0x3D4 : 0x3B4; 549 crtcdata = crtcindex + 1; 550 551 /* CHECK MISCELLANEOUS OUTPUT FLAG */ 552 553 if (flags & GFX_VGA_FLAG_MISC_OUTPUT) { 554 /* RESTORE MISCELLANEOUS OUTPUT REGISTER VALUE */ 555 556 OUTB(0x3C2, vga->miscOutput); 557 } 558 559 /* CHECK STANDARD CRTC FLAG */ 560 561 if (flags & GFX_VGA_FLAG_STD_CRTC) { 562 /* UNLOCK STANDARD CRTC REGISTERS */ 563 564 OUTB(crtcindex, 0x11); 565 OUTB(crtcdata, 0); 566 567 /* RESTORE STANDARD CRTC REGISTERS */ 568 569 for (i = 0; i < GFX_STD_CRTC_REGS; i++) { 570 OUTB(crtcindex, (unsigned char) i); 571 OUTB(crtcdata, vga->stdCRTCregs[i]); 572 } 573 } 574 575 /* CHECK EXTENDED CRTC FLAG */ 576 577 if (flags & GFX_VGA_FLAG_EXT_CRTC) { 578 /* UNLOCK EXTENDED CRTC REGISTERS */ 579 580 OUTB(crtcindex, 0x30); 581 OUTB(crtcdata, 0x57); 582 OUTB(crtcdata, 0x4C); 583 584 /* RESTORE EXTENDED CRTC REGISTERS */ 585 586 for (i = 0; i < GFX_EXT_CRTC_REGS; i++) { 587 OUTB(crtcindex, (unsigned char) (0x40 + i)); 588 OUTB(crtcdata, vga->extCRTCregs[i]); 589 } 590 591 /* LOCK EXTENDED CRTC REGISTERS */ 592 593 OUTB(crtcindex, 0x30); 594 OUTB(crtcdata, 0x00); 595 596 /* CHECK IF DIRECT FRAME BUFFER MODE (VESA MODE) */ 597 598 if (vga->extCRTCregs[0x03] & 1) { 599 /* SET BORDER COLOR TO BLACK */ 600 /* This really should be another thing saved/restored, but */ 601 /* Durango currently doesn't do the attr controller registers. */ 602 603 INB(0x3BA); /* Reset flip-flop */ 604 INB(0x3DA); 605 OUTB(0x3C0, 0x11); 606 OUTB(0x3C0, 0x00); 607 } 608 } 609 return (0); 610} 611 612/*---------------------------------------------------------------------------- 613 * gfx_vga_mode_switch 614 * 615 * This routine programs the SoftVGA register to indicate that a mode switch 616 * is in progress. This results in a cleaner mode switch since SoftVGA will 617 * not validate the hardware with intermediate values. 618 *---------------------------------------------------------------------------- 619 */ 620int 621gfx_vga_mode_switch(int active) 622{ 623 unsigned short crtcindex, crtcdata; 624 625 crtcindex = (INB(0x3CC) & 0x01) ? 0x3D4 : 0x3B4; 626 crtcdata = crtcindex + 1; 627 628 /* UNLOCK EXTENDED CRTC REGISTERS */ 629 630 OUTB(crtcindex, CRTC_EXTENDED_REGISTER_LOCK); 631 OUTB(crtcdata, 0x57); 632 OUTB(crtcdata, 0x4C); 633 634 /* SIGNAL THE BEGINNING OR END OF THE MODE SWITCH */ 635 /* SoftVGA will hold off validating the back end hardware. */ 636 637 OUTB(crtcindex, CRTC_MODE_SWITCH_CONTROL); 638 active = active ? 1 : 0; 639 OUTB(crtcdata, (unsigned char) active); 640 641 /* WAIT UNTIL SOFTVGA HAS VALIDATED MODE IF ENDING MODE SWITCH */ 642 /* This is for VSA1 only, where SoftVGA waits until the next */ 643 /* vertical blank to validate the hardware state. */ 644 645 if ((!active) && (!(gu1_detect_vsa2()))) { 646 OUTB(crtcindex, 0x33); 647 while (INB(crtcdata) & 0x80); 648 } 649 650 /* LOCK EXTENDED CRTC REGISTERS */ 651 652 OUTB(crtcindex, CRTC_EXTENDED_REGISTER_LOCK); 653 OUTB(crtcdata, 0x00); 654 return (0); 655} 656 657/*---------------------------------------------------------------------------- 658 * gu1_detect_vsa2 659 * 660 * This routine detects if VSA2 is present. The interface to SoftVGA 661 * changed slightly. 662 *---------------------------------------------------------------------------- 663 */ 664int 665gu1_detect_vsa2(void) 666{ 667 unsigned short crtcindex, crtcdata; 668 669 crtcindex = (INB(0x3CC) & 0x01) ? 0x3D4 : 0x3B4; 670 crtcdata = crtcindex + 1; 671 OUTB(crtcindex, 0x35); 672 if (INB(crtcdata) != 'C') 673 return (0); 674 OUTB(crtcindex, 0x36); 675 if (INB(crtcdata) != 'X') 676 return (0); 677 return (1); 678} 679 680/* END OF FILE */ 681