gx_vga.c revision f29dbc25
1/* Copyright (c) 2003-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#ifdef HAVE_CONFIG_H 33#include "config.h" 34#endif 35 36#include <stdlib.h> 37#include <string.h> 38 39/* VGA STRUCTURE */ 40 41#define GU2_STD_CRTC_REGS 25 42#define GU2_EXT_CRTC_REGS 15 43#define GU2_GDC_REGS 9 44#define GU2_SEQ_REGS 5 45 46#define GU2_VGA_FLAG_MISC_OUTPUT 0x1 47#define GU2_VGA_FLAG_STD_CRTC 0x2 48#define GU2_VGA_FLAG_EXT_CRTC 0x4 49#define GU2_VGA_FLAG_GDC 0x10 50#define GU2_VGA_FLAG_SEQ 0x20 51#define GU2_VGA_FLAG_PALETTE 0x40 52#define GU2_VGA_FLAG_ATTR 0x80 53 54static unsigned int GDCregs[10]; 55static unsigned int SEQregs[10]; 56static unsigned int palette[256]; 57static unsigned int ATTRregs[32]; 58static unsigned char *font_data = NULL; 59 60#define VGA_BLOCK 0x40000 /* 256 k */ 61 62void gu2_vga_extcrtc(char offset, int reset); 63int gu2_get_vga_active(void); 64void gu2_vga_font_data(int flag); 65void gu2_set_vga(int reset); 66int gu2_vga_seq_blanking(void); 67int gu2_vga_attr_ctrl(int reset); 68void gu2_vga_to_gfx(void); 69void gu2_gfx_to_vga(int vga_mode); 70int gu2_vga_seq_reset(int reset); 71int gu2_vga_save(gfx_vga_struct * vga, int flags); 72void gu2_vga_clear_extended(void); 73int gu2_vga_restore(gfx_vga_struct * vga, int flags); 74 75int 76gu2_get_vga_active(void) 77{ 78 int data = gfx_read_reg32(MDC_GENERAL_CFG); 79 80 if (data & MDC_GCFG_VGAE) 81 return 1; 82 83 return 0; 84} 85 86void 87gu2_vga_font_data(int flag) 88{ 89 if (flag == 0) { 90 if (font_data == NULL) { 91 font_data = malloc(VGA_BLOCK); 92 } 93 94 DEBUGMSG(1, (0, X_NONE, "Saving VGA Data\n")); 95 memcpy(font_data, gfx_virt_fbptr, VGA_BLOCK); 96 } else if (font_data) { 97 DEBUGMSG(1, (0, X_NONE, "Restore VGA Data\n")); 98 memcpy(gfx_virt_fbptr, font_data, VGA_BLOCK); 99 free(font_data); 100 font_data = NULL; 101 } 102} 103 104void 105gu2_set_vga(int reset) 106{ 107 int data = gfx_read_reg32(MDC_GENERAL_CFG); 108 109 if (reset) 110 data |= MDC_GCFG_VGAE; 111 else 112 data &= ~MDC_GCFG_VGAE; 113 114 gfx_write_reg32(MDC_GENERAL_CFG, data); 115} 116 117int 118gu2_vga_seq_blanking(void) 119{ 120 int tmp; 121 122 gfx_outb(0x3C4, 1); 123 tmp = gfx_inb(0x3C5); 124 tmp |= 0x20; 125 tmp |= tmp << 8; 126 gfx_outw(0x3C4, tmp); 127 128 gfx_delay_milliseconds(1); 129 return (GFX_STATUS_OK); 130} 131 132int 133gu2_vga_attr_ctrl(int reset) 134{ 135 int tmp; 136 137 tmp = gfx_inb(0x3DA); 138 gfx_outb(0x3C0, (unsigned char)(reset ? 0x00 : 0x20)); 139 if (reset) 140 tmp = gfx_inb(0x3DA); 141 142 return (GFX_STATUS_OK); 143} 144 145void 146gu2_vga_to_gfx(void) 147{ 148 gu2_vga_attr_ctrl(0); 149 150 gu2_vga_seq_blanking(); 151 gfx_delay_milliseconds(2); 152 153 gu2_vga_extcrtc(0x3F, 1); 154} 155 156void 157gu2_gfx_to_vga(int vga_mode) 158{ 159 int tmp; 160 char sequencer; 161 162 gu2_vga_extcrtc(0x40, vga_mode); 163 164 /* clear the display blanking bit */ 165 gfx_outb(MDC_SEQUENCER_INDEX, MDC_SEQUENCER_CLK_MODE); 166 sequencer = gfx_inb(MDC_SEQUENCER_DATA); 167 sequencer &= ~MDC_CLK_MODE_SCREEN_OFF; 168 sequencer |= 1; 169 gfx_outb(MDC_SEQUENCER_DATA, sequencer); 170 171 gfx_delay_milliseconds(1); 172 173 /*restart the sequencer */ 174 gfx_outw(0x3C4, 0x300); 175 176 /* turn on the attribute controler */ 177 tmp = gfx_inb(0x3DA); 178 gfx_outb(0x3C0, 0x20); 179 tmp = gfx_inb(0x3DA); 180 181 gu2_vga_extcrtc(0x3F, 0); 182} 183 184/*--------------------------------------------------------------------------- 185 * gfx_vga_seq_reset 186 * 187 * This routine enables or disables SoftVGA. It is used to make SoftVGA 188 * "be quiet" and not interfere with any of the direct hardware access from 189 * Durango. For VSA1, the sequencer is reset to stop text redraws. VSA2 may 190 * provide a better way to have SoftVGA sit in the background. 191 *--------------------------------------------------------------------------- 192 */ 193int 194gu2_vga_seq_reset(int reset) 195{ 196 gfx_outb(0x3C4, 0); 197 gfx_outb(0x3C5, (unsigned char)(reset ? 0x00 : 0x03)); 198 return (GFX_STATUS_OK); 199} 200 201/*--------------------------------------------------------------------------- 202 * gfx_vga_save 203 * 204 * This routine saves the state of the VGA registers into the specified 205 * structure. Flags indicate what portions of the register state need to 206 * be saved. 207 *---------------------------------------------------------------------------- 208 */ 209int 210gu2_vga_save(gfx_vga_struct * vga, int flags) 211{ 212 int i; 213 unsigned short crtcindex, crtcdata; 214 215 crtcindex = (gfx_inb(0x3CC) & 0x01) ? 0x3D4 : 0x3B4; 216 crtcdata = crtcindex + 1; 217 218 /* CHECK MISCELLANEOUS OUTPUT FLAG */ 219 220 if (flags & GU2_VGA_FLAG_MISC_OUTPUT) { 221 /* SAVE MISCCELLANEOUS OUTPUT REGISTER */ 222 vga->miscOutput = gfx_inb(0x3CC); 223 } 224 225 /* CHECK SEQ */ 226 227 if (flags & GU2_VGA_FLAG_SEQ) { 228 /* SAVE STANDARD CRTC REGISTERS */ 229 for (i = 1; i < GU2_SEQ_REGS; i++) { 230 gfx_outb(0x3C4, (unsigned char)i); 231 SEQregs[i] = gfx_inb(0x3C5); 232 } 233 } 234 235 /* CHECK STANDARD CRTC FLAG */ 236 237 if (flags & GU2_VGA_FLAG_STD_CRTC) { 238 /* SAVE STANDARD CRTC REGISTERS */ 239 for (i = 0; i < GU2_STD_CRTC_REGS; i++) { 240 gfx_outb(crtcindex, (unsigned char)i); 241 vga->stdCRTCregs[i] = gfx_inb(crtcdata); 242 } 243 } 244 245 /* CHECK GDC */ 246 247 if (flags & GU2_VGA_FLAG_GDC) { 248 /* SAVE STANDARD CRTC REGISTERS */ 249 for (i = 0; i < GU2_GDC_REGS; i++) { 250 gfx_outb(0x3CE, (unsigned char)i); 251 GDCregs[i] = gfx_inb(0x3CF); 252 } 253 } 254 255 /* CHECK EXTENDED CRTC FLAG */ 256 257 if (flags & GU2_VGA_FLAG_EXT_CRTC) { 258 /* SAVE EXTENDED CRTC REGISTERS */ 259 for (i = 0; i < GU2_EXT_CRTC_REGS; i++) { 260 gfx_outb(crtcindex, (unsigned char)(0x40 + i)); 261 vga->extCRTCregs[i] = gfx_inb(crtcdata); 262 } 263 } 264 265 if (flags & GU2_VGA_FLAG_PALETTE) { 266 /* SAVE PALETTE DATA */ 267 for (i = 0; i < 0x100; i++) { 268 gfx_outb(0x3C7, i); 269 palette[i] = gfx_inb(0x3C9); 270 } 271 } 272 273 if (flags & GU2_VGA_FLAG_ATTR) { 274 /* SAVE Attribute DATA */ 275 for (i = 0; i < 21; i++) { 276 gfx_inb(0x3DA); 277 gfx_outb(0x3C0, i); 278 ATTRregs[i] = gfx_inb(0x3C1); 279 } 280 } 281 282 /* save the VGA data */ 283 gu2_vga_font_data(0); 284 return (0); 285} 286 287/*---------------------------------------------------------------------------- 288 * gfx_vga_clear_extended 289 * 290 * This routine clears the extended SoftVGA register values to have SoftVGA 291 * behave like standard VGA. 292 *---------------------------------------------------------------------------- 293 */ 294void 295gu2_vga_clear_extended(void) 296{ 297 int i; 298 unsigned short crtcindex, crtcdata; 299 300 crtcindex = (gfx_inb(0x3CC) & 0x01) ? 0x3D4 : 0x3B4; 301 crtcdata = crtcindex + 1; 302 303 gfx_outb(crtcindex, 0x30); 304 gfx_outb(crtcdata, 0x57); 305 gfx_outb(crtcdata, 0x4C); 306 for (i = 0x41; i <= 0x4F; i++) { 307 gfx_outb(crtcindex, (unsigned char)i); 308 gfx_outb(crtcdata, 0); 309 } 310 311 gfx_outb(crtcindex, 0x30); 312 gfx_outb(crtcdata, 0x00); 313} 314 315void 316gu2_vga_extcrtc(char offset, int reset) 317{ 318 unsigned short crtcindex, crtcdata; 319 320 crtcindex = (gfx_inb(0x3CC) & 0x01) ? 0x3D4 : 0x3B4; 321 crtcdata = crtcindex + 1; 322 323 /* UNLOCK EXTENDED CRTC REGISTERS */ 324 325 gfx_outb(crtcindex, 0x30); 326 gfx_outb(crtcdata, 0x57); 327 gfx_outb(crtcdata, 0x4C); 328 329 /* RESTORE EXTENDED CRTC REGISTERS */ 330 331 gfx_outb(crtcindex, offset); 332 gfx_outb(crtcdata, reset); 333} 334 335/*---------------------------------------------------------------------------- 336 * gfx_vga_restore 337 * 338 * This routine restores the state of the VGA registers from the specified 339 * structure. Flags indicate what portions of the register state need to 340 * be saved. 341 *---------------------------------------------------------------------------- 342 */ 343int 344gu2_vga_restore(gfx_vga_struct * vga, int flags) 345{ 346 int i; 347 unsigned short crtcindex, crtcdata; 348 349 crtcindex = (gfx_inb(0x3CC) & 0x01) ? 0x3D4 : 0x3B4; 350 crtcdata = crtcindex + 1; 351 352 /* CHECK MISCELLANEOUS OUTPUT FLAG */ 353 354 if (flags & GU2_VGA_FLAG_MISC_OUTPUT) { 355 /* RESTORE MISCELLANEOUS OUTPUT REGISTER VALUE */ 356 gfx_outb(0x3C2, vga->miscOutput); 357 } 358 359 /* CHECK SEQ */ 360 361 if (flags & GU2_VGA_FLAG_SEQ) { 362 /* RESTORE STANDARD CRTC REGISTERS */ 363 for (i = 1; i < GU2_SEQ_REGS; i++) { 364 gfx_outb(0x3C4, (unsigned char)i); 365 gfx_outb(0x3C5, SEQregs[i]); 366 } 367 } 368 369 /* CHECK STANDARD CRTC FLAG */ 370 371 if (flags & GU2_VGA_FLAG_STD_CRTC) { 372 /* UNLOCK STANDARD CRTC REGISTERS */ 373 gfx_outb(crtcindex, 0x11); 374 gfx_outb(crtcdata, 0); 375 376 /* RESTORE STANDARD CRTC REGISTERS */ 377 378 for (i = 0; i < GU2_STD_CRTC_REGS; i++) { 379 gfx_outb(crtcindex, (unsigned char)i); 380 gfx_outb(crtcdata, vga->stdCRTCregs[i]); 381 } 382 } 383 384 /* CHECK GDC */ 385 386 if (flags & GU2_VGA_FLAG_GDC) { 387 /* SAVE STANDARD CRTC REGISTERS */ 388 for (i = 0; i < GU2_GDC_REGS; i++) { 389 gfx_outb(0x3CE, (unsigned char)i); 390 gfx_outb(0x3CF, GDCregs[i]); 391 } 392 } 393 394 /* CHECK EXTENDED CRTC FLAG */ 395 396 if (flags & GU2_VGA_FLAG_EXT_CRTC) { 397 /* UNLOCK EXTENDED CRTC REGISTERS */ 398 gfx_outb(crtcindex, 0x30); 399 gfx_outb(crtcdata, 0x57); 400 gfx_outb(crtcdata, 0x4C); 401 402 /* RESTORE EXTENDED CRTC REGISTERS */ 403 404 for (i = 1; i < GU2_EXT_CRTC_REGS; i++) { 405 gfx_outb(crtcindex, (unsigned char)(0x40 + i)); 406 gfx_outb(crtcdata, vga->extCRTCregs[i]); 407 } 408 409 /* LOCK EXTENDED CRTC REGISTERS */ 410 411 gfx_outb(crtcindex, 0x30); 412 gfx_outb(crtcdata, 0x00); 413 414 /* CHECK IF DIRECT FRAME BUFFER MODE (VESA MODE) */ 415 416 if (vga->extCRTCregs[0x03] & 1) { 417 /* SET BORDER COLOR TO BLACK */ 418 /* This really should be another thing saved/restored, but */ 419 /* Durango currently doesn't do the attr controller registers. */ 420 421 gfx_inb(0x3BA); /* Reset flip-flop */ 422 gfx_inb(0x3DA); 423 gfx_outb(0x3C0, 0x11); 424 gfx_outb(0x3C0, 0x00); 425 } 426 } 427 428 if (flags & GU2_VGA_FLAG_PALETTE) { 429 /* RESTORE PALETTE DATA */ 430 for (i = 0; i < 0x100; i++) { 431 gfx_outb(0x3C8, i); 432 gfx_outb(0x3C9, palette[i]); 433 } 434 } 435 436 if (flags & GU2_VGA_FLAG_ATTR) { 437 /* RESTORE Attribute DATA */ 438 for (i = 0; i < 21; i++) { 439 gfx_inb(0x3DA); 440 gfx_outb(0x3C0, i); 441 gfx_outb(0x3C0, ATTRregs[i]); 442 } 443 /* SAVE Attribute DATA */ 444 445 for (i = 0; i < 21; i++) { 446 gfx_inb(0x3DA); 447 gfx_outb(0x3C0, i); 448 } 449 } 450 451 /* restore the VGA data */ 452 gu2_vga_font_data(1); 453 454 return (0); 455} 456 457/* END OF FILE */ 458