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 26void gu1_enable_compression(void); /* private routine definition */ 27void gu1_disable_compression(void); /* private routine definition */ 28void gfx_reset_video(void); /* private routine definition */ 29int gfx_set_display_control(int sync_polarities); /* private routine 30 * definition */ 31int gu1_set_specified_mode(DISPLAYMODE * pMode, int bpp); 32 33/* VIDEO BUFFER SIZE */ 34 35unsigned long vid_buf_size = 0; 36int vid_enabled = 0; 37 38/*---------------------------------------------------------------------------- 39 * GU1_DELAY_APPROXIMATE (PRIVATE ROUTINE - NOT PART OF DURANGO API) 40 * 41 * Delay the requested number of milliseconds by reading a register. This 42 * function generally takes longer than the requested time. 43 *---------------------------------------------------------------------------- 44 */ 45 46#define READS_PER_MILLISECOND 60000L 47 48void 49gu1_delay_approximate(unsigned long milliseconds) 50{ 51 /* ASSUME 300 MHz, 5 CLOCKS PER READ */ 52 53 unsigned long loop; 54 55 loop = milliseconds * READS_PER_MILLISECOND; 56 while (loop-- > 0) { 57 READ_REG32(DC_UNLOCK); 58 } 59} 60 61/*---------------------------------------------------------------------------- 62 * GU1_DELAY_PRECISE (PRIVATE ROUTINE - NOT PART OF DURANGO API) 63 * 64 * Delay the number of milliseconds on a more precise level, varying only by 65 * 1/10 of a ms. This function should only be called if an SC1200 is present. 66 *---------------------------------------------------------------------------- 67 */ 68void 69gu1_delay_precise(unsigned long milliseconds) 70{ 71#if GFX_VIDEO_SC1200 72 73#define LOOP 1000 74 unsigned long i, timer_start, timer_end, total_ticks, previous_ticks, 75 temp_ticks; 76 77 /* Get current time */ 78 timer_start = IND(SC1200_CB_BASE_ADDR + SC1200_CB_TMVALUE); 79 80 /* Calculate expected end time */ 81 if (INB(SC1200_CB_BASE_ADDR + SC1200_CB_TMCNFG) & SC1200_TMCLKSEL_27MHZ) 82 total_ticks = 27000 * milliseconds; /* timer resolution is 27 MHz */ 83 else 84 total_ticks = 1000 * milliseconds; /* timer resolution is 1 MHz */ 85 86 if (total_ticks > ((unsigned long) 0xffffffff - timer_start)) 87 /* wrap-around */ 88 timer_end = total_ticks - ((unsigned long) 0xffffffff - timer_start); 89 else 90 timer_end = timer_start + total_ticks; 91 92 /* in case of wrap around */ 93 if (timer_end < timer_start) { 94 previous_ticks = timer_start; 95 while (1) { 96 temp_ticks = IND(SC1200_CB_BASE_ADDR + SC1200_CB_TMVALUE); 97 if (temp_ticks < previous_ticks) 98 break; 99 else 100 previous_ticks = temp_ticks; 101 for (i = 0; i < LOOP; i++) 102 READ_REG32(DC_UNLOCK); 103 } 104 } 105 106 /* now the non-wrap around part */ 107 while (1) { 108 for (i = 0; i < LOOP; i++) 109 READ_REG32(DC_UNLOCK); 110 if (IND(SC1200_CB_BASE_ADDR + SC1200_CB_TMVALUE) > timer_end) 111 break; 112 } 113#endif /* GFX_VIDEO_SC1200 */ 114} 115 116/*---------------------------------------------------------------------------- 117 * WARNING!!!! INACCURATE DELAY MECHANISM 118 * 119 * In an effort to keep the code self contained and operating system 120 * independent, the delay loop just performs reads of a display controller 121 * register. This time will vary for faster processors. The delay can always 122 * be longer than intended, only effecting the time of the mode switch 123 * (obviously want it to still be under a second). Problems with the hardware 124 * only arise if the delay is not long enough. 125 * 126 * For the SC1200, the high resolution timer can be used as an accurate 127 * mechanism for keeping time. However, in order to avoid a busy loop of IO 128 * reads, the timer is polled in-between busy loops, and therefore the actual 129 * delay might be longer than the requested delay by the time of one busy loop 130 * (which on a 200 MHz system took 95 us) 131 * 132 * There are thus two delay functions which are called from the main API 133 * routine. 134 * One is meant to be more precise and should only called if an SC1200 is 135 * present. 136 *---------------------------------------------------------------------------- 137 */ 138#if GFX_DISPLAY_DYNAMIC 139void 140gu1_delay_milliseconds(unsigned long milliseconds) 141#else 142void 143gfx_delay_milliseconds(unsigned long milliseconds) 144#endif 145{ 146#if GFX_VIDEO_SC1200 147#if GFX_VIDEO_DYNAMIC 148 if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) { 149#endif 150 gu1_delay_precise(milliseconds); 151 return; 152#if GFX_VIDEO_DYNAMIC 153 } 154#endif 155#endif /* GFX_VIDEO_SC1200 */ 156 gu1_delay_approximate(milliseconds); 157} 158 159#if GFX_DISPLAY_DYNAMIC 160void 161gu1_delay_microseconds(unsigned long microseconds) 162#else 163void 164gfx_delay_microseconds(unsigned long microseconds) 165#endif 166{ 167 /* ASSUME 300 MHz, 2 CLOCKS PER INCREMENT */ 168 unsigned long loop_count = microseconds * 150; 169 170 while (loop_count-- > 0) { 171 ; 172 } 173} 174 175/*---------------------------------------------------------------------------- 176 * GFX_VIDEO_SHUTDOWN 177 * 178 * This routine disables the display controller output. 179 *---------------------------------------------------------------------------- 180 */ 181void 182gu1_video_shutdown(void) 183{ 184 unsigned long unlock; 185 unsigned long gcfg, tcfg; 186 187 /* DISABLE COMPRESSION */ 188 gu1_disable_compression(); 189 190 /* ALSO DISABLE VIDEO */ 191 /* Use private "reset video" routine to do all that is needed. */ 192 /* SC1200, for example, also disables the alpha blending regions. */ 193 gfx_reset_video(); 194 195 /* UNLOCK THE DISPLAY CONTROLLER REGISTERS */ 196 unlock = READ_REG32(DC_UNLOCK); 197 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 198 199 /* READ THE CURRENT GX VALUES */ 200 gcfg = READ_REG32(DC_GENERAL_CFG); 201 tcfg = READ_REG32(DC_TIMING_CFG); 202 203 /* BLANK THE GX DISPLAY AND DISABLE THE TIMING GENERATOR */ 204 tcfg &= ~((unsigned long) DC_TCFG_BLKE | (unsigned long) DC_TCFG_TGEN); 205 WRITE_REG32(DC_TIMING_CFG, tcfg); 206 207 /* DELAY: WAIT FOR PENDING MEMORY REQUESTS */ 208 /* This delay is used to make sure that all pending requests to the */ 209 /* memory controller have completed before disabling the FIFO load. */ 210 gfx_delay_milliseconds(1); 211 212 /* DISABLE DISPLAY FIFO LOAD AND DISABLE COMPRESSION */ 213 gcfg &= ~(unsigned long) (DC_GCFG_DFLE | DC_GCFG_CMPE | DC_GCFG_DECE); 214 WRITE_REG32(DC_GENERAL_CFG, gcfg); 215 WRITE_REG32(DC_UNLOCK, unlock); 216 return; 217} 218 219/*---------------------------------------------------------------------------- 220 * GFX_SET_DISPLAY_BPP 221 * 222 * This routine programs the bpp in the display controller. 223 *---------------------------------------------------------------------------- 224 */ 225#if GFX_DISPLAY_DYNAMIC 226int 227gu1_set_display_bpp(unsigned short bpp) 228#else 229int 230gfx_set_display_bpp(unsigned short bpp) 231#endif 232{ 233 unsigned long ocfg, lock; 234 235 lock = READ_REG32(DC_UNLOCK); 236 ocfg = READ_REG32(DC_OUTPUT_CFG) & ~(DC_OCFG_8BPP | DC_OCFG_555); 237 238 /* SET DC PIXEL FORMAT */ 239 if (bpp == 8) 240 ocfg |= DC_OCFG_8BPP; 241 else if (bpp == 15) 242 ocfg |= DC_OCFG_555; 243 else if (bpp != 16) 244 return GFX_STATUS_BAD_PARAMETER; 245 246 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 247 WRITE_REG32(DC_OUTPUT_CFG, ocfg); 248 WRITE_REG32(DC_UNLOCK, lock); 249 250 /* SET BPP IN GRAPHICS PIPELINE */ 251 gfx_set_bpp(bpp); 252 253 return 0; 254} 255 256/*---------------------------------------------------------------------------- 257 * GFX_SET_SPECIFIED_MODE 258 * This routine uses the parameters in the specified display mode structure 259 * to program the display controller hardware. 260 *---------------------------------------------------------------------------- 261 */ 262int 263gu1_set_specified_mode(DISPLAYMODE * pMode, int bpp) 264{ 265 unsigned long unlock, value; 266 unsigned long gcfg, tcfg, ocfg; 267 unsigned long size, pitch; 268 unsigned long hactive, vactive; 269 270 gbpp = bpp; 271 272 /* CHECK WHETHER TIMING CHANGE IS ALLOWED */ 273 /* Flag used for locking also overrides timing change restriction */ 274 if (gfx_timing_lock && !(pMode->flags & GFX_MODE_LOCK_TIMING)) 275 return GFX_STATUS_ERROR; 276 277 /* SET GLOBAL FLAG */ 278 if (pMode->flags & GFX_MODE_LOCK_TIMING) 279 gfx_timing_lock = 1; 280 281 /* DISABLE COMPRESSION */ 282 gu1_disable_compression(); 283 284 /* ALSO DISABLE VIDEO */ 285 /* Use private "reset video" routine to do all that is needed. */ 286 /* SC1200, for example, also disables the alpha blending regions. */ 287 gfx_reset_video(); 288 289 /* UNLOCK THE DISPLAY CONTROLLER REGISTERS */ 290 unlock = READ_REG32(DC_UNLOCK); 291 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 292 293 /* READ THE CURRENT GX VALUES */ 294 gcfg = READ_REG32(DC_GENERAL_CFG); 295 tcfg = READ_REG32(DC_TIMING_CFG); 296 297 /* BLANK THE GX DISPLAY AND DISABLE THE TIMING GENERATOR */ 298 tcfg &= ~((unsigned long) DC_TCFG_BLKE | (unsigned long) DC_TCFG_TGEN); 299 WRITE_REG32(DC_TIMING_CFG, tcfg); 300 301 /* DELAY: WAIT FOR PENDING MEMORY REQUESTS 302 * This delay is used to make sure that all pending requests to the 303 * memory controller have completed before disabling the FIFO load. 304 */ 305 gfx_delay_milliseconds(1); 306 307 /* DISABLE DISPLAY FIFO LOAD AND DISABLE COMPRESSION */ 308 gcfg &= ~(unsigned long) (DC_GCFG_DFLE | DC_GCFG_CMPE | DC_GCFG_DECE); 309 WRITE_REG32(DC_GENERAL_CFG, gcfg); 310 311 /* CLEAR THE "DCLK_MUL" FIELD */ 312 gcfg &= ~(unsigned long) (DC_GCFG_DDCK | DC_GCFG_DPCK | DC_GCFG_DFCK); 313 gcfg &= ~(unsigned long) DC_GCFG_DCLK_MASK; 314 WRITE_REG32(DC_GENERAL_CFG, gcfg); 315 316 /* SET THE DOT CLOCK FREQUENCY */ 317 /* Mask off the divide by two bit (bit 31) */ 318 gfx_set_clock_frequency(pMode->frequency & 0x7FFFFFFF); 319 320 /* DELAY: WAIT FOR THE PLL TO SETTLE */ 321 /* This allows the dot clock frequency that was just set to settle. */ 322 gfx_delay_milliseconds(1); 323 324 /* SET THE "DCLK_MUL" FIELD OF DC_GENERAL_CFG */ 325 /* The GX hardware divides the dot clock, so 2x really means that the */ 326 /* internal dot clock equals the external dot clock. */ 327 if (pMode->frequency & 0x80000000) 328 gcfg |= 0x0040; 329 else 330 gcfg |= 0x0080; 331 332 WRITE_REG32(DC_GENERAL_CFG, gcfg); 333 334 /* DELAY: WAIT FOR THE ADL TO LOCK */ 335 /* This allows the clock generatation within GX to settle. This is */ 336 /* needed since some of the register writes that follow require that */ 337 /* clock to be present. */ 338 gfx_delay_milliseconds(1); 339 340 /* SET THE GX DISPLAY CONTROLLER PARAMETERS */ 341 WRITE_REG32(DC_FB_ST_OFFSET, 0); 342 WRITE_REG32(DC_CB_ST_OFFSET, 0); 343 WRITE_REG32(DC_CURS_ST_OFFSET, 0); 344 345 /* SET LINE SIZE AND PITCH */ 346 /* Flat panels use the current flat panel line size to */ 347 /* calculate the pitch, but load the true line size */ 348 /* for the mode into the "Frame Buffer Line Size" field */ 349 /* of DC_BUF_SIZE. */ 350 if (PanelEnable) 351 size = ModeWidth; 352 else 353 size = pMode->hactive; 354 355 if (bpp > 8) 356 size <<= 1; 357 358 /* ONLY PYRAMID SUPPORTS 4K LINE SIZE */ 359 if (size <= 1024) { 360 pitch = 1024; 361 /* SPECIAL CASE */ 362 /* Graphics acceleration in 16-bit pixel line double modes */ 363 /* requires a pitch of 2048. */ 364 if ((pMode->flags & GFX_MODE_LINE_DOUBLE) && bpp > 8) 365 pitch <<= 1; 366 } 367 else { 368 if (gfx_cpu_version == GFX_CPU_PYRAMID) 369 pitch = (size <= 2048) ? 2048 : 4096; 370 else 371 pitch = 2048; 372 } 373 374 WRITE_REG32(DC_LINE_DELTA, pitch >> 2); 375 376 if (PanelEnable) { 377 size = pMode->hactive; 378 if (bpp > 8) 379 size <<= 1; 380 } 381 382 /* ADD 2 TO SIZE FOR POSSIBLE START ADDRESS ALIGNMENTS */ 383 WRITE_REG32(DC_BUF_SIZE, (size >> 3) + 2); 384 385 /* ALWAYS ENABLE "PANEL" DATA FROM MEDIAGX */ 386 /* That is really just the 18 BPP data bus to the companion chip */ 387 ocfg = DC_OCFG_PCKE | DC_OCFG_PDEL | DC_OCFG_PDEH; 388 389 /* SET PIXEL FORMAT */ 390 if (bpp == 8) 391 ocfg |= DC_OCFG_8BPP; 392 else if (bpp == 15) 393 ocfg |= DC_OCFG_555; 394 395 /* ENABLE TIMING GENERATOR, SYNCS, AND FP DATA */ 396 tcfg = DC_TCFG_FPPE | DC_TCFG_HSYE | DC_TCFG_VSYE | DC_TCFG_BLKE | 397 DC_TCFG_TGEN; 398 399 /* SET FIFO PRIORITY, DCLK MULTIPLIER, AND FIFO ENABLE */ 400 /* Default 6/5 for FIFO, 2x for DCLK multiplier. */ 401 gcfg = (6 << DC_GCFG_DFHPEL_POS) | (5 << DC_GCFG_DFHPSL_POS) | DC_GCFG_DFLE; 402 403 /* INCREASE FIFO PRIORITY FOR LARGE MODES */ 404 if (pMode->hactive == 1280 && pMode->vactive == 1024) { 405 if ((bpp == 8) && (pMode->flags & GFX_MODE_85HZ)) 406 gcfg = 407 (8l << DC_GCFG_DFHPEL_POS) | (7l << DC_GCFG_DFHPSL_POS) | 408 DC_GCFG_DFLE; 409 410 if ((bpp > 8) && (pMode->flags & GFX_MODE_75HZ)) 411 gcfg = 412 (7l << DC_GCFG_DFHPEL_POS) | (6l << DC_GCFG_DFHPSL_POS) | 413 DC_GCFG_DFLE; 414 415 if ((bpp > 8) && (pMode->flags & GFX_MODE_85HZ)) 416 gcfg = 417 (9l << DC_GCFG_DFHPEL_POS) | (8l << DC_GCFG_DFHPSL_POS) | 418 DC_GCFG_DFLE; 419 } 420 421 /* SET DOT CLOCK MULTIPLIER */ 422 /* Bit 31 of frequency indicates divide frequency by two */ 423 if (pMode->frequency & 0x80000000) 424 gcfg |= (1l << DC_GCFG_DCLK_POS); 425 else 426 gcfg |= (2l << DC_GCFG_DCLK_POS); 427 428 /* DIVIDE VIDEO CLOCK */ 429 /* CPU core frequencies above 266 MHz will divide the video */ 430 /* clock by 4 to ensure that we are running below 150 MHz. */ 431 if (gfx_cpu_frequency > 266) 432 gcfg |= DC_GCFG_VCLK_DIV; 433 434 /* ALWAYS ENABLE VIDEO IN THE DISPLAY CONTROLLER */ 435 /* Enabling video at an inopportune momemt can corrupt the DC fetch */ 436 /* engine and cause screen artifacts or system hang. */ 437 gcfg |= (DC_GCFG_VIDE | DC_GCFG_VRDY); 438 439 /* SET THE PIXEL AND LINE DOUBLE BITS IF NECESSARY */ 440 hactive = pMode->hactive; 441 vactive = pMode->vactive; 442 gfx_line_double = 0; 443 gfx_pixel_double = 0; 444 445 if (pMode->flags & GFX_MODE_LINE_DOUBLE) { 446 gcfg |= DC_GCFG_LDBL; 447 hactive <<= 1; 448 449 /* SET GLOBAL FLAG */ 450 gfx_line_double = 1; 451 } 452 453 if (pMode->flags & GFX_MODE_PIXEL_DOUBLE) { 454 tcfg |= DC_TCFG_PXDB; 455 vactive <<= 1; 456 457 /* SET GLOBAL FLAG */ 458 gfx_pixel_double = 1; 459 } 460 461 /* COMBINE AND SET TIMING VALUES */ 462 463 value = (unsigned long) (hactive - 1) | 464 (((unsigned long) (pMode->htotal - 1)) << 16); 465 WRITE_REG32(DC_H_TIMING_1, value); 466 value = (unsigned long) (pMode->hblankstart - 1) | 467 (((unsigned long) (pMode->hblankend - 1)) << 16); 468 WRITE_REG32(DC_H_TIMING_2, value); 469 value = (unsigned long) (pMode->hsyncstart - 1) | 470 (((unsigned long) (pMode->hsyncend - 1)) << 16); 471 WRITE_REG32(DC_H_TIMING_3, value); 472 WRITE_REG32(DC_FP_H_TIMING, value); 473 value = (unsigned long) (vactive - 1) | 474 (((unsigned long) (pMode->vtotal - 1)) << 16); 475 WRITE_REG32(DC_V_TIMING_1, value); 476 value = (unsigned long) (pMode->vblankstart - 1) | 477 (((unsigned long) (pMode->vblankend - 1)) << 16); 478 WRITE_REG32(DC_V_TIMING_2, value); 479 value = (unsigned long) (pMode->vsyncstart - 1) | 480 (((unsigned long) (pMode->vsyncend - 1)) << 16); 481 WRITE_REG32(DC_V_TIMING_3, value); 482 value = (unsigned long) (pMode->vsyncstart - 2) | 483 (((unsigned long) (pMode->vsyncend - 2)) << 16); 484 WRITE_REG32(DC_FP_V_TIMING, value); 485 486 WRITE_REG32(DC_OUTPUT_CFG, ocfg); 487 WRITE_REG32(DC_TIMING_CFG, tcfg); 488 gfx_delay_milliseconds(1); /* delay after TIMING_CFG */ 489 WRITE_REG32(DC_GENERAL_CFG, gcfg); 490 491 /* ENABLE FLAT PANEL CENTERING */ 492 /* For 640x480 modes displayed with the 9211 within a 800x600 */ 493 /* flat panel display, turn on flat panel centering. */ 494 if (PanelEnable) { 495 if (ModeWidth < PanelWidth) { 496 tcfg = READ_REG32(DC_TIMING_CFG); 497 tcfg = tcfg | DC_TCFG_FCEN; 498 WRITE_REG32(DC_TIMING_CFG, tcfg); 499 gfx_delay_milliseconds(1); /* delay after TIMING_CFG */ 500 } 501 } 502 503 /* CONFIGURE DISPLAY OUTPUT FROM VIDEO PROCESSOR */ 504 gfx_set_display_control(((pMode->flags & GFX_MODE_NEG_HSYNC) ? 1 : 0) | 505 ((pMode->flags & GFX_MODE_NEG_VSYNC) ? 2 : 0)); 506 507 /* RESTORE VALUE OF DC_UNLOCK */ 508 WRITE_REG32(DC_UNLOCK, unlock); 509 510 /* ALSO WRITE GP_BLIT_STATUS FOR PITCH AND 8/18 BPP */ 511 /* Remember, only Pyramid supports 4K line pitch */ 512 value = 0; 513 if (bpp > 8) 514 value |= BC_16BPP; 515 if ((gfx_cpu_version == GFX_CPU_PYRAMID) && (pitch > 2048)) 516 value |= BC_FB_WIDTH_4096; 517 else if (pitch > 1024) 518 value |= BC_FB_WIDTH_2048; 519 520 WRITE_REG16(GP_BLIT_STATUS, (unsigned short) value); 521 522 return GFX_STATUS_OK; 523} /* end gfx_set_specified_mode() */ 524 525/*---------------------------------------------------------------------------- 526 * GFX_IS_DISPLAY_MODE_SUPPORTED 527 * 528 * This routine sets the specified display mode. 529 * 530 * Returns the index of the mode if successful and mode returned, -1 if the 531 * mode could not be found. 532 *---------------------------------------------------------------------------- 533 */ 534#if GFX_DISPLAY_DYNAMIC 535int 536gu1_is_display_mode_supported(int xres, int yres, int bpp, int hz) 537#else 538int 539gfx_is_display_mode_supported(int xres, int yres, int bpp, int hz) 540#endif 541{ 542 unsigned int mode = 0; 543 unsigned long hz_flag = 0, bpp_flag = 0; 544 545 /* SET FLAGS TO MATCH REFRESH RATE */ 546 if (hz == 56) 547 hz_flag = GFX_MODE_56HZ; 548 else if (hz == 60) 549 hz_flag = GFX_MODE_60HZ; 550 else if (hz == 70) 551 hz_flag = GFX_MODE_70HZ; 552 else if (hz == 72) 553 hz_flag = GFX_MODE_72HZ; 554 else if (hz == 75) 555 hz_flag = GFX_MODE_75HZ; 556 else if (hz == 85) 557 hz_flag = GFX_MODE_85HZ; 558 else 559 return -1; 560 561 /* SET BPP FLAGS TO LIMIT MODE SELECTION */ 562 if (bpp == 8) 563 bpp_flag = GFX_MODE_8BPP; 564 else if (bpp == 15) 565 bpp_flag = GFX_MODE_15BPP; 566 else if (bpp == 16) 567 bpp_flag = GFX_MODE_16BPP; 568 else 569 return -1; 570 571 /* ONLY PYRAMID SUPPORTS 4K PITCH */ 572 if (gfx_cpu_version != GFX_CPU_PYRAMID && xres > 1024) { 573 if (bpp > 8) 574 return (-1); /* return with mode not found */ 575 } 576 577 /* LOOP THROUGH THE AVAILABLE MODES TO FIND A MATCH */ 578 for (mode = 0; mode < NUM_GX_DISPLAY_MODES; mode++) { 579 if ((DisplayParams[mode].hactive == (unsigned short) xres) && 580 (DisplayParams[mode].vactive == (unsigned short) yres) && 581 (DisplayParams[mode].flags & hz_flag) && 582 (DisplayParams[mode].flags & bpp_flag)) { 583 584 /* SET THE DISPLAY CONTROLLER FOR THE SELECTED MODE */ 585 return (mode); 586 } 587 } 588 return (-1); 589} 590 591/*---------------------------------------------------------------------------- 592 * GFX_SET_DISPLAY_MODE 593 * 594 * This routine sets the specified display mode. 595 * 596 * Returns 1 if successful, 0 if mode could not be set. 597 *---------------------------------------------------------------------------- 598 */ 599#if GFX_DISPLAY_DYNAMIC 600int 601gu1_set_display_mode(int xres, int yres, int bpp, int hz) 602#else 603int 604gfx_set_display_mode(int xres, int yres, int bpp, int hz) 605#endif 606{ 607 int mode; 608 609 /* DISABLE FLAT PANEL */ 610 /* Flat Panel settings are enabled by the function gfx_set_fixed_timings 611 * and disabled by gfx_set_display_mode. */ 612 PanelEnable = 0; 613 614 mode = gfx_is_display_mode_supported(xres, yres, bpp, hz); 615 if (mode >= 0) { 616 if (gu1_set_specified_mode(&DisplayParams[mode], bpp) == GFX_STATUS_OK) 617 return (1); 618 } 619 return (0); 620} 621 622/*---------------------------------------------------------------------------- 623 * GFX_SET_DISPLAY_TIMINGS 624 * 625 * This routine sets the display controller mode using the specified timing 626 * values (as opposed to using the tables internal to Durango). 627 * 628 * Returns GFX_STATUS_OK on success, GFX_STATUS_ERROR otherwise. 629 *---------------------------------------------------------------------------- 630 */ 631#if GFX_DISPLAY_DYNAMIC 632int 633gu1_set_display_timings(unsigned short bpp, unsigned short flags, 634 unsigned short hactive, unsigned short hblankstart, 635 unsigned short hsyncstart, unsigned short hsyncend, 636 unsigned short hblankend, unsigned short htotal, 637 unsigned short vactive, unsigned short vblankstart, 638 unsigned short vsyncstart, unsigned short vsyncend, 639 unsigned short vblankend, unsigned short vtotal, 640 unsigned long frequency) 641#else 642int 643gfx_set_display_timings(unsigned short bpp, unsigned short flags, 644 unsigned short hactive, unsigned short hblankstart, 645 unsigned short hsyncstart, unsigned short hsyncend, 646 unsigned short hblankend, unsigned short htotal, 647 unsigned short vactive, unsigned short vblankstart, 648 unsigned short vsyncstart, unsigned short vsyncend, 649 unsigned short vblankend, unsigned short vtotal, 650 unsigned long frequency) 651#endif 652{ 653 /* SET MODE STRUCTURE WITH SPECIFIED VALUES */ 654 655 gfx_display_mode.flags = 0; 656 if (flags & 1) 657 gfx_display_mode.flags |= GFX_MODE_NEG_HSYNC; 658 if (flags & 2) 659 gfx_display_mode.flags |= GFX_MODE_NEG_VSYNC; 660 if (flags & 0x1000) 661 gfx_display_mode.flags |= GFX_MODE_LOCK_TIMING; 662 gfx_display_mode.hactive = hactive; 663 gfx_display_mode.hblankstart = hblankstart; 664 gfx_display_mode.hsyncstart = hsyncstart; 665 gfx_display_mode.hsyncend = hsyncend; 666 gfx_display_mode.hblankend = hblankend; 667 gfx_display_mode.htotal = htotal; 668 gfx_display_mode.vactive = vactive; 669 gfx_display_mode.vblankstart = vblankstart; 670 gfx_display_mode.vsyncstart = vsyncstart; 671 gfx_display_mode.vsyncend = vsyncend; 672 gfx_display_mode.vblankend = vblankend; 673 gfx_display_mode.vtotal = vtotal; 674 gfx_display_mode.frequency = frequency; 675 676 /* CALL ROUTINE TO SET MODE */ 677 return (gu1_set_specified_mode(&gfx_display_mode, bpp)); 678} 679 680/*---------------------------------------------------------------------------- 681 * GFX_SET_VTOTAL 682 * 683 * This routine sets the display controller vertical total to 684 * "vtotal". As a side effect it also sets vertical blank end. 685 * It should be used when only this value needs to be changed, 686 * due to speed considerations. 687 * 688 * Note: it is the caller's responsibility to make sure that 689 * a legal vtotal is used, i.e. that "vtotal" is greater than or 690 * equal to vsync end. 691 * 692 * Always returns 0. 693 *---------------------------------------------------------------------------- 694 */ 695#if GFX_DISPLAY_DYNAMIC 696int 697gu1_set_vtotal(unsigned short vtotal) 698#else 699int 700gfx_set_vtotal(unsigned short vtotal) 701#endif 702{ 703 unsigned long unlock, tcfg, timing1, timing2; 704 705 /* UNLOCK THE DISPLAY CONTROLLER REGISTERS */ 706 unlock = READ_REG32(DC_UNLOCK); 707 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 708 709 /* READ THE CURRENT GX VALUES */ 710 tcfg = READ_REG32(DC_TIMING_CFG); 711 timing1 = READ_REG32(DC_V_TIMING_1); 712 timing2 = READ_REG32(DC_V_TIMING_2); 713 714 /* DISABLE THE TIMING GENERATOR */ 715 WRITE_REG32(DC_TIMING_CFG, tcfg & ~(unsigned long) DC_TCFG_TGEN); 716 717 /* WRITE NEW TIMING VALUES */ 718 WRITE_REG32(DC_V_TIMING_1, 719 (timing1 & 0xffff) | (unsigned long) (vtotal - 1) << 16); 720 WRITE_REG32(DC_V_TIMING_2, 721 (timing2 & 0xffff) | (unsigned long) (vtotal - 1) << 16); 722 723 /* RESTORE GX VALUES */ 724 WRITE_REG32(DC_TIMING_CFG, tcfg); 725 WRITE_REG32(DC_UNLOCK, unlock); 726 727 return (0); 728} 729 730/*--------------------------------------------------------------------------- 731 * gfx_set_display_pitch 732 * 733 * This routine sets the pitch of the frame buffer to the specified value. 734 *--------------------------------------------------------------------------- 735 */ 736#if GFX_DISPLAY_DYNAMIC 737void 738gu1_set_display_pitch(unsigned short pitch) 739#else 740void 741gfx_set_display_pitch(unsigned short pitch) 742#endif 743{ 744 unsigned long value = 0; 745 unsigned long lock = READ_REG32(DC_UNLOCK); 746 747 value = READ_REG32(DC_LINE_DELTA) & 0xFFFFF000; 748 value |= (pitch >> 2); 749 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 750 WRITE_REG32(DC_LINE_DELTA, value); 751 WRITE_REG32(DC_UNLOCK, lock); 752 753 /* ALSO UPDATE PITCH IN GRAPHICS ENGINE */ 754 /* Pyramid alone supports 4K line pitch */ 755 value = (unsigned long) READ_REG16(GP_BLIT_STATUS); 756 value &= ~(BC_FB_WIDTH_2048 | BC_FB_WIDTH_4096); 757 758 if ((gfx_cpu_version == GFX_CPU_PYRAMID) && (pitch > 2048)) 759 value |= BC_FB_WIDTH_4096; 760 761 else if (pitch > 1024) 762 value |= BC_FB_WIDTH_2048; 763 764 WRITE_REG16(GP_BLIT_STATUS, (unsigned short) value); 765 return; 766} 767 768/*--------------------------------------------------------------------------- 769 * gfx_set_display_offset 770 * 771 * This routine sets the start address of the frame buffer. It is 772 * typically used to pan across a virtual desktop (frame buffer larger than 773 * the displayed screen) or to flip the display between multiple buffers. 774 *--------------------------------------------------------------------------- 775 */ 776#if GFX_DISPLAY_DYNAMIC 777void 778gu1_set_display_offset(unsigned long offset) 779#else 780void 781gfx_set_display_offset(unsigned long offset) 782#endif 783{ 784 /* UPDATE FRAME BUFFER OFFSET */ 785 786 unsigned long lock; 787 788 lock = READ_REG32(DC_UNLOCK); 789 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 790 791 /* START ADDRESS EFFECTS DISPLAY COMPRESSION */ 792 /* Disable compression for non-zero start address values. */ 793 /* Enable compression if offset is zero and compression is intended to */ 794 /* be enabled from a previous call to "gfx_set_compression_enable". */ 795 /* Compression should be disabled BEFORE the offset is changed */ 796 /* and enabled AFTER the offset is changed. */ 797 if (offset == 0) { 798 WRITE_REG32(DC_FB_ST_OFFSET, offset); 799 if (gfx_compression_enabled) { 800 /* WAIT FOR THE OFFSET TO BE LATCHED */ 801 gfx_wait_vertical_blank(); 802 gu1_enable_compression(); 803 } 804 } 805 else { 806 /* ONLY DISABLE COMPRESSION ONCE */ 807 if (gfx_compression_active) 808 gu1_disable_compression(); 809 810 WRITE_REG32(DC_FB_ST_OFFSET, offset); 811 } 812 813 WRITE_REG32(DC_UNLOCK, lock); 814} 815 816/*--------------------------------------------------------------------------- 817 * gfx_set_display_palette_entry 818 * 819 * This routine sets an palette entry in the display controller. 820 * A 32-bit X:R:G:B value. 821 *--------------------------------------------------------------------------- 822 */ 823#if GFX_DISPLAY_DYNAMIC 824int 825gu1_set_display_palette_entry(unsigned long index, unsigned long palette) 826#else 827int 828gfx_set_display_palette_entry(unsigned long index, unsigned long palette) 829#endif 830{ 831 unsigned long data; 832 833 if (index > 0xFF) 834 return GFX_STATUS_BAD_PARAMETER; 835 836 WRITE_REG32(DC_PAL_ADDRESS, index); 837 data = ((palette >> 2) & 0x0003F) | 838 ((palette >> 4) & 0x00FC0) | ((palette >> 6) & 0x3F000); 839 WRITE_REG32(DC_PAL_DATA, data); 840 841 return (0); 842} 843 844/*--------------------------------------------------------------------------- 845 * gfx_set_display_palette 846 * 847 * This routine sets the entire palette in the display controller. 848 * A pointer is provided to a 256 entry table of 32-bit X:R:G:B values. 849 * 850 * Restriction: 851 * Due to SC1200 Issue #748 (in Notes DB) this function should be called only 852 * when DCLK is active, i.e PLL is already powered up and genlock is not 853 * active. 854 *--------------------------------------------------------------------------- 855 */ 856#if GFX_DISPLAY_DYNAMIC 857int 858gu1_set_display_palette(unsigned long *palette) 859#else 860int 861gfx_set_display_palette(unsigned long *palette) 862#endif 863{ 864 unsigned long data, i; 865 866 WRITE_REG32(DC_PAL_ADDRESS, 0); 867 if (palette) { 868 for (i = 0; i < 256; i++) { 869 /* CONVERT 24 BPP COLOR DATA TO 18 BPP COLOR DATA */ 870 data = ((palette[i] >> 2) & 0x0003F) | 871 ((palette[i] >> 4) & 0x00FC0) | ((palette[i] >> 6) & 0x3F000); 872 WRITE_REG32(DC_PAL_DATA, data); 873 } 874 } 875 return (0); 876} 877 878/*--------------------------------------------------------------------------- 879 * gfx_set_cursor_enable 880 * 881 * This routine enables or disables the hardware cursor. 882 * 883 * WARNING: The cusrsor start offset must be set by setting the cursor 884 * position before calling this routine to assure that memory reads do not 885 * go past the end of graphics memory (this can hang GXm). 886 *--------------------------------------------------------------------------- 887 */ 888#if GFX_DISPLAY_DYNAMIC 889void 890gu1_set_cursor_enable(int enable) 891#else 892void 893gfx_set_cursor_enable(int enable) 894#endif 895{ 896 unsigned long unlock, gcfg; 897 898 /* SET OR CLEAR CURSOR ENABLE BIT */ 899 unlock = READ_REG32(DC_UNLOCK); 900 gcfg = READ_REG32(DC_GENERAL_CFG); 901 if (enable) 902 gcfg |= DC_GCFG_CURE; 903 else 904 gcfg &= ~(DC_GCFG_CURE); 905 906 /* WRITE NEW REGISTER VALUE */ 907 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 908 WRITE_REG32(DC_GENERAL_CFG, gcfg); 909 WRITE_REG32(DC_UNLOCK, unlock); 910} 911 912/*--------------------------------------------------------------------------- 913 * gfx_set_cursor_colors 914 * 915 * This routine sets the colors of the hardware cursor. 916 * 917 * Restriction: 918 * Due to SC1200 Issue #748 (in Notes DB) this function should be called only 919 * when DCLK is active, i.e PLL is already powered up. 920 *--------------------------------------------------------------------------- 921 */ 922#if GFX_DISPLAY_DYNAMIC 923void 924gu1_set_cursor_colors(unsigned long bkcolor, unsigned long fgcolor) 925#else 926void 927gfx_set_cursor_colors(unsigned long bkcolor, unsigned long fgcolor) 928#endif 929{ 930 unsigned long value; 931 932 /* If genlock is enabled DCLK might be disabled in vertical blank. */ 933 /* Due to SC1200 Issue #748 in Notes DB this would fail the cursor color settings */ 934 /* So Wait for vertical blank to end */ 935 936#if GFX_VIDEO_SC1200 937 if (gfx_test_timing_active()) 938 while ((gfx_get_vline()) > gfx_get_vactive()); 939#endif 940 /* SET CURSOR COLORS */ 941 WRITE_REG32(DC_PAL_ADDRESS, 0x100); 942 value = ((bkcolor & 0x000000FC) >> 2) | 943 ((bkcolor & 0x0000FC00) >> (2 + 8 - 6)) | 944 ((bkcolor & 0x00FC0000) >> (2 + 16 - 12)); 945 WRITE_REG32(DC_PAL_DATA, value); 946 value = ((fgcolor & 0x000000FC) >> 2) | 947 ((fgcolor & 0x0000FC00) >> (2 + 8 - 6)) | 948 ((fgcolor & 0x00FC0000) >> (2 + 16 - 12)); 949 WRITE_REG32(DC_PAL_DATA, value); 950} 951 952/*--------------------------------------------------------------------------- 953 * gfx_set_cursor_position 954 * 955 * This routine sets the position of the hardware cusror. The starting 956 * offset of the cursor buffer must be specified so that the routine can 957 * properly clip scanlines if the cursor is off the top of the screen. 958 *--------------------------------------------------------------------------- 959 */ 960#if GFX_DISPLAY_DYNAMIC 961void 962gu1_set_cursor_position(unsigned long memoffset, 963 unsigned short xpos, unsigned short ypos, 964 unsigned short xhotspot, unsigned short yhotspot) 965#else 966void 967gfx_set_cursor_position(unsigned long memoffset, 968 unsigned short xpos, unsigned short ypos, 969 unsigned short xhotspot, unsigned short yhotspot) 970#endif 971{ 972 unsigned long unlock; 973 974 short x, y; 975 short xoffset = 0; 976 short yoffset = 0; 977 978 /* SUPPORT CURSOR IN EMULATED VGA MODES */ 979 /* Timings are for twice the resolution */ 980 if (gfx_pixel_double) 981 xpos <<= 1; 982 983 if (gfx_line_double) 984 ypos <<= 1; 985 986 x = (short) xpos - (short) xhotspot; 987 y = (short) ypos - (short) yhotspot; 988 if (x < -31) 989 return; 990 991 if (y < -31) 992 return; 993 994 if (x < 0) { 995 xoffset = -x; 996 x = 0; 997 } 998 999 if (y < 0) { 1000 yoffset = -y; 1001 y = 0; 1002 } 1003 1004 memoffset += (unsigned long) yoffset << 3; 1005 1006 if (PanelEnable) { 1007 if ((ModeWidth > PanelWidth) || (ModeHeight > PanelHeight)) { 1008 gfx_enable_panning(xpos, ypos); 1009 x = x - (short) panelLeft; 1010 y = y - (short) panelTop; 1011 } 1012 } 1013 1014 /* SET CURSOR POSITION */ 1015 unlock = READ_REG32(DC_UNLOCK); 1016 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 1017 WRITE_REG32(DC_CURS_ST_OFFSET, memoffset); 1018 WRITE_REG32(DC_CURSOR_X, (unsigned long) x | 1019 (((unsigned long) xoffset) << 11)); 1020 WRITE_REG32(DC_CURSOR_Y, (unsigned long) y | 1021 (((unsigned long) yoffset) << 11)); 1022 WRITE_REG32(DC_UNLOCK, unlock); 1023} 1024 1025/*--------------------------------------------------------------------------- 1026 * gfx_set_cursor_shape32 1027 * 1028 * This routine loads 32x32 cursor data into the specified location in 1029 * graphics memory. 1030 *--------------------------------------------------------------------------- 1031 */ 1032#if GFX_DISPLAY_DYNAMIC 1033void 1034gu1_set_cursor_shape32(unsigned long memoffset, 1035 unsigned long *andmask, unsigned long *xormask) 1036#else 1037void 1038gfx_set_cursor_shape32(unsigned long memoffset, 1039 unsigned long *andmask, unsigned long *xormask) 1040#endif 1041{ 1042 int i; 1043 unsigned long value; 1044 1045 for (i = 0; i < 32; i++) { 1046 /* CONVERT TO 16 BITS AND MASK, 16 BITS XOR MASK PER DWORD */ 1047 value = (andmask[i] & 0xFFFF0000) | (xormask[i] >> 16); 1048 WRITE_FB32(memoffset, value); 1049 memoffset += 4; 1050 value = (andmask[i] << 16) | (xormask[i] & 0x0000FFFF); 1051 WRITE_FB32(memoffset, value); 1052 memoffset += 4; 1053 } 1054} 1055 1056/*--------------------------------------------------------------------------- 1057 * gu1_enable_compression 1058 * 1059 * This is a private routine to this module (not exposed in the Durango API). 1060 * It enables display compression. 1061 *--------------------------------------------------------------------------- 1062 */ 1063void 1064gu1_enable_compression(void) 1065{ 1066 int i; 1067 unsigned long unlock, gcfg, offset; 1068 1069 /* DO NOT ENABLE IF START ADDRESS IS NOT ZERO */ 1070 offset = READ_REG32(DC_FB_ST_OFFSET) & 0x003FFFFF; 1071 if (offset != 0) 1072 return; 1073 1074 /* DO NOT ENABLE IF WE ARE WITHIN AN EMULATED VGA MODE */ 1075 if (gfx_line_double || gfx_pixel_double) 1076 return; 1077 1078 /* SET GLOBAL INDICATOR */ 1079 gfx_compression_active = 1; 1080 1081 /* CLEAR DIRTY/VALID BITS IN MEMORY CONTROLLER */ 1082 /* Software is required to do this before enabling compression. */ 1083 /* Don't want controller to think that old lines are still valid. */ 1084 for (i = 0; i < 1024; i++) { 1085 WRITE_REG32(MC_DR_ADD, i); 1086 WRITE_REG32(MC_DR_ACC, 0); 1087 } 1088 1089 /* TURN ON COMPRESSION CONTROL BITS */ 1090 unlock = READ_REG32(DC_UNLOCK); 1091 gcfg = READ_REG32(DC_GENERAL_CFG); 1092 gcfg |= DC_GCFG_CMPE | DC_GCFG_DECE; 1093 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 1094 WRITE_REG32(DC_GENERAL_CFG, gcfg); 1095 WRITE_REG32(DC_UNLOCK, unlock); 1096} 1097 1098/*--------------------------------------------------------------------------- 1099 * gu1_disable_compression 1100 * 1101 * This is a private routine to this module (not exposed in the Durango API). 1102 * It disables display compression. 1103 *--------------------------------------------------------------------------- 1104 */ 1105void 1106gu1_disable_compression(void) 1107{ 1108 unsigned long unlock, gcfg; 1109 1110 /* SET GLOBAL INDICATOR */ 1111 gfx_compression_active = 0; 1112 1113 /* TURN OFF COMPRESSION CONTROL BITS */ 1114 unlock = READ_REG32(DC_UNLOCK); 1115 gcfg = READ_REG32(DC_GENERAL_CFG); 1116 gcfg &= ~(DC_GCFG_CMPE | DC_GCFG_DECE); 1117 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 1118 WRITE_REG32(DC_GENERAL_CFG, gcfg); 1119 WRITE_REG32(DC_UNLOCK, unlock); 1120} 1121 1122/*--------------------------------------------------------------------------- 1123 * gfx_set_compression_enable 1124 * 1125 * This routine enables or disables display compression. 1126 *--------------------------------------------------------------------------- 1127 */ 1128#if GFX_DISPLAY_DYNAMIC 1129int 1130gu1_set_compression_enable(int enable) 1131#else 1132int 1133gfx_set_compression_enable(int enable) 1134#endif 1135{ 1136 /* SET GLOBAL VARIABLE FOR INTENDED STATE */ 1137 /* Compression can only be enabled for non-zero start address values. */ 1138 /* Keep state to enable compression on start address changes. */ 1139 gfx_compression_enabled = enable; 1140 if (enable) 1141 gu1_enable_compression(); 1142 else 1143 gu1_disable_compression(); 1144 1145 return (0); 1146} 1147 1148/*--------------------------------------------------------------------------- 1149 * gfx_set_compression_offset 1150 * 1151 * This routine sets the base offset for the compression buffer. 1152 *--------------------------------------------------------------------------- 1153 */ 1154#if GFX_DISPLAY_DYNAMIC 1155int 1156gu1_set_compression_offset(unsigned long offset) 1157#else 1158int 1159gfx_set_compression_offset(unsigned long offset) 1160#endif 1161{ 1162 unsigned long lock; 1163 1164 /* MUST BE 16-BYTE ALIGNED FOR GXLV */ 1165 if (offset & 0x0F) 1166 return (1); 1167 1168 /* SET REGISTER VALUE */ 1169 lock = READ_REG32(DC_UNLOCK); 1170 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 1171 WRITE_REG32(DC_CB_ST_OFFSET, offset); 1172 WRITE_REG32(DC_UNLOCK, lock); 1173 return (0); 1174} 1175 1176/*--------------------------------------------------------------------------- 1177 * gfx_set_compression_pitch 1178 * 1179 * This routine sets the pitch, in bytes, of the compression buffer. 1180 *--------------------------------------------------------------------------- 1181 */ 1182#if GFX_DISPLAY_DYNAMIC 1183int 1184gu1_set_compression_pitch(unsigned short pitch) 1185#else 1186int 1187gfx_set_compression_pitch(unsigned short pitch) 1188#endif 1189{ 1190 unsigned long lock, line_delta; 1191 1192 /* SET REGISTER VALUE */ 1193 lock = READ_REG32(DC_UNLOCK); 1194 line_delta = READ_REG32(DC_LINE_DELTA) & 0xFF800FFF; 1195 line_delta |= ((unsigned long) pitch << 10l) & 0x007FF000; 1196 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 1197 WRITE_REG32(DC_LINE_DELTA, line_delta); 1198 WRITE_REG32(DC_UNLOCK, lock); 1199 return (0); 1200} 1201 1202/*--------------------------------------------------------------------------- 1203 * gfx_set_compression_size 1204 * 1205 * This routine sets the line size of the compression buffer, which is the 1206 * maximum number of bytes allowed to store a compressed line. 1207 *--------------------------------------------------------------------------- 1208 */ 1209#if GFX_DISPLAY_DYNAMIC 1210int 1211gu1_set_compression_size(unsigned short size) 1212#else 1213int 1214gfx_set_compression_size(unsigned short size) 1215#endif 1216{ 1217 unsigned long lock, buf_size; 1218 1219 /* SUBTRACT 16 FROM SIZE */ 1220 /* The display controller will actually write */ 1221 /* 2 extra QWords. So, if we assume that "size" */ 1222 /* refers to the allocated size, we must subtract */ 1223 /* 16 bytes. */ 1224 size -= 16; 1225 1226 /* SET REGISTER VALUE */ 1227 lock = READ_REG32(DC_UNLOCK); 1228 buf_size = READ_REG32(DC_BUF_SIZE) & 0xFFFF01FF; 1229 buf_size |= (((size >> 2) + 1) & 0x7F) << 9; 1230 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 1231 WRITE_REG32(DC_BUF_SIZE, buf_size); 1232 WRITE_REG32(DC_UNLOCK, lock); 1233 return (0); 1234} 1235 1236/*--------------------------------------------------------------------------- 1237 * gfx_set_display_video_enable (PRIVATE ROUTINE - NOT PART OF API) 1238 * 1239 * This routine enables/disables video on GX. 1240 *--------------------------------------------------------------------------- 1241 */ 1242#if GFX_DISPLAY_DYNAMIC 1243void 1244gu1_set_display_video_enable(int enable) 1245#else 1246void 1247gfx_set_display_video_enable(int enable) 1248#endif 1249{ 1250 unsigned long lock, gcfg, buf_size; 1251 1252 lock = READ_REG32(DC_UNLOCK); 1253 gcfg = READ_REG32(DC_GENERAL_CFG); 1254 buf_size = READ_REG32(DC_BUF_SIZE); 1255 1256 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 1257 1258 vid_enabled = enable; 1259 1260 /* SET THE BUFFER SIZE TO A NON-ZERO VALUE ONLY WHEN */ 1261 /* ENABLING VIDEO */ 1262 if (enable) { 1263 gcfg |= (DC_GCFG_VIDE | DC_GCFG_VRDY); 1264 WRITE_REG32(DC_GENERAL_CFG, gcfg); 1265 1266 WRITE_REG32(DC_BUF_SIZE, (buf_size & 0x0000FFFFl) | vid_buf_size); 1267 } 1268 /* CLEAR THE VIDEO BUFFER SIZE WHEN DISABLING VIDEO */ 1269 else { 1270 gcfg &= ~(DC_GCFG_VIDE); 1271 WRITE_REG32(DC_GENERAL_CFG, gcfg); 1272 1273 vid_buf_size = buf_size & 0xFFFF0000l; 1274 WRITE_REG32(DC_BUF_SIZE, buf_size & 0x0000FFFFl); 1275 } 1276 1277 WRITE_REG32(DC_UNLOCK, lock); 1278 return; 1279} 1280 1281/*--------------------------------------------------------------------------- 1282 * gfx_set_display_video_size (PRIVATE ROUTINE - NOT PART OF API) 1283 * 1284 * This routine is called by "gfx_set_video_size". It abstracts the 1285 * version of the display controller from the video overlay routines. 1286 *--------------------------------------------------------------------------- 1287 */ 1288#if GFX_DISPLAY_DYNAMIC 1289void 1290gu1_set_display_video_size(unsigned short width, unsigned short height) 1291#else 1292void 1293gfx_set_display_video_size(unsigned short width, unsigned short height) 1294#endif 1295{ 1296 unsigned long lock, size, value; 1297 1298 size = (unsigned long) (width << 1) * (unsigned long) height; 1299 1300 /* STORE THE VIDEO BUFFER SIZE AS A GLOBAL */ 1301 vid_buf_size = ((size + 63) >> 6) << 16; 1302 1303 lock = READ_REG32(DC_UNLOCK); 1304 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 1305 value = READ_REG32(DC_BUF_SIZE) & 0x0000FFFF; 1306 value |= vid_buf_size; 1307 WRITE_REG32(DC_BUF_SIZE, value); 1308 WRITE_REG32(DC_UNLOCK, lock); 1309} 1310 1311/*--------------------------------------------------------------------------- 1312 * gfx_set_display_video_offset (PRIVATE ROUTINE - NOT PART OF API) 1313 * 1314 * This routine is called by "gfx_set_video_offset". It abstracts the 1315 * version of the display controller from the video overlay routines. 1316 *--------------------------------------------------------------------------- 1317 */ 1318#if GFX_DISPLAY_DYNAMIC 1319void 1320gu1_set_display_video_offset(unsigned long offset) 1321#else 1322void 1323gfx_set_display_video_offset(unsigned long offset) 1324#endif 1325{ 1326 unsigned long lock; 1327 1328 lock = READ_REG32(DC_UNLOCK); 1329 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 1330 offset &= 0x003FFFFF; 1331 WRITE_REG32(DC_VID_ST_OFFSET, offset); 1332 WRITE_REG32(DC_UNLOCK, lock); 1333} 1334 1335/*--------------------------------------------------------------------------- 1336 * gfx_set_display_priority_high 1337 * 1338 * This routine controls the x-bus round robin arbitration mechanism. 1339 * When enable is TRUE, graphics pipeline requests and non-critical display 1340 * controller requests are arbitrated at the same priority as processor 1341 * requests. When FALSE processor requests are arbitrated at a higher priority 1342 *--------------------------------------------------------------------------- 1343 */ 1344#if GFX_DISPLAY_DYNAMIC 1345void 1346gu1_set_display_priority_high(int enable) 1347#else 1348void 1349gfx_set_display_priority_high(int enable) 1350#endif 1351{ 1352 unsigned long lock, control; 1353 1354 lock = READ_REG32(DC_UNLOCK); 1355 control = READ_REG32(MC_MEM_CNTRL1); 1356 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 1357 if (enable) 1358 control |= MC_XBUSARB; 1359 else 1360 control &= ~(MC_XBUSARB); 1361 WRITE_REG32(MC_MEM_CNTRL1, control); 1362 WRITE_REG32(DC_UNLOCK, lock); 1363 return; 1364} 1365 1366/*--------------------------------------------------------------------------- 1367 * gfx_test_timing_active 1368 *--------------------------------------------------------------------------- 1369 */ 1370#if GFX_DISPLAY_DYNAMIC 1371int 1372gu1_test_timing_active(void) 1373#else 1374int 1375gfx_test_timing_active(void) 1376#endif 1377{ 1378 if (READ_REG32(DC_TIMING_CFG) & DC_TCFG_TGEN) 1379 return (1); 1380 else 1381 return (0); 1382} 1383 1384/*--------------------------------------------------------------------------- 1385 * gfx_test_vertical_active 1386 *--------------------------------------------------------------------------- 1387 */ 1388#if GFX_DISPLAY_DYNAMIC 1389int 1390gu1_test_vertical_active(void) 1391#else 1392int 1393gfx_test_vertical_active(void) 1394#endif 1395{ 1396 if (READ_REG32(DC_TIMING_CFG) & DC_TCFG_VNA) 1397 return (0); 1398 else 1399 return (1); 1400} 1401 1402/*--------------------------------------------------------------------------- 1403 * gfx_wait_vertical_blank 1404 *--------------------------------------------------------------------------- 1405 */ 1406#if GFX_DISPLAY_DYNAMIC 1407int 1408gu1_wait_vertical_blank(void) 1409#else 1410int 1411gfx_wait_vertical_blank(void) 1412#endif 1413{ 1414 if (gfx_test_timing_active()) { 1415 while (!gfx_test_vertical_active()); 1416 while (gfx_test_vertical_active()); 1417 } 1418 1419 return (0); 1420} 1421 1422/*--------------------------------------------------------------------------- 1423 * gfx_enable_panning 1424 * 1425 * This routine enables the panning when the Mode is bigger than the panel 1426 * size. 1427 *--------------------------------------------------------------------------- 1428 */ 1429#if GFX_DISPLAY_DYNAMIC 1430void 1431gu1_enable_panning(int x, int y) 1432#else 1433void 1434gfx_enable_panning(int x, int y) 1435#endif 1436{ 1437 unsigned long modeBytesPerPixel; 1438 unsigned long modeBytesPerScanline = 0; 1439 unsigned long startAddress = 0; 1440 1441 modeBytesPerPixel = (gbpp + 7) / 8; 1442 modeBytesPerScanline = 1443 (((ModeWidth + 1023) / 1024) * 1024) * modeBytesPerPixel; 1444 1445 /* TEST FOR NO-WORK */ 1446 if (x >= DeltaX && (unsigned short) x < (PanelWidth + DeltaX) && 1447 y >= DeltaY && (unsigned short) y < (PanelHeight + DeltaY)) 1448 return; 1449 1450 /* ADJUST PANNING VARIABLES WHEN CURSOR EXCEEDS BOUNDARY */ 1451 /* Test the boundary conditions for each coordinate and update */ 1452 /* all variables and the starting offset accordingly. */ 1453 if (x < DeltaX) 1454 DeltaX = x; 1455 else if ((unsigned short) x >= (DeltaX + PanelWidth)) 1456 DeltaX = x - PanelWidth + 1; 1457 1458 if (y < DeltaY) 1459 DeltaY = y; 1460 else if ((unsigned short) y >= (DeltaY + PanelHeight)) 1461 DeltaY = y - PanelHeight + 1; 1462 1463 /* CALCULATE THE START OFFSET */ 1464 startAddress = 1465 (DeltaX * modeBytesPerPixel) + (DeltaY * modeBytesPerScanline); 1466 1467 gfx_set_display_offset(startAddress); 1468 1469 /* SET PANEL COORDINATES */ 1470 /* Panel's x position must be DWORD aligned */ 1471 panelTop = DeltaY; 1472 panelLeft = DeltaX * modeBytesPerPixel; 1473 1474 if (panelLeft & 3) 1475 panelLeft = (panelLeft & 0xFFFFFFFC) + 4; 1476 1477 panelLeft /= modeBytesPerPixel; 1478 1479} 1480 1481/*--------------------------------------------------------------------------- 1482 * gfx_set_fixed_timings 1483 *--------------------------------------------------------------------------- 1484 */ 1485#if GFX_DISPLAY_DYNAMIC 1486int 1487gu1_set_fixed_timings(int panelResX, int panelResY, unsigned short width, 1488 unsigned short height, unsigned short bpp) 1489#else 1490int 1491gfx_set_fixed_timings(int panelResX, int panelResY, unsigned short width, 1492 unsigned short height, unsigned short bpp) 1493#endif 1494{ 1495 unsigned int mode; 1496 1497 ModeWidth = width; 1498 ModeHeight = height; 1499 PanelWidth = (unsigned short) panelResX; 1500 PanelHeight = (unsigned short) panelResY; 1501 PanelEnable = 1; 1502 1503 /* LOOP THROUGH THE AVAILABLE MODES TO FIND A MATCH */ 1504 for (mode = 0; mode < NUM_FIXED_TIMINGS_MODES; mode++) { 1505 if ((FixedParams[mode].xres == width) && 1506 (FixedParams[mode].yres == height) && 1507 (FixedParams[mode].panelresx == panelResX) && 1508 (FixedParams[mode].panelresy == panelResY)) { 1509 1510 /* SET THE 92xx FOR THE SELECTED MODE */ 1511 FIXEDTIMINGS *fmode = &FixedParams[mode]; 1512 1513 gfx_set_display_timings(bpp, 3, fmode->hactive, 1514 fmode->hblankstart, fmode->hsyncstart, 1515 fmode->hsyncend, fmode->hblankend, 1516 fmode->htotal, fmode->vactive, 1517 fmode->vblankstart, fmode->vsyncstart, 1518 fmode->vsyncend, fmode->vblankend, 1519 fmode->vtotal, fmode->frequency); 1520 1521 return (1); 1522 } /* end if() */ 1523 } /* end for() */ 1524 1525 return (-1); 1526} 1527 1528/*--------------------------------------------------------------------------- 1529 * gfx_set_panel_present 1530 *--------------------------------------------------------------------------- 1531 */ 1532#if GFX_DISPLAY_DYNAMIC 1533int 1534gu1_set_panel_present(int panelResX, int panelResY, unsigned short width, 1535 unsigned short height, unsigned short bpp) 1536#else 1537int 1538gfx_set_panel_present(int panelResX, int panelResY, unsigned short width, 1539 unsigned short height, unsigned short bpp) 1540#endif 1541{ 1542 /* SET VALID BPP */ 1543 /* 16BPP is the default. */ 1544 if (bpp != 8 && bpp != 15 && bpp != 16) 1545 bpp = 16; 1546 1547 /* RECORD PANEL PARAMETERS */ 1548 /* This routine does not touch any panel timings. It is used when custom 1549 * panel settings are set up in advance by the BIOS or an application, but 1550 * the application still requires access to other panel functionality 1551 * provided by Durango (i.e. panning) 1552 * */ 1553 1554 ModeWidth = width; 1555 ModeHeight = height; 1556 PanelWidth = (unsigned short) panelResX; 1557 PanelHeight = (unsigned short) panelResY; 1558 PanelEnable = 1; 1559 gbpp = bpp; 1560 1561 /* PROGRAM THE BPP IN THE DISPLAY CONTROLLER */ 1562 gfx_set_display_bpp(bpp); 1563 1564 return (GFX_STATUS_OK); 1565} 1566 1567/*-----------------------------------------------------------------------* 1568 * THE FOLLOWING READ ROUTINES ARE ALWAYS INCLUDED: * 1569 * gfx_get_hsync_end, gfx_get_htotal, gfx_get_vsync_end, gfx_get_vtotal * 1570 * are used by the video overlay routines. * 1571 * * 1572 * gfx_get_vline and gfx_vactive are used to prevent an issue for the * 1573 * SC1200. * 1574 * * 1575 * The others are part of the Durango API. * 1576 *-----------------------------------------------------------------------*/ 1577 1578/*--------------------------------------------------------------------------- 1579 * gfx_get_display_pitch 1580 * 1581 * This routine returns the current pitch of the frame buffer, in bytes. 1582 *--------------------------------------------------------------------------- 1583 */ 1584#if GFX_DISPLAY_DYNAMIC 1585unsigned short 1586gu1_get_display_pitch(void) 1587#else 1588unsigned short 1589gfx_get_display_pitch(void) 1590#endif 1591{ 1592 unsigned long value; 1593 1594 if (gfx_cpu_version == GFX_CPU_PYRAMID) { 1595 /* Pyramid update for 4KB line pitch */ 1596 value = (READ_REG32(DC_LINE_DELTA) & 0x07FF) << 2; 1597 } 1598 else { 1599 value = (READ_REG32(DC_LINE_DELTA) & 0x03FF) << 2; 1600 } 1601 1602 return ((unsigned short) value); 1603} 1604 1605/*---------------------------------------------------------------------------- 1606 * GFX_GET_DISPLAY_DETAILS 1607 * 1608 * This routine gets the specified display mode. 1609 * 1610 * Returns 1 if successful, 0 if mode could not be get. 1611 *---------------------------------------------------------------------------- 1612 */ 1613#if GFX_DISPLAY_DYNAMIC 1614int 1615gu1_get_display_details(unsigned int mode, int *xres, int *yres, int *hz) 1616#else 1617int 1618gfx_get_display_details(unsigned int mode, int *xres, int *yres, int *hz) 1619#endif 1620{ 1621 if (mode < NUM_GX_DISPLAY_MODES) { 1622 if (DisplayParams[mode].flags & GFX_MODE_56HZ) 1623 *hz = 56; 1624 else if (DisplayParams[mode].flags & GFX_MODE_60HZ) 1625 *hz = 60; 1626 else if (DisplayParams[mode].flags & GFX_MODE_70HZ) 1627 *hz = 70; 1628 else if (DisplayParams[mode].flags & GFX_MODE_72HZ) 1629 *hz = 72; 1630 else if (DisplayParams[mode].flags & GFX_MODE_75HZ) 1631 *hz = 75; 1632 else if (DisplayParams[mode].flags & GFX_MODE_85HZ) 1633 *hz = 85; 1634 1635 *xres = DisplayParams[mode].hactive; 1636 *yres = DisplayParams[mode].vactive; 1637 1638 return (1); 1639 } 1640 return (0); 1641} 1642 1643/*---------------------------------------------------------------------------- 1644 * GFX_GET_DISPLAY_MODE_COUNT 1645 * 1646 * Returns number of modes supported. 1647 *---------------------------------------------------------------------------- 1648 */ 1649#if GFX_DISPLAY_DYNAMIC 1650int 1651gu1_get_display_mode_count(void) 1652#else 1653int 1654gfx_get_display_mode_count(void) 1655#endif 1656{ 1657 return (NUM_GX_DISPLAY_MODES); 1658} 1659 1660/*---------------------------------------------------------------------------- 1661 * gfx_get_frame_buffer_line_size 1662 * 1663 * Returns the current frame buffer line size, in bytes 1664 *---------------------------------------------------------------------------- 1665 */ 1666#if GFX_DISPLAY_DYNAMIC 1667unsigned long 1668gu1_get_frame_buffer_line_size(void) 1669#else 1670unsigned long 1671gfx_get_frame_buffer_line_size(void) 1672#endif 1673{ 1674 return ((READ_REG32(DC_BUF_SIZE) & 0x1FF) << 3); 1675} 1676 1677/*---------------------------------------------------------------------------- 1678 * gfx_mode_frequency_supported 1679 * 1680 * This routine examines if the requested mode with pixel frequency is supported. 1681 * 1682 * Returns >0 if successful , <0 if freq. could not be found and matched. 1683 *---------------------------------------------------------------------------- 1684 */ 1685#if GFX_DISPLAY_DYNAMIC 1686int 1687gu1_mode_frequency_supported(int xres, int yres, int bpp, 1688 unsigned long frequency) 1689#else 1690int 1691gfx_mode_frequency_supported(int xres, int yres, int bpp, 1692 unsigned long frequency) 1693#endif 1694{ 1695 unsigned int index; 1696 unsigned long value; 1697 unsigned long bpp_flag = 0; 1698 1699 bpp_flag = GFX_MODE_8BPP; 1700 if (bpp > 8) 1701 bpp_flag = GFX_MODE_16BPP; 1702 1703 for (index = 0; index < NUM_GX_DISPLAY_MODES; index++) { 1704 if ((DisplayParams[index].hactive == (unsigned short) xres) && 1705 (DisplayParams[index].vactive == (unsigned short) yres) && 1706 (DisplayParams[index].flags & bpp_flag) && 1707 (DisplayParams[index].frequency == frequency)) { 1708 int hz = 0; 1709 1710 value = DisplayParams[index].flags; 1711 1712 if (value & GFX_MODE_56HZ) 1713 hz = 56; 1714 else if (value & GFX_MODE_60HZ) 1715 hz = 60; 1716 else if (value & GFX_MODE_70HZ) 1717 hz = 70; 1718 else if (value & GFX_MODE_72HZ) 1719 hz = 72; 1720 else if (value & GFX_MODE_75HZ) 1721 hz = 75; 1722 else if (value & GFX_MODE_85HZ) 1723 hz = 85; 1724 1725 return (hz); 1726 } 1727 } 1728 return (-1); 1729} 1730 1731/*---------------------------------------------------------------------------- 1732 * gfx_refreshrate_from_frequency 1733 * 1734 * This routine maps the frequency to close match refresh rate 1735 *---------------------------------------------------------------------------- 1736 */ 1737#if GFX_DISPLAY_DYNAMIC 1738int 1739gu1_get_refreshrate_from_frequency(int xres, int yres, int bpp, int *hz, 1740 unsigned long frequency) 1741#else 1742int 1743gfx_get_refreshrate_from_frequency(int xres, int yres, int bpp, int *hz, 1744 unsigned long frequency) 1745#endif 1746{ 1747 unsigned int index, closematch = 0; 1748 unsigned long value; 1749 unsigned long bpp_flag = 0; 1750 long min, diff; 1751 1752 *hz = 60; 1753 1754 bpp_flag = GFX_MODE_8BPP; 1755 if (bpp > 8) 1756 bpp_flag = GFX_MODE_16BPP; 1757 1758 /* FIND THE REGISTER VALUES FOR THE DESIRED FREQUENCY */ 1759 /* Search the table for the closest frequency (16.16 format). */ 1760 min = 0x7fffffff; 1761 for (index = 0; index < NUM_GX_DISPLAY_MODES; index++) { 1762 if ((DisplayParams[index].htotal == (unsigned short) xres) && 1763 (DisplayParams[index].vtotal == (unsigned short) yres) && 1764 (DisplayParams[index].flags & bpp_flag)) { 1765 diff = (long) frequency - (long) DisplayParams[index].frequency; 1766 if (diff < 0) 1767 diff = -diff; 1768 1769 if (diff < min) { 1770 min = diff; 1771 closematch = index; 1772 } 1773 } 1774 } 1775 1776 value = DisplayParams[closematch].flags; 1777 1778 if (value & GFX_MODE_56HZ) 1779 *hz = 56; 1780 else if (value & GFX_MODE_60HZ) 1781 *hz = 60; 1782 else if (value & GFX_MODE_70HZ) 1783 *hz = 70; 1784 else if (value & GFX_MODE_72HZ) 1785 *hz = 72; 1786 else if (value & GFX_MODE_75HZ) 1787 *hz = 75; 1788 else if (value & GFX_MODE_85HZ) 1789 *hz = 85; 1790 1791 return (1); 1792} 1793 1794/*---------------------------------------------------------------------------- 1795 * gfx_refreshrate_from_mode 1796 * 1797 * This routine is identical to the gfx_get_refreshrate_from_frequency, 1798 * except that the active timing values are compared instead of the total 1799 * values. Some modes (such as 70Hz and 72Hz) may be confused in this routine 1800 *---------------------------------------------------------------------------- 1801 */ 1802#if GFX_DISPLAY_DYNAMIC 1803int 1804gu1_get_refreshrate_from_mode(int xres, int yres, int bpp, int *hz, 1805 unsigned long frequency) 1806#else 1807int 1808gfx_get_refreshrate_from_mode(int xres, int yres, int bpp, int *hz, 1809 unsigned long frequency) 1810#endif 1811{ 1812 unsigned int index, closematch = 0; 1813 unsigned long value; 1814 unsigned long bpp_flag = 0; 1815 long min, diff; 1816 1817 *hz = 60; 1818 1819 bpp_flag = GFX_MODE_8BPP; 1820 if (bpp > 8) 1821 bpp_flag = GFX_MODE_16BPP; 1822 1823 /* FIND THE REGISTER VALUES FOR THE DESIRED FREQUENCY */ 1824 /* Search the table for the closest frequency (16.16 format). */ 1825 min = 0x7fffffff; 1826 for (index = 0; index < NUM_GX_DISPLAY_MODES; index++) { 1827 if ((DisplayParams[index].hactive == (unsigned short) xres) && 1828 (DisplayParams[index].vactive == (unsigned short) yres) && 1829 (DisplayParams[index].flags & bpp_flag)) { 1830 diff = (long) frequency - (long) DisplayParams[index].frequency; 1831 if (diff < 0) 1832 diff = -diff; 1833 1834 if (diff < min) { 1835 min = diff; 1836 closematch = index; 1837 } 1838 } 1839 } 1840 1841 value = DisplayParams[closematch].flags; 1842 1843 if (value & GFX_MODE_56HZ) 1844 *hz = 56; 1845 else if (value & GFX_MODE_60HZ) 1846 *hz = 60; 1847 else if (value & GFX_MODE_70HZ) 1848 *hz = 70; 1849 else if (value & GFX_MODE_72HZ) 1850 *hz = 72; 1851 else if (value & GFX_MODE_75HZ) 1852 *hz = 75; 1853 else if (value & GFX_MODE_85HZ) 1854 *hz = 85; 1855 1856 return (1); 1857} 1858 1859/*---------------------------------------------------------------------------- 1860 * gfx_get_frequency_from_refreshrate 1861 * 1862 * This routine maps the refresh rate to the closest matching PLL frequency. 1863 *---------------------------------------------------------------------------- 1864 */ 1865#if GFX_DISPLAY_DYNAMIC 1866int 1867gu1_get_frequency_from_refreshrate(int xres, int yres, int bpp, int hz, 1868 int *frequency) 1869#else 1870int 1871gfx_get_frequency_from_refreshrate(int xres, int yres, int bpp, int hz, 1872 int *frequency) 1873#endif 1874{ 1875 unsigned int index; 1876 int retval = -1; 1877 unsigned long hz_flag = 0; 1878 unsigned long bpp_flag = 0; 1879 1880 *frequency = 0; 1881 1882 if (hz == 56) 1883 hz_flag = GFX_MODE_56HZ; 1884 else if (hz == 60) 1885 hz_flag = GFX_MODE_60HZ; 1886 else if (hz == 70) 1887 hz_flag = GFX_MODE_70HZ; 1888 else if (hz == 72) 1889 hz_flag = GFX_MODE_72HZ; 1890 else if (hz == 75) 1891 hz_flag = GFX_MODE_75HZ; 1892 else if (hz == 85) 1893 hz_flag = GFX_MODE_85HZ; 1894 1895 bpp_flag = GFX_MODE_8BPP; 1896 if (bpp > 8) 1897 bpp_flag = GFX_MODE_16BPP; 1898 1899 /* FIND THE REGISTER VALUES FOR THE DESIRED FREQUENCY */ 1900 1901 for (index = 0; index < NUM_GX_DISPLAY_MODES; index++) { 1902 if ((DisplayParams[index].hactive == (unsigned short) xres) && 1903 (DisplayParams[index].vactive == (unsigned short) yres) && 1904 (DisplayParams[index].flags & bpp_flag) && 1905 (DisplayParams[index].flags & hz_flag)) { 1906 *frequency = DisplayParams[index].frequency; 1907 retval = 1; 1908 } 1909 } 1910 return retval; 1911} 1912 1913/*--------------------------------------------------------------------------- 1914 * gfx_get_max_supported_pixel_clock 1915 * 1916 * This routine returns the maximum recommended speed for the pixel clock. The 1917 * return value is an integer of the format xxxyyy, where xxx.yyy is the maximum 1918 * floating point pixel clock speed. 1919 *--------------------------------------------------------------------------- 1920 */ 1921#if GFX_DISPLAY_DYNAMIC 1922unsigned long 1923gu1_get_max_supported_pixel_clock(void) 1924#else 1925unsigned long 1926gfx_get_max_supported_pixel_clock(void) 1927#endif 1928{ 1929 /* ALL CHIPS CAN HANDLE 1280X1024@85HZ - 157.5 MHz */ 1930 return 157500; 1931} 1932 1933/*---------------------------------------------------------------------------- 1934 * gfx_get_display_mode 1935 * 1936 * This routine gets the specified display mode. 1937 * 1938 * Returns: >0 if successful and mode returned, <0 if mode could not be found. 1939 *---------------------------------------------------------------------------- 1940 */ 1941#if GFX_DISPLAY_DYNAMIC 1942int 1943gu1_get_display_mode(int *xres, int *yres, int *bpp, int *hz) 1944#else 1945int 1946gfx_get_display_mode(int *xres, int *yres, int *bpp, int *hz) 1947#endif 1948{ 1949 unsigned int mode = 0; 1950 unsigned long pll_freq = 0, bpp_flag = 0; 1951 1952 *xres = gfx_get_hactive(); 1953 *yres = gfx_get_vactive(); 1954 *bpp = gfx_get_display_bpp(); 1955 pll_freq = gfx_get_clock_frequency(); 1956 1957 /* SUPPORT EMULATED VGA MODES */ 1958 if (gfx_pixel_double) 1959 *xres >>= 1; 1960 1961 if (gfx_line_double) 1962 *yres >>= 1; 1963 1964 /* SET BPP FLAGS TO LIMIT MODE SELECTION */ 1965 bpp_flag = GFX_MODE_8BPP; 1966 if (*bpp > 8) 1967 bpp_flag = GFX_MODE_16BPP; 1968 1969 for (mode = 0; mode < NUM_GX_DISPLAY_MODES; mode++) { 1970 if ((DisplayParams[mode].hactive == (unsigned short) *xres) && 1971 (DisplayParams[mode].vactive == (unsigned short) *yres) && 1972 (DisplayParams[mode].frequency == pll_freq) && 1973 (DisplayParams[mode].flags & bpp_flag)) { 1974 1975 pll_freq = DisplayParams[mode].flags; 1976 1977 if (pll_freq & GFX_MODE_56HZ) 1978 *hz = 56; 1979 else if (pll_freq & GFX_MODE_60HZ) 1980 *hz = 60; 1981 else if (pll_freq & GFX_MODE_70HZ) 1982 *hz = 70; 1983 else if (pll_freq & GFX_MODE_72HZ) 1984 *hz = 72; 1985 else if (pll_freq & GFX_MODE_75HZ) 1986 *hz = 75; 1987 else if (pll_freq & GFX_MODE_85HZ) 1988 *hz = 85; 1989 1990 return (1); 1991 } 1992 } 1993 return (-1); 1994} 1995 1996/*--------------------------------------------------------------------------- 1997 * gfx_get_hactive 1998 *--------------------------------------------------------------------------- 1999 */ 2000#if GFX_DISPLAY_DYNAMIC 2001unsigned short 2002gu1_get_hactive(void) 2003#else 2004unsigned short 2005gfx_get_hactive(void) 2006#endif 2007{ 2008 return ((unsigned short) ((READ_REG32(DC_H_TIMING_1) & 0x07F8) + 8)); 2009} 2010 2011/*--------------------------------------------------------------------------- 2012 * gfx_get_hsync_start 2013 *--------------------------------------------------------------------------- 2014 */ 2015#if GFX_DISPLAY_DYNAMIC 2016unsigned short 2017gu1_get_hsync_start(void) 2018#else 2019unsigned short 2020gfx_get_hsync_start(void) 2021#endif 2022{ 2023 return ((unsigned short) ((READ_REG32(DC_H_TIMING_3) & 0x07F8) + 8)); 2024} 2025 2026/*--------------------------------------------------------------------------- 2027 * gfx_get_hsync_end 2028 *--------------------------------------------------------------------------- 2029 */ 2030#if GFX_DISPLAY_DYNAMIC 2031unsigned short 2032gu1_get_hsync_end(void) 2033#else 2034unsigned short 2035gfx_get_hsync_end(void) 2036#endif 2037{ 2038 return ((unsigned short) (((READ_REG32(DC_H_TIMING_3) >> 16) & 0x07F8) + 2039 8)); 2040} 2041 2042/*--------------------------------------------------------------------------- 2043 * gfx_get_htotal 2044 *--------------------------------------------------------------------------- 2045 */ 2046#if GFX_DISPLAY_DYNAMIC 2047unsigned short 2048gu1_get_htotal(void) 2049#else 2050unsigned short 2051gfx_get_htotal(void) 2052#endif 2053{ 2054 return ((unsigned short) (((READ_REG32(DC_H_TIMING_1) >> 16) & 0x07F8) + 2055 8)); 2056} 2057 2058/*--------------------------------------------------------------------------- 2059 * gfx_get_vactive 2060 *--------------------------------------------------------------------------- 2061 */ 2062#if GFX_DISPLAY_DYNAMIC 2063unsigned short 2064gu1_get_vactive(void) 2065#else 2066unsigned short 2067gfx_get_vactive(void) 2068#endif 2069{ 2070 return ((unsigned short) ((READ_REG32(DC_V_TIMING_1) & 0x07FF) + 1)); 2071} 2072 2073/*--------------------------------------------------------------------------- 2074 * gfx_get_vsync_end 2075 *--------------------------------------------------------------------------- 2076 */ 2077#if GFX_DISPLAY_DYNAMIC 2078unsigned short 2079gu1_get_vsync_end(void) 2080#else 2081unsigned short 2082gfx_get_vsync_end(void) 2083#endif 2084{ 2085 return ((unsigned short) (((READ_REG32(DC_V_TIMING_3) >> 16) & 0x07FF) + 2086 1)); 2087} 2088 2089/*--------------------------------------------------------------------------- 2090 * gfx_get_vtotal 2091 *--------------------------------------------------------------------------- 2092 */ 2093#if GFX_DISPLAY_DYNAMIC 2094unsigned short 2095gu1_get_vtotal(void) 2096#else 2097unsigned short 2098gfx_get_vtotal(void) 2099#endif 2100{ 2101 return ((unsigned short) (((READ_REG32(DC_V_TIMING_1) >> 16) & 0x07FF) + 2102 1)); 2103} 2104 2105/*----------------------------------------------------------------------------- 2106 * gfx_get_display_bpp 2107 * 2108 * This routine returns the current color depth of the active display. 2109 *----------------------------------------------------------------------------- 2110 */ 2111#if GFX_DISPLAY_DYNAMIC 2112unsigned short 2113gu1_get_display_bpp(void) 2114#else 2115unsigned short 2116gfx_get_display_bpp(void) 2117#endif 2118{ 2119 switch (READ_REG32(DC_OUTPUT_CFG) & 3) { 2120 case 0: 2121 return (16); 2122 case 2: 2123 return (15); 2124 } 2125 return (8); 2126} 2127 2128/*--------------------------------------------------------------------------- 2129 * gfx_get_vline 2130 *--------------------------------------------------------------------------- 2131 */ 2132#if GFX_DISPLAY_DYNAMIC 2133unsigned short 2134gu1_get_vline(void) 2135#else 2136unsigned short 2137gfx_get_vline(void) 2138#endif 2139{ 2140 unsigned short current_scan_line; 2141 2142 /* Read similar value twice to ensure that the value is not transitioning */ 2143 do { 2144 current_scan_line = (unsigned short) READ_REG32(DC_V_LINE_CNT) & 0x07FF; 2145 } while (current_scan_line != 2146 (unsigned short) (READ_REG32(DC_V_LINE_CNT) & 0x07FF)); 2147 2148 return (current_scan_line); 2149} 2150 2151/*----------------------------------------------------------------------------- 2152 * gfx_get_display_offset 2153 *----------------------------------------------------------------------------- 2154 */ 2155#if GFX_DISPLAY_DYNAMIC 2156unsigned long 2157gu1_get_display_offset(void) 2158#else 2159unsigned long 2160gfx_get_display_offset(void) 2161#endif 2162{ 2163 return (READ_REG32(DC_FB_ST_OFFSET) & 0x003FFFFF); 2164} 2165 2166/*----------------------------------------------------------------------------- 2167 * gfx_get_cursor_offset 2168 *----------------------------------------------------------------------------- 2169 */ 2170#if GFX_DISPLAY_DYNAMIC 2171unsigned long 2172gu1_get_cursor_offset(void) 2173#else 2174unsigned long 2175gfx_get_cursor_offset(void) 2176#endif 2177{ 2178 return (READ_REG32(DC_CURS_ST_OFFSET) & 0x003FFFFF); 2179} 2180 2181#if GFX_READ_ROUTINES 2182 2183/*************************************************************/ 2184/* READ ROUTINES | INCLUDED FOR DIAGNOSTIC PURPOSES ONLY */ 2185/*************************************************************/ 2186 2187/*--------------------------------------------------------------------------- 2188 * gfx_get_hblank_start 2189 *--------------------------------------------------------------------------- 2190 */ 2191#if GFX_DISPLAY_DYNAMIC 2192unsigned short 2193gu1_get_hblank_start(void) 2194#else 2195unsigned short 2196gfx_get_hblank_start(void) 2197#endif 2198{ 2199 return ((unsigned short) ((READ_REG32(DC_H_TIMING_2) & 0x07F8) + 8)); 2200} 2201 2202/*--------------------------------------------------------------------------- 2203 * gfx_get_hblank_end 2204 *--------------------------------------------------------------------------- 2205 */ 2206#if GFX_DISPLAY_DYNAMIC 2207unsigned short 2208gu1_get_hblank_end(void) 2209#else 2210unsigned short 2211gfx_get_hblank_end(void) 2212#endif 2213{ 2214 return ((unsigned short) (((READ_REG32(DC_H_TIMING_2) >> 16) & 0x07F8) + 2215 8)); 2216} 2217 2218/*--------------------------------------------------------------------------- 2219 * gfx_get_vblank_start 2220 *--------------------------------------------------------------------------- 2221 */ 2222#if GFX_DISPLAY_DYNAMIC 2223unsigned short 2224gu1_get_vblank_start(void) 2225#else 2226unsigned short 2227gfx_get_vblank_start(void) 2228#endif 2229{ 2230 return ((unsigned short) ((READ_REG32(DC_V_TIMING_2) & 0x07FF) + 1)); 2231} 2232 2233/*--------------------------------------------------------------------------- 2234 * gfx_get_vsync_start 2235 *--------------------------------------------------------------------------- 2236 */ 2237#if GFX_DISPLAY_DYNAMIC 2238unsigned short 2239gu1_get_vsync_start(void) 2240#else 2241unsigned short 2242gfx_get_vsync_start(void) 2243#endif 2244{ 2245 return ((unsigned short) ((READ_REG32(DC_V_TIMING_3) & 0x07FF) + 1)); 2246} 2247 2248/*--------------------------------------------------------------------------- 2249 * gfx_get_vblank_end 2250 *--------------------------------------------------------------------------- 2251 */ 2252#if GFX_DISPLAY_DYNAMIC 2253unsigned short 2254gu1_get_vblank_end(void) 2255#else 2256unsigned short 2257gfx_get_vblank_end(void) 2258#endif 2259{ 2260 return ((unsigned short) (((READ_REG32(DC_V_TIMING_2) >> 16) & 0x07FF) + 2261 1)); 2262} 2263 2264/*----------------------------------------------------------------------------- 2265 * gfx_get_display_palette_entry 2266 *----------------------------------------------------------------------------- 2267 */ 2268#if GFX_DISPLAY_DYNAMIC 2269int 2270gu1_get_display_palette_entry(unsigned long index, unsigned long *palette) 2271#else 2272int 2273gfx_get_display_palette_entry(unsigned long index, unsigned long *palette) 2274#endif 2275{ 2276 unsigned long data; 2277 2278 if (index > 0xFF) 2279 return GFX_STATUS_BAD_PARAMETER; 2280 2281 WRITE_REG32(DC_PAL_ADDRESS, index); 2282 data = READ_REG32(DC_PAL_DATA); 2283 data = ((data << 2) & 0x000000FC) | 2284 ((data << 4) & 0x0000FC00) | ((data << 6) & 0x00FC0000); 2285 2286 *palette = data; 2287 return 0; 2288} 2289 2290/*----------------------------------------------------------------------------- 2291 * gfx_get_display_palette 2292 *----------------------------------------------------------------------------- 2293 */ 2294#if GFX_DISPLAY_DYNAMIC 2295void 2296gu1_get_display_palette(unsigned long *palette) 2297#else 2298void 2299gfx_get_display_palette(unsigned long *palette) 2300#endif 2301{ 2302 unsigned long i, data; 2303 2304 WRITE_REG32(DC_PAL_ADDRESS, 0); 2305 for (i = 0; i < 256; i++) { 2306 data = READ_REG32(DC_PAL_DATA); 2307 data = ((data << 2) & 0x000000FC) | 2308 ((data << 4) & 0x0000FC00) | ((data << 6) & 0x00FC0000); 2309 palette[i] = data; 2310 } 2311} 2312 2313/*----------------------------------------------------------------------------- 2314 * gfx_get_cursor_enable 2315 *----------------------------------------------------------------------------- 2316 */ 2317#if GFX_DISPLAY_DYNAMIC 2318unsigned long 2319gu1_get_cursor_enable(void) 2320#else 2321unsigned long 2322gfx_get_cursor_enable(void) 2323#endif 2324{ 2325 return (READ_REG32(DC_GENERAL_CFG) & DC_GCFG_CURE); 2326} 2327 2328/*----------------------------------------------------------------------------- 2329 * gfx_get_cursor_position 2330 *----------------------------------------------------------------------------- 2331 */ 2332#if GFX_DISPLAY_DYNAMIC 2333unsigned long 2334gu1_get_cursor_position(void) 2335#else 2336unsigned long 2337gfx_get_cursor_position(void) 2338#endif 2339{ 2340 return ((READ_REG32(DC_CURSOR_X) & 0x07FF) | 2341 ((READ_REG32(DC_CURSOR_Y) << 16) & 0x03FF0000)); 2342} 2343 2344/*----------------------------------------------------------------------------- 2345 * gfx_get_cursor_clip 2346 *----------------------------------------------------------------------------- 2347 */ 2348#if GFX_DISPLAY_DYNAMIC 2349unsigned long 2350gu1_get_cursor_clip(void) 2351#else 2352unsigned long 2353gfx_get_cursor_clip(void) 2354#endif 2355{ 2356 return (((READ_REG32(DC_CURSOR_X) >> 11) & 0x01F) | 2357 ((READ_REG32(DC_CURSOR_Y) << 5) & 0x1F0000)); 2358} 2359 2360/*----------------------------------------------------------------------------- 2361 * gfx_get_cursor_color 2362 *----------------------------------------------------------------------------- 2363 */ 2364#if GFX_DISPLAY_DYNAMIC 2365unsigned long 2366gu1_get_cursor_color(int color) 2367#else 2368unsigned long 2369gfx_get_cursor_color(int color) 2370#endif 2371{ 2372 unsigned long data; 2373 2374 if (color) { 2375 WRITE_REG32(DC_PAL_ADDRESS, 0x101); 2376 } 2377 else { 2378 WRITE_REG32(DC_PAL_ADDRESS, 0x100); 2379 } 2380 data = READ_REG32(DC_PAL_DATA); 2381 data = ((data << 6) & 0x00FC0000) | 2382 ((data << 4) & 0x0000FC00) | ((data << 2) & 0x000000FC); 2383 return (data); 2384} 2385 2386/*----------------------------------------------------------------------------- 2387 * gfx_get_compression_enable 2388 *----------------------------------------------------------------------------- 2389 */ 2390#if GFX_DISPLAY_DYNAMIC 2391int 2392gu1_get_compression_enable(void) 2393#else 2394int 2395gfx_get_compression_enable(void) 2396#endif 2397{ 2398 unsigned long gcfg; 2399 2400 gcfg = READ_REG32(DC_GENERAL_CFG); 2401 if (gcfg & DC_GCFG_CMPE) 2402 return (1); 2403 else 2404 return (0); 2405} 2406 2407/*----------------------------------------------------------------------------- 2408 * gfx_get_compression_offset 2409 *----------------------------------------------------------------------------- 2410 */ 2411#if GFX_DISPLAY_DYNAMIC 2412unsigned long 2413gu1_get_compression_offset(void) 2414#else 2415unsigned long 2416gfx_get_compression_offset(void) 2417#endif 2418{ 2419 unsigned long offset; 2420 2421 offset = READ_REG32(DC_CB_ST_OFFSET) & 0x003FFFFF; 2422 return (offset); 2423} 2424 2425/*----------------------------------------------------------------------------- 2426 * gfx_get_compression_pitch 2427 *----------------------------------------------------------------------------- 2428 */ 2429#if GFX_DISPLAY_DYNAMIC 2430unsigned short 2431gu1_get_compression_pitch(void) 2432#else 2433unsigned short 2434gfx_get_compression_pitch(void) 2435#endif 2436{ 2437 unsigned short pitch; 2438 2439 pitch = (unsigned short) (READ_REG32(DC_LINE_DELTA) >> 12) & 0x03FF; 2440 return (pitch << 2); 2441} 2442 2443/*----------------------------------------------------------------------------- 2444 * gfx_get_compression_size 2445 *----------------------------------------------------------------------------- 2446 */ 2447#if GFX_DISPLAY_DYNAMIC 2448unsigned short 2449gu1_get_compression_size(void) 2450#else 2451unsigned short 2452gfx_get_compression_size(void) 2453#endif 2454{ 2455 unsigned short size; 2456 2457 size = (unsigned short) ((READ_REG32(DC_BUF_SIZE) >> 9) & 0x7F) - 1; 2458 return ((size << 2) + 16); 2459} 2460 2461/*----------------------------------------------------------------------------- 2462 * gfx_get_valid_bit 2463 *----------------------------------------------------------------------------- 2464 */ 2465#if GFX_DISPLAY_DYNAMIC 2466int 2467gu1_get_valid_bit(int line) 2468#else 2469int 2470gfx_get_valid_bit(int line) 2471#endif 2472{ 2473 int valid; 2474 2475 WRITE_REG32(MC_DR_ADD, line); 2476 valid = (int) READ_REG32(MC_DR_ACC) & 1; 2477 return (valid); 2478} 2479 2480/*--------------------------------------------------------------------------- 2481 * gfx_get_display_video_offset (PRIVATE ROUTINE - NOT PART OF API) 2482 * 2483 * This routine is called by "gfx_get_video_offset". It abstracts the 2484 * version of the display controller from the video overlay routines. 2485 *--------------------------------------------------------------------------- 2486 */ 2487#if GFX_DISPLAY_DYNAMIC 2488unsigned long 2489gu1_get_display_video_offset(void) 2490#else 2491unsigned long 2492gfx_get_display_video_offset(void) 2493#endif 2494{ 2495 return (READ_REG32(DC_VID_ST_OFFSET) & 0x003FFFFF); 2496} 2497 2498/*--------------------------------------------------------------------------- 2499 * gfx_get_display_video_size (PRIVATE ROUTINE - NOT PART OF API) 2500 * 2501 * This routine is called by "gfx_get_video_size". It abstracts the 2502 * version of the display controller from the video overlay routines. 2503 *--------------------------------------------------------------------------- 2504 */ 2505#if GFX_DISPLAY_DYNAMIC 2506unsigned long 2507gu1_get_display_video_size(void) 2508#else 2509unsigned long 2510gfx_get_display_video_size(void) 2511#endif 2512{ 2513 /* RETURN TOTAL SIZE, IN BYTES */ 2514 return ((READ_REG32(DC_BUF_SIZE) >> 10) & 0x000FFFC0); 2515} 2516 2517/*----------------------------------------------------------------------------- 2518 * gfx_get_display_priority_high 2519 *----------------------------------------------------------------------------- 2520 */ 2521#if GFX_DISPLAY_DYNAMIC 2522int 2523gu1_get_display_priority_high(void) 2524#else 2525int 2526gfx_get_display_priority_high(void) 2527#endif 2528{ 2529 if (READ_REG32(MC_MEM_CNTRL1) & MC_XBUSARB) 2530 return (1); 2531 else 2532 return (0); 2533} 2534 2535#endif /* GFX_READ_ROUTINES */ 2536 2537/* END OF FILE */ 2538