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