disp_gu1.c revision f29dbc25
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 } else { 367 if (gfx_cpu_version == GFX_CPU_PYRAMID) 368 pitch = (size <= 2048) ? 2048 : 4096; 369 else 370 pitch = 2048; 371 } 372 373 WRITE_REG32(DC_LINE_DELTA, pitch >> 2); 374 375 if (PanelEnable) { 376 size = pMode->hactive; 377 if (bpp > 8) 378 size <<= 1; 379 } 380 381 /* ADD 2 TO SIZE FOR POSSIBLE START ADDRESS ALIGNMENTS */ 382 WRITE_REG32(DC_BUF_SIZE, (size >> 3) + 2); 383 384 /* ALWAYS ENABLE "PANEL" DATA FROM MEDIAGX */ 385 /* That is really just the 18 BPP data bus to the companion chip */ 386 ocfg = DC_OCFG_PCKE | DC_OCFG_PDEL | DC_OCFG_PDEH; 387 388 /* SET PIXEL FORMAT */ 389 if (bpp == 8) 390 ocfg |= DC_OCFG_8BPP; 391 else if (bpp == 15) 392 ocfg |= DC_OCFG_555; 393 394 /* ENABLE TIMING GENERATOR, SYNCS, AND FP DATA */ 395 tcfg = DC_TCFG_FPPE | DC_TCFG_HSYE | DC_TCFG_VSYE | DC_TCFG_BLKE | 396 DC_TCFG_TGEN; 397 398 /* SET FIFO PRIORITY, DCLK MULTIPLIER, AND FIFO ENABLE */ 399 /* Default 6/5 for FIFO, 2x for DCLK multiplier. */ 400 gcfg = 401 (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], 617 bpp) == GFX_STATUS_OK) 618 return (1); 619 } 620 return (0); 621} 622 623/*---------------------------------------------------------------------------- 624 * GFX_SET_DISPLAY_TIMINGS 625 * 626 * This routine sets the display controller mode using the specified timing 627 * values (as opposed to using the tables internal to Durango). 628 * 629 * Returns GFX_STATUS_OK on success, GFX_STATUS_ERROR otherwise. 630 *---------------------------------------------------------------------------- 631 */ 632#if GFX_DISPLAY_DYNAMIC 633int 634gu1_set_display_timings(unsigned short bpp, unsigned short flags, 635 unsigned short hactive, unsigned short hblankstart, 636 unsigned short hsyncstart, unsigned short hsyncend, 637 unsigned short hblankend, unsigned short htotal, 638 unsigned short vactive, unsigned short vblankstart, 639 unsigned short vsyncstart, unsigned short vsyncend, 640 unsigned short vblankend, unsigned short vtotal, 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, unsigned long frequency) 650#endif 651{ 652 /* SET MODE STRUCTURE WITH SPECIFIED VALUES */ 653 654 gfx_display_mode.flags = 0; 655 if (flags & 1) 656 gfx_display_mode.flags |= GFX_MODE_NEG_HSYNC; 657 if (flags & 2) 658 gfx_display_mode.flags |= GFX_MODE_NEG_VSYNC; 659 if (flags & 0x1000) 660 gfx_display_mode.flags |= GFX_MODE_LOCK_TIMING; 661 gfx_display_mode.hactive = hactive; 662 gfx_display_mode.hblankstart = hblankstart; 663 gfx_display_mode.hsyncstart = hsyncstart; 664 gfx_display_mode.hsyncend = hsyncend; 665 gfx_display_mode.hblankend = hblankend; 666 gfx_display_mode.htotal = htotal; 667 gfx_display_mode.vactive = vactive; 668 gfx_display_mode.vblankstart = vblankstart; 669 gfx_display_mode.vsyncstart = vsyncstart; 670 gfx_display_mode.vsyncend = vsyncend; 671 gfx_display_mode.vblankend = vblankend; 672 gfx_display_mode.vtotal = vtotal; 673 gfx_display_mode.frequency = frequency; 674 675 /* CALL ROUTINE TO SET MODE */ 676 return (gu1_set_specified_mode(&gfx_display_mode, bpp)); 677} 678 679/*---------------------------------------------------------------------------- 680 * GFX_SET_VTOTAL 681 * 682 * This routine sets the display controller vertical total to 683 * "vtotal". As a side effect it also sets vertical blank end. 684 * It should be used when only this value needs to be changed, 685 * due to speed considerations. 686 * 687 * Note: it is the caller's responsibility to make sure that 688 * a legal vtotal is used, i.e. that "vtotal" is greater than or 689 * equal to vsync end. 690 * 691 * Always returns 0. 692 *---------------------------------------------------------------------------- 693 */ 694#if GFX_DISPLAY_DYNAMIC 695int 696gu1_set_vtotal(unsigned short vtotal) 697#else 698int 699gfx_set_vtotal(unsigned short vtotal) 700#endif 701{ 702 unsigned long unlock, tcfg, timing1, timing2; 703 704 /* UNLOCK THE DISPLAY CONTROLLER REGISTERS */ 705 unlock = READ_REG32(DC_UNLOCK); 706 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 707 708 /* READ THE CURRENT GX VALUES */ 709 tcfg = READ_REG32(DC_TIMING_CFG); 710 timing1 = READ_REG32(DC_V_TIMING_1); 711 timing2 = READ_REG32(DC_V_TIMING_2); 712 713 /* DISABLE THE TIMING GENERATOR */ 714 WRITE_REG32(DC_TIMING_CFG, tcfg & ~(unsigned long)DC_TCFG_TGEN); 715 716 /* WRITE NEW TIMING VALUES */ 717 WRITE_REG32(DC_V_TIMING_1, 718 (timing1 & 0xffff) | (unsigned long)(vtotal - 1) << 16); 719 WRITE_REG32(DC_V_TIMING_2, 720 (timing2 & 0xffff) | (unsigned long)(vtotal - 1) << 16); 721 722 /* RESTORE GX VALUES */ 723 WRITE_REG32(DC_TIMING_CFG, tcfg); 724 WRITE_REG32(DC_UNLOCK, unlock); 725 726 return (0); 727} 728 729/*--------------------------------------------------------------------------- 730 * gfx_set_display_pitch 731 * 732 * This routine sets the pitch of the frame buffer to the specified value. 733 *--------------------------------------------------------------------------- 734 */ 735#if GFX_DISPLAY_DYNAMIC 736void 737gu1_set_display_pitch(unsigned short pitch) 738#else 739void 740gfx_set_display_pitch(unsigned short pitch) 741#endif 742{ 743 unsigned long value = 0; 744 unsigned long lock = READ_REG32(DC_UNLOCK); 745 746 value = READ_REG32(DC_LINE_DELTA) & 0xFFFFF000; 747 value |= (pitch >> 2); 748 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 749 WRITE_REG32(DC_LINE_DELTA, value); 750 WRITE_REG32(DC_UNLOCK, lock); 751 752 /* ALSO UPDATE PITCH IN GRAPHICS ENGINE */ 753 /* Pyramid alone supports 4K line pitch */ 754 value = (unsigned long)READ_REG16(GP_BLIT_STATUS); 755 value &= ~(BC_FB_WIDTH_2048 | BC_FB_WIDTH_4096); 756 757 if ((gfx_cpu_version == GFX_CPU_PYRAMID) && (pitch > 2048)) 758 value |= BC_FB_WIDTH_4096; 759 760 else if (pitch > 1024) 761 value |= BC_FB_WIDTH_2048; 762 763 WRITE_REG16(GP_BLIT_STATUS, (unsigned short)value); 764 return; 765} 766 767/*--------------------------------------------------------------------------- 768 * gfx_set_display_offset 769 * 770 * This routine sets the start address of the frame buffer. It is 771 * typically used to pan across a virtual desktop (frame buffer larger than 772 * the displayed screen) or to flip the display between multiple buffers. 773 *--------------------------------------------------------------------------- 774 */ 775#if GFX_DISPLAY_DYNAMIC 776void 777gu1_set_display_offset(unsigned long offset) 778#else 779void 780gfx_set_display_offset(unsigned long offset) 781#endif 782{ 783 /* UPDATE FRAME BUFFER OFFSET */ 784 785 unsigned long lock; 786 787 lock = READ_REG32(DC_UNLOCK); 788 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 789 790 /* START ADDRESS EFFECTS DISPLAY COMPRESSION */ 791 /* Disable compression for non-zero start addresss values. */ 792 /* Enable compression if offset is zero and comression is intended to */ 793 /* be enabled from a previous call to "gfx_set_compression_enable". */ 794 /* Compression should be disabled BEFORE the offset is changed */ 795 /* and enabled AFTER the offset is changed. */ 796 if (offset == 0) { 797 WRITE_REG32(DC_FB_ST_OFFSET, offset); 798 if (gfx_compression_enabled) { 799 /* WAIT FOR THE OFFSET TO BE LATCHED */ 800 gfx_wait_vertical_blank(); 801 gu1_enable_compression(); 802 } 803 } else { 804 /* ONLY DISABLE COMPRESSION ONCE */ 805 if (gfx_compression_active) 806 gu1_disable_compression(); 807 808 WRITE_REG32(DC_FB_ST_OFFSET, offset); 809 } 810 811 WRITE_REG32(DC_UNLOCK, lock); 812} 813 814/*--------------------------------------------------------------------------- 815 * gfx_set_display_palette_entry 816 * 817 * This routine sets an palette entry in the display controller. 818 * A 32-bit X:R:G:B value. 819 *--------------------------------------------------------------------------- 820 */ 821#if GFX_DISPLAY_DYNAMIC 822int 823gu1_set_display_palette_entry(unsigned long index, unsigned long palette) 824#else 825int 826gfx_set_display_palette_entry(unsigned long index, unsigned long palette) 827#endif 828{ 829 unsigned long data; 830 831 if (index > 0xFF) 832 return GFX_STATUS_BAD_PARAMETER; 833 834 WRITE_REG32(DC_PAL_ADDRESS, index); 835 data = ((palette >> 2) & 0x0003F) | 836 ((palette >> 4) & 0x00FC0) | ((palette >> 6) & 0x3F000); 837 WRITE_REG32(DC_PAL_DATA, data); 838 839 return (0); 840} 841 842/*--------------------------------------------------------------------------- 843 * gfx_set_display_palette 844 * 845 * This routine sets the entire palette in the display controller. 846 * A pointer is provided to a 256 entry table of 32-bit X:R:G:B values. 847 * 848 * Restriction: 849 * Due to SC1200 Issue #748 (in Notes DB) this function should be called only 850 * when DCLK is active, i.e PLL is already powered up and genlock is not 851 * active. 852 *--------------------------------------------------------------------------- 853 */ 854#if GFX_DISPLAY_DYNAMIC 855int 856gu1_set_display_palette(unsigned long *palette) 857#else 858int 859gfx_set_display_palette(unsigned long *palette) 860#endif 861{ 862 unsigned long data, i; 863 864 WRITE_REG32(DC_PAL_ADDRESS, 0); 865 if (palette) { 866 for (i = 0; i < 256; i++) { 867 /* CONVERT 24 BPP COLOR DATA TO 18 BPP COLOR DATA */ 868 data = ((palette[i] >> 2) & 0x0003F) | 869 ((palette[i] >> 4) & 0x00FC0) | ((palette[i] >> 6) & 0x3F000); 870 WRITE_REG32(DC_PAL_DATA, data); 871 } 872 } 873 return (0); 874} 875 876/*--------------------------------------------------------------------------- 877 * gfx_set_cursor_enable 878 * 879 * This routine enables or disables the hardware cursor. 880 * 881 * WARNING: The cusrsor start offset must be set by setting the cursor 882 * position before calling this routine to assure that memory reads do not 883 * go past the end of graphics memory (this can hang GXm). 884 *--------------------------------------------------------------------------- 885 */ 886#if GFX_DISPLAY_DYNAMIC 887void 888gu1_set_cursor_enable(int enable) 889#else 890void 891gfx_set_cursor_enable(int enable) 892#endif 893{ 894 unsigned long unlock, gcfg; 895 896 /* SET OR CLEAR CURSOR ENABLE BIT */ 897 unlock = READ_REG32(DC_UNLOCK); 898 gcfg = READ_REG32(DC_GENERAL_CFG); 899 if (enable) 900 gcfg |= DC_GCFG_CURE; 901 else 902 gcfg &= ~(DC_GCFG_CURE); 903 904 /* WRITE NEW REGISTER VALUE */ 905 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 906 WRITE_REG32(DC_GENERAL_CFG, gcfg); 907 WRITE_REG32(DC_UNLOCK, unlock); 908} 909 910/*--------------------------------------------------------------------------- 911 * gfx_set_cursor_colors 912 * 913 * This routine sets the colors of the hardware cursor. 914 * 915 * Restriction: 916 * Due to SC1200 Issue #748 (in Notes DB) this function should be called only 917 * when DCLK is active, i.e PLL is already powered up. 918 *--------------------------------------------------------------------------- 919 */ 920#if GFX_DISPLAY_DYNAMIC 921void 922gu1_set_cursor_colors(unsigned long bkcolor, unsigned long fgcolor) 923#else 924void 925gfx_set_cursor_colors(unsigned long bkcolor, unsigned long fgcolor) 926#endif 927{ 928 unsigned long value; 929 930 /* If genlock is enabled DCLK might be disabled in vertical blank. */ 931 /* Due to SC1200 Issue #748 in Notes DB this would fail the cursor color settings */ 932 /* So Wait for vertical blank to end */ 933 934#if GFX_VIDEO_SC1200 935 if (gfx_test_timing_active()) 936 while ((gfx_get_vline()) > gfx_get_vactive()) ; 937#endif 938 /* SET CURSOR COLORS */ 939 WRITE_REG32(DC_PAL_ADDRESS, 0x100); 940 value = ((bkcolor & 0x000000FC) >> 2) | 941 ((bkcolor & 0x0000FC00) >> (2 + 8 - 6)) | 942 ((bkcolor & 0x00FC0000) >> (2 + 16 - 12)); 943 WRITE_REG32(DC_PAL_DATA, value); 944 value = ((fgcolor & 0x000000FC) >> 2) | 945 ((fgcolor & 0x0000FC00) >> (2 + 8 - 6)) | 946 ((fgcolor & 0x00FC0000) >> (2 + 16 - 12)); 947 WRITE_REG32(DC_PAL_DATA, value); 948} 949 950/*--------------------------------------------------------------------------- 951 * gfx_set_cursor_position 952 * 953 * This routine sets the position of the hardware cusror. The starting 954 * offset of the cursor buffer must be specified so that the routine can 955 * properly clip scanlines if the cursor is off the top of the screen. 956 *--------------------------------------------------------------------------- 957 */ 958#if GFX_DISPLAY_DYNAMIC 959void 960gu1_set_cursor_position(unsigned long memoffset, 961 unsigned short xpos, unsigned short ypos, 962 unsigned short xhotspot, unsigned short yhotspot) 963#else 964void 965gfx_set_cursor_position(unsigned long memoffset, 966 unsigned short xpos, unsigned short ypos, 967 unsigned short xhotspot, unsigned short yhotspot) 968#endif 969{ 970 unsigned long unlock; 971 972 short x, y; 973 short xoffset = 0; 974 short yoffset = 0; 975 976 /* SUPPORT CURSOR IN EMULATED VGA MODES */ 977 /* Timings are for twice the resolution */ 978 if (gfx_pixel_double) 979 xpos <<= 1; 980 981 if (gfx_line_double) 982 ypos <<= 1; 983 984 x = (short)xpos - (short)xhotspot; 985 y = (short)ypos - (short)yhotspot; 986 if (x < -31) 987 return; 988 989 if (y < -31) 990 return; 991 992 if (x < 0) { 993 xoffset = -x; 994 x = 0; 995 } 996 997 if (y < 0) { 998 yoffset = -y; 999 y = 0; 1000 } 1001 1002 memoffset += (unsigned long)yoffset << 3; 1003 1004 if (PanelEnable) { 1005 if ((ModeWidth > PanelWidth) || (ModeHeight > PanelHeight)) { 1006 gfx_enable_panning(xpos, ypos); 1007 x = x - (short)panelLeft; 1008 y = y - (short)panelTop; 1009 } 1010 } 1011 1012 /* SET CURSOR POSITION */ 1013 unlock = READ_REG32(DC_UNLOCK); 1014 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 1015 WRITE_REG32(DC_CURS_ST_OFFSET, memoffset); 1016 WRITE_REG32(DC_CURSOR_X, (unsigned long)x | 1017 (((unsigned long)xoffset) << 11)); 1018 WRITE_REG32(DC_CURSOR_Y, (unsigned long)y | 1019 (((unsigned long)yoffset) << 11)); 1020 WRITE_REG32(DC_UNLOCK, unlock); 1021} 1022 1023/*--------------------------------------------------------------------------- 1024 * gfx_set_cursor_shape32 1025 * 1026 * This routine loads 32x32 cursor data into the specified location in 1027 * graphics memory. 1028 *--------------------------------------------------------------------------- 1029 */ 1030#if GFX_DISPLAY_DYNAMIC 1031void 1032gu1_set_cursor_shape32(unsigned long memoffset, 1033 unsigned long *andmask, unsigned long *xormask) 1034#else 1035void 1036gfx_set_cursor_shape32(unsigned long memoffset, 1037 unsigned long *andmask, unsigned long *xormask) 1038#endif 1039{ 1040 int i; 1041 unsigned long value; 1042 1043 for (i = 0; i < 32; i++) { 1044 /* CONVERT TO 16 BITS AND MASK, 16 BITS XOR MASK PER DWORD */ 1045 value = (andmask[i] & 0xFFFF0000) | (xormask[i] >> 16); 1046 WRITE_FB32(memoffset, value); 1047 memoffset += 4; 1048 value = (andmask[i] << 16) | (xormask[i] & 0x0000FFFF); 1049 WRITE_FB32(memoffset, value); 1050 memoffset += 4; 1051 } 1052} 1053 1054/*--------------------------------------------------------------------------- 1055 * gu1_enable_compression 1056 * 1057 * This is a private routine to this module (not exposed in the Durango API). 1058 * It enables display compression. 1059 *--------------------------------------------------------------------------- 1060 */ 1061void 1062gu1_enable_compression(void) 1063{ 1064 int i; 1065 unsigned long unlock, gcfg, offset; 1066 1067 /* DO NOT ENABLE IF START ADDRESS IS NOT ZERO */ 1068 offset = READ_REG32(DC_FB_ST_OFFSET) & 0x003FFFFF; 1069 if (offset != 0) 1070 return; 1071 1072 /* DO NOT ENABLE IF WE ARE WITHIN AN EMULATED VGA MODE */ 1073 if (gfx_line_double || gfx_pixel_double) 1074 return; 1075 1076 /* SET GLOBAL INDICATOR */ 1077 gfx_compression_active = 1; 1078 1079 /* CLEAR DIRTY/VALID BITS IN MEMORY CONTROLLER */ 1080 /* Software is required to do this before enabling compression. */ 1081 /* Don't want controller to think that old lines are still valid. */ 1082 for (i = 0; i < 1024; i++) { 1083 WRITE_REG32(MC_DR_ADD, i); 1084 WRITE_REG32(MC_DR_ACC, 0); 1085 } 1086 1087 /* TURN ON COMPRESSION CONTROL BITS */ 1088 unlock = READ_REG32(DC_UNLOCK); 1089 gcfg = READ_REG32(DC_GENERAL_CFG); 1090 gcfg |= DC_GCFG_CMPE | DC_GCFG_DECE; 1091 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 1092 WRITE_REG32(DC_GENERAL_CFG, gcfg); 1093 WRITE_REG32(DC_UNLOCK, unlock); 1094} 1095 1096/*--------------------------------------------------------------------------- 1097 * gu1_disable_compression 1098 * 1099 * This is a private routine to this module (not exposed in the Durango API). 1100 * It disables display compression. 1101 *--------------------------------------------------------------------------- 1102 */ 1103void 1104gu1_disable_compression(void) 1105{ 1106 unsigned long unlock, gcfg; 1107 1108 /* SET GLOBAL INDICATOR */ 1109 gfx_compression_active = 0; 1110 1111 /* TURN OFF COMPRESSION CONTROL BITS */ 1112 unlock = READ_REG32(DC_UNLOCK); 1113 gcfg = READ_REG32(DC_GENERAL_CFG); 1114 gcfg &= ~(DC_GCFG_CMPE | DC_GCFG_DECE); 1115 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 1116 WRITE_REG32(DC_GENERAL_CFG, gcfg); 1117 WRITE_REG32(DC_UNLOCK, unlock); 1118} 1119 1120/*--------------------------------------------------------------------------- 1121 * gfx_set_compression_enable 1122 * 1123 * This routine enables or disables display compression. 1124 *--------------------------------------------------------------------------- 1125 */ 1126#if GFX_DISPLAY_DYNAMIC 1127int 1128gu1_set_compression_enable(int enable) 1129#else 1130int 1131gfx_set_compression_enable(int enable) 1132#endif 1133{ 1134 /* SET GLOBAL VARIABLE FOR INTENDED STATE */ 1135 /* Compression can only be enabled for non-zero start address values. */ 1136 /* Keep state to enable compression on start address changes. */ 1137 gfx_compression_enabled = enable; 1138 if (enable) 1139 gu1_enable_compression(); 1140 else 1141 gu1_disable_compression(); 1142 1143 return (0); 1144} 1145 1146/*--------------------------------------------------------------------------- 1147 * gfx_set_compression_offset 1148 * 1149 * This routine sets the base offset for the compression buffer. 1150 *--------------------------------------------------------------------------- 1151 */ 1152#if GFX_DISPLAY_DYNAMIC 1153int 1154gu1_set_compression_offset(unsigned long offset) 1155#else 1156int 1157gfx_set_compression_offset(unsigned long offset) 1158#endif 1159{ 1160 unsigned long lock; 1161 1162 /* MUST BE 16-BYTE ALIGNED FOR GXLV */ 1163 if (offset & 0x0F) 1164 return (1); 1165 1166 /* SET REGISTER VALUE */ 1167 lock = READ_REG32(DC_UNLOCK); 1168 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 1169 WRITE_REG32(DC_CB_ST_OFFSET, offset); 1170 WRITE_REG32(DC_UNLOCK, lock); 1171 return (0); 1172} 1173 1174/*--------------------------------------------------------------------------- 1175 * gfx_set_compression_pitch 1176 * 1177 * This routine sets the pitch, in bytes, of the compression buffer. 1178 *--------------------------------------------------------------------------- 1179 */ 1180#if GFX_DISPLAY_DYNAMIC 1181int 1182gu1_set_compression_pitch(unsigned short pitch) 1183#else 1184int 1185gfx_set_compression_pitch(unsigned short pitch) 1186#endif 1187{ 1188 unsigned long lock, line_delta; 1189 1190 /* SET REGISTER VALUE */ 1191 lock = READ_REG32(DC_UNLOCK); 1192 line_delta = READ_REG32(DC_LINE_DELTA) & 0xFF800FFF; 1193 line_delta |= ((unsigned long)pitch << 10l) & 0x007FF000; 1194 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 1195 WRITE_REG32(DC_LINE_DELTA, line_delta); 1196 WRITE_REG32(DC_UNLOCK, lock); 1197 return (0); 1198} 1199 1200/*--------------------------------------------------------------------------- 1201 * gfx_set_compression_size 1202 * 1203 * This routine sets the line size of the compression buffer, which is the 1204 * maximum number of bytes allowed to store a compressed line. 1205 *--------------------------------------------------------------------------- 1206 */ 1207#if GFX_DISPLAY_DYNAMIC 1208int 1209gu1_set_compression_size(unsigned short size) 1210#else 1211int 1212gfx_set_compression_size(unsigned short size) 1213#endif 1214{ 1215 unsigned long lock, buf_size; 1216 1217 /* SUBTRACT 16 FROM SIZE */ 1218 /* The display controller will actually write */ 1219 /* 2 extra QWords. So, if we assume that "size" */ 1220 /* refers to the allocated size, we must subtract */ 1221 /* 16 bytes. */ 1222 size -= 16; 1223 1224 /* SET REGISTER VALUE */ 1225 lock = READ_REG32(DC_UNLOCK); 1226 buf_size = READ_REG32(DC_BUF_SIZE) & 0xFFFF01FF; 1227 buf_size |= (((size >> 2) + 1) & 0x7F) << 9; 1228 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 1229 WRITE_REG32(DC_BUF_SIZE, buf_size); 1230 WRITE_REG32(DC_UNLOCK, lock); 1231 return (0); 1232} 1233 1234/*--------------------------------------------------------------------------- 1235 * gfx_set_display_video_enable (PRIVATE ROUTINE - NOT PART OF API) 1236 * 1237 * This routine enables/disables video on GX. 1238 *--------------------------------------------------------------------------- 1239 */ 1240#if GFX_DISPLAY_DYNAMIC 1241void 1242gu1_set_display_video_enable(int enable) 1243#else 1244void 1245gfx_set_display_video_enable(int enable) 1246#endif 1247{ 1248 unsigned long lock, gcfg, buf_size; 1249 1250 lock = READ_REG32(DC_UNLOCK); 1251 gcfg = READ_REG32(DC_GENERAL_CFG); 1252 buf_size = READ_REG32(DC_BUF_SIZE); 1253 1254 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 1255 1256 vid_enabled = enable; 1257 1258 /* SET THE BUFFER SIZE TO A NON-ZERO VALUE ONLY WHEN */ 1259 /* ENABLING VIDEO */ 1260 if (enable) { 1261 gcfg |= (DC_GCFG_VIDE | DC_GCFG_VRDY); 1262 WRITE_REG32(DC_GENERAL_CFG, gcfg); 1263 1264 WRITE_REG32(DC_BUF_SIZE, (buf_size & 0x0000FFFFl) | vid_buf_size); 1265 } 1266 /* CLEAR THE VIDEO BUFFER SIZE WHEN DISABLING VIDEO */ 1267 else { 1268 gcfg &= ~(DC_GCFG_VIDE); 1269 WRITE_REG32(DC_GENERAL_CFG, gcfg); 1270 1271 vid_buf_size = buf_size & 0xFFFF0000l; 1272 WRITE_REG32(DC_BUF_SIZE, buf_size & 0x0000FFFFl); 1273 } 1274 1275 WRITE_REG32(DC_UNLOCK, lock); 1276 return; 1277} 1278 1279/*--------------------------------------------------------------------------- 1280 * gfx_set_display_video_size (PRIVATE ROUTINE - NOT PART OF API) 1281 * 1282 * This routine is called by "gfx_set_video_size". It abstracts the 1283 * version of the display controller from the video overlay routines. 1284 *--------------------------------------------------------------------------- 1285 */ 1286#if GFX_DISPLAY_DYNAMIC 1287void 1288gu1_set_display_video_size(unsigned short width, unsigned short height) 1289#else 1290void 1291gfx_set_display_video_size(unsigned short width, unsigned short height) 1292#endif 1293{ 1294 unsigned long lock, size, value; 1295 1296 size = (unsigned long)(width << 1) * (unsigned long)height; 1297 1298 /* STORE THE VIDEO BUFFER SIZE AS A GLOBAL */ 1299 vid_buf_size = ((size + 63) >> 6) << 16; 1300 1301 lock = READ_REG32(DC_UNLOCK); 1302 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 1303 value = READ_REG32(DC_BUF_SIZE) & 0x0000FFFF; 1304 value |= vid_buf_size; 1305 WRITE_REG32(DC_BUF_SIZE, value); 1306 WRITE_REG32(DC_UNLOCK, lock); 1307} 1308 1309/*--------------------------------------------------------------------------- 1310 * gfx_set_display_video_offset (PRIVATE ROUTINE - NOT PART OF API) 1311 * 1312 * This routine is called by "gfx_set_video_offset". It abstracts the 1313 * version of the display controller from the video overlay routines. 1314 *--------------------------------------------------------------------------- 1315 */ 1316#if GFX_DISPLAY_DYNAMIC 1317void 1318gu1_set_display_video_offset(unsigned long offset) 1319#else 1320void 1321gfx_set_display_video_offset(unsigned long offset) 1322#endif 1323{ 1324 unsigned long lock; 1325 1326 lock = READ_REG32(DC_UNLOCK); 1327 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 1328 offset &= 0x003FFFFF; 1329 WRITE_REG32(DC_VID_ST_OFFSET, offset); 1330 WRITE_REG32(DC_UNLOCK, lock); 1331} 1332 1333/*--------------------------------------------------------------------------- 1334 * gfx_set_display_priority_high 1335 * 1336 * This routine controls the x-bus round robin arbitration mechanism. 1337 * When enable is TRUE, graphics pipeline requests and non-critical display 1338 * controller requests are arbitrated at the same priority as processor 1339 * requests. When FALSE processor requests are arbitrated at a higher priority 1340 *--------------------------------------------------------------------------- 1341 */ 1342#if GFX_DISPLAY_DYNAMIC 1343void 1344gu1_set_display_priority_high(int enable) 1345#else 1346void 1347gfx_set_display_priority_high(int enable) 1348#endif 1349{ 1350 unsigned long lock, control; 1351 1352 lock = READ_REG32(DC_UNLOCK); 1353 control = READ_REG32(MC_MEM_CNTRL1); 1354 WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); 1355 if (enable) 1356 control |= MC_XBUSARB; 1357 else 1358 control &= ~(MC_XBUSARB); 1359 WRITE_REG32(MC_MEM_CNTRL1, control); 1360 WRITE_REG32(DC_UNLOCK, lock); 1361 return; 1362} 1363 1364/*--------------------------------------------------------------------------- 1365 * gfx_test_timing_active 1366 *--------------------------------------------------------------------------- 1367 */ 1368#if GFX_DISPLAY_DYNAMIC 1369int 1370gu1_test_timing_active(void) 1371#else 1372int 1373gfx_test_timing_active(void) 1374#endif 1375{ 1376 if (READ_REG32(DC_TIMING_CFG) & DC_TCFG_TGEN) 1377 return (1); 1378 else 1379 return (0); 1380} 1381 1382/*--------------------------------------------------------------------------- 1383 * gfx_test_vertical_active 1384 *--------------------------------------------------------------------------- 1385 */ 1386#if GFX_DISPLAY_DYNAMIC 1387int 1388gu1_test_vertical_active(void) 1389#else 1390int 1391gfx_test_vertical_active(void) 1392#endif 1393{ 1394 if (READ_REG32(DC_TIMING_CFG) & DC_TCFG_VNA) 1395 return (0); 1396 else 1397 return (1); 1398} 1399 1400/*--------------------------------------------------------------------------- 1401 * gfx_wait_vertical_blank 1402 *--------------------------------------------------------------------------- 1403 */ 1404#if GFX_DISPLAY_DYNAMIC 1405int 1406gu1_wait_vertical_blank(void) 1407#else 1408int 1409gfx_wait_vertical_blank(void) 1410#endif 1411{ 1412 if (gfx_test_timing_active()) { 1413 while (!gfx_test_vertical_active()) ; 1414 while (gfx_test_vertical_active()) ; 1415 } 1416 1417 return (0); 1418} 1419 1420/*--------------------------------------------------------------------------- 1421 * gfx_enable_panning 1422 * 1423 * This routine enables the panning when the Mode is bigger than the panel 1424 * size. 1425 *--------------------------------------------------------------------------- 1426 */ 1427#if GFX_DISPLAY_DYNAMIC 1428void 1429gu1_enable_panning(int x, int y) 1430#else 1431void 1432gfx_enable_panning(int x, int y) 1433#endif 1434{ 1435 unsigned long modeBytesPerPixel; 1436 unsigned long modeBytesPerScanline = 0; 1437 unsigned long startAddress = 0; 1438 1439 modeBytesPerPixel = (gbpp + 7) / 8; 1440 modeBytesPerScanline = 1441 (((ModeWidth + 1023) / 1024) * 1024) * modeBytesPerPixel; 1442 1443 /* TEST FOR NO-WORK */ 1444 if (x >= DeltaX && (unsigned short)x < (PanelWidth + DeltaX) && 1445 y >= DeltaY && (unsigned short)y < (PanelHeight + DeltaY)) 1446 return; 1447 1448 /* ADJUST PANNING VARIABLES WHEN CURSOR EXCEEDS BOUNDARY */ 1449 /* Test the boundary conditions for each coordinate and update */ 1450 /* all variables and the starting offset accordingly. */ 1451 if (x < DeltaX) 1452 DeltaX = x; 1453 else if ((unsigned short)x >= (DeltaX + PanelWidth)) 1454 DeltaX = x - PanelWidth + 1; 1455 1456 if (y < DeltaY) 1457 DeltaY = y; 1458 else if ((unsigned short)y >= (DeltaY + PanelHeight)) 1459 DeltaY = y - PanelHeight + 1; 1460 1461 /* CALCULATE THE START OFFSET */ 1462 startAddress = 1463 (DeltaX * modeBytesPerPixel) + (DeltaY * modeBytesPerScanline); 1464 1465 gfx_set_display_offset(startAddress); 1466 1467 /* SET PANEL COORDINATES */ 1468 /* Panel's x position must be DWORD aligned */ 1469 panelTop = DeltaY; 1470 panelLeft = DeltaX * modeBytesPerPixel; 1471 1472 if (panelLeft & 3) 1473 panelLeft = (panelLeft & 0xFFFFFFFC) + 4; 1474 1475 panelLeft /= modeBytesPerPixel; 1476 1477} 1478 1479/*--------------------------------------------------------------------------- 1480 * gfx_set_fixed_timings 1481 *--------------------------------------------------------------------------- 1482 */ 1483#if GFX_DISPLAY_DYNAMIC 1484int 1485gu1_set_fixed_timings(int panelResX, int panelResY, unsigned short width, 1486 unsigned short height, unsigned short bpp) 1487#else 1488int 1489gfx_set_fixed_timings(int panelResX, int panelResY, unsigned short width, 1490 unsigned short height, unsigned short bpp) 1491#endif 1492{ 1493 unsigned int mode; 1494 1495 ModeWidth = width; 1496 ModeHeight = height; 1497 PanelWidth = (unsigned short)panelResX; 1498 PanelHeight = (unsigned short)panelResY; 1499 PanelEnable = 1; 1500 1501 /* LOOP THROUGH THE AVAILABLE MODES TO FIND A MATCH */ 1502 for (mode = 0; mode < NUM_FIXED_TIMINGS_MODES; mode++) { 1503 if ((FixedParams[mode].xres == width) && 1504 (FixedParams[mode].yres == height) && 1505 (FixedParams[mode].panelresx == panelResX) && 1506 (FixedParams[mode].panelresy == panelResY)) { 1507 1508 /* SET THE 92xx FOR THE SELECTED MODE */ 1509 FIXEDTIMINGS *fmode = &FixedParams[mode]; 1510 1511 gfx_set_display_timings(bpp, 3, fmode->hactive, 1512 fmode->hblankstart, fmode->hsyncstart, fmode->hsyncend, 1513 fmode->hblankend, fmode->htotal, fmode->vactive, 1514 fmode->vblankstart, fmode->vsyncstart, fmode->vsyncend, 1515 fmode->vblankend, fmode->vtotal, fmode->frequency); 1516 1517 return (1); 1518 } /* end if() */ 1519 } /* end for() */ 1520 1521 return (-1); 1522} 1523 1524/*--------------------------------------------------------------------------- 1525 * gfx_set_panel_present 1526 *--------------------------------------------------------------------------- 1527 */ 1528#if GFX_DISPLAY_DYNAMIC 1529int 1530gu1_set_panel_present(int panelResX, int panelResY, unsigned short width, 1531 unsigned short height, unsigned short bpp) 1532#else 1533int 1534gfx_set_panel_present(int panelResX, int panelResY, unsigned short width, 1535 unsigned short height, unsigned short bpp) 1536#endif 1537{ 1538 /* SET VALID BPP */ 1539 /* 16BPP is the default. */ 1540 if (bpp != 8 && bpp != 15 && bpp != 16) 1541 bpp = 16; 1542 1543 /* RECORD PANEL PARAMETERS */ 1544 /* This routine does not touch any panel timings. It is used when custom 1545 * panel settings are set up in advance by the BIOS or an application, but 1546 * the application still requires access to other panel functionality 1547 * provided by Durango (i.e. panning) 1548 * */ 1549 1550 ModeWidth = width; 1551 ModeHeight = height; 1552 PanelWidth = (unsigned short)panelResX; 1553 PanelHeight = (unsigned short)panelResY; 1554 PanelEnable = 1; 1555 gbpp = bpp; 1556 1557 /* PROGRAM THE BPP IN THE DISPLAY CONTROLLER */ 1558 gfx_set_display_bpp(bpp); 1559 1560 return (GFX_STATUS_OK); 1561} 1562 1563/*-----------------------------------------------------------------------* 1564 * THE FOLLOWING READ ROUTINES ARE ALWAYS INCLUDED: * 1565 * gfx_get_hsync_end, gfx_get_htotal, gfx_get_vsync_end, gfx_get_vtotal * 1566 * are used by the video overlay routines. * 1567 * * 1568 * gfx_get_vline and gfx_vactive are used to prevent an issue for the * 1569 * SC1200. * 1570 * * 1571 * The others are part of the Durango API. * 1572 *-----------------------------------------------------------------------*/ 1573 1574/*--------------------------------------------------------------------------- 1575 * gfx_get_display_pitch 1576 * 1577 * This routine returns the current pitch of the frame buffer, in bytes. 1578 *--------------------------------------------------------------------------- 1579 */ 1580#if GFX_DISPLAY_DYNAMIC 1581unsigned short 1582gu1_get_display_pitch(void) 1583#else 1584unsigned short 1585gfx_get_display_pitch(void) 1586#endif 1587{ 1588 unsigned long value; 1589 1590 if (gfx_cpu_version == GFX_CPU_PYRAMID) { 1591 /* Pyramid update for 4KB line pitch */ 1592 value = (READ_REG32(DC_LINE_DELTA) & 0x07FF) << 2; 1593 } else { 1594 value = (READ_REG32(DC_LINE_DELTA) & 0x03FF) << 2; 1595 } 1596 1597 return ((unsigned short)value); 1598} 1599 1600/*---------------------------------------------------------------------------- 1601 * GFX_GET_DISPLAY_DETAILS 1602 * 1603 * This routine gets the specified display mode. 1604 * 1605 * Returns 1 if successful, 0 if mode could not be get. 1606 *---------------------------------------------------------------------------- 1607 */ 1608#if GFX_DISPLAY_DYNAMIC 1609int 1610gu1_get_display_details(unsigned int mode, int *xres, int *yres, int *hz) 1611#else 1612int 1613gfx_get_display_details(unsigned int mode, int *xres, int *yres, int *hz) 1614#endif 1615{ 1616 if (mode < NUM_GX_DISPLAY_MODES) { 1617 if (DisplayParams[mode].flags & GFX_MODE_56HZ) 1618 *hz = 56; 1619 else if (DisplayParams[mode].flags & GFX_MODE_60HZ) 1620 *hz = 60; 1621 else if (DisplayParams[mode].flags & GFX_MODE_70HZ) 1622 *hz = 70; 1623 else if (DisplayParams[mode].flags & GFX_MODE_72HZ) 1624 *hz = 72; 1625 else if (DisplayParams[mode].flags & GFX_MODE_75HZ) 1626 *hz = 75; 1627 else if (DisplayParams[mode].flags & GFX_MODE_85HZ) 1628 *hz = 85; 1629 1630 *xres = DisplayParams[mode].hactive; 1631 *yres = DisplayParams[mode].vactive; 1632 1633 return (1); 1634 } 1635 return (0); 1636} 1637 1638/*---------------------------------------------------------------------------- 1639 * GFX_GET_DISPLAY_MODE_COUNT 1640 * 1641 * Returns number of modes supported. 1642 *---------------------------------------------------------------------------- 1643 */ 1644#if GFX_DISPLAY_DYNAMIC 1645int 1646gu1_get_display_mode_count(void) 1647#else 1648int 1649gfx_get_display_mode_count(void) 1650#endif 1651{ 1652 return (NUM_GX_DISPLAY_MODES); 1653} 1654 1655/*---------------------------------------------------------------------------- 1656 * gfx_get_frame_buffer_line_size 1657 * 1658 * Returns the current frame buffer line size, in bytes 1659 *---------------------------------------------------------------------------- 1660 */ 1661#if GFX_DISPLAY_DYNAMIC 1662unsigned long 1663gu1_get_frame_buffer_line_size(void) 1664#else 1665unsigned long 1666gfx_get_frame_buffer_line_size(void) 1667#endif 1668{ 1669 return ((READ_REG32(DC_BUF_SIZE) & 0x1FF) << 3); 1670} 1671 1672/*---------------------------------------------------------------------------- 1673 * gfx_mode_frequency_supported 1674 * 1675 * This routine examines if the requested mode with pixel frequency is supported. 1676 * 1677 * Returns >0 if successful , <0 if freq. could not be found and matched. 1678 *---------------------------------------------------------------------------- 1679 */ 1680#if GFX_DISPLAY_DYNAMIC 1681int 1682gu1_mode_frequency_supported(int xres, int yres, int bpp, 1683 unsigned long frequency) 1684#else 1685int 1686gfx_mode_frequency_supported(int xres, int yres, int bpp, 1687 unsigned long frequency) 1688#endif 1689{ 1690 unsigned int index; 1691 unsigned long value; 1692 unsigned long bpp_flag = 0; 1693 1694 bpp_flag = GFX_MODE_8BPP; 1695 if (bpp > 8) 1696 bpp_flag = GFX_MODE_16BPP; 1697 1698 for (index = 0; index < NUM_GX_DISPLAY_MODES; index++) { 1699 if ((DisplayParams[index].hactive == (unsigned short)xres) && 1700 (DisplayParams[index].vactive == (unsigned short)yres) && 1701 (DisplayParams[index].flags & bpp_flag) && 1702 (DisplayParams[index].frequency == frequency)) { 1703 int hz = 0; 1704 1705 value = DisplayParams[index].flags; 1706 1707 if (value & GFX_MODE_56HZ) 1708 hz = 56; 1709 else if (value & GFX_MODE_60HZ) 1710 hz = 60; 1711 else if (value & GFX_MODE_70HZ) 1712 hz = 70; 1713 else if (value & GFX_MODE_72HZ) 1714 hz = 72; 1715 else if (value & GFX_MODE_75HZ) 1716 hz = 75; 1717 else if (value & GFX_MODE_85HZ) 1718 hz = 85; 1719 1720 return (hz); 1721 } 1722 } 1723 return (-1); 1724} 1725 1726/*---------------------------------------------------------------------------- 1727 * gfx_refreshrate_from_frequency 1728 * 1729 * This routine maps the frequency to close match refresh rate 1730 *---------------------------------------------------------------------------- 1731 */ 1732#if GFX_DISPLAY_DYNAMIC 1733int 1734gu1_get_refreshrate_from_frequency(int xres, int yres, int bpp, int *hz, 1735 unsigned long frequency) 1736#else 1737int 1738gfx_get_refreshrate_from_frequency(int xres, int yres, int bpp, int *hz, 1739 unsigned long frequency) 1740#endif 1741{ 1742 unsigned int index, closematch = 0; 1743 unsigned long value; 1744 unsigned long bpp_flag = 0; 1745 long min, diff; 1746 1747 *hz = 60; 1748 1749 bpp_flag = GFX_MODE_8BPP; 1750 if (bpp > 8) 1751 bpp_flag = GFX_MODE_16BPP; 1752 1753 /* FIND THE REGISTER VALUES FOR THE DESIRED FREQUENCY */ 1754 /* Search the table for the closest frequency (16.16 format). */ 1755 min = 0x7fffffff; 1756 for (index = 0; index < NUM_GX_DISPLAY_MODES; index++) { 1757 if ((DisplayParams[index].htotal == (unsigned short)xres) && 1758 (DisplayParams[index].vtotal == (unsigned short)yres) && 1759 (DisplayParams[index].flags & bpp_flag)) { 1760 diff = (long)frequency - (long)DisplayParams[index].frequency; 1761 if (diff < 0) 1762 diff = -diff; 1763 1764 if (diff < min) { 1765 min = diff; 1766 closematch = index; 1767 } 1768 } 1769 } 1770 1771 value = DisplayParams[closematch].flags; 1772 1773 if (value & GFX_MODE_56HZ) 1774 *hz = 56; 1775 else if (value & GFX_MODE_60HZ) 1776 *hz = 60; 1777 else if (value & GFX_MODE_70HZ) 1778 *hz = 70; 1779 else if (value & GFX_MODE_72HZ) 1780 *hz = 72; 1781 else if (value & GFX_MODE_75HZ) 1782 *hz = 75; 1783 else if (value & GFX_MODE_85HZ) 1784 *hz = 85; 1785 1786 return (1); 1787} 1788 1789/*---------------------------------------------------------------------------- 1790 * gfx_refreshrate_from_mode 1791 * 1792 * This routine is identical to the gfx_get_refreshrate_from_frequency, 1793 * except that the active timing values are compared instead of the total 1794 * values. Some modes (such as 70Hz and 72Hz) may be confused in this routine 1795 *---------------------------------------------------------------------------- 1796 */ 1797#if GFX_DISPLAY_DYNAMIC 1798int 1799gu1_get_refreshrate_from_mode(int xres, int yres, int bpp, int *hz, 1800 unsigned long frequency) 1801#else 1802int 1803gfx_get_refreshrate_from_mode(int xres, int yres, int bpp, int *hz, 1804 unsigned long frequency) 1805#endif 1806{ 1807 unsigned int index, closematch = 0; 1808 unsigned long value; 1809 unsigned long bpp_flag = 0; 1810 long min, diff; 1811 1812 *hz = 60; 1813 1814 bpp_flag = GFX_MODE_8BPP; 1815 if (bpp > 8) 1816 bpp_flag = GFX_MODE_16BPP; 1817 1818 /* FIND THE REGISTER VALUES FOR THE DESIRED FREQUENCY */ 1819 /* Search the table for the closest frequency (16.16 format). */ 1820 min = 0x7fffffff; 1821 for (index = 0; index < NUM_GX_DISPLAY_MODES; index++) { 1822 if ((DisplayParams[index].hactive == (unsigned short)xres) && 1823 (DisplayParams[index].vactive == (unsigned short)yres) && 1824 (DisplayParams[index].flags & bpp_flag)) { 1825 diff = (long)frequency - (long)DisplayParams[index].frequency; 1826 if (diff < 0) 1827 diff = -diff; 1828 1829 if (diff < min) { 1830 min = diff; 1831 closematch = index; 1832 } 1833 } 1834 } 1835 1836 value = DisplayParams[closematch].flags; 1837 1838 if (value & GFX_MODE_56HZ) 1839 *hz = 56; 1840 else if (value & GFX_MODE_60HZ) 1841 *hz = 60; 1842 else if (value & GFX_MODE_70HZ) 1843 *hz = 70; 1844 else if (value & GFX_MODE_72HZ) 1845 *hz = 72; 1846 else if (value & GFX_MODE_75HZ) 1847 *hz = 75; 1848 else if (value & GFX_MODE_85HZ) 1849 *hz = 85; 1850 1851 return (1); 1852} 1853 1854/*---------------------------------------------------------------------------- 1855 * gfx_get_frequency_from_refreshrate 1856 * 1857 * This routine maps the refresh rate to the closest matching PLL frequency. 1858 *---------------------------------------------------------------------------- 1859 */ 1860#if GFX_DISPLAY_DYNAMIC 1861int 1862gu1_get_frequency_from_refreshrate(int xres, int yres, int bpp, int hz, 1863 int *frequency) 1864#else 1865int 1866gfx_get_frequency_from_refreshrate(int xres, int yres, int bpp, int hz, 1867 int *frequency) 1868#endif 1869{ 1870 unsigned int index; 1871 int retval = -1; 1872 unsigned long hz_flag = 0; 1873 unsigned long bpp_flag = 0; 1874 1875 *frequency = 0; 1876 1877 if (hz == 56) 1878 hz_flag = GFX_MODE_56HZ; 1879 else if (hz == 60) 1880 hz_flag = GFX_MODE_60HZ; 1881 else if (hz == 70) 1882 hz_flag = GFX_MODE_70HZ; 1883 else if (hz == 72) 1884 hz_flag = GFX_MODE_72HZ; 1885 else if (hz == 75) 1886 hz_flag = GFX_MODE_75HZ; 1887 else if (hz == 85) 1888 hz_flag = GFX_MODE_85HZ; 1889 1890 bpp_flag = GFX_MODE_8BPP; 1891 if (bpp > 8) 1892 bpp_flag = GFX_MODE_16BPP; 1893 1894 /* FIND THE REGISTER VALUES FOR THE DESIRED FREQUENCY */ 1895 1896 for (index = 0; index < NUM_GX_DISPLAY_MODES; index++) { 1897 if ((DisplayParams[index].hactive == (unsigned short)xres) && 1898 (DisplayParams[index].vactive == (unsigned short)yres) && 1899 (DisplayParams[index].flags & bpp_flag) && 1900 (DisplayParams[index].flags & hz_flag)) { 1901 *frequency = DisplayParams[index].frequency; 1902 retval = 1; 1903 } 1904 } 1905 return retval; 1906} 1907 1908/*--------------------------------------------------------------------------- 1909 * gfx_get_max_supported_pixel_clock 1910 * 1911 * This routine returns the maximum recommended speed for the pixel clock. The 1912 * return value is an integer of the format xxxyyy, where xxx.yyy is the maximum 1913 * floating point pixel clock speed. 1914 *--------------------------------------------------------------------------- 1915 */ 1916#if GFX_DISPLAY_DYNAMIC 1917unsigned long 1918gu1_get_max_supported_pixel_clock(void) 1919#else 1920unsigned long 1921gfx_get_max_supported_pixel_clock(void) 1922#endif 1923{ 1924 /* ALL CHIPS CAN HANDLE 1280X1024@85HZ - 157.5 MHz */ 1925 return 157500; 1926} 1927 1928/*---------------------------------------------------------------------------- 1929 * gfx_get_display_mode 1930 * 1931 * This routine gets the specified display mode. 1932 * 1933 * Returns: >0 if successful and mode returned, <0 if mode could not be found. 1934 *---------------------------------------------------------------------------- 1935 */ 1936#if GFX_DISPLAY_DYNAMIC 1937int 1938gu1_get_display_mode(int *xres, int *yres, int *bpp, int *hz) 1939#else 1940int 1941gfx_get_display_mode(int *xres, int *yres, int *bpp, int *hz) 1942#endif 1943{ 1944 unsigned int mode = 0; 1945 unsigned long pll_freq = 0, bpp_flag = 0; 1946 1947 *xres = gfx_get_hactive(); 1948 *yres = gfx_get_vactive(); 1949 *bpp = gfx_get_display_bpp(); 1950 pll_freq = gfx_get_clock_frequency(); 1951 1952 /* SUPPORT EMULATED VGA MODES */ 1953 if (gfx_pixel_double) 1954 *xres >>= 1; 1955 1956 if (gfx_line_double) 1957 *yres >>= 1; 1958 1959 /* SET BPP FLAGS TO LIMIT MODE SELECTION */ 1960 bpp_flag = GFX_MODE_8BPP; 1961 if (*bpp > 8) 1962 bpp_flag = GFX_MODE_16BPP; 1963 1964 for (mode = 0; mode < NUM_GX_DISPLAY_MODES; mode++) { 1965 if ((DisplayParams[mode].hactive == (unsigned short)*xres) && 1966 (DisplayParams[mode].vactive == (unsigned short)*yres) && 1967 (DisplayParams[mode].frequency == pll_freq) && 1968 (DisplayParams[mode].flags & bpp_flag)) { 1969 1970 pll_freq = DisplayParams[mode].flags; 1971 1972 if (pll_freq & GFX_MODE_56HZ) 1973 *hz = 56; 1974 else if (pll_freq & GFX_MODE_60HZ) 1975 *hz = 60; 1976 else if (pll_freq & GFX_MODE_70HZ) 1977 *hz = 70; 1978 else if (pll_freq & GFX_MODE_72HZ) 1979 *hz = 72; 1980 else if (pll_freq & GFX_MODE_75HZ) 1981 *hz = 75; 1982 else if (pll_freq & GFX_MODE_85HZ) 1983 *hz = 85; 1984 1985 return (1); 1986 } 1987 } 1988 return (-1); 1989} 1990 1991/*--------------------------------------------------------------------------- 1992 * gfx_get_hactive 1993 *--------------------------------------------------------------------------- 1994 */ 1995#if GFX_DISPLAY_DYNAMIC 1996unsigned short 1997gu1_get_hactive(void) 1998#else 1999unsigned short 2000gfx_get_hactive(void) 2001#endif 2002{ 2003 return ((unsigned short)((READ_REG32(DC_H_TIMING_1) & 0x07F8) + 8)); 2004} 2005 2006/*--------------------------------------------------------------------------- 2007 * gfx_get_hsync_start 2008 *--------------------------------------------------------------------------- 2009 */ 2010#if GFX_DISPLAY_DYNAMIC 2011unsigned short 2012gu1_get_hsync_start(void) 2013#else 2014unsigned short 2015gfx_get_hsync_start(void) 2016#endif 2017{ 2018 return ((unsigned short)((READ_REG32(DC_H_TIMING_3) & 0x07F8) + 8)); 2019} 2020 2021/*--------------------------------------------------------------------------- 2022 * gfx_get_hsync_end 2023 *--------------------------------------------------------------------------- 2024 */ 2025#if GFX_DISPLAY_DYNAMIC 2026unsigned short 2027gu1_get_hsync_end(void) 2028#else 2029unsigned short 2030gfx_get_hsync_end(void) 2031#endif 2032{ 2033 return ((unsigned short)(((READ_REG32(DC_H_TIMING_3) >> 16) & 0x07F8) + 2034 8)); 2035} 2036 2037/*--------------------------------------------------------------------------- 2038 * gfx_get_htotal 2039 *--------------------------------------------------------------------------- 2040 */ 2041#if GFX_DISPLAY_DYNAMIC 2042unsigned short 2043gu1_get_htotal(void) 2044#else 2045unsigned short 2046gfx_get_htotal(void) 2047#endif 2048{ 2049 return ((unsigned short)(((READ_REG32(DC_H_TIMING_1) >> 16) & 0x07F8) + 2050 8)); 2051} 2052 2053/*--------------------------------------------------------------------------- 2054 * gfx_get_vactive 2055 *--------------------------------------------------------------------------- 2056 */ 2057#if GFX_DISPLAY_DYNAMIC 2058unsigned short 2059gu1_get_vactive(void) 2060#else 2061unsigned short 2062gfx_get_vactive(void) 2063#endif 2064{ 2065 return ((unsigned short)((READ_REG32(DC_V_TIMING_1) & 0x07FF) + 1)); 2066} 2067 2068/*--------------------------------------------------------------------------- 2069 * gfx_get_vsync_end 2070 *--------------------------------------------------------------------------- 2071 */ 2072#if GFX_DISPLAY_DYNAMIC 2073unsigned short 2074gu1_get_vsync_end(void) 2075#else 2076unsigned short 2077gfx_get_vsync_end(void) 2078#endif 2079{ 2080 return ((unsigned short)(((READ_REG32(DC_V_TIMING_3) >> 16) & 0x07FF) + 2081 1)); 2082} 2083 2084/*--------------------------------------------------------------------------- 2085 * gfx_get_vtotal 2086 *--------------------------------------------------------------------------- 2087 */ 2088#if GFX_DISPLAY_DYNAMIC 2089unsigned short 2090gu1_get_vtotal(void) 2091#else 2092unsigned short 2093gfx_get_vtotal(void) 2094#endif 2095{ 2096 return ((unsigned short)(((READ_REG32(DC_V_TIMING_1) >> 16) & 0x07FF) + 2097 1)); 2098} 2099 2100/*----------------------------------------------------------------------------- 2101 * gfx_get_display_bpp 2102 * 2103 * This routine returns the current color depth of the active display. 2104 *----------------------------------------------------------------------------- 2105 */ 2106#if GFX_DISPLAY_DYNAMIC 2107unsigned short 2108gu1_get_display_bpp(void) 2109#else 2110unsigned short 2111gfx_get_display_bpp(void) 2112#endif 2113{ 2114 switch (READ_REG32(DC_OUTPUT_CFG) & 3) { 2115 case 0: 2116 return (16); 2117 case 2: 2118 return (15); 2119 } 2120 return (8); 2121} 2122 2123/*--------------------------------------------------------------------------- 2124 * gfx_get_vline 2125 *--------------------------------------------------------------------------- 2126 */ 2127#if GFX_DISPLAY_DYNAMIC 2128unsigned short 2129gu1_get_vline(void) 2130#else 2131unsigned short 2132gfx_get_vline(void) 2133#endif 2134{ 2135 unsigned short current_scan_line; 2136 2137 /* Read similar value twice to ensure that the value is not transitioning */ 2138 do { 2139 current_scan_line = 2140 (unsigned short)READ_REG32(DC_V_LINE_CNT) & 0x07FF; 2141 } while (current_scan_line != 2142 (unsigned short)(READ_REG32(DC_V_LINE_CNT) & 0x07FF)); 2143 2144 return (current_scan_line); 2145} 2146 2147/*----------------------------------------------------------------------------- 2148 * gfx_get_display_offset 2149 *----------------------------------------------------------------------------- 2150 */ 2151#if GFX_DISPLAY_DYNAMIC 2152unsigned long 2153gu1_get_display_offset(void) 2154#else 2155unsigned long 2156gfx_get_display_offset(void) 2157#endif 2158{ 2159 return (READ_REG32(DC_FB_ST_OFFSET) & 0x003FFFFF); 2160} 2161 2162/*----------------------------------------------------------------------------- 2163 * gfx_get_cursor_offset 2164 *----------------------------------------------------------------------------- 2165 */ 2166#if GFX_DISPLAY_DYNAMIC 2167unsigned long 2168gu1_get_cursor_offset(void) 2169#else 2170unsigned long 2171gfx_get_cursor_offset(void) 2172#endif 2173{ 2174 return (READ_REG32(DC_CURS_ST_OFFSET) & 0x003FFFFF); 2175} 2176 2177#if GFX_READ_ROUTINES 2178 2179/*************************************************************/ 2180/* READ ROUTINES | INCLUDED FOR DIAGNOSTIC PURPOSES ONLY */ 2181/*************************************************************/ 2182 2183/*--------------------------------------------------------------------------- 2184 * gfx_get_hblank_start 2185 *--------------------------------------------------------------------------- 2186 */ 2187#if GFX_DISPLAY_DYNAMIC 2188unsigned short 2189gu1_get_hblank_start(void) 2190#else 2191unsigned short 2192gfx_get_hblank_start(void) 2193#endif 2194{ 2195 return ((unsigned short)((READ_REG32(DC_H_TIMING_2) & 0x07F8) + 8)); 2196} 2197 2198/*--------------------------------------------------------------------------- 2199 * gfx_get_hblank_end 2200 *--------------------------------------------------------------------------- 2201 */ 2202#if GFX_DISPLAY_DYNAMIC 2203unsigned short 2204gu1_get_hblank_end(void) 2205#else 2206unsigned short 2207gfx_get_hblank_end(void) 2208#endif 2209{ 2210 return ((unsigned short)(((READ_REG32(DC_H_TIMING_2) >> 16) & 0x07F8) + 2211 8)); 2212} 2213 2214/*--------------------------------------------------------------------------- 2215 * gfx_get_vblank_start 2216 *--------------------------------------------------------------------------- 2217 */ 2218#if GFX_DISPLAY_DYNAMIC 2219unsigned short 2220gu1_get_vblank_start(void) 2221#else 2222unsigned short 2223gfx_get_vblank_start(void) 2224#endif 2225{ 2226 return ((unsigned short)((READ_REG32(DC_V_TIMING_2) & 0x07FF) + 1)); 2227} 2228 2229/*--------------------------------------------------------------------------- 2230 * gfx_get_vsync_start 2231 *--------------------------------------------------------------------------- 2232 */ 2233#if GFX_DISPLAY_DYNAMIC 2234unsigned short 2235gu1_get_vsync_start(void) 2236#else 2237unsigned short 2238gfx_get_vsync_start(void) 2239#endif 2240{ 2241 return ((unsigned short)((READ_REG32(DC_V_TIMING_3) & 0x07FF) + 1)); 2242} 2243 2244/*--------------------------------------------------------------------------- 2245 * gfx_get_vblank_end 2246 *--------------------------------------------------------------------------- 2247 */ 2248#if GFX_DISPLAY_DYNAMIC 2249unsigned short 2250gu1_get_vblank_end(void) 2251#else 2252unsigned short 2253gfx_get_vblank_end(void) 2254#endif 2255{ 2256 return ((unsigned short)(((READ_REG32(DC_V_TIMING_2) >> 16) & 0x07FF) + 2257 1)); 2258} 2259 2260/*----------------------------------------------------------------------------- 2261 * gfx_get_display_palette_entry 2262 *----------------------------------------------------------------------------- 2263 */ 2264#if GFX_DISPLAY_DYNAMIC 2265int 2266gu1_get_display_palette_entry(unsigned long index, unsigned long *palette) 2267#else 2268int 2269gfx_get_display_palette_entry(unsigned long index, unsigned long *palette) 2270#endif 2271{ 2272 unsigned long data; 2273 2274 if (index > 0xFF) 2275 return GFX_STATUS_BAD_PARAMETER; 2276 2277 WRITE_REG32(DC_PAL_ADDRESS, index); 2278 data = READ_REG32(DC_PAL_DATA); 2279 data = ((data << 2) & 0x000000FC) | 2280 ((data << 4) & 0x0000FC00) | ((data << 6) & 0x00FC0000); 2281 2282 *palette = data; 2283 return 0; 2284} 2285 2286/*----------------------------------------------------------------------------- 2287 * gfx_get_display_palette 2288 *----------------------------------------------------------------------------- 2289 */ 2290#if GFX_DISPLAY_DYNAMIC 2291void 2292gu1_get_display_palette(unsigned long *palette) 2293#else 2294void 2295gfx_get_display_palette(unsigned long *palette) 2296#endif 2297{ 2298 unsigned long i, data; 2299 2300 WRITE_REG32(DC_PAL_ADDRESS, 0); 2301 for (i = 0; i < 256; i++) { 2302 data = READ_REG32(DC_PAL_DATA); 2303 data = ((data << 2) & 0x000000FC) | 2304 ((data << 4) & 0x0000FC00) | ((data << 6) & 0x00FC0000); 2305 palette[i] = data; 2306 } 2307} 2308 2309/*----------------------------------------------------------------------------- 2310 * gfx_get_cursor_enable 2311 *----------------------------------------------------------------------------- 2312 */ 2313#if GFX_DISPLAY_DYNAMIC 2314unsigned long 2315gu1_get_cursor_enable(void) 2316#else 2317unsigned long 2318gfx_get_cursor_enable(void) 2319#endif 2320{ 2321 return (READ_REG32(DC_GENERAL_CFG) & DC_GCFG_CURE); 2322} 2323 2324/*----------------------------------------------------------------------------- 2325 * gfx_get_cursor_position 2326 *----------------------------------------------------------------------------- 2327 */ 2328#if GFX_DISPLAY_DYNAMIC 2329unsigned long 2330gu1_get_cursor_position(void) 2331#else 2332unsigned long 2333gfx_get_cursor_position(void) 2334#endif 2335{ 2336 return ((READ_REG32(DC_CURSOR_X) & 0x07FF) | 2337 ((READ_REG32(DC_CURSOR_Y) << 16) & 0x03FF0000)); 2338} 2339 2340/*----------------------------------------------------------------------------- 2341 * gfx_get_cursor_clip 2342 *----------------------------------------------------------------------------- 2343 */ 2344#if GFX_DISPLAY_DYNAMIC 2345unsigned long 2346gu1_get_cursor_clip(void) 2347#else 2348unsigned long 2349gfx_get_cursor_clip(void) 2350#endif 2351{ 2352 return (((READ_REG32(DC_CURSOR_X) >> 11) & 0x01F) | 2353 ((READ_REG32(DC_CURSOR_Y) << 5) & 0x1F0000)); 2354} 2355 2356/*----------------------------------------------------------------------------- 2357 * gfx_get_cursor_color 2358 *----------------------------------------------------------------------------- 2359 */ 2360#if GFX_DISPLAY_DYNAMIC 2361unsigned long 2362gu1_get_cursor_color(int color) 2363#else 2364unsigned long 2365gfx_get_cursor_color(int color) 2366#endif 2367{ 2368 unsigned long data; 2369 2370 if (color) { 2371 WRITE_REG32(DC_PAL_ADDRESS, 0x101); 2372 } else { 2373 WRITE_REG32(DC_PAL_ADDRESS, 0x100); 2374 } 2375 data = READ_REG32(DC_PAL_DATA); 2376 data = ((data << 6) & 0x00FC0000) | 2377 ((data << 4) & 0x0000FC00) | ((data << 2) & 0x000000FC); 2378 return (data); 2379} 2380 2381/*----------------------------------------------------------------------------- 2382 * gfx_get_compression_enable 2383 *----------------------------------------------------------------------------- 2384 */ 2385#if GFX_DISPLAY_DYNAMIC 2386int 2387gu1_get_compression_enable(void) 2388#else 2389int 2390gfx_get_compression_enable(void) 2391#endif 2392{ 2393 unsigned long gcfg; 2394 2395 gcfg = READ_REG32(DC_GENERAL_CFG); 2396 if (gcfg & DC_GCFG_CMPE) 2397 return (1); 2398 else 2399 return (0); 2400} 2401 2402/*----------------------------------------------------------------------------- 2403 * gfx_get_compression_offset 2404 *----------------------------------------------------------------------------- 2405 */ 2406#if GFX_DISPLAY_DYNAMIC 2407unsigned long 2408gu1_get_compression_offset(void) 2409#else 2410unsigned long 2411gfx_get_compression_offset(void) 2412#endif 2413{ 2414 unsigned long offset; 2415 2416 offset = READ_REG32(DC_CB_ST_OFFSET) & 0x003FFFFF; 2417 return (offset); 2418} 2419 2420/*----------------------------------------------------------------------------- 2421 * gfx_get_compression_pitch 2422 *----------------------------------------------------------------------------- 2423 */ 2424#if GFX_DISPLAY_DYNAMIC 2425unsigned short 2426gu1_get_compression_pitch(void) 2427#else 2428unsigned short 2429gfx_get_compression_pitch(void) 2430#endif 2431{ 2432 unsigned short pitch; 2433 2434 pitch = (unsigned short)(READ_REG32(DC_LINE_DELTA) >> 12) & 0x03FF; 2435 return (pitch << 2); 2436} 2437 2438/*----------------------------------------------------------------------------- 2439 * gfx_get_compression_size 2440 *----------------------------------------------------------------------------- 2441 */ 2442#if GFX_DISPLAY_DYNAMIC 2443unsigned short 2444gu1_get_compression_size(void) 2445#else 2446unsigned short 2447gfx_get_compression_size(void) 2448#endif 2449{ 2450 unsigned short size; 2451 2452 size = (unsigned short)((READ_REG32(DC_BUF_SIZE) >> 9) & 0x7F) - 1; 2453 return ((size << 2) + 16); 2454} 2455 2456/*----------------------------------------------------------------------------- 2457 * gfx_get_valid_bit 2458 *----------------------------------------------------------------------------- 2459 */ 2460#if GFX_DISPLAY_DYNAMIC 2461int 2462gu1_get_valid_bit(int line) 2463#else 2464int 2465gfx_get_valid_bit(int line) 2466#endif 2467{ 2468 int valid; 2469 2470 WRITE_REG32(MC_DR_ADD, line); 2471 valid = (int)READ_REG32(MC_DR_ACC) & 1; 2472 return (valid); 2473} 2474 2475/*--------------------------------------------------------------------------- 2476 * gfx_get_display_video_offset (PRIVATE ROUTINE - NOT PART OF API) 2477 * 2478 * This routine is called by "gfx_get_video_offset". It abstracts the 2479 * version of the display controller from the video overlay routines. 2480 *--------------------------------------------------------------------------- 2481 */ 2482#if GFX_DISPLAY_DYNAMIC 2483unsigned long 2484gu1_get_display_video_offset(void) 2485#else 2486unsigned long 2487gfx_get_display_video_offset(void) 2488#endif 2489{ 2490 return (READ_REG32(DC_VID_ST_OFFSET) & 0x003FFFFF); 2491} 2492 2493/*--------------------------------------------------------------------------- 2494 * gfx_get_display_video_size (PRIVATE ROUTINE - NOT PART OF API) 2495 * 2496 * This routine is called by "gfx_get_video_size". It abstracts the 2497 * version of the display controller from the video overlay routines. 2498 *--------------------------------------------------------------------------- 2499 */ 2500#if GFX_DISPLAY_DYNAMIC 2501unsigned long 2502gu1_get_display_video_size(void) 2503#else 2504unsigned long 2505gfx_get_display_video_size(void) 2506#endif 2507{ 2508 /* RETURN TOTAL SIZE, IN BYTES */ 2509 return ((READ_REG32(DC_BUF_SIZE) >> 10) & 0x000FFFC0); 2510} 2511 2512/*----------------------------------------------------------------------------- 2513 * gfx_get_display_priority_high 2514 *----------------------------------------------------------------------------- 2515 */ 2516#if GFX_DISPLAY_DYNAMIC 2517int 2518gu1_get_display_priority_high(void) 2519#else 2520int 2521gfx_get_display_priority_high(void) 2522#endif 2523{ 2524 if (READ_REG32(MC_MEM_CNTRL1) & MC_XBUSARB) 2525 return (1); 2526 else 2527 return (0); 2528} 2529 2530#endif /* GFX_READ_ROUTINES */ 2531 2532/* END OF FILE */ 2533