via_outputs.c revision 90b17f1b
1dbbd9e4bSmacallan/* 2dbbd9e4bSmacallan * Copyright 2005-2007 The Openchrome Project [openchrome.org] 3dbbd9e4bSmacallan * Copyright 2004-2005 The Unichrome Project [unichrome.sf.net] 4dbbd9e4bSmacallan * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. 5dbbd9e4bSmacallan * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. 6dbbd9e4bSmacallan * 7dbbd9e4bSmacallan * Permission is hereby granted, free of charge, to any person obtaining a 8dbbd9e4bSmacallan * copy of this software and associated documentation files (the "Software"), 9dbbd9e4bSmacallan * to deal in the Software without restriction, including without limitation 10dbbd9e4bSmacallan * the rights to use, copy, modify, merge, publish, distribute, sub license, 11dbbd9e4bSmacallan * and/or sell copies of the Software, and to permit persons to whom the 12dbbd9e4bSmacallan * Software is furnished to do so, subject to the following conditions: 13dbbd9e4bSmacallan * 14cfa76ccdSmrg * The above copyright notice and this permission notice (including the 15cfa76ccdSmrg * next paragraph) shall be included in all copies or substantial portions 16cfa76ccdSmrg * of the Software. 17dbbd9e4bSmacallan * 18dbbd9e4bSmacallan * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19dbbd9e4bSmacallan * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20dbbd9e4bSmacallan * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 21dbbd9e4bSmacallan * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22dbbd9e4bSmacallan * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23dbbd9e4bSmacallan * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24dbbd9e4bSmacallan * DEALINGS IN THE SOFTWARE. 25dbbd9e4bSmacallan */ 26dbbd9e4bSmacallan 27dbbd9e4bSmacallan/* 28dbbd9e4bSmacallan * via_outputs.c 29dbbd9e4bSmacallan * 30dbbd9e4bSmacallan * Everything to do with setting and changing xf86Outputs. 31dbbd9e4bSmacallan * 32dbbd9e4bSmacallan */ 33dbbd9e4bSmacallan 34dbbd9e4bSmacallan#ifdef HAVE_CONFIG_H 35e96acad6Smrg#include "config.h" 36e96acad6Smrg#endif 37e96acad6Smrg 381c397cbaSmrg#include "via_driver.h" 391c397cbaSmrg#include <unistd.h> 401c397cbaSmrg 41cfa76ccdSmrg/* 42e96acad6Smrg * Modetable nonsense. 43e96acad6Smrg * 44dbbd9e4bSmacallan */ 45dbbd9e4bSmacallan#include "via_mode.h" 46dbbd9e4bSmacallan 47dbbd9e4bSmacallanstatic void 48dbbd9e4bSmacallanViaPrintMode(ScrnInfoPtr pScrn, DisplayModePtr mode) 49dbbd9e4bSmacallan{ 50dbbd9e4bSmacallan xf86PrintModeline(pScrn->scrnIndex, mode); 51dbbd9e4bSmacallan 52dbbd9e4bSmacallan xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcHDisplay: 0x%x\n", 53dbbd9e4bSmacallan mode->CrtcHDisplay); 54dbbd9e4bSmacallan xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcHBlankStart: 0x%x\n", 55dbbd9e4bSmacallan mode->CrtcHBlankStart); 56dbbd9e4bSmacallan xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcHSyncStart: 0x%x\n", 57dbbd9e4bSmacallan mode->CrtcHSyncStart); 58dbbd9e4bSmacallan xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcHSyncEnd: 0x%x\n", 59e96acad6Smrg mode->CrtcHSyncEnd); 60e96acad6Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcHBlankEnd: 0x%x\n", 61e96acad6Smrg mode->CrtcHBlankEnd); 62dbbd9e4bSmacallan xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcHTotal: 0x%x\n", 63dbbd9e4bSmacallan mode->CrtcHTotal); 64dbbd9e4bSmacallan xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcHSkew: 0x%x\n", 65dbbd9e4bSmacallan mode->CrtcHSkew); 66dbbd9e4bSmacallan xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcVDisplay: 0x%x\n", 67dbbd9e4bSmacallan mode->CrtcVDisplay); 68dbbd9e4bSmacallan xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcVBlankStart: 0x%x\n", 69dbbd9e4bSmacallan mode->CrtcVBlankStart); 70dbbd9e4bSmacallan xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcVSyncStart: 0x%x\n", 71dbbd9e4bSmacallan mode->CrtcVSyncStart); 72dbbd9e4bSmacallan xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcVSyncEnd: 0x%x\n", 73dbbd9e4bSmacallan mode->CrtcVSyncEnd); 74cfa76ccdSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcVBlankEnd: 0x%x\n", 75cfa76ccdSmrg mode->CrtcVBlankEnd); 76cfa76ccdSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcVTotal: 0x%x\n", 77dbbd9e4bSmacallan mode->CrtcVTotal); 78dbbd9e4bSmacallan 79dbbd9e4bSmacallan} 80dbbd9e4bSmacallan 81/* 82 * 83 * TV specific code. 84 * 85 */ 86void 87ViaTVSave(ScrnInfoPtr pScrn) 88{ 89 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 90 91 if (pBIOSInfo->TVSave) 92 pBIOSInfo->TVSave(pScrn); 93} 94 95void 96ViaTVRestore(ScrnInfoPtr pScrn) 97{ 98 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 99 100 if (pBIOSInfo->TVRestore) 101 pBIOSInfo->TVRestore(pScrn); 102} 103 104static Bool 105ViaTVDACSense(ScrnInfoPtr pScrn) 106{ 107 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 108 109 if (pBIOSInfo->TVDACSense) 110 return pBIOSInfo->TVDACSense(pScrn); 111 return FALSE; 112} 113 114static void 115ViaTVSetMode(xf86CrtcPtr crtc, DisplayModePtr mode) 116{ 117 ScrnInfoPtr pScrn = crtc->scrn; 118 VIAPtr pVia = VIAPTR(pScrn); 119 VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; 120 121 if (pBIOSInfo->TVModeI2C) 122 pBIOSInfo->TVModeI2C(pScrn, mode); 123 124 if (pBIOSInfo->TVModeCrtc) 125 pBIOSInfo->TVModeCrtc(crtc, mode); 126 127 /* TV reset. */ 128 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1D, 0x00); 129 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1D, 0x80); 130} 131 132void 133ViaTVPower(ScrnInfoPtr pScrn, Bool On) 134{ 135 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 136 137#ifdef HAVE_DEBUG 138 if (On) 139 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaTVPower: On.\n"); 140 else 141 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaTVPower: Off.\n"); 142#endif 143 144 if (pBIOSInfo->TVPower) 145 pBIOSInfo->TVPower(pScrn, On); 146} 147 148#ifdef HAVE_DEBUG 149void 150ViaTVPrintRegs(ScrnInfoPtr pScrn) 151{ 152 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 153 154 if (pBIOSInfo->TVPrintRegs) 155 pBIOSInfo->TVPrintRegs(pScrn); 156} 157#endif /* HAVE_DEBUG */ 158 159static void 160via_tv_create_resources(xf86OutputPtr output) 161{ 162} 163 164#ifdef RANDR_12_INTERFACE 165static Bool 166via_tv_set_property(xf86OutputPtr output, Atom property, 167 RRPropertyValuePtr value) 168{ 169 return FALSE; 170} 171 172static Bool 173via_tv_get_property(xf86OutputPtr output, Atom property) 174{ 175 return FALSE; 176} 177#endif 178 179static void 180via_tv_dpms(xf86OutputPtr output, int mode) 181{ 182 ScrnInfoPtr pScrn = output->scrn; 183 184 switch (mode) { 185 case DPMSModeOn: 186 ViaTVPower(pScrn, TRUE); 187 break; 188 189 case DPMSModeStandby: 190 case DPMSModeSuspend: 191 case DPMSModeOff: 192 ViaTVPower(pScrn, FALSE); 193 break; 194 } 195} 196 197static void 198via_tv_save(xf86OutputPtr output) 199{ 200 ScrnInfoPtr pScrn = output->scrn; 201 202 ViaTVSave(pScrn); 203} 204 205static void 206via_tv_restore(xf86OutputPtr output) 207{ 208 ScrnInfoPtr pScrn = output->scrn; 209 210 ViaTVRestore(pScrn); 211} 212 213static int 214via_tv_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) 215{ 216 ScrnInfoPtr pScrn = output->scrn; 217 VIAPtr pVia = VIAPTR(pScrn); 218 int ret = MODE_OK; 219 220 if (pVia->UseLegacyModeSwitch) { 221 VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; 222 223 if (pBIOSInfo->TVModeValid) { 224 ret = pBIOSInfo->TVModeValid(pScrn, pMode); 225 if (ret != MODE_OK) { 226 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 227 "Mode \"%s\" is not supported by TV encoder.\n", 228 pMode->name); 229 } 230 } 231 } else { 232 if (!ViaModeDotClockTranslate(pScrn, pMode)) 233 return MODE_NOCLOCK; 234 } 235 return ret; 236} 237 238static Bool 239via_tv_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, 240 DisplayModePtr adjusted_mode) 241{ 242 return TRUE; 243} 244 245static void 246via_tv_prepare(xf86OutputPtr output) 247{ 248 via_tv_dpms(output, DPMSModeOff); 249} 250 251static void 252via_tv_commit(xf86OutputPtr output) 253{ 254 via_tv_dpms(output, DPMSModeOn); 255} 256 257static void 258ViaDisplayEnableDVO(ScrnInfoPtr pScrn, int port) 259{ 260 vgaHWPtr hwp = VGAHWPTR(pScrn); 261 262 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaDisplayEnableDVO, port: %d\n", port)); 263 switch (port) { 264 case VIA_DI_PORT_DVP0: 265 ViaSeqMask(hwp, 0x1E, 0xC0, 0xC0); 266 break; 267 case VIA_DI_PORT_DVP1: 268 ViaSeqMask(hwp, 0x1E, 0x30, 0x30); 269 break; 270 } 271} 272 273static void 274ViaDisplayDisableDVO(ScrnInfoPtr pScrn, int port) 275{ 276 vgaHWPtr hwp = VGAHWPTR(pScrn); 277 278 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaDisplayDisableDVO, port: %d\n", port)); 279 switch (port) { 280 case VIA_DI_PORT_DVP0: 281 ViaSeqMask(hwp, 0x1E, 0x00, 0xC0); 282 break; 283 case VIA_DI_PORT_DVP1: 284 ViaSeqMask(hwp, 0x1E, 0x00, 0x30); 285 break; 286 } 287} 288 289static void 290ViaDisplaySetStreamOnDVO(ScrnInfoPtr pScrn, int port, int iga) 291{ 292 vgaHWPtr hwp = VGAHWPTR(pScrn); 293 int regNum; 294 295 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaDisplaySetStreamOnDVO, port: %d\n", port)); 296 297 switch (port) { 298 case VIA_DI_PORT_DVP0: 299 regNum = 0x96; 300 break; 301 case VIA_DI_PORT_DVP1: 302 regNum = 0x9B; 303 break; 304 case VIA_DI_PORT_DFPLOW: 305 regNum = 0x97; 306 break; 307 case VIA_DI_PORT_DFPHIGH: 308 regNum = 0x99; 309 break; 310 } 311 312 if (!iga) 313 ViaCrtcMask(hwp, regNum, 0x00, 0x10); 314 else 315 ViaCrtcMask(hwp, regNum, 0x10, 0x10); 316} 317 318static void 319via_tv_mode_set(xf86OutputPtr output, DisplayModePtr mode, 320 DisplayModePtr adjusted_mode) 321{ 322 ScrnInfoPtr pScrn = output->scrn; 323 VIAPtr pVia = VIAPTR(pScrn); 324 VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; 325 326 /* TV on FirstCrtc */ 327 if (output->crtc) { 328 drmmode_crtc_private_ptr iga = output->crtc->driver_private; 329 330 ViaDisplaySetStreamOnDVO(pScrn, pBIOSInfo->TVDIPort, iga->index); 331 } 332 ViaDisplayEnableDVO(pScrn, pBIOSInfo->TVDIPort); 333 334 ViaTVSetMode(output->crtc, adjusted_mode); 335 336 pVia->FirstInit = FALSE; 337} 338 339static xf86OutputStatus 340via_tv_detect(xf86OutputPtr output) 341{ 342 xf86OutputStatus status = XF86OutputStatusDisconnected; 343 ScrnInfoPtr pScrn = output->scrn; 344 345 if (ViaTVDACSense(pScrn)) 346 status = XF86OutputStatusConnected; 347 return status; 348} 349 350static DisplayModePtr 351via_tv_get_modes(xf86OutputPtr output) 352{ 353 DisplayModePtr modes = NULL, mode = NULL; 354 ScrnInfoPtr pScrn = output->scrn; 355 VIAPtr pVia = VIAPTR(pScrn); 356 int i; 357 358 for (i = 0; i < pVia->pBIOSInfo->TVNumModes; i++) { 359 mode = xf86DuplicateMode(&pVia->pBIOSInfo->TVModes[i]); 360 modes = xf86ModesAdd(modes, mode); 361 } 362 return modes; 363} 364 365static void 366via_tv_destroy(xf86OutputPtr output) 367{ 368} 369 370static const xf86OutputFuncsRec via_tv_funcs = { 371 .create_resources = via_tv_create_resources, 372#ifdef RANDR_12_INTERFACE 373 .set_property = via_tv_set_property, 374 .get_property = via_tv_get_property, 375#endif 376 .dpms = via_tv_dpms, 377 .save = via_tv_save, 378 .restore = via_tv_restore, 379 .mode_valid = via_tv_mode_valid, 380 .mode_fixup = via_tv_mode_fixup, 381 .prepare = via_tv_prepare, 382 .commit = via_tv_commit, 383 .mode_set = via_tv_mode_set, 384 .detect = via_tv_detect, 385 .get_modes = via_tv_get_modes, 386 .destroy = via_tv_destroy, 387}; 388 389/* 390 * 391 */ 392static Bool 393via_tv_init(ScrnInfoPtr pScrn) 394{ 395 VIAPtr pVia = VIAPTR(pScrn); 396 VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; 397 xf86OutputPtr output = NULL; 398 399 /* preset some pBIOSInfo TV related values -- move up */ 400 pBIOSInfo->TVEncoder = VIA_NONETV; 401 pBIOSInfo->TVI2CDev = NULL; 402 pBIOSInfo->TVSave = NULL; 403 pBIOSInfo->TVRestore = NULL; 404 pBIOSInfo->TVDACSense = NULL; 405 pBIOSInfo->TVModeValid = NULL; 406 pBIOSInfo->TVModeI2C = NULL; 407 pBIOSInfo->TVModeCrtc = NULL; 408 pBIOSInfo->TVPower = NULL; 409 pBIOSInfo->TVModes = NULL; 410 pBIOSInfo->TVPrintRegs = NULL; 411 pBIOSInfo->LCDPower = NULL; 412 pBIOSInfo->TVNumRegs = 0; 413 414 /* 415 * On an SK43G (KM400/Ch7011), false positive detections at a VT162x 416 * chip were observed, so try to detect the Ch7011 first. 417 */ 418 if (pVia->pI2CBus2 && xf86I2CProbeAddress(pVia->pI2CBus2, 0xEC)) 419 pBIOSInfo->TVI2CDev = ViaCH7xxxDetect(pScrn, pVia->pI2CBus2, 0xEC); 420 else if (pVia->pI2CBus2 && xf86I2CProbeAddress(pVia->pI2CBus2, 0x40)) 421 pBIOSInfo->TVI2CDev = ViaVT162xDetect(pScrn, pVia->pI2CBus2, 0x40); 422 else if (pVia->pI2CBus3 && xf86I2CProbeAddress(pVia->pI2CBus3, 0x40)) 423 pBIOSInfo->TVI2CDev = ViaVT162xDetect(pScrn, pVia->pI2CBus3, 0x40); 424 else if (pVia->pI2CBus2 && xf86I2CProbeAddress(pVia->pI2CBus2, 0xEA)) 425 pBIOSInfo->TVI2CDev = ViaCH7xxxDetect(pScrn, pVia->pI2CBus2, 0xEA); 426 else if (pVia->pI2CBus3 && xf86I2CProbeAddress(pVia->pI2CBus3, 0xEA)) 427 pBIOSInfo->TVI2CDev = ViaCH7xxxDetect(pScrn, pVia->pI2CBus3, 0xEA); 428 429 if (!pBIOSInfo->TVI2CDev) 430 return FALSE; 431 432 switch (pBIOSInfo->TVEncoder) { 433 case VIA_VT1621: 434 case VIA_VT1622: 435 case VIA_VT1623: 436 case VIA_VT1625: 437 ViaVT162xInit(pScrn); 438 break; 439 case VIA_CH7011: 440 case VIA_CH7019A: 441 case VIA_CH7019B: 442 ViaCH7xxxInit(pScrn); 443 break; 444 default: 445 return FALSE; 446 break; 447 } 448 449 if (!pBIOSInfo->TVSave || !pBIOSInfo->TVRestore 450 || !pBIOSInfo->TVDACSense || !pBIOSInfo->TVModeValid 451 || !pBIOSInfo->TVModeI2C || !pBIOSInfo->TVModeCrtc 452 || !pBIOSInfo->TVPower || !pBIOSInfo->TVModes 453 || !pBIOSInfo->TVPrintRegs) { 454 455 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 456 "via_tv_init: TVEncoder was not properly initialised.\n"); 457 458 xf86DestroyI2CDevRec(pBIOSInfo->TVI2CDev, TRUE); 459 pBIOSInfo->TVI2CDev = NULL; 460 pBIOSInfo->TVOutput = TVOUTPUT_NONE; 461 pBIOSInfo->TVEncoder = VIA_NONETV; 462 pBIOSInfo->TVI2CDev = NULL; 463 pBIOSInfo->TVSave = NULL; 464 pBIOSInfo->TVRestore = NULL; 465 pBIOSInfo->TVDACSense = NULL; 466 pBIOSInfo->TVModeValid = NULL; 467 pBIOSInfo->TVModeI2C = NULL; 468 pBIOSInfo->TVModeCrtc = NULL; 469 pBIOSInfo->TVPower = NULL; 470 pBIOSInfo->TVModes = NULL; 471 pBIOSInfo->TVPrintRegs = NULL; 472 pBIOSInfo->TVNumRegs = 0; 473 474 return FALSE; 475 } 476 477 output = xf86OutputCreate(pScrn, &via_tv_funcs, "TV-1"); 478 pVia->FirstInit = TRUE; 479 480 if (output) { 481 /* Allow tv output on both crtcs, set bit 0 and 1. */ 482 output->possible_crtcs = 0x3; 483 } else { 484 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "via_tv_init: Failed to create output for TV-1.\n"); 485 } 486 487 pBIOSInfo->tv = output; 488 /* Save now */ 489 pBIOSInfo->TVSave(pScrn); 490 491#ifdef HAVE_DEBUG 492 if (VIAPTR(pScrn)->PrintTVRegs) 493 pBIOSInfo->TVPrintRegs(pScrn); 494#endif 495 return TRUE; 496} 497 498static void 499via_dp_create_resources(xf86OutputPtr output) 500{ 501} 502 503#ifdef RANDR_12_INTERFACE 504static Bool 505via_dp_set_property(xf86OutputPtr output, Atom property, 506 RRPropertyValuePtr value) 507{ 508 return FALSE; 509} 510 511static Bool 512via_dp_get_property(xf86OutputPtr output, Atom property) 513{ 514 return FALSE; 515} 516#endif 517 518static void 519via_dp_dpms(xf86OutputPtr output, int mode) 520{ 521 ScrnInfoPtr pScrn = output->scrn; 522 523 switch (mode) { 524 case DPMSModeOn: 525 ViaDFPPower(pScrn, TRUE); 526 break; 527 528 case DPMSModeStandby: 529 case DPMSModeSuspend: 530 case DPMSModeOff: 531 ViaDFPPower(pScrn, FALSE); 532 break; 533 } 534} 535 536static void 537via_dp_save(xf86OutputPtr output) 538{ 539} 540 541static void 542via_dp_restore(xf86OutputPtr output) 543{ 544} 545 546static int 547via_dp_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) 548{ 549 ScrnInfoPtr pScrn = output->scrn; 550 551 if (!ViaModeDotClockTranslate(pScrn, pMode)) 552 return MODE_NOCLOCK; 553 return MODE_OK; 554} 555 556static Bool 557via_dp_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, 558 DisplayModePtr adjusted_mode) 559{ 560 return TRUE; 561} 562 563static void 564via_dp_prepare(xf86OutputPtr output) 565{ 566} 567 568static void 569via_dp_commit(xf86OutputPtr output) 570{ 571} 572 573static void 574via_dp_mode_set(xf86OutputPtr output, DisplayModePtr mode, 575 DisplayModePtr adjusted_mode) 576{ 577 ScrnInfoPtr pScrn = output->scrn; 578 579 if (output->crtc) { 580 drmmode_crtc_private_ptr iga = output->crtc->driver_private; 581 CARD8 value = 0x00; /* Value for IGA 1 */ 582 vgaHWPtr hwp = VGAHWPTR(pScrn); 583 584 /* IGA 2 */ 585 if (iga->index) 586 value = 0x10; 587 ViaSeqMask(hwp, 0x99, value, 0x10); 588 } 589 ViaDFPPower(pScrn, TRUE); 590} 591 592static xf86OutputStatus 593via_dp_detect(xf86OutputPtr output) 594{ 595 xf86OutputStatus status = XF86OutputStatusDisconnected; 596 ScrnInfoPtr pScrn = output->scrn; 597 VIAPtr pVia = VIAPTR(pScrn); 598 xf86MonPtr mon; 599 600 mon = xf86OutputGetEDID(output, pVia->pI2CBus2); 601 if (mon && DIGITAL(mon->features.input_type)) { 602 xf86OutputSetEDID(output, mon); 603 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DDC pI2CBus2 detected a DP\n")); 604 status = XF86OutputStatusConnected; 605 } 606 return status; 607} 608 609static void 610via_dp_destroy(xf86OutputPtr output) 611{ 612} 613 614static const xf86OutputFuncsRec via_dp_funcs = { 615 .create_resources = via_dp_create_resources, 616#ifdef RANDR_12_INTERFACE 617 .set_property = via_dp_set_property, 618 .get_property = via_dp_get_property, 619#endif 620 .dpms = via_dp_dpms, 621 .save = via_dp_save, 622 .restore = via_dp_restore, 623 .mode_valid = via_dp_mode_valid, 624 .mode_fixup = via_dp_mode_fixup, 625 .prepare = via_dp_prepare, 626 .commit = via_dp_commit, 627 .mode_set = via_dp_mode_set, 628 .detect = via_dp_detect, 629 .get_modes = xf86OutputGetEDIDModes, 630 .destroy = via_dp_destroy, 631}; 632 633void 634via_dp_init(ScrnInfoPtr pScrn) 635{ 636 VIAPtr pVia = VIAPTR(pScrn); 637 xf86OutputPtr output = NULL; 638 639 if (pVia->pI2CBus2) 640 output = xf86OutputCreate(pScrn, &via_dp_funcs, "DP-1"); 641 if (output) { 642 output->possible_crtcs = 0x1; 643 output->possible_clones = 0; 644 output->interlaceAllowed = TRUE; 645 output->doubleScanAllowed = FALSE; 646 } 647} 648 649/* 650 * Enables CRT using DPMS registers. 651 */ 652static void 653ViaDisplayEnableCRT(ScrnInfoPtr pScrn) 654{ 655 vgaHWPtr hwp = VGAHWPTR(pScrn); 656 657 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaDisplayEnableCRT\n")); 658 ViaCrtcMask(hwp, 0x36, 0x00, 0x30); 659} 660 661/* 662 * Disables CRT using DPMS registers. 663 */ 664static void 665ViaDisplayDisableCRT(ScrnInfoPtr pScrn) 666{ 667 vgaHWPtr hwp = VGAHWPTR(pScrn); 668 669 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaDisplayDisableCRT\n")); 670 ViaCrtcMask(hwp, 0x36, 0x30, 0x30); 671} 672 673static void 674via_analog_create_resources(xf86OutputPtr output) 675{ 676} 677 678#ifdef RANDR_12_INTERFACE 679static Bool 680via_analog_set_property(xf86OutputPtr output, Atom property, 681 RRPropertyValuePtr value) 682{ 683 return FALSE; 684} 685 686static Bool 687via_analog_get_property(xf86OutputPtr output, Atom property) 688{ 689 return FALSE; 690} 691#endif 692 693static void 694via_analog_dpms(xf86OutputPtr output, int mode) 695{ 696 ScrnInfoPtr pScrn = output->scrn; 697 698 switch (mode) { 699 case DPMSModeOn: 700 ViaDisplayEnableCRT(pScrn); 701 break; 702 703 case DPMSModeStandby: 704 case DPMSModeSuspend: 705 case DPMSModeOff: 706 ViaDisplayDisableCRT(pScrn); 707 break; 708 } 709} 710 711static void 712via_analog_save(xf86OutputPtr output) 713{ 714} 715 716static void 717via_analog_restore(xf86OutputPtr output) 718{ 719} 720 721static int 722via_analog_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) 723{ 724 ScrnInfoPtr pScrn = output->scrn; 725 726 if (!ViaModeDotClockTranslate(pScrn, pMode)) 727 return MODE_NOCLOCK; 728 return MODE_OK; 729} 730 731static Bool 732via_analog_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, 733 DisplayModePtr adjusted_mode) 734{ 735 return TRUE; 736} 737 738static void 739via_analog_prepare(xf86OutputPtr output) 740{ 741 via_analog_dpms(output, DPMSModeOff); 742} 743 744static void 745via_analog_commit(xf86OutputPtr output) 746{ 747 via_analog_dpms(output, DPMSModeOn); 748} 749 750static void 751via_analog_mode_set(xf86OutputPtr output, DisplayModePtr mode, 752 DisplayModePtr adjusted_mode) 753{ 754 ScrnInfoPtr pScrn = output->scrn; 755 756 if (output->crtc) { 757 drmmode_crtc_private_ptr iga = output->crtc->driver_private; 758 CARD8 value = 0x00; /* Value for IGA 1 */ 759 vgaHWPtr hwp = VGAHWPTR(pScrn); 760 761 /* IGA 2 */ 762 if (iga->index) 763 value = 0x40; 764 ViaSeqMask(hwp, 0x16, value, 0x40); 765 } 766 ViaDisplayEnableCRT(pScrn); 767} 768 769static xf86OutputStatus 770via_analog_detect(xf86OutputPtr output) 771{ 772 xf86OutputStatus status = XF86OutputStatusDisconnected; 773 ScrnInfoPtr pScrn = output->scrn; 774 VIAPtr pVia = VIAPTR(pScrn); 775 xf86MonPtr mon; 776 777 mon = xf86OutputGetEDID(output, pVia->pI2CBus1); 778 if (mon && !DIGITAL(mon->features.input_type)) { 779 xf86OutputSetEDID(output, mon); 780 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DDC pI2CBus1 detected a CRT\n")); 781 status = XF86OutputStatusConnected; 782 } else { 783 vgaHWPtr hwp = VGAHWPTR(pScrn); 784 CARD8 SR01 = hwp->readSeq(hwp, 0x01); 785 CARD8 SR40 = hwp->readSeq(hwp, 0x40); 786 CARD8 CR36 = hwp->readCrtc(hwp, 0x36); 787 788 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Test for CRT with VSYNC\n")); 789 /* We have to power on the display to detect it */ 790 ViaSeqMask(hwp, 0x01, 0x00, 0x20); 791 ViaCrtcMask(hwp, 0x36, 0x00, 0xF0); 792 793 /* Wait for vblank */ 794 usleep(16); 795 796 /* Detect the load on pins */ 797 ViaSeqMask(hwp, 0x40, 0x80, 0x80); 798 799 if ((VIA_CX700 == pVia->Chipset) || 800 (VIA_VX800 == pVia->Chipset) || 801 (VIA_VX855 == pVia->Chipset) || 802 (VIA_VX900 == pVia->Chipset)) 803 ViaSeqMask(hwp, 0x40, 0x00, 0x80); 804 805 if (ViaVgahwIn(hwp, 0x3C2) & 0x20) 806 status = XF86OutputStatusConnected; 807 808 if ((VIA_CX700 == pVia->Chipset) || 809 (VIA_VX800 == pVia->Chipset) || 810 (VIA_VX855 == pVia->Chipset) || 811 (VIA_VX900 == pVia->Chipset)) 812 ViaSeqMask(hwp, 0x40, 0x00, 0x80); 813 814 /* Restore previous state */ 815 hwp->writeSeq(hwp, 0x40, SR40); 816 hwp->writeSeq(hwp, 0x01, SR01); 817 hwp->writeCrtc(hwp, 0x36, CR36); 818 } 819 return status; 820} 821 822static void 823via_analog_destroy(xf86OutputPtr output) 824{ 825} 826 827static const xf86OutputFuncsRec via_analog_funcs = { 828 .create_resources = via_analog_create_resources, 829#ifdef RANDR_12_INTERFACE 830 .set_property = via_analog_set_property, 831 .get_property = via_analog_get_property, 832#endif 833 .dpms = via_analog_dpms, 834 .save = via_analog_save, 835 .restore = via_analog_restore, 836 .mode_valid = via_analog_mode_valid, 837 .mode_fixup = via_analog_mode_fixup, 838 .prepare = via_analog_prepare, 839 .commit = via_analog_commit, 840 .mode_set = via_analog_mode_set, 841 .detect = via_analog_detect, 842 .get_modes = xf86OutputGetEDIDModes, 843 .destroy = via_analog_destroy, 844}; 845 846void 847via_analog_init(ScrnInfoPtr pScrn) 848{ 849 VIAPtr pVia = VIAPTR(pScrn); 850 VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; 851 xf86OutputPtr output = NULL; 852 853 if (pVia->pI2CBus1) { 854 output = xf86OutputCreate(pScrn, &via_analog_funcs, "VGA-1"); 855 856 output->possible_crtcs = 0x3; 857 output->possible_clones = 0; 858 output->interlaceAllowed = TRUE; 859 output->doubleScanAllowed = FALSE; 860 pBIOSInfo->analog = output; 861 } 862} 863 864/* 865 * 866 */ 867void 868ViaOutputsDetect(ScrnInfoPtr pScrn) 869{ 870 VIAPtr pVia = VIAPTR(pScrn); 871 VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; 872 873 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaOutputsDetect\n")); 874 875 pBIOSInfo->analog = NULL; 876 877 /* LVDS */ 878 via_lvds_init(pScrn); 879 880 /* VGA */ 881 via_analog_init(pScrn); 882 883 /* 884 * FIXME: xf86I2CProbeAddress(pVia->pI2CBus3, 0x40) 885 * disables the panel on P4M900 886 */ 887 /* TV encoder */ 888 if ((pVia->Chipset != VIA_P4M900) || (pVia->ActiveDevice & VIA_DEVICE_TV)) 889 via_tv_init(pScrn); 890 891 if (pVia->ActiveDevice & VIA_DEVICE_DFP) { 892 switch (pVia->Chipset) { 893 case VIA_CX700: 894 case VIA_VX800: 895 case VIA_VX855: 896 case VIA_VX900: 897 via_dp_init(pScrn); 898 break; 899 } 900 } 901} 902 903#ifdef HAVE_DEBUG 904/* 905 * Returns: 906 * Bit[7] 2nd Path 907 * Bit[6] 1/0 MHS Enable/Disable 908 * Bit[5] 0 = Bypass Callback, 1 = Enable Callback 909 * Bit[4] 0 = Hot-Key Sequence Control (OEM Specific) 910 * Bit[3] LCD 911 * Bit[2] TV 912 * Bit[1] CRT 913 * Bit[0] DVI 914 */ 915static CARD8 916VIAGetActiveDisplay(ScrnInfoPtr pScrn) 917{ 918 vgaHWPtr hwp = VGAHWPTR(pScrn); 919 CARD8 tmp; 920 921 tmp = (hwp->readCrtc(hwp, 0x3E) >> 4); 922 tmp |= ((hwp->readCrtc(hwp, 0x3B) & 0x18) << 3); 923 924 return tmp; 925} 926#endif /* HAVE_DEBUG */ 927 928/* 929 * 930 */ 931CARD32 932ViaGetMemoryBandwidth(ScrnInfoPtr pScrn) 933{ 934 VIAPtr pVia = VIAPTR(pScrn); 935 936 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaGetMemoryBandwidth. Memory type: %d\n", pVia->MemClk)); 937 938 switch (pVia->MemClk) { 939 case VIA_MEM_SDR66: 940 case VIA_MEM_SDR100: 941 case VIA_MEM_SDR133: 942 return VIA_BW_MIN; 943 case VIA_MEM_DDR200: 944 return VIA_BW_DDR200; 945 case VIA_MEM_DDR266: 946 case VIA_MEM_DDR333: 947 case VIA_MEM_DDR400: 948 return VIA_BW_DDR400; 949 case VIA_MEM_DDR533: 950 case VIA_MEM_DDR667: 951 return VIA_BW_DDR667; 952 case VIA_MEM_DDR800: 953 case VIA_MEM_DDR1066: 954 return VIA_BW_DDR1066; 955 default: 956 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 957 "ViaBandwidthAllowed: Unknown memory type: %d\n", pVia->MemClk); 958 return VIA_BW_MIN; 959 } 960} 961 962/* 963 * 964 * Some very common abstractions. 965 * 966 */ 967 968/* 969 * Standard vga call really. 970 * Needs to be called to reset the dotclock (after SR40:2/1 reset) 971 */ 972void 973ViaSetUseExternalClock(vgaHWPtr hwp) 974{ 975 CARD8 data; 976 977 DEBUG(xf86DrvMsg(hwp->pScrn->scrnIndex, X_INFO, 978 "ViaSetUseExternalClock\n")); 979 980 data = hwp->readMiscOut(hwp); 981 hwp->writeMiscOut(hwp, data | 0x0C); 982} 983 984/* 985 * 986 */ 987static void 988ViaSetDotclock(ScrnInfoPtr pScrn, CARD32 clock, int base, int probase) 989{ 990 vgaHWPtr hwp = VGAHWPTR(pScrn); 991 VIAPtr pVia = VIAPTR(pScrn); 992 993 DEBUG(xf86DrvMsg(hwp->pScrn->scrnIndex, X_INFO, 994 "ViaSetDotclock to 0x%06x\n", (unsigned)clock)); 995 996 if ((pVia->Chipset == VIA_CLE266) || (pVia->Chipset == VIA_KM400)) { 997 hwp->writeSeq(hwp, base, clock >> 8); 998 hwp->writeSeq(hwp, base+1, clock & 0xFF); 999 } else { /* unichrome pro */ 1000 union pllparams pll; 1001 int dtz, dr, dn, dm; 1002 pll.packed = clock; 1003 dtz = pll.params.dtz; 1004 dr = pll.params.dr; 1005 dn = pll.params.dn; 1006 dm = pll.params.dm; 1007 1008 /* The VX855 and VX900 do not modify dm/dn, but earlier chipsets do. */ 1009 if ((pVia->Chipset != VIA_VX855) && (pVia->Chipset != VIA_VX900)) { 1010 dm -= 2; 1011 dn -= 2; 1012 } 1013 1014 hwp->writeSeq(hwp, probase, dm & 0xff); 1015 hwp->writeSeq(hwp, probase+1, ((dm >> 8) & 0x03) | (dr << 2) | ((dtz & 1) << 7)); 1016 hwp->writeSeq(hwp, probase+2, (dn & 0x7f) | ((dtz & 2) << 6)); 1017 } 1018} 1019 1020/* 1021 * 1022 */ 1023static void 1024ViaSetPrimaryDotclock(ScrnInfoPtr pScrn, CARD32 clock) 1025{ 1026 vgaHWPtr hwp = VGAHWPTR(pScrn); 1027 1028 ViaSetDotclock(pScrn, clock, 0x46, 0x44); 1029 1030 ViaSeqMask(hwp, 0x40, 0x02, 0x02); 1031 ViaSeqMask(hwp, 0x40, 0x00, 0x02); 1032} 1033 1034/* 1035 * 1036 */ 1037void 1038ViaSetSecondaryDotclock(ScrnInfoPtr pScrn, CARD32 clock) 1039{ 1040 vgaHWPtr hwp = VGAHWPTR(pScrn); 1041 1042 ViaSetDotclock(pScrn, clock, 0x44, 0x4A); 1043 1044 ViaSeqMask(hwp, 0x40, 0x04, 0x04); 1045 ViaSeqMask(hwp, 0x40, 0x00, 0x04); 1046} 1047 1048/* 1049 * 1050 */ 1051static void 1052ViaSetECKDotclock(ScrnInfoPtr pScrn, CARD32 clock) 1053{ 1054 /* Does the non-pro chip have an ECK clock ? */ 1055 ViaSetDotclock(pScrn, clock, 0, 0x47); 1056} 1057 1058static CARD32 1059ViaComputeDotClock(unsigned clock) 1060{ 1061 double fout, fref, err, minErr; 1062 CARD32 dr, dn, dm, maxdm, maxdn; 1063 CARD32 factual, best; 1064 1065 fref = 14.31818e6; 1066 fout = (double)clock * 1.e3; 1067 1068 factual = ~0; 1069 maxdm = 127; 1070 maxdn = 7; 1071 minErr = 1e10; 1072 best = 0; 1073 1074 for (dr = 0; dr < 4; ++dr) { 1075 for (dn = (dr == 0) ? 2 : 1; dn <= maxdn; ++dn) { 1076 for (dm = 1; dm <= maxdm; ++dm) { 1077 factual = fref * dm; 1078 factual /= (dn << dr); 1079 err = fabs((double)factual / fout - 1.); 1080 if (err < minErr) { 1081 minErr = err; 1082 best = (dm & 127) | ((dn & 31) << 8) | (dr << 14); 1083 } 1084 } 1085 } 1086 } 1087 return best; 1088} 1089 1090static CARD32 1091ViaComputeProDotClock(unsigned clock) 1092{ 1093 double fvco, fout, fref, err, minErr; 1094 CARD32 dr = 0, dn, dm, maxdm, maxdn; 1095 CARD32 factual; 1096 union pllparams bestClock; 1097 1098 fref = 14.318e6; 1099 fout = (double)clock * 1.e3; 1100 1101 factual = ~0; 1102 maxdm = factual / 14318000U; 1103 minErr = 1.e10; 1104 bestClock.packed = 0U; 1105 1106 do { 1107 fvco = fout * (1 << dr); 1108 } while (fvco < 300.e6 && dr++ < 8); 1109 1110 if (dr == 8) { 1111 return 0; 1112 } 1113 1114 if (clock < 30000) 1115 maxdn = 8; 1116 else if (clock < 45000) 1117 maxdn = 7; 1118 else if (clock < 170000) 1119 maxdn = 6; 1120 else 1121 maxdn = 5; 1122 1123 for (dn = 2; dn < maxdn; ++dn) { 1124 for (dm = 2; dm < maxdm; ++dm) { 1125 factual = 14318000U * dm; 1126 factual /= dn << dr; 1127 if ((err = fabs((double)factual / fout - 1.)) < 0.005) { 1128 if (err < minErr) { 1129 minErr = err; 1130 bestClock.params.dtz = 1; 1131 bestClock.params.dr = dr; 1132 bestClock.params.dn = dn; 1133 bestClock.params.dm = dm; 1134 } 1135 } 1136 } 1137 } 1138 1139 return bestClock.packed; 1140} 1141 1142/* 1143 * 1144 */ 1145CARD32 1146ViaModeDotClockTranslate(ScrnInfoPtr pScrn, DisplayModePtr mode) 1147{ 1148 VIAPtr pVia = VIAPTR(pScrn); 1149 int i; 1150 1151 if ((pVia->Chipset == VIA_CLE266) || (pVia->Chipset == VIA_KM400)) { 1152 CARD32 best1 = 0, best2; 1153 1154 for (i = 0; ViaDotClocks[i].DotClock; i++) 1155 if (ViaDotClocks[i].DotClock == mode->Clock) { 1156 best1 = ViaDotClocks[i].UniChrome; 1157 break; 1158 } 1159 1160 best2 = ViaComputeDotClock(mode->Clock); 1161 1162 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1163 "ViaComputeDotClock %d : %04x : %04x\n", 1164 mode->Clock, (unsigned int)best1, (unsigned int)best2)); 1165 1166 return best2; 1167 } else { 1168 for (i = 0; ViaDotClocks[i].DotClock; i++) 1169 if (ViaDotClocks[i].DotClock == mode->Clock) 1170 return ViaDotClocks[i].UniChromePro.packed; 1171 return ViaComputeProDotClock(mode->Clock); 1172 } 1173 1174 return 0; 1175} 1176 1177/* 1178 * 1179 */ 1180void 1181ViaModePrimaryLegacy(xf86CrtcPtr crtc, DisplayModePtr mode) 1182{ 1183 ScrnInfoPtr pScrn = crtc->scrn; 1184 vgaHWPtr hwp = VGAHWPTR(pScrn); 1185 VIAPtr pVia = VIAPTR(pScrn); 1186 VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; 1187 1188 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaModePrimaryLegacy\n")); 1189 DEBUG(ViaPrintMode(pScrn, mode)); 1190 1191 /* Turn off Screen */ 1192 ViaCrtcMask(hwp, 0x17, 0x00, 0x80); 1193 1194 /* Clean Second Path Status */ 1195 hwp->writeCrtc(hwp, 0x6A, 0x00); 1196 hwp->writeCrtc(hwp, 0x6B, 0x00); 1197 hwp->writeCrtc(hwp, 0x6C, 0x00); 1198 hwp->writeCrtc(hwp, 0x93, 0x00); 1199 1200 ViaCRTCInit(pScrn); 1201 ViaFirstCRTCSetMode(pScrn, mode); 1202 pBIOSInfo->Clock = ViaModeDotClockTranslate(pScrn, mode); 1203 pBIOSInfo->ClockExternal = FALSE; 1204 1205 /* Enable MMIO & PCI burst (1 wait state) */ 1206 ViaSeqMask(hwp, 0x1A, 0x06, 0x06); 1207 1208 if (pBIOSInfo->analog->status == XF86OutputStatusConnected) 1209 ViaCrtcMask(hwp, 0x36, 0x30, 0x30); 1210 else 1211 ViaSeqMask(hwp, 0x16, 0x00, 0x40); 1212 1213 if ((pBIOSInfo->tv && pBIOSInfo->tv->status == XF86OutputStatusConnected)) { 1214 /* Quick 'n dirty workaround for non-primary case until TVCrtcMode 1215 * is removed -- copy from clock handling code below */ 1216 if ((pVia->Chipset == VIA_CLE266) && CLE266_REV_IS_AX(pVia->ChipRev)) 1217 ViaSetPrimaryDotclock(pScrn, 0x471C); /* CLE266Ax uses 2x XCLK */ 1218 else if (pVia->Chipset != VIA_CLE266 && pVia->Chipset != VIA_KM400) 1219 ViaSetPrimaryDotclock(pScrn, 0x529001); 1220 else 1221 ViaSetPrimaryDotclock(pScrn, 0x871C); 1222 ViaSetUseExternalClock(hwp); 1223 1224 ViaTVSetMode(crtc, mode); 1225 } else 1226 ViaTVPower(pScrn, FALSE); 1227 1228 ViaSetPrimaryFIFO(pScrn, mode); 1229 1230 if (pBIOSInfo->ClockExternal) { 1231 if ((pVia->Chipset == VIA_CLE266) && CLE266_REV_IS_AX(pVia->ChipRev)) 1232 ViaSetPrimaryDotclock(pScrn, 0x471C); /* CLE266Ax uses 2x XCLK */ 1233 else if (pVia->Chipset != VIA_CLE266 && pVia->Chipset != VIA_KM400) 1234 ViaSetPrimaryDotclock(pScrn, 0x529001); 1235 else 1236 ViaSetPrimaryDotclock(pScrn, 0x871C); 1237 if (pVia->Chipset == VIA_CLE266 || pVia->Chipset == VIA_KM400) 1238 ViaCrtcMask(hwp, 0x6B, 0x01, 0x01); 1239 } else { 1240 ViaSetPrimaryDotclock(pScrn, pBIOSInfo->Clock); 1241 ViaSetUseExternalClock(hwp); 1242 ViaCrtcMask(hwp, 0x6B, 0x00, 0x01); 1243 } 1244 1245 /* Enable CRT Controller (3D5.17 Hardware Reset) */ 1246 ViaCrtcMask(hwp, 0x17, 0x80, 0x80); 1247 1248 hwp->disablePalette(hwp); 1249} 1250 1251/* 1252 * 1253 */ 1254void 1255ViaModeSecondaryLegacy(xf86CrtcPtr crtc, DisplayModePtr mode) 1256{ 1257 ScrnInfoPtr pScrn = crtc->scrn; 1258 vgaHWPtr hwp = VGAHWPTR(pScrn); 1259 VIAPtr pVia = VIAPTR(pScrn); 1260 VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; 1261 1262 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaModeSecondaryLegacy\n")); 1263 DEBUG(ViaPrintMode(pScrn, mode)); 1264 1265 /* Turn off Screen */ 1266 ViaCrtcMask(hwp, 0x17, 0x00, 0x80); 1267 1268 ViaSecondCRTCSetMode(pScrn, mode); 1269 1270 if (pBIOSInfo->tv && pBIOSInfo->tv->status == XF86OutputStatusConnected) 1271 ViaTVSetMode(crtc, mode); 1272 1273 /* CLE266A2 apparently doesn't like this */ 1274 if (!(pVia->Chipset == VIA_CLE266 && pVia->ChipRev == 0x02)) 1275 ViaCrtcMask(hwp, 0x6C, 0x00, 0x1E); 1276 1277 ViaSetSecondaryFIFO(pScrn, mode); 1278 1279 ViaSetSecondaryDotclock(pScrn, pBIOSInfo->Clock); 1280 ViaSetUseExternalClock(hwp); 1281 1282 ViaCrtcMask(hwp, 0x17, 0x80, 0x80); 1283 1284 hwp->disablePalette(hwp); 1285} 1286 1287void 1288ViaDFPPower(ScrnInfoPtr pScrn, Bool On) 1289{ 1290#ifdef HAVE_DEBUG 1291 if (On) 1292 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaDFPPower: On.\n"); 1293 else 1294 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaDFPPower: Off.\n"); 1295#endif 1296 vgaHWPtr hwp = VGAHWPTR(pScrn); 1297 1298 /* Display Channel Select */ 1299 ViaCrtcMask(hwp, 0xD2, 0x30, 0x30); 1300 1301 if (On) 1302 /* Power on TMDS */ 1303 ViaCrtcMask(hwp, 0xD2, 0x00, 0x08); 1304 else 1305 /* Power off TMDS */ 1306 ViaCrtcMask(hwp, 0xD2, 0x08, 0x08); 1307} 1308 1309void 1310ViaModeFirstCRTC(ScrnInfoPtr pScrn, DisplayModePtr mode) 1311{ 1312 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaModeFirstCRTC\n"); 1313 vgaHWPtr hwp = VGAHWPTR(pScrn); 1314 VIAPtr pVia = VIAPTR(pScrn); 1315 VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; 1316 1317 /* Turn off Screen */ 1318 ViaCrtcMask(hwp, 0x17, 0x00, 0x80); 1319 1320 ViaFirstCRTCSetMode(pScrn, mode); 1321 pBIOSInfo->Clock = ViaModeDotClockTranslate(pScrn, mode); 1322 pBIOSInfo->ClockExternal = FALSE; 1323 1324 /* Enable MMIO & PCI burst (1 wait state) */ 1325 switch (pVia->Chipset) { 1326 case VIA_CLE266: 1327 case VIA_KM400: 1328 case VIA_K8M800: 1329 case VIA_PM800: 1330 case VIA_VM800: 1331 ViaSeqMask(hwp, 0x1A, 0x06, 0x06); 1332 break; 1333 default: 1334 ViaSeqMask(hwp, 0x1A, 0x0C, 0x0C); 1335 break; 1336 } 1337 1338 ViaSetPrimaryFIFO(pScrn, mode); 1339 1340 ViaSetPrimaryDotclock(pScrn, pBIOSInfo->Clock); 1341 ViaSetUseExternalClock(hwp); 1342 ViaCrtcMask(hwp, 0x6B, 0x00, 0x01); 1343 1344 hwp->disablePalette(hwp); 1345 1346 /* Turn on Screen */ 1347 ViaCrtcMask(hwp, 0x17, 0x80, 0x80); 1348} 1349 1350void 1351ViaModeSecondCRTC(ScrnInfoPtr pScrn, DisplayModePtr mode) 1352{ 1353 VIAPtr pVia = VIAPTR(pScrn); 1354 VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; 1355 vgaHWPtr hwp = VGAHWPTR(pScrn); 1356 DisplayModePtr realMode = mode; 1357 1358 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaModeSecondCRTC\n")); 1359 1360 ViaSecondCRTCSetMode(pScrn, realMode); 1361 ViaSetSecondaryFIFO(pScrn, realMode); 1362 pBIOSInfo->Clock = ViaModeDotClockTranslate(pScrn, realMode); 1363 1364 /* Fix LCD scaling */ 1365 ViaSecondCRTCHorizontalQWCount(pScrn, mode->CrtcHDisplay); 1366 1367 pBIOSInfo->ClockExternal = FALSE; 1368 ViaSetSecondaryDotclock(pScrn, pBIOSInfo->Clock); 1369 ViaSetUseExternalClock(hwp); 1370 1371 hwp->disablePalette(hwp); 1372} 1373