atimode.c revision 1b12faf6
1/* 2 * Copyright 2000 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that copyright 7 * notice and this permission notice appear in supporting documentation, and 8 * that the name of Marc Aurele La France not be used in advertising or 9 * publicity pertaining to distribution of the software without specific, 10 * written prior permission. Marc Aurele La France makes no representations 11 * about the suitability of this software for any purpose. It is provided 12 * "as-is" without express or implied warranty. 13 * 14 * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO 16 * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20 * PERFORMANCE OF THIS SOFTWARE. 21 */ 22 23#ifdef HAVE_CONFIG_H 24#include "config.h" 25#endif 26 27#include <string.h> 28 29#include "ati.h" 30#include "atichip.h" 31#include "atidac.h" 32#include "atidsp.h" 33#include "atimach64.h" 34#include "atimach64io.h" 35#include "atimode.h" 36#include "atiprint.h" 37#include "atirgb514.h" 38#include "ativga.h" 39#include "atiwonder.h" 40#include "atiwonderio.h" 41 42#ifdef TV_OUT 43 44#include "vbe.h" 45 46#endif /* TV_OUT */ 47 48#ifndef AVOID_CPIO 49 50/* 51 * ATICopyVGAMemory -- 52 * 53 * This function is called to copy one or all banks of a VGA plane. 54 */ 55static void 56ATICopyVGAMemory 57( 58 ATIPtr pATI, 59 ATIHWPtr pATIHW, 60 pointer *saveptr, 61 pointer *from, 62 pointer *to 63) 64{ 65 unsigned int iBank; 66 67 for (iBank = 0; iBank < pATIHW->nBank; iBank++) 68 { 69 (*pATIHW->SetBank)(pATI, iBank); 70 (void)memcpy(*to, *from, 0x00010000U); 71 *saveptr = (char *)(*saveptr) + 0x00010000U; 72 } 73} 74 75/* 76 * ATISwap -- 77 * 78 * This function saves/restores video memory contents during video mode 79 * switches. 80 */ 81static void 82ATISwap 83( 84 int iScreen, 85 ATIPtr pATI, 86 ATIHWPtr pATIHW, 87 Bool ToFB 88) 89{ 90 pointer save, *from, *to; 91 unsigned int iPlane = 0, PlaneMask = 1; 92 CARD8 seq2, seq4, gra1, gra3, gra4, gra5, gra6, gra8; 93 94 /* 95 * This is only done for non-accelerator modes. If the video state on 96 * server entry was an accelerator mode, the application that relinquished 97 * the console had better do the Right Thing (tm) anyway by saving and 98 * restoring its own video memory contents. 99 */ 100 if (pATIHW->crtc != ATI_CRTC_VGA) 101 return; 102 103 if (ToFB) 104 { 105 if (!pATIHW->frame_buffer) 106 return; 107 108 from = &save; 109 to = &pATI->pBank; 110 } 111 else 112 { 113 /* Allocate the memory */ 114 if (!pATIHW->frame_buffer) 115 { 116 pATIHW->frame_buffer = 117 (pointer)malloc(pATIHW->nBank * pATIHW->nPlane * 0x00010000U); 118 if (!pATIHW->frame_buffer) 119 { 120 xf86DrvMsg(iScreen, X_WARNING, 121 "Temporary frame buffer could not be allocated.\n"); 122 return; 123 } 124 } 125 126 from = &pATI->pBank; 127 to = &save; 128 } 129 130 /* Turn off screen */ 131 ATIVGASaveScreen(pATI, SCREEN_SAVER_ON); 132 133 /* Save register values to be modified */ 134 seq2 = GetReg(SEQX, 0x02U); 135 seq4 = GetReg(SEQX, 0x04U); 136 gra1 = GetReg(GRAX, 0x01U); 137 gra3 = GetReg(GRAX, 0x03U); 138 gra5 = GetReg(GRAX, 0x05U); 139 gra6 = GetReg(GRAX, 0x06U); 140 gra8 = GetReg(GRAX, 0x08U); 141 142 save = pATIHW->frame_buffer; 143 144 /* Temporarily normalise the mode */ 145 if (gra1 != 0x00U) 146 PutReg(GRAX, 0x01U, 0x00U); 147 if (gra3 != 0x00U) 148 PutReg(GRAX, 0x03U, 0x00U); 149 if (gra6 != 0x05U) 150 PutReg(GRAX, 0x06U, 0x05U); 151 if (gra8 != 0xFFU) 152 PutReg(GRAX, 0x08U, 0xFFU); 153 154 if (seq4 & 0x08U) 155 { 156 /* Setup packed mode memory */ 157 if (seq2 != 0x0FU) 158 PutReg(SEQX, 0x02U, 0x0FU); 159 if (seq4 != 0x0AU) 160 PutReg(SEQX, 0x04U, 0x0AU); 161 if (pATI->Chip < ATI_CHIP_264CT) 162 { 163 if (gra5 != 0x00U) 164 PutReg(GRAX, 0x05U, 0x00U); 165 } 166 else 167 { 168 if (gra5 != 0x40U) 169 PutReg(GRAX, 0x05U, 0x40U); 170 } 171 172 ATICopyVGAMemory(pATI, pATIHW, &save, from, to); 173 174 if (seq2 != 0x0FU) 175 PutReg(SEQX, 0x02U, seq2); 176 if (seq4 != 0x0AU) 177 PutReg(SEQX, 0x04U, seq4); 178 if (pATI->Chip < ATI_CHIP_264CT) 179 { 180 if (gra5 != 0x00U) 181 PutReg(GRAX, 0x05U, gra5); 182 } 183 else 184 { 185 if (gra5 != 0x40U) 186 PutReg(GRAX, 0x05U, gra5); 187 } 188 } 189 else 190 { 191 gra4 = GetReg(GRAX, 0x04U); 192 193 /* Setup planar mode memory */ 194 if (seq4 != 0x06U) 195 PutReg(SEQX, 0x04U, 0x06U); 196 if (gra5 != 0x00U) 197 PutReg(GRAX, 0x05U, 0x00U); 198 199 for (; iPlane < pATIHW->nPlane; iPlane++) 200 { 201 PutReg(SEQX, 0x02U, PlaneMask); 202 PutReg(GRAX, 0x04U, iPlane); 203 ATICopyVGAMemory(pATI, pATIHW, &save, from, to); 204 PlaneMask <<= 1; 205 } 206 207 PutReg(SEQX, 0x02U, seq2); 208 if (seq4 != 0x06U) 209 PutReg(SEQX, 0x04U, seq4); 210 PutReg(GRAX, 0x04U, gra4); 211 if (gra5 != 0x00U) 212 PutReg(GRAX, 0x05U, gra5); 213 } 214 215 /* Restore registers */ 216 if (gra1 != 0x00U) 217 PutReg(GRAX, 0x01U, gra1); 218 if (gra3 != 0x00U) 219 PutReg(GRAX, 0x03U, gra3); 220 if (gra6 != 0x05U) 221 PutReg(GRAX, 0x06U, gra6); 222 if (gra8 != 0xFFU) 223 PutReg(GRAX, 0x08U, gra8); 224 225 /* Back to bank 0 */ 226 (*pATIHW->SetBank)(pATI, 0); 227} 228 229#endif /* AVOID_CPIO */ 230 231/* 232 * ATIModePreInit -- 233 * 234 * This function initialises an ATIHWRec with information common to all video 235 * states generated by the driver. 236 */ 237void 238ATIModePreInit 239( 240 ScrnInfoPtr pScreenInfo, 241 ATIPtr pATI, 242 ATIHWPtr pATIHW 243) 244{ 245 CARD32 lcd_index; 246 247#ifndef AVOID_CPIO 248 249 if (pATI->VGAAdapter) 250 { 251 /* Fill in VGA data */ 252 ATIVGAPreInit(pATI, pATIHW); 253 254 /* Fill in VGA Wonder data */ 255 if (pATI->CPIO_VGAWonder) 256 ATIVGAWonderPreInit(pATI, pATIHW); 257 } 258 259#endif /* AVOID_CPIO */ 260 261 { 262 /* Fill in Mach64 data */ 263 ATIMach64PreInit(pScreenInfo, pATI, pATIHW); 264 265 if (pATI->Chip >= ATI_CHIP_264CT) 266 { 267 /* Ensure proper VCLK source */ 268 pATIHW->pll_vclk_cntl = ATIMach64GetPLLReg(PLL_VCLK_CNTL) | 269 (PLL_VCLK_SRC_SEL | PLL_VCLK_RESET); 270 271 /* Set provisional values for other PLL registers */ 272 pATIHW->pll_vclk_post_div = ATIMach64GetPLLReg(PLL_VCLK_POST_DIV); 273 pATIHW->pll_vclk0_fb_div = ATIMach64GetPLLReg(PLL_VCLK0_FB_DIV); 274 pATIHW->pll_vclk1_fb_div = ATIMach64GetPLLReg(PLL_VCLK1_FB_DIV); 275 pATIHW->pll_vclk2_fb_div = ATIMach64GetPLLReg(PLL_VCLK2_FB_DIV); 276 pATIHW->pll_vclk3_fb_div = ATIMach64GetPLLReg(PLL_VCLK3_FB_DIV); 277 pATIHW->pll_xclk_cntl = ATIMach64GetPLLReg(PLL_XCLK_CNTL); 278 279 /* For now disable extended reference and feedback dividers */ 280 if (pATI->Chip >= ATI_CHIP_264LT) 281 pATIHW->pll_ext_vpll_cntl = 282 ATIMach64GetPLLReg(PLL_EXT_VPLL_CNTL) & 283 ~(PLL_EXT_VPLL_EN | PLL_EXT_VPLL_VGA_EN | 284 PLL_EXT_VPLL_INSYNC); 285 286 /* Initialise CRTC data for LCD panels */ 287 if (pATI->LCDPanelID >= 0) 288 { 289 if (pATI->Chip == ATI_CHIP_264LT) 290 { 291 pATIHW->lcd_gen_ctrl = inr(LCD_GEN_CTRL); 292 } 293 else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || 294 (pATI->Chip == ATI_CHIP_264XL) || 295 (pATI->Chip == ATI_CHIP_MOBILITY)) */ 296 { 297 lcd_index = inr(LCD_INDEX); 298 pATIHW->lcd_index = lcd_index & 299 ~(LCD_REG_INDEX | LCD_DISPLAY_DIS | LCD_SRC_SEL | 300 LCD_CRTC2_DISPLAY_DIS); 301 if (pATI->Chip != ATI_CHIP_264XL) 302 pATIHW->lcd_index |= LCD_CRTC2_DISPLAY_DIS; 303 pATIHW->config_panel = 304 ATIMach64GetLCDReg(LCD_CONFIG_PANEL) | 305 DONT_SHADOW_HEND; 306 pATIHW->lcd_gen_ctrl = 307 ATIMach64GetLCDReg(LCD_GEN_CNTL) & ~CRTC_RW_SELECT; 308 outr(LCD_INDEX, lcd_index); 309 } 310 311 pATIHW->lcd_gen_ctrl &= 312 ~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 | MCLK_PM_EN | 313 VCLK_DAC_PM_EN | USE_SHADOWED_VEND | 314 USE_SHADOWED_ROWCUR | SHADOW_EN | SHADOW_RW_EN); 315 pATIHW->lcd_gen_ctrl |= DONT_SHADOW_VPAR | LOCK_8DOT; 316 317 if (!pATI->OptionPanelDisplay) 318 { 319 /* 320 * Use primary CRTC to drive the CRT. Turn off panel 321 * interface. 322 */ 323 pATIHW->lcd_gen_ctrl &= ~LCD_ON; 324 pATIHW->lcd_gen_ctrl |= CRT_ON; 325 } 326 else 327 { 328 /* Use primary CRTC to drive the panel */ 329 pATIHW->lcd_gen_ctrl |= LCD_ON; 330 331 /* If requested, also force CRT on */ 332 if (pATI->OptionCRTDisplay) 333 pATIHW->lcd_gen_ctrl |= CRT_ON; 334 } 335 } 336 } 337 else if (pATI->DAC == ATI_DAC_IBMRGB514) 338 { 339 ATIRGB514PreInit(pATI, pATIHW); 340 } 341 } 342 343 /* Set RAMDAC data */ 344 ATIDACPreInit(pScreenInfo, pATI, pATIHW); 345} 346 347/* 348 * ATIModeSave -- 349 * 350 * This function saves the current video state. 351 */ 352void 353ATIModeSave 354( 355 ScrnInfoPtr pScreenInfo, 356 ATIPtr pATI, 357 ATIHWPtr pATIHW 358) 359{ 360 361#ifndef AVOID_CPIO 362 363 int Index; 364 365 /* Get back to bank 0 */ 366 (*pATIHW->SetBank)(pATI, 0); 367 368#endif /* AVOID_CPIO */ 369 370 if (pATI->Chip >= ATI_CHIP_264CT) 371 { 372 pATIHW->pll_vclk_cntl = ATIMach64GetPLLReg(PLL_VCLK_CNTL) | 373 PLL_VCLK_RESET; 374 pATIHW->pll_vclk_post_div = ATIMach64GetPLLReg(PLL_VCLK_POST_DIV); 375 pATIHW->pll_vclk0_fb_div = ATIMach64GetPLLReg(PLL_VCLK0_FB_DIV); 376 pATIHW->pll_vclk1_fb_div = ATIMach64GetPLLReg(PLL_VCLK1_FB_DIV); 377 pATIHW->pll_vclk2_fb_div = ATIMach64GetPLLReg(PLL_VCLK2_FB_DIV); 378 pATIHW->pll_vclk3_fb_div = ATIMach64GetPLLReg(PLL_VCLK3_FB_DIV); 379 pATIHW->pll_xclk_cntl = ATIMach64GetPLLReg(PLL_XCLK_CNTL); 380 if (pATI->Chip >= ATI_CHIP_264LT) 381 pATIHW->pll_ext_vpll_cntl = ATIMach64GetPLLReg(PLL_EXT_VPLL_CNTL); 382 383 /* Save LCD registers */ 384 if (pATI->LCDPanelID >= 0) 385 { 386 if (pATI->Chip == ATI_CHIP_264LT) 387 { 388 pATIHW->horz_stretching = inr(HORZ_STRETCHING); 389 pATIHW->vert_stretching = inr(VERT_STRETCHING); 390 pATIHW->lcd_gen_ctrl = inr(LCD_GEN_CTRL); 391 392 /* Set up to save non-shadow registers */ 393 outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl & ~SHADOW_RW_EN); 394 } 395 else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || 396 (pATI->Chip == ATI_CHIP_264XL) || 397 (pATI->Chip == ATI_CHIP_MOBILITY)) */ 398 { 399 pATIHW->lcd_index = inr(LCD_INDEX); 400 pATIHW->config_panel = ATIMach64GetLCDReg(LCD_CONFIG_PANEL); 401 pATIHW->lcd_gen_ctrl = ATIMach64GetLCDReg(LCD_GEN_CNTL); 402 pATIHW->horz_stretching = 403 ATIMach64GetLCDReg(LCD_HORZ_STRETCHING); 404 pATIHW->vert_stretching = 405 ATIMach64GetLCDReg(LCD_VERT_STRETCHING); 406 pATIHW->ext_vert_stretch = 407 ATIMach64GetLCDReg(LCD_EXT_VERT_STRETCH); 408 409 /* Set up to save non-shadow registers */ 410 ATIMach64PutLCDReg(LCD_GEN_CNTL, 411 pATIHW->lcd_gen_ctrl & ~(CRTC_RW_SELECT | SHADOW_RW_EN)); 412 } 413 } 414 } 415 416#ifndef AVOID_CPIO 417 418 if (pATI->VGAAdapter) 419 { 420 /* Save VGA data */ 421 ATIVGASave(pATI, pATIHW); 422 423 /* Save VGA Wonder data */ 424 if (pATI->CPIO_VGAWonder) 425 ATIVGAWonderSave(pATI, pATIHW); 426 } 427 428#endif /* AVOID_CPIO */ 429 430 { 431 /* Save Mach64 data */ 432 ATIMach64Save(pATI, pATIHW); 433 434 if (pATI->Chip >= ATI_CHIP_264VTB) 435 { 436 /* Save DSP data */ 437 ATIDSPSave(pATI, pATIHW); 438 439 if (pATI->LCDPanelID >= 0) 440 { 441 /* Switch to shadow registers */ 442 if (pATI->Chip == ATI_CHIP_264LT) 443 outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl | SHADOW_RW_EN); 444 else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || 445 (pATI->Chip == ATI_CHIP_264XL) || 446 (pATI->Chip == ATI_CHIP_MOBILITY)) */ 447 ATIMach64PutLCDReg(LCD_GEN_CNTL, 448 (pATIHW->lcd_gen_ctrl & ~CRTC_RW_SELECT) | 449 SHADOW_RW_EN); 450 451#ifndef AVOID_CPIO 452 453 /* Save shadow VGA CRTC registers */ 454 for (Index = 0; 455 Index < NumberOf(pATIHW->shadow_vga); 456 Index++) 457 pATIHW->shadow_vga[Index] = 458 GetReg(CRTX(pATI->CPIO_VGABase), Index); 459 460#endif /* AVOID_CPIO */ 461 462 /* Save shadow Mach64 CRTC registers */ 463 pATIHW->shadow_h_total_disp = inr(CRTC_H_TOTAL_DISP); 464 pATIHW->shadow_h_sync_strt_wid = inr(CRTC_H_SYNC_STRT_WID); 465 pATIHW->shadow_v_total_disp = inr(CRTC_V_TOTAL_DISP); 466 pATIHW->shadow_v_sync_strt_wid = inr(CRTC_V_SYNC_STRT_WID); 467 468 /* Restore CRTC selection and shadow state */ 469 if (pATI->Chip == ATI_CHIP_264LT) 470 { 471 outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl); 472 } 473 else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || 474 (pATI->Chip == ATI_CHIP_264XL) || 475 (pATI->Chip == ATI_CHIP_MOBILITY)) */ 476 { 477 ATIMach64PutLCDReg(LCD_GEN_CNTL, pATIHW->lcd_gen_ctrl); 478 outr(LCD_INDEX, pATIHW->lcd_index); 479 } 480 } 481 } 482 else if (pATI->DAC == ATI_DAC_IBMRGB514) 483 ATIRGB514Save(pATI, pATIHW); 484 } 485 486 /* Save RAMDAC state */ 487 ATIDACSave(pATI, pATIHW); 488 489 if (pATIHW != &pATI->NewHW) 490 { 491 pATIHW->FeedbackDivider = 0; /* Don't programme clock */ 492 } 493 494#ifndef AVOID_CPIO 495 496 /* Save video memory */ 497 ATISwap(pScreenInfo->scrnIndex, pATI, pATIHW, FALSE); 498 499 if (pATI->VGAAdapter) 500 ATIVGASaveScreen(pATI, SCREEN_SAVER_OFF); /* Turn on screen */ 501 502#endif /* AVOID_CPIO */ 503 504} 505 506/* 507 * ATIModeCalculate -- 508 * 509 * This function fills in an ATIHWRec with all register values needed to enable 510 * a video state. It's important that this be done without modifying the 511 * current video state. 512 */ 513Bool 514ATIModeCalculate 515( 516 int iScreen, 517 ATIPtr pATI, 518 ATIHWPtr pATIHW, 519 DisplayModePtr pMode 520) 521{ 522 CARD32 lcd_index; 523 int Index, ECPClock, MaxScalerClock; 524 525 /* Fill in Mach64 data */ 526 ATIMach64Calculate(pATI, pATIHW, pMode); 527 528 /* Set up LCD register values */ 529 if (pATI->LCDPanelID >= 0) 530 { 531 int VDisplay = pMode->VDisplay; 532 533 if (pMode->Flags & V_DBLSCAN) 534 VDisplay <<= 1; 535 if (pMode->VScan > 1) 536 VDisplay *= pMode->VScan; 537 if (pMode->Flags & V_INTERLACE) 538 VDisplay >>= 1; 539 540 /* Ensure secondary CRTC is completely disabled */ 541 pATIHW->crtc_gen_cntl &= ~(CRTC2_EN | CRTC2_PIX_WIDTH); 542 543 if (pATI->Chip == ATI_CHIP_264LT) 544 { 545 pATIHW->horz_stretching = inr(HORZ_STRETCHING); 546 } 547 else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || 548 (pATI->Chip == ATI_CHIP_264XL) || 549 (pATI->Chip == ATI_CHIP_MOBILITY)) */ 550 { 551 lcd_index = inr(LCD_INDEX); 552 pATIHW->horz_stretching = ATIMach64GetLCDReg(LCD_HORZ_STRETCHING); 553 pATIHW->ext_vert_stretch = 554 ATIMach64GetLCDReg(LCD_EXT_VERT_STRETCH) & 555 ~(AUTO_VERT_RATIO | VERT_STRETCH_MODE | VERT_STRETCH_RATIO3); 556 557 /* 558 * Don't use vertical blending if the mode is too wide or not 559 * vertically stretched. 560 */ 561 if (pATI->OptionPanelDisplay && 562 (pMode->HDisplay <= pATI->LCDVBlendFIFOSize) && 563 (VDisplay < pATI->LCDVertical)) 564 pATIHW->ext_vert_stretch |= VERT_STRETCH_MODE; 565 566 outr(LCD_INDEX, lcd_index); 567 } 568 569 pATIHW->horz_stretching &= 570 ~(HORZ_STRETCH_RATIO | HORZ_STRETCH_LOOP | AUTO_HORZ_RATIO | 571 HORZ_STRETCH_MODE | HORZ_STRETCH_EN); 572 if (pATI->OptionPanelDisplay && 573 (pMode->HDisplay < pATI->LCDHorizontal)) 574 do 575 { 576 /* 577 * The horizontal blender misbehaves when HDisplay is less than a 578 * a certain threshold (440 for a 1024-wide panel). It doesn't 579 * stretch such modes enough. Use pixel replication instead of 580 * blending to stretch modes that can be made to exactly fit the 581 * panel width. The undocumented "NoLCDBlend" option allows the 582 * pixel-replicated mode to be slightly wider or narrower than the 583 * panel width. It also causes a mode that is exactly half as wide 584 * as the panel to be pixel-replicated, rather than blended. 585 */ 586 int HDisplay = pMode->HDisplay & ~7; 587 int nStretch = pATI->LCDHorizontal / HDisplay; 588 int Remainder = pATI->LCDHorizontal % HDisplay; 589 590 if ((!Remainder && ((nStretch > 2) || !pATI->OptionBlend)) || 591 (((HDisplay * 16) / pATI->LCDHorizontal) < 7)) 592 { 593 static const char StretchLoops[] = {10, 12, 13, 15, 16}; 594 int horz_stretch_loop = -1, BestRemainder; 595 int Numerator = HDisplay, Denominator = pATI->LCDHorizontal; 596 597 ATIReduceRatio(&Numerator, &Denominator); 598 599 BestRemainder = (Numerator * 16) / Denominator; 600 Index = NumberOf(StretchLoops); 601 while (--Index >= 0) 602 { 603 Remainder = 604 ((Denominator - Numerator) * StretchLoops[Index]) % 605 Denominator; 606 if (Remainder < BestRemainder) 607 { 608 horz_stretch_loop = Index; 609 if (!(BestRemainder = Remainder)) 610 break; 611 } 612#if 0 613 /* 614 * Enabling this code allows the pixel-replicated mode to 615 * be slightly wider than the panel width. 616 */ 617 Remainder = Denominator - Remainder; 618 if (Remainder < BestRemainder) 619 { 620 horz_stretch_loop = Index; 621 BestRemainder = Remainder; 622 } 623#endif 624 } 625 626 if ((horz_stretch_loop >= 0) && 627 (!BestRemainder || !pATI->OptionBlend)) 628 { 629 int horz_stretch_ratio = 0, Accumulator = 0; 630 int reuse_previous = 1; 631 632 Index = StretchLoops[horz_stretch_loop]; 633 634 while (--Index >= 0) 635 { 636 if (Accumulator > 0) 637 horz_stretch_ratio |= reuse_previous; 638 else 639 Accumulator += Denominator; 640 Accumulator -= Numerator; 641 reuse_previous <<= 1; 642 } 643 644 pATIHW->horz_stretching |= HORZ_STRETCH_EN | 645 SetBits(horz_stretch_loop, HORZ_STRETCH_LOOP) | 646 SetBits(horz_stretch_ratio, HORZ_STRETCH_RATIO); 647 break; /* Out of the do { ... } while (0) */ 648 } 649 } 650 651 pATIHW->horz_stretching |= (HORZ_STRETCH_MODE | HORZ_STRETCH_EN) | 652 SetBits((HDisplay * (MaxBits(HORZ_STRETCH_BLEND) + 1)) / 653 pATI->LCDHorizontal, HORZ_STRETCH_BLEND); 654 } while (0); 655 656 if (!pATI->OptionPanelDisplay || (VDisplay >= pATI->LCDVertical)) 657 { 658 pATIHW->vert_stretching = 0; 659 } 660 else 661 { 662 pATIHW->vert_stretching = (VERT_STRETCH_USE0 | VERT_STRETCH_EN) | 663 SetBits((VDisplay * (MaxBits(VERT_STRETCH_RATIO0) + 1)) / 664 pATI->LCDVertical, VERT_STRETCH_RATIO0); 665 } 666 667#ifndef AVOID_CPIO 668 669 /* Copy non-shadow CRTC register values to the shadow set */ 670 for (Index = 0; Index < NumberOf(pATIHW->shadow_vga); Index++) 671 pATIHW->shadow_vga[Index] = pATIHW->crt[Index]; 672 673#endif /* AVOID_CPIO */ 674 675 pATIHW->shadow_h_total_disp = pATIHW->crtc_h_total_disp; 676 pATIHW->shadow_h_sync_strt_wid = pATIHW->crtc_h_sync_strt_wid; 677 pATIHW->shadow_v_total_disp = pATIHW->crtc_v_total_disp; 678 pATIHW->shadow_v_sync_strt_wid = pATIHW->crtc_v_sync_strt_wid; 679 } 680 681 /* Fill in clock data */ 682 if (!ATIClockCalculate(iScreen, pATI, pATIHW, pMode)) 683 return FALSE; 684 685 /* Setup ECP clock divider */ 686 if (pATI->Chip >= ATI_CHIP_264VT) 687 { 688 if (pATI->Chip <= ATI_CHIP_264VT3) 689 MaxScalerClock = 80000; 690 else if (pATI->Chip <= ATI_CHIP_264GT2C) 691 MaxScalerClock = 100000; 692 else if (pATI->Chip == ATI_CHIP_264GTPRO) 693 MaxScalerClock = 125000; 694 else if (pATI->Chip <= ATI_CHIP_MOBILITY) 695 MaxScalerClock = 135000; 696 else 697 MaxScalerClock = 80000; /* Conservative */ 698 pATIHW->pll_vclk_cntl &= ~PLL_ECP_DIV; 699#ifdef TV_OUT 700 if (pATI->OptionTvOut) { 701 /* XXX Don't do this for TVOut! */ 702 } 703 else 704#endif /* TV_OUT */ 705 { 706 ECPClock = pMode->SynthClock; 707 for (Index = 0; (ECPClock > MaxScalerClock) && (Index < 2); Index++) 708 ECPClock >>= 1; 709 pATIHW->pll_vclk_cntl |= SetBits(Index, PLL_ECP_DIV); 710 } 711 } 712 else if (pATI->DAC == ATI_DAC_IBMRGB514) 713 { 714 ATIRGB514Calculate(pATI, pATIHW, pMode); 715 } 716 717 return TRUE; 718} 719 720#ifdef TV_OUT 721 722static void 723ATISetVBEMode 724( 725 ScrnInfoPtr pScreenInfo, 726 ATIPtr pATI, 727 ATIHWPtr pATIHW 728) 729{ 730 if (pATIHW->crtc == ATI_CRTC_MACH64) { 731 int vbemode, modekey; 732 733 /* Find a suitable VESA VBE mode, if one exists */ 734 modekey = (pScreenInfo->depth << 16) | 735 (pScreenInfo->currentMode->HDisplay); 736 737 switch (modekey) { 738 case (15<<16)|(640): 739 vbemode = 0x110; 740 break; 741 case (16<<16)|(640): 742 vbemode = 0x111; 743 break; 744#if 0 745 case (24<<16)|(640): 746 vbemode = 0x112; 747 break; 748#endif 749 case (15<<16)|(800): 750 vbemode = 0x113; 751 break; 752 case (16<<16)|(800): 753 vbemode = 0x114; 754 break; 755#if 0 756 case (24<<16)|(800): 757 vbemode = 0x115; 758 break; 759#endif 760 case (15<<16)|(1024): 761 vbemode = 0x116; 762 break; 763 case (16<<16)|(1024): 764 vbemode = 0x117; 765 break; 766#if 0 767 case (24<<16)|(1024): 768 vbemode = 0x118; 769 break; 770#endif 771 default: 772 xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, 773 "Mode not supported for TV-Out: depth: %d HDisplay: %d\n", 774 modekey>>16, modekey & 0xffff); 775 return; 776 } 777 778 if (pATI->pVBE) { 779 780 /* Preserve video memory contents */ 781 vbemode |= (1<<15); 782 783 if (VBESetVBEMode(pATI->pVBE, vbemode, NULL)) { 784 xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, 785 "VBESetMode: 0x%X (width: %d, pitch: %d, depth: %d)\n", 786 vbemode, 787 pScreenInfo->currentMode->HDisplay, 788 pScreenInfo->displayWidth, 789 pScreenInfo->depth); 790 outr(CRTC_OFF_PITCH, 791 SetBits(pScreenInfo->displayWidth>>3, CRTC_PITCH)); 792 } else { 793 xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, "VBESetMode failed.\n"); 794 } 795 } else { 796 xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, "VBE module not loaded.\n"); 797 } 798 } else { 799 /* restore text mode with VBESetMode */ 800 if (pATI->pVBE) { 801 if (VBESetVBEMode(pATI->pVBE, pATI->vbemode, NULL)) { 802 xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, "Restoring VESA mode: 0x%x\n", 803 pATI->vbemode); 804 } else { 805 xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, "VBESetMode failed.\n"); 806 } 807 } else { 808 xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, "VBE module not loaded.\n"); 809 } 810 } 811 if (xf86ServerIsExiting()) { 812 if (pATI->pVBE) vbeFree(pATI->pVBE); 813 if (pATI->pInt10) xf86FreeInt10(pATI->pInt10); 814 } 815} 816 817#endif /* TV_OUT */ 818 819/* 820 * ATIModeSet -- 821 * 822 * This function sets a video mode. It writes out all video state data that 823 * has been previously calculated or saved. 824 */ 825void 826ATIModeSet 827( 828 ScrnInfoPtr pScreenInfo, 829 ATIPtr pATI, 830 ATIHWPtr pATIHW 831) 832{ 833 834#ifndef AVOID_CPIO 835 836 int Index; 837 838 /* Get back to bank 0 */ 839 (*pATIHW->SetBank)(pATI, 0); 840 841#endif /* AVOID_CPIO */ 842 843 { 844 /* Stop CRTC */ 845 outr(CRTC_GEN_CNTL, 846 pATIHW->crtc_gen_cntl & ~(CRTC_EXT_DISP_EN | CRTC_EN)); 847 848 if (pATI->Chip >= ATI_CHIP_264CT) 849 { 850 ATIMach64PutPLLReg(PLL_VCLK_CNTL, pATIHW->pll_vclk_cntl); 851 ATIMach64PutPLLReg(PLL_VCLK_POST_DIV, pATIHW->pll_vclk_post_div); 852 ATIMach64PutPLLReg(PLL_VCLK0_FB_DIV, pATIHW->pll_vclk0_fb_div); 853 ATIMach64PutPLLReg(PLL_VCLK1_FB_DIV, pATIHW->pll_vclk1_fb_div); 854 ATIMach64PutPLLReg(PLL_VCLK2_FB_DIV, pATIHW->pll_vclk2_fb_div); 855 ATIMach64PutPLLReg(PLL_VCLK3_FB_DIV, pATIHW->pll_vclk3_fb_div); 856 ATIMach64PutPLLReg(PLL_XCLK_CNTL, pATIHW->pll_xclk_cntl); 857 if (pATI->Chip >= ATI_CHIP_264LT) 858 ATIMach64PutPLLReg(PLL_EXT_VPLL_CNTL, 859 pATIHW->pll_ext_vpll_cntl); 860 ATIMach64PutPLLReg(PLL_VCLK_CNTL, 861 pATIHW->pll_vclk_cntl & ~PLL_VCLK_RESET); 862 863 /* Load LCD registers */ 864 if (pATI->LCDPanelID >= 0) 865 { 866 if (pATI->Chip == ATI_CHIP_264LT) 867 { 868 /* Update non-shadow registers first */ 869 outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl & ~SHADOW_RW_EN); 870 871 /* Temporarily disable stretching */ 872 outr(HORZ_STRETCHING, pATIHW->horz_stretching & 873 ~(HORZ_STRETCH_MODE | HORZ_STRETCH_EN)); 874 outr(VERT_STRETCHING, pATIHW->vert_stretching & 875 ~(VERT_STRETCH_RATIO1 | VERT_STRETCH_RATIO2 | 876 VERT_STRETCH_USE0 | VERT_STRETCH_EN)); 877 } 878 else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || 879 (pATI->Chip == ATI_CHIP_264XL) || 880 (pATI->Chip == ATI_CHIP_MOBILITY)) */ 881 { 882 /* Update non-shadow registers first */ 883 ATIMach64PutLCDReg(LCD_CONFIG_PANEL, pATIHW->config_panel); 884 ATIMach64PutLCDReg(LCD_GEN_CNTL, pATIHW->lcd_gen_ctrl & 885 ~(CRTC_RW_SELECT | SHADOW_RW_EN)); 886 887 /* Temporarily disable stretching */ 888 ATIMach64PutLCDReg(LCD_HORZ_STRETCHING, 889 pATIHW->horz_stretching & 890 ~(HORZ_STRETCH_MODE | HORZ_STRETCH_EN)); 891 ATIMach64PutLCDReg(LCD_VERT_STRETCHING, 892 pATIHW->vert_stretching & 893 ~(VERT_STRETCH_RATIO1 | VERT_STRETCH_RATIO2 | 894 VERT_STRETCH_USE0 | VERT_STRETCH_EN)); 895 } 896 } 897 } 898 } 899 900 switch (pATIHW->crtc) 901 { 902 903#ifndef AVOID_CPIO 904 905 case ATI_CRTC_VGA: 906 /* Start sequencer reset */ 907 PutReg(SEQX, 0x00U, 0x00U); 908 909 /* Set pixel clock */ 910 if ((pATIHW->FeedbackDivider > 0)) 911 ATIClockSet(pATI, pATIHW); 912 913 /* Set up RAMDAC */ 914 if (pATI->DAC == ATI_DAC_IBMRGB514) 915 ATIRGB514Set(pATI, pATIHW); 916 917 /* Load VGA Wonder */ 918 if (pATI->CPIO_VGAWonder) 919 ATIVGAWonderSet(pATI, pATIHW); 920 921 /* Load VGA device */ 922 ATIVGASet(pATI, pATIHW); 923 924 /* Load Mach64 registers */ 925 { 926 /* Load MMIO registers */ 927 if (pATI->Block0Base) 928 ATIMach64Set(pATI, pATIHW); 929 930 outr(CRTC_GEN_CNTL, pATIHW->crtc_gen_cntl); 931 outr(CUR_CLR0, pATIHW->cur_clr0); 932 outr(CUR_CLR1, pATIHW->cur_clr1); 933 outr(CUR_OFFSET, pATIHW->cur_offset); 934 outr(CUR_HORZ_VERT_POSN, pATIHW->cur_horz_vert_posn); 935 outr(CUR_HORZ_VERT_OFF, pATIHW->cur_horz_vert_off); 936 outr(BUS_CNTL, pATIHW->bus_cntl); 937 outr(MEM_VGA_WP_SEL, pATIHW->mem_vga_wp_sel); 938 outr(MEM_VGA_RP_SEL, pATIHW->mem_vga_rp_sel); 939 outr(DAC_CNTL, pATIHW->dac_cntl); 940 outr(GEN_TEST_CNTL, pATIHW->gen_test_cntl | GEN_GUI_EN); 941 outr(GEN_TEST_CNTL, pATIHW->gen_test_cntl); 942 outr(GEN_TEST_CNTL, pATIHW->gen_test_cntl | GEN_GUI_EN); 943 outr(CONFIG_CNTL, pATIHW->config_cntl); 944 if (pATI->Chip >= ATI_CHIP_264CT) 945 { 946 outr(CRTC_H_TOTAL_DISP, pATIHW->crtc_h_total_disp); 947 outr(CRTC_H_SYNC_STRT_WID, pATIHW->crtc_h_sync_strt_wid); 948 outr(CRTC_V_TOTAL_DISP, pATIHW->crtc_v_total_disp); 949 outr(CRTC_V_SYNC_STRT_WID, pATIHW->crtc_v_sync_strt_wid); 950 outr(CRTC_OFF_PITCH, pATIHW->crtc_off_pitch); 951 if (pATI->Chip >= ATI_CHIP_264VTB) 952 { 953 outr(MEM_CNTL, pATIHW->mem_cntl); 954 outr(MPP_CONFIG, pATIHW->mpp_config); 955 outr(MPP_STROBE_SEQ, pATIHW->mpp_strobe_seq); 956 outr(TVO_CNTL, pATIHW->tvo_cntl); 957 } 958 } 959 } 960 961 break; 962 963#endif /* AVOID_CPIO */ 964 965 case ATI_CRTC_MACH64: 966 /* Load Mach64 CRTC registers */ 967 ATIMach64Set(pATI, pATIHW); 968 969#ifndef AVOID_CPIO 970 971 if (pATI->VGAAdapter) 972 { 973 /* Oddly enough, these need to be set also, maybe others */ 974 PutReg(SEQX, 0x02U, pATIHW->seq[2]); 975 PutReg(SEQX, 0x04U, pATIHW->seq[4]); 976 PutReg(GRAX, 0x06U, pATIHW->gra[6]); 977 if (pATI->CPIO_VGAWonder) 978 ATIModifyExtReg(pATI, 0xB6U, -1, 0x00U, pATIHW->b6); 979 } 980 981#endif /* AVOID_CPIO */ 982 983 break; 984 985 default: 986 break; 987 } 988 989 if (pATI->LCDPanelID >= 0) 990 { 991 /* Switch to shadow registers */ 992 if (pATI->Chip == ATI_CHIP_264LT) 993 outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl | SHADOW_RW_EN); 994 else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || 995 (pATI->Chip == ATI_CHIP_264XL) || 996 (pATI->Chip == ATI_CHIP_MOBILITY)) */ 997 ATIMach64PutLCDReg(LCD_GEN_CNTL, 998 (pATIHW->lcd_gen_ctrl & ~CRTC_RW_SELECT) | SHADOW_RW_EN); 999 1000 /* Restore shadow registers */ 1001 switch (pATIHW->crtc) 1002 { 1003 1004#ifndef AVOID_CPIO 1005 1006 case ATI_CRTC_VGA: 1007 for (Index = 0; 1008 Index < NumberOf(pATIHW->shadow_vga); 1009 Index++) 1010 PutReg(CRTX(pATI->CPIO_VGABase), Index, 1011 pATIHW->shadow_vga[Index]); 1012 /* Fall through */ 1013 1014#endif /* AVOID_CPIO */ 1015 1016 case ATI_CRTC_MACH64: 1017 outr(CRTC_H_TOTAL_DISP, pATIHW->shadow_h_total_disp); 1018 outr(CRTC_H_SYNC_STRT_WID, pATIHW->shadow_h_sync_strt_wid); 1019 outr(CRTC_V_TOTAL_DISP, pATIHW->shadow_v_total_disp); 1020 outr(CRTC_V_SYNC_STRT_WID, pATIHW->shadow_v_sync_strt_wid); 1021 break; 1022 1023 default: 1024 break; 1025 } 1026 1027 /* Restore CRTC selection & shadow state and enable stretching */ 1028 if (pATI->Chip == ATI_CHIP_264LT) 1029 { 1030 outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl); 1031 outr(HORZ_STRETCHING, pATIHW->horz_stretching); 1032 outr(VERT_STRETCHING, pATIHW->vert_stretching); 1033 } 1034 else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || 1035 (pATI->Chip == ATI_CHIP_264XL) || 1036 (pATI->Chip == ATI_CHIP_MOBILITY)) */ 1037 { 1038 ATIMach64PutLCDReg(LCD_GEN_CNTL, pATIHW->lcd_gen_ctrl); 1039 ATIMach64PutLCDReg(LCD_HORZ_STRETCHING, pATIHW->horz_stretching); 1040 ATIMach64PutLCDReg(LCD_VERT_STRETCHING, pATIHW->vert_stretching); 1041 ATIMach64PutLCDReg(LCD_EXT_VERT_STRETCH, pATIHW->ext_vert_stretch); 1042 outr(LCD_INDEX, pATIHW->lcd_index); 1043 } 1044 } 1045 1046 /* 1047 * Set DSP registers. Note that, for some reason, sequencer resets clear 1048 * the DSP_CONFIG register on early integrated controllers. 1049 */ 1050 if (pATI->Chip >= ATI_CHIP_264VTB) 1051 ATIDSPSet(pATI, pATIHW); 1052 1053 /* Load RAMDAC */ 1054 ATIDACSet(pATI, pATIHW); 1055 1056 /* Reset hardware cursor caching */ 1057 pATI->CursorXOffset = pATI->CursorYOffset = (CARD16)(-1); 1058 1059#ifdef TV_OUT 1060 1061 /* Set VBE mode for TV-Out */ 1062 if (pATI->OptionTvOut /* && pATI->tvActive */) 1063 ATISetVBEMode(pScreenInfo, pATI, pATIHW); 1064 1065#endif /* TV_OUT */ 1066 1067#ifndef AVOID_CPIO 1068 1069 /* Restore video memory */ 1070 ATISwap(pScreenInfo->scrnIndex, pATI, pATIHW, TRUE); 1071 1072 if (pATI->VGAAdapter) 1073 ATIVGASaveScreen(pATI, SCREEN_SAVER_OFF); /* Turn on screen */ 1074 1075#endif /* AVOID_CPIO */ 1076 1077 if ((xf86GetVerbosity() > 3) && (pATIHW == &pATI->NewHW)) 1078 { 1079 xf86ErrorFVerb(4, "\n After setting mode \"%s\":\n\n", 1080 pScreenInfo->currentMode->name); 1081 ATIPrintMode(pScreenInfo->currentMode); 1082 ATIPrintRegisters(pATI); 1083 } 1084} 1085