via_outputs.c revision 1a337bac
1/* 2 * Copyright 2016 Kevin Brace 3 * Copyright 2005-2016 The OpenChrome Project 4 * [http://www.freedesktop.org/wiki/Openchrome] 5 * Copyright 2004-2005 The Unichrome Project [unichrome.sf.net] 6 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. 7 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining a 10 * copy of this software and associated documentation files (the "Software"), 11 * to deal in the Software without restriction, including without limitation 12 * the rights to use, copy, modify, merge, publish, distribute, sub license, 13 * and/or sell copies of the Software, and to permit persons to whom the 14 * Software is furnished to do so, subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice (including the 17 * next paragraph) shall be included in all copies or substantial portions 18 * of the Software. 19 * 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 * DEALINGS IN THE SOFTWARE. 27 */ 28 29/* 30 * via_outputs.c 31 * 32 * Everything to do with setting and changing xf86Outputs. 33 * 34 */ 35 36#ifdef HAVE_CONFIG_H 37#include "config.h" 38#endif 39 40#include "via_driver.h" 41#include <unistd.h> 42 43/* 44 * Modetable nonsense. 45 * 46 */ 47#include "via_mode.h" 48 49static void 50ViaPrintMode(ScrnInfoPtr pScrn, DisplayModePtr mode) 51{ 52 xf86PrintModeline(pScrn->scrnIndex, mode); 53 54 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcHDisplay: 0x%x\n", 55 mode->CrtcHDisplay); 56 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcHBlankStart: 0x%x\n", 57 mode->CrtcHBlankStart); 58 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcHSyncStart: 0x%x\n", 59 mode->CrtcHSyncStart); 60 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcHSyncEnd: 0x%x\n", 61 mode->CrtcHSyncEnd); 62 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcHBlankEnd: 0x%x\n", 63 mode->CrtcHBlankEnd); 64 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcHTotal: 0x%x\n", 65 mode->CrtcHTotal); 66 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcHSkew: 0x%x\n", 67 mode->CrtcHSkew); 68 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcVDisplay: 0x%x\n", 69 mode->CrtcVDisplay); 70 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcVBlankStart: 0x%x\n", 71 mode->CrtcVBlankStart); 72 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcVSyncStart: 0x%x\n", 73 mode->CrtcVSyncStart); 74 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcVSyncEnd: 0x%x\n", 75 mode->CrtcVSyncEnd); 76 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcVBlankEnd: 0x%x\n", 77 mode->CrtcVBlankEnd); 78 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcVTotal: 0x%x\n", 79 mode->CrtcVTotal); 80 81} 82 83/* 84 * 85 * TV specific code. 86 * 87 */ 88void 89ViaTVSave(ScrnInfoPtr pScrn) 90{ 91 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 92 93 if (pBIOSInfo->TVSave) 94 pBIOSInfo->TVSave(pScrn); 95} 96 97void 98ViaTVRestore(ScrnInfoPtr pScrn) 99{ 100 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 101 102 if (pBIOSInfo->TVRestore) 103 pBIOSInfo->TVRestore(pScrn); 104} 105 106static Bool 107ViaTVDACSense(ScrnInfoPtr pScrn) 108{ 109 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 110 111 if (pBIOSInfo->TVDACSense) 112 return pBIOSInfo->TVDACSense(pScrn); 113 return FALSE; 114} 115 116static void 117ViaTVSetMode(xf86CrtcPtr crtc, DisplayModePtr mode) 118{ 119 ScrnInfoPtr pScrn = crtc->scrn; 120 VIAPtr pVia = VIAPTR(pScrn); 121 VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; 122 123 if (pBIOSInfo->TVModeI2C) 124 pBIOSInfo->TVModeI2C(pScrn, mode); 125 126 if (pBIOSInfo->TVModeCrtc) 127 pBIOSInfo->TVModeCrtc(crtc, mode); 128 129 /* TV reset. */ 130 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1D, 0x00); 131 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1D, 0x80); 132} 133 134void 135ViaTVPower(ScrnInfoPtr pScrn, Bool On) 136{ 137 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 138 139#ifdef HAVE_DEBUG 140 if (On) 141 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaTVPower: On.\n"); 142 else 143 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaTVPower: Off.\n"); 144#endif 145 146 if (pBIOSInfo->TVPower) 147 pBIOSInfo->TVPower(pScrn, On); 148} 149 150#ifdef HAVE_DEBUG 151void 152ViaTVPrintRegs(ScrnInfoPtr pScrn) 153{ 154 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 155 156 if (pBIOSInfo->TVPrintRegs) 157 pBIOSInfo->TVPrintRegs(pScrn); 158} 159#endif /* HAVE_DEBUG */ 160 161static void 162via_tv_create_resources(xf86OutputPtr output) 163{ 164} 165 166#ifdef RANDR_12_INTERFACE 167static Bool 168via_tv_set_property(xf86OutputPtr output, Atom property, 169 RRPropertyValuePtr value) 170{ 171 return TRUE; 172} 173 174static Bool 175via_tv_get_property(xf86OutputPtr output, Atom property) 176{ 177 return FALSE; 178} 179#endif 180 181static void 182via_tv_dpms(xf86OutputPtr output, int mode) 183{ 184 ScrnInfoPtr pScrn = output->scrn; 185 186 switch (mode) { 187 case DPMSModeOn: 188 ViaTVPower(pScrn, TRUE); 189 break; 190 191 case DPMSModeStandby: 192 case DPMSModeSuspend: 193 case DPMSModeOff: 194 ViaTVPower(pScrn, FALSE); 195 break; 196 } 197} 198 199static void 200via_tv_save(xf86OutputPtr output) 201{ 202 ScrnInfoPtr pScrn = output->scrn; 203 204 ViaTVSave(pScrn); 205} 206 207static void 208via_tv_restore(xf86OutputPtr output) 209{ 210 ScrnInfoPtr pScrn = output->scrn; 211 212 ViaTVRestore(pScrn); 213} 214 215static int 216via_tv_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) 217{ 218 ScrnInfoPtr pScrn = output->scrn; 219 VIAPtr pVia = VIAPTR(pScrn); 220 int ret = MODE_OK; 221 222 if (!ViaModeDotClockTranslate(pScrn, pMode)) 223 return MODE_NOCLOCK; 224 225 return ret; 226} 227 228static Bool 229via_tv_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, 230 DisplayModePtr adjusted_mode) 231{ 232 return TRUE; 233} 234 235static void 236via_tv_prepare(xf86OutputPtr output) 237{ 238 via_tv_dpms(output, DPMSModeOff); 239} 240 241static void 242via_tv_commit(xf86OutputPtr output) 243{ 244 via_tv_dpms(output, DPMSModeOn); 245} 246 247static void 248ViaDisplayEnableDVO(ScrnInfoPtr pScrn, int port) 249{ 250 vgaHWPtr hwp = VGAHWPTR(pScrn); 251 252 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaDisplayEnableDVO, port: %d\n", 253 port)); 254 switch (port) { 255 case VIA_DI_PORT_DVP0: 256 ViaSeqMask(hwp, 0x1E, 0xC0, 0xC0); 257 break; 258 case VIA_DI_PORT_DVP1: 259 ViaSeqMask(hwp, 0x1E, 0x30, 0x30); 260 break; 261 } 262} 263 264static void 265ViaDisplayDisableDVO(ScrnInfoPtr pScrn, int port) 266{ 267 vgaHWPtr hwp = VGAHWPTR(pScrn); 268 269 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaDisplayDisableDVO, port: %d\n", 270 port)); 271 switch (port) { 272 case VIA_DI_PORT_DVP0: 273 ViaSeqMask(hwp, 0x1E, 0x00, 0xC0); 274 break; 275 case VIA_DI_PORT_DVP1: 276 ViaSeqMask(hwp, 0x1E, 0x00, 0x30); 277 break; 278 } 279} 280 281static void 282ViaDisplaySetStreamOnDVO(ScrnInfoPtr pScrn, int port, int iga) 283{ 284 vgaHWPtr hwp = VGAHWPTR(pScrn); 285 int regNum; 286 287 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaDisplaySetStreamOnDVO, port: %d\n", 288 port)); 289 290 switch (port) { 291 case VIA_DI_PORT_DVP0: 292 regNum = 0x96; 293 break; 294 case VIA_DI_PORT_DVP1: 295 regNum = 0x9B; 296 break; 297 case VIA_DI_PORT_DFPLOW: 298 regNum = 0x97; 299 break; 300 case VIA_DI_PORT_DFPHIGH: 301 regNum = 0x99; 302 break; 303 } 304 305 if (!iga) 306 ViaCrtcMask(hwp, regNum, 0x00, 0x10); 307 else 308 ViaCrtcMask(hwp, regNum, 0x10, 0x10); 309} 310 311static void 312via_tv_mode_set(xf86OutputPtr output, DisplayModePtr mode, 313 DisplayModePtr adjusted_mode) 314{ 315 ScrnInfoPtr pScrn = output->scrn; 316 VIAPtr pVia = VIAPTR(pScrn); 317 VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; 318 319 /* TV on FirstCrtc */ 320 if (output->crtc) { 321 drmmode_crtc_private_ptr iga = output->crtc->driver_private; 322 323 ViaDisplaySetStreamOnDVO(pScrn, pBIOSInfo->TVDIPort, iga->index); 324 } 325 ViaDisplayEnableDVO(pScrn, pBIOSInfo->TVDIPort); 326 327 ViaTVSetMode(output->crtc, adjusted_mode); 328 329 pVia->FirstInit = FALSE; 330} 331 332static xf86OutputStatus 333via_tv_detect(xf86OutputPtr output) 334{ 335 xf86OutputStatus status = XF86OutputStatusDisconnected; 336 ScrnInfoPtr pScrn = output->scrn; 337 338 if (ViaTVDACSense(pScrn)) 339 status = XF86OutputStatusConnected; 340 return status; 341} 342 343static DisplayModePtr 344via_tv_get_modes(xf86OutputPtr output) 345{ 346 DisplayModePtr modes = NULL, mode = NULL; 347 ScrnInfoPtr pScrn = output->scrn; 348 VIAPtr pVia = VIAPTR(pScrn); 349 int i; 350 351 for (i = 0; i < pVia->pBIOSInfo->TVNumModes; i++) { 352 mode = xf86DuplicateMode(&pVia->pBIOSInfo->TVModes[i]); 353 modes = xf86ModesAdd(modes, mode); 354 } 355 return modes; 356} 357 358static void 359via_tv_destroy(xf86OutputPtr output) 360{ 361} 362 363static const xf86OutputFuncsRec via_tv_funcs = { 364 .create_resources = via_tv_create_resources, 365#ifdef RANDR_12_INTERFACE 366 .set_property = via_tv_set_property, 367#endif 368#ifdef RANDR_13_INTERFACE 369 .get_property = via_tv_get_property, 370#endif 371 .dpms = via_tv_dpms, 372 .save = via_tv_save, 373 .restore = via_tv_restore, 374 .mode_valid = via_tv_mode_valid, 375 .mode_fixup = via_tv_mode_fixup, 376 .prepare = via_tv_prepare, 377 .commit = via_tv_commit, 378 .mode_set = via_tv_mode_set, 379 .detect = via_tv_detect, 380 .get_modes = via_tv_get_modes, 381 .destroy = via_tv_destroy, 382}; 383 384/* 385 * 386 */ 387static Bool 388via_tv_init(ScrnInfoPtr pScrn) 389{ 390 VIAPtr pVia = VIAPTR(pScrn); 391 VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; 392 xf86OutputPtr output = NULL; 393 394 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 395 "Entered via_tv_init.\n")); 396 397 /* preset some pBIOSInfo TV related values -- move up */ 398 pBIOSInfo->TVEncoder = VIA_NONETV; 399 pBIOSInfo->TVI2CDev = NULL; 400 pBIOSInfo->TVSave = NULL; 401 pBIOSInfo->TVRestore = NULL; 402 pBIOSInfo->TVDACSense = NULL; 403 pBIOSInfo->TVModeValid = NULL; 404 pBIOSInfo->TVModeI2C = NULL; 405 pBIOSInfo->TVModeCrtc = NULL; 406 pBIOSInfo->TVPower = NULL; 407 pBIOSInfo->TVModes = NULL; 408 pBIOSInfo->TVPrintRegs = NULL; 409 pBIOSInfo->LCDPower = NULL; 410 pBIOSInfo->TVNumRegs = 0; 411 412 /* 413 * On an SK43G (KM400/Ch7011), false positive detections at a VT162x 414 * chip were observed, so try to detect the Ch7011 first. 415 */ 416 if (pVia->pI2CBus2 && xf86I2CProbeAddress(pVia->pI2CBus2, 0xEC)) 417 pBIOSInfo->TVI2CDev = ViaCH7xxxDetect(pScrn, pVia->pI2CBus2, 0xEC); 418 else if (pVia->pI2CBus2 && xf86I2CProbeAddress(pVia->pI2CBus2, 0x40)) 419 pBIOSInfo->TVI2CDev = ViaVT162xDetect(pScrn, pVia->pI2CBus2, 0x40); 420 else if (pVia->pI2CBus3 && xf86I2CProbeAddress(pVia->pI2CBus3, 0x40)) 421 pBIOSInfo->TVI2CDev = ViaVT162xDetect(pScrn, pVia->pI2CBus3, 0x40); 422 else if (pVia->pI2CBus2 && xf86I2CProbeAddress(pVia->pI2CBus2, 0xEA)) 423 pBIOSInfo->TVI2CDev = ViaCH7xxxDetect(pScrn, pVia->pI2CBus2, 0xEA); 424 else if (pVia->pI2CBus3 && xf86I2CProbeAddress(pVia->pI2CBus3, 0xEA)) 425 pBIOSInfo->TVI2CDev = ViaCH7xxxDetect(pScrn, pVia->pI2CBus3, 0xEA); 426 427 if (!pBIOSInfo->TVI2CDev) { 428 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 429 "Did not detect a TV encoder.\n"); 430 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 431 "Exiting via_tv_init.\n")); 432 433 return FALSE; 434 } 435 436 switch (pBIOSInfo->TVEncoder) { 437 case VIA_VT1621: 438 case VIA_VT1622: 439 case VIA_VT1623: 440 case VIA_VT1625: 441 ViaVT162xInit(pScrn); 442 break; 443 case VIA_CH7011: 444 case VIA_CH7019A: 445 case VIA_CH7019B: 446 ViaCH7xxxInit(pScrn); 447 break; 448 default: 449 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 450 "Was not able to initialize a known TV encoder.\n"); 451 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 452 "Exiting via_tv_init.\n")); 453 return FALSE; 454 break; 455 } 456 457 if (!pBIOSInfo->TVSave || !pBIOSInfo->TVRestore 458 || !pBIOSInfo->TVDACSense || !pBIOSInfo->TVModeValid 459 || !pBIOSInfo->TVModeI2C || !pBIOSInfo->TVModeCrtc 460 || !pBIOSInfo->TVPower || !pBIOSInfo->TVModes 461 || !pBIOSInfo->TVPrintRegs) { 462 463 xf86DestroyI2CDevRec(pBIOSInfo->TVI2CDev, TRUE); 464 465 pBIOSInfo->TVI2CDev = NULL; 466 pBIOSInfo->TVOutput = TVOUTPUT_NONE; 467 pBIOSInfo->TVEncoder = VIA_NONETV; 468 pBIOSInfo->TVI2CDev = NULL; 469 pBIOSInfo->TVSave = NULL; 470 pBIOSInfo->TVRestore = NULL; 471 pBIOSInfo->TVDACSense = NULL; 472 pBIOSInfo->TVModeValid = NULL; 473 pBIOSInfo->TVModeI2C = NULL; 474 pBIOSInfo->TVModeCrtc = NULL; 475 pBIOSInfo->TVPower = NULL; 476 pBIOSInfo->TVModes = NULL; 477 pBIOSInfo->TVPrintRegs = NULL; 478 pBIOSInfo->TVNumRegs = 0; 479 480 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 481 "TV encoder was not properly initialized.\n"); 482 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 483 "Exiting via_tv_init.\n")); 484 return FALSE; 485 } 486 487 output = xf86OutputCreate(pScrn, &via_tv_funcs, "TV-1"); 488 pVia->FirstInit = TRUE; 489 490 if (output) { 491 /* Allow tv output on both crtcs, set bit 0 and 1. */ 492 output->possible_crtcs = 0x3; 493 } else { 494 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 495 "Failed to register TV-1.\n"); 496 } 497 498 pBIOSInfo->tv = output; 499 /* Save now */ 500 pBIOSInfo->TVSave(pScrn); 501 502#ifdef HAVE_DEBUG 503 if (VIAPTR(pScrn)->PrintTVRegs) 504 pBIOSInfo->TVPrintRegs(pScrn); 505#endif 506 507 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 508 "Exiting via_tv_init.\n")); 509 return TRUE; 510} 511 512/* 513 * Enables or disables analog VGA output by controlling DAC 514 * (Digital to Analog Converter) output state. 515 */ 516static void 517viaAnalogOutput(ScrnInfoPtr pScrn, Bool outputState) 518{ 519 vgaHWPtr hwp = VGAHWPTR(pScrn); 520 521 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 522 "Entered viaAnalogOutput.\n")); 523 524 /* This register controls analog VGA DAC output state. */ 525 /* 3X5.47[2] - DACOFF Backdoor Register 526 * 0: DAC on 527 * 1: DAC off */ 528 ViaCrtcMask(hwp, 0x47, outputState ? 0x00 : 0x04, 0x04); 529 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 530 "Analog VGA Output: %s\n", 531 outputState ? "On" : "Off"); 532 533 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 534 "Exiting viaAnalogOutput.\n")); 535} 536 537/* 538 * Specifies IGA1 or IGA2 for analog VGA DAC source. 539 */ 540static void 541viaAnalogSource(ScrnInfoPtr pScrn, CARD8 displaySource) 542{ 543 vgaHWPtr hwp = VGAHWPTR(pScrn); 544 CARD8 value = displaySource; 545 546 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 547 "Entered viaAnalogSource.\n")); 548 549 ViaSeqMask(hwp, 0x16, value << 6, 0x40); 550 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 551 "Analog VGA Output Source: IGA%d\n", 552 (value & 0x01) + 1); 553 554 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 555 "Exiting viaAnalogSource.\n")); 556} 557 558/* 559 * Intializes analog VGA related registers. 560 */ 561static void 562viaAnalogInit(ScrnInfoPtr pScrn) 563{ 564 vgaHWPtr hwp = VGAHWPTR(pScrn); 565 VIAPtr pVia = VIAPTR(pScrn); 566 567 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 568 "Entered viaAnalogInit.\n")); 569 570 /* 3X5.37[7] - DAC Power Save Control 1 571 * 0: Depend on Rx3X5.37[5:4] setting 572 * 1: DAC always goes into power save mode 573 * 3X5.37[6] - DAC Power Down Control 574 * 0: Depend on Rx3X5.47[2] setting 575 * 1: DAC never goes to power down mode 576 * 3X5.37[5:4] - DAC Power Save Control 2 577 * 00: DAC never goes to power save mode 578 * 01: DAC goes to power save mode by line 579 * 10: DAC goes to power save mode by frame 580 * 11: DAC goes to power save mode by line and frame 581 * 3X5.37[3] - DAC PEDESTAL Control 582 * 3X5.37[2:0] - DAC Factor 583 * (Default: 100) */ 584 ViaCrtcMask(hwp, 0x37, 0x04, 0xFF); 585 586 switch (pVia->Chipset) { 587 case VIA_CX700: 588 case VIA_VX800: 589 case VIA_VX855: 590 case VIA_VX900: 591 /* 3C5.5E[0] - CRT DACOFF Setting 592 * 1: CRT DACOFF controlled by 3C5.01[5] */ 593 ViaSeqMask(hwp, 0x5E, 0x01, 0x01); 594 break; 595 default: 596 break; 597 } 598 599 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 600 "Exiting viaAnalogInit.\n")); 601} 602 603static void 604via_analog_create_resources(xf86OutputPtr output) 605{ 606} 607 608#ifdef RANDR_12_INTERFACE 609static Bool 610via_analog_set_property(xf86OutputPtr output, Atom property, 611 RRPropertyValuePtr value) 612{ 613 return TRUE; 614} 615 616static Bool 617via_analog_get_property(xf86OutputPtr output, Atom property) 618{ 619 return FALSE; 620} 621#endif 622 623static void 624via_analog_dpms(xf86OutputPtr output, int mode) 625{ 626 ScrnInfoPtr pScrn = output->scrn; 627 628 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 629 "Entered via_analog_dpms.\n")); 630 631 switch (mode) { 632 case DPMSModeOn: 633 viaAnalogOutput(pScrn, TRUE); 634 break; 635 case DPMSModeStandby: 636 case DPMSModeSuspend: 637 case DPMSModeOff: 638 viaAnalogOutput(pScrn, FALSE); 639 break; 640 default: 641 break; 642 } 643 644 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 645 "Exiting via_analog_dpms.\n")); 646} 647 648static void 649via_analog_save(xf86OutputPtr output) 650{ 651} 652 653static void 654via_analog_restore(xf86OutputPtr output) 655{ 656} 657 658static int 659via_analog_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) 660{ 661 ScrnInfoPtr pScrn = output->scrn; 662 663 if (!ViaModeDotClockTranslate(pScrn, pMode)) 664 return MODE_NOCLOCK; 665 return MODE_OK; 666} 667 668static Bool 669via_analog_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, 670 DisplayModePtr adjusted_mode) 671{ 672 return TRUE; 673} 674 675static void 676via_analog_prepare(xf86OutputPtr output) 677{ 678 via_analog_dpms(output, DPMSModeOff); 679} 680 681static void 682via_analog_commit(xf86OutputPtr output) 683{ 684 via_analog_dpms(output, DPMSModeOn); 685} 686 687static void 688via_analog_mode_set(xf86OutputPtr output, DisplayModePtr mode, 689 DisplayModePtr adjusted_mode) 690{ 691 ScrnInfoPtr pScrn = output->scrn; 692 vgaHWPtr hwp = VGAHWPTR(pScrn); 693 drmmode_crtc_private_ptr iga = output->crtc->driver_private; 694 695 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 696 "Entered via_analog_mode_set.\n")); 697 698 viaAnalogInit(pScrn); 699 700 if (output->crtc) { 701 viaAnalogSource(pScrn, iga->index ? 0x01 : 0x00); 702 } 703 704 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 705 "Exiting via_analog_mode_set.\n")); 706} 707 708static xf86OutputStatus 709via_analog_detect(xf86OutputPtr output) 710{ 711 xf86OutputStatus status = XF86OutputStatusDisconnected; 712 ScrnInfoPtr pScrn = output->scrn; 713 VIAPtr pVia = VIAPTR(pScrn); 714 xf86MonPtr mon; 715 716 /* Probe I2C Bus 1 to see if a VGA monitor is connected. */ 717 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 718 "Probing for a VGA monitor on I2C Bus 1.\n"); 719 mon = xf86OutputGetEDID(output, pVia->pI2CBus1); 720 if (mon && (!mon->features.input_type)) { 721 xf86OutputSetEDID(output, mon); 722 status = XF86OutputStatusConnected; 723 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 724 "Detected a VGA monitor on I2C Bus 1.\n"); 725 } else { 726 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 727 "Did not detect a VGA monitor on I2C Bus 1.\n"); 728 729 /* Probe I2C Bus 2 to see if a VGA monitor is connected. */ 730 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 731 "Probing for a VGA monitor on I2C Bus 2.\n"); 732 mon = xf86OutputGetEDID(output, pVia->pI2CBus2); 733 if (mon && (!mon->features.input_type)) { 734 xf86OutputSetEDID(output, mon); 735 status = XF86OutputStatusConnected; 736 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 737 "Detected a VGA monitor on I2C Bus 2.\n"); 738 } else { 739 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 740 "Did not detect a VGA monitor on I2C Bus 2.\n"); 741 742 /* Perform manual detection of a VGA monitor since */ 743 /* it was not detected via I2C buses. */ 744 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 745 "Now perform manual detection of a VGA " 746 "monitor.\n"); 747 vgaHWPtr hwp = VGAHWPTR(pScrn); 748 CARD8 SR01 = hwp->readSeq(hwp, 0x01); 749 CARD8 SR40 = hwp->readSeq(hwp, 0x40); 750 CARD8 CR36 = hwp->readCrtc(hwp, 0x36); 751 752 /* We have to power on the display to detect it */ 753 ViaSeqMask(hwp, 0x01, 0x00, 0x20); 754 ViaCrtcMask(hwp, 0x36, 0x00, 0xF0); 755 756 /* Wait for vblank */ 757 usleep(16); 758 759 /* Detect the load on pins */ 760 ViaSeqMask(hwp, 0x40, 0x80, 0x80); 761 762 if ((VIA_CX700 == pVia->Chipset) || 763 (VIA_VX800 == pVia->Chipset) || 764 (VIA_VX855 == pVia->Chipset) || 765 (VIA_VX900 == pVia->Chipset)) 766 ViaSeqMask(hwp, 0x40, 0x00, 0x80); 767 768 if (ViaVgahwIn(hwp, 0x3C2) & 0x20) { 769 status = XF86OutputStatusConnected; 770 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 771 "Detected a VGA monitor using manual " 772 "detection method.\n"); 773 } 774 775 if ((VIA_CX700 == pVia->Chipset) || 776 (VIA_VX800 == pVia->Chipset) || 777 (VIA_VX855 == pVia->Chipset) || 778 (VIA_VX900 == pVia->Chipset)) 779 ViaSeqMask(hwp, 0x40, 0x00, 0x80); 780 781 /* Restore previous state */ 782 hwp->writeSeq(hwp, 0x40, SR40); 783 hwp->writeSeq(hwp, 0x01, SR01); 784 hwp->writeCrtc(hwp, 0x36, CR36); 785 } 786 } 787 788 return status; 789} 790 791static void 792via_analog_destroy(xf86OutputPtr output) 793{ 794} 795 796static const xf86OutputFuncsRec via_analog_funcs = { 797 .create_resources = via_analog_create_resources, 798#ifdef RANDR_12_INTERFACE 799 .set_property = via_analog_set_property, 800#endif 801#ifdef RANDR_13_INTERFACE 802 .get_property = via_analog_get_property, 803#endif 804 .dpms = via_analog_dpms, 805 .save = via_analog_save, 806 .restore = via_analog_restore, 807 .mode_valid = via_analog_mode_valid, 808 .mode_fixup = via_analog_mode_fixup, 809 .prepare = via_analog_prepare, 810 .commit = via_analog_commit, 811 .mode_set = via_analog_mode_set, 812 .detect = via_analog_detect, 813 .get_modes = xf86OutputGetEDIDModes, 814 .destroy = via_analog_destroy, 815}; 816 817void 818via_analog_init(ScrnInfoPtr pScrn) 819{ 820 VIAPtr pVia = VIAPTR(pScrn); 821 VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; 822 xf86OutputPtr output = NULL; 823 824 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 825 "Entered via_analog_init.\n")); 826 827 if (!pVia->pI2CBus1 || !pVia->pI2CBus2) { 828 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 829 "I2C Bus 1 or I2C Bus 2 does not exist.\n"); 830 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 831 "Exiting via_analog_init.\n")); 832 return; 833 } 834 835 output = xf86OutputCreate(pScrn, &via_analog_funcs, "VGA-1"); 836 837 output->possible_crtcs = 0x3; 838 output->possible_clones = 0; 839 output->interlaceAllowed = TRUE; 840 output->doubleScanAllowed = FALSE; 841 pBIOSInfo->analog = output; 842 843 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 844 "Exiting via_analog_init.\n")); 845} 846 847static void 848via_dvi_create_resources(xf86OutputPtr output) 849{ 850} 851 852#ifdef RANDR_12_INTERFACE 853static Bool 854via_dvi_set_property(xf86OutputPtr output, Atom property, 855 RRPropertyValuePtr value) 856{ 857 return TRUE; 858} 859 860static Bool 861via_dvi_get_property(xf86OutputPtr output, Atom property) 862{ 863 return FALSE; 864} 865#endif 866 867static void 868via_dvi_dpms(xf86OutputPtr output, int mode) 869{ 870 ScrnInfoPtr pScrn = output->scrn; 871 872 switch (mode) { 873 case DPMSModeOn: 874 via_vt1632_power(output, TRUE); 875 break; 876 case DPMSModeStandby: 877 case DPMSModeSuspend: 878 case DPMSModeOff: 879 via_vt1632_power(output, FALSE); 880 break; 881 default: 882 break; 883 } 884} 885 886static void 887via_dvi_save(xf86OutputPtr output) 888{ 889 via_vt1632_save(output); 890} 891 892static void 893via_dvi_restore(xf86OutputPtr output) 894{ 895 via_vt1632_restore(output); 896} 897 898static int 899via_dvi_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) 900{ 901 return via_vt1632_mode_valid(output, pMode); 902} 903 904static Bool 905via_dvi_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, 906 DisplayModePtr adjusted_mode) 907{ 908 return TRUE; 909} 910 911static void 912via_dvi_prepare(xf86OutputPtr output) 913{ 914} 915 916static void 917via_dvi_commit(xf86OutputPtr output) 918{ 919} 920 921static void 922via_dvi_mode_set(xf86OutputPtr output, DisplayModePtr mode, 923 DisplayModePtr adjusted_mode) 924{ 925 ScrnInfoPtr pScrn = output->scrn; 926 vgaHWPtr hwp = VGAHWPTR(pScrn); 927 928 via_vt1632_mode_set(output, mode, adjusted_mode); 929} 930 931static xf86OutputStatus 932via_dvi_detect(xf86OutputPtr output) 933{ 934 xf86OutputStatus status = XF86OutputStatusDisconnected; 935 ScrnInfoPtr pScrn = output->scrn; 936 VIAPtr pVia = VIAPTR(pScrn); 937 ViaVT1632Ptr Private = output->driver_private; 938 xf86MonPtr mon; 939 940 /* Check for the DVI presence via VT1632A first before accessing 941 * I2C bus. */ 942 status = via_vt1632_detect(output); 943 if (status == XF86OutputStatusConnected) { 944 945 /* Since DVI presence was established, access the I2C bus 946 * assigned to DVI. */ 947 mon = xf86OutputGetEDID(output, Private->VT1632I2CDev->pI2CBus); 948 949 /* Is the interface type digital? */ 950 if (mon && DIGITAL(mon->features.input_type)) { 951 xf86OutputSetEDID(output, mon); 952 } else { 953 status = XF86OutputStatusDisconnected; 954 } 955 } 956 957 return status; 958} 959 960static void 961via_dvi_destroy(xf86OutputPtr output) 962{ 963} 964 965static const xf86OutputFuncsRec via_dvi_funcs = { 966 .create_resources = via_dvi_create_resources, 967#ifdef RANDR_12_INTERFACE 968 .set_property = via_dvi_set_property, 969#endif 970#ifdef RANDR_13_INTERFACE 971 .get_property = via_dvi_get_property, 972#endif 973 .dpms = via_dvi_dpms, 974 .save = via_dvi_save, 975 .restore = via_dvi_restore, 976 .mode_valid = via_dvi_mode_valid, 977 .mode_fixup = via_dvi_mode_fixup, 978 .prepare = via_dvi_prepare, 979 .commit = via_dvi_commit, 980 .mode_set = via_dvi_mode_set, 981 .detect = via_dvi_detect, 982 .get_modes = xf86OutputGetEDIDModes, 983 .destroy = via_dvi_destroy, 984}; 985 986void 987via_dvi_init(ScrnInfoPtr pScrn) 988{ 989 VIAPtr pVia = VIAPTR(pScrn); 990 xf86OutputPtr output = NULL; 991 ViaVT1632Ptr private_data = NULL; 992 I2CBusPtr pBus = NULL; 993 I2CDevPtr pDev = NULL; 994 I2CSlaveAddr addr = 0x10; 995 996 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 997 "Entered via_dvi_init.\n")); 998 999 if (!pVia->pI2CBus2 || !pVia->pI2CBus3) { 1000 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1001 "I2C Bus 2 or I2C Bus 3 does not exist.\n"); 1002 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1003 "Exiting via_dvi_init.\n")); 1004 return; 1005 } 1006 1007 if (xf86I2CProbeAddress(pVia->pI2CBus3, addr)) { 1008 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1009 "Will probe I2C Bus 3 for a possible " 1010 "external TMDS transmitter.\n")); 1011 pBus = pVia->pI2CBus3; 1012 } else if (xf86I2CProbeAddress(pVia->pI2CBus2, addr)) { 1013 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1014 "Will probe I2C Bus 2 for a possible " 1015 "external TMDS transmitter.\n")); 1016 pBus = pVia->pI2CBus2; 1017 } else { 1018 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1019 "Did not find a possible external TMDS transmitter " 1020 "on I2C Bus 2 or I2C Bus 3.\n"); 1021 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1022 "Exiting via_dvi_init.\n")); 1023 return; 1024 } 1025 1026 pDev = xf86CreateI2CDevRec(); 1027 if (!pDev) { 1028 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1029 "Failed to create an I2C bus structure.\n"); 1030 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1031 "Exiting via_dvi_init.\n")); 1032 return; 1033 } 1034 1035 pDev->DevName = "VT1632A"; 1036 pDev->SlaveAddr = addr; 1037 pDev->pI2CBus = pBus; 1038 if (!xf86I2CDevInit(pDev)) { 1039 xf86DestroyI2CDevRec(pDev, TRUE); 1040 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1041 "Failed to initialize a device on I2C bus.\n"); 1042 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1043 "Exiting via_dvi_init.\n")); 1044 return; 1045 } 1046 1047 if (!via_vt1632_probe(pScrn, pDev)) { 1048 xf86DestroyI2CDevRec(pDev, TRUE); 1049 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1050 "Exiting via_dvi_init.\n")); 1051 return; 1052 } 1053 1054 private_data = via_vt1632_init(pScrn, pDev); 1055 if (!private_data) { 1056 xf86DestroyI2CDevRec(pDev, TRUE); 1057 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1058 "Exiting via_dvi_init.\n")); 1059 return; 1060 } 1061 1062 output = xf86OutputCreate(pScrn, &via_dvi_funcs, "DVI-1"); 1063 if (output) { 1064 output->driver_private = private_data; 1065 output->possible_crtcs = 0x2; 1066 output->possible_clones = 0; 1067 output->interlaceAllowed = FALSE; 1068 output->doubleScanAllowed = FALSE; 1069 } 1070 1071 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1072 "Exiting via_dvi_init.\n")); 1073} 1074 1075/* 1076 * Reads off the VIA Technologies IGP pin strapping for 1077 * display detection purposes. 1078 */ 1079void 1080viaProbePinStrapping(ScrnInfoPtr pScrn) 1081{ 1082 vgaHWPtr hwp = VGAHWPTR(pScrn); 1083 VIAPtr pVia = VIAPTR(pScrn); 1084 CARD8 sr12, sr13, sr5a; 1085 1086 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1087 "Entered viaProbePinStrapping.\n")); 1088 1089 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1090 "Probing VIA Technologies IGP pin strapping . . .\n"); 1091 1092 if ((pVia->Chipset == VIA_CX700) 1093 || (pVia->Chipset == VIA_VX800) 1094 || (pVia->Chipset == VIA_VX855) 1095 || (pVia->Chipset == VIA_VX900)) { 1096 1097 sr5a = hwp->readSeq(hwp, 0x5A); 1098 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1099 "SR5A: 0x%02X\n", sr5a)); 1100 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1101 "Setting 3C5.5A[0] to 0.\n"); 1102 ViaSeqMask(hwp, 0x5A, sr5a & 0xFE, 0x01); 1103 } 1104 1105 sr12 = hwp->readSeq(hwp, 0x12); 1106 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1107 "SR12: 0x%02X\n", sr12)); 1108 sr13 = hwp->readSeq(hwp, 0x13); 1109 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1110 "SR13: 0x%02X\n", sr13)); 1111 1112 switch (pVia->Chipset) { 1113 case VIA_CLE266: 1114 case VIA_KM400: 1115 1116 /* 3C5.12[4] - FPD17 pin strapping 1117 * 0: TMDS transmitter (DVI) / capture device 1118 * 1: Flat panel */ 1119 if (sr12 & 0x10) { 1120 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1121 "A flat panel is connected to " 1122 "flat panel interface.\n"); 1123 1124 /* 3C5.12[3:0] - FPD16-13 pin strapping 1125 * 0 ~ 15: Flat panel code defined 1126 * by VIA Technologies */ 1127 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1128 "Detected Flat Panel Type from " 1129 "Strapping Pins: %d\n", sr12 & 0x0F); 1130 } else { 1131 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1132 "A TMDS transmitter (DVI) / capture device is " 1133 "connected to flat panel interface.\n"); 1134 } 1135 1136 /* 3C5.12[5] - FPD18 pin strapping 1137 * 0: TMDS transmitter (DVI) 1138 * 1: TV encoder */ 1139 if (sr12 & 0x20) { 1140 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1141 "A TMDS transmitter (DVI) is connected to " 1142 "DVI port.\n"); 1143 } else { 1144 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1145 "A TV encoder is connected to " 1146 "DVI port.\n"); 1147 1148 /* 3C5.13[4:3] - FPD21-20 pin strapping 1149 * 00: PAL 1150 * 01: NTSC 1151 * 10: PAL-N 1152 * 11: PAL-NC */ 1153 if (sr13 & 0x04) { 1154 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1155 "NTSC for the TV encoder.\n"); 1156 } else { 1157 if (!(sr13 & 0x08)) { 1158 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1159 "PAL for the TV encoder.\n"); 1160 } else { 1161 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1162 "PAL%s for the TV encoder.\n", 1163 sr13 & 0x04 ? "-NC" : "-N"); 1164 } 1165 } 1166 1167 /* 3C5.12[6] - FPD19 pin strapping 1168 * 0: 525 lines (NTSC) 1169 * 1: 625 lines (PAL) */ 1170 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1171 "%s lines for the TV encoder.\n", 1172 sr12 & 0x40 ? "625" : "525"); 1173 } 1174 1175 break; 1176 1177 case VIA_K8M800: 1178 case VIA_PM800: 1179 case VIA_P4M800PRO: 1180 1181 /* 3C5.12[6] - DVP0D6 pin strapping 1182 * 0: Disable DVP0 (Digital Video Port 0) for 1183 * DVI or TV out use 1184 * 1: Enable DVP0 (Digital Video Port 0) for 1185 * DVI or TV out use */ 1186 if (sr12 & 0x40) { 1187 1188 /* 3C5.12[5] - DVP0D5 pin strapping 1189 * 0: TMDS transmitter (DVI) 1190 * 1: TV encoder */ 1191 if (sr12 & 0x20) { 1192 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1193 "A TV encoder is detected on " 1194 "DVP0 (Digital Video Port 0).\n"); 1195 } else { 1196 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1197 "A TMDS transmitter (DVI) is detected on " 1198 "DVP0 (Digital Video Port 0).\n"); 1199 } 1200 } 1201 1202 1203 /* 3C5.13[3] - DVP0D8 pin strapping 1204 * 0: AGP pins are used for AGP 1205 * 1: AGP pins are used by FPDP 1206 * (Flat Panel Display Port) */ 1207 if (sr13 & 0x08) { 1208 1209 /* 3C5.12[4] - DVP0D4 pin strapping 1210 * 0: Dual 12-bit FPDP (Flat Panel Display Port) 1211 * 1: 24-bit FPDP (Flat Panel Display Port) */ 1212 if (sr12 & 0x10) { 1213 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1214 "24-bit FPDP (Flat Panel Display Port) " 1215 "detected.\n"); 1216 1217 /* 3C5.12[3:0] - DVP0D3-0 pin strapping 1218 * 0 ~ 15: Flat panel code defined 1219 * by VIA Technologies */ 1220 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1221 "Detected Flat Panel Type from " 1222 "Strapping Pins: %d\n", sr12 & 0x0F); 1223 } else { 1224 1225 /* 3C5.12[6] - DVP0D6 pin strapping 1226 * 0: Disable DVP0 (Digital Video Port 0) for 1227 * DVI or TV out use 1228 * 1: Enable DVP0 (Digital Video Port 0) for 1229 * DVI or TV out use 1230 * 3C5.12[5] - DVP0D5 pin strapping 1231 * 0: TMDS transmitter (DVI) 1232 * 1: TV encoder */ 1233 if ((!(sr12 & 0x40)) && (!(sr12 & 0x20))) { 1234 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1235 "A TV encoder is connected to " 1236 "FPDP (Flat Panel Display Port).\n"); 1237 } else { 1238 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1239 "Dual 12-bit FPDP (Flat Panel Display Port) " 1240 "detected.\n"); 1241 1242 /* 3C5.12[3:0] - DVP0D3-0 pin strapping 1243 * 0 ~ 15: Flat panel code defined 1244 * by VIA Technologies */ 1245 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1246 "Detected Flat Panel Type from " 1247 "Strapping Pins: %d\n", sr12 & 0x0F); 1248 } 1249 } 1250 } 1251 1252 break; 1253 1254 default: 1255 break; 1256 } 1257 1258 if ((pVia->Chipset == VIA_CX700) 1259 || (pVia->Chipset == VIA_VX800) 1260 || (pVia->Chipset == VIA_VX855) 1261 || (pVia->Chipset == VIA_VX900)) { 1262 1263 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1264 "Setting 3C5.5A[0] to 1.\n"); 1265 ViaSeqMask(hwp, 0x5A, sr5a | 0x01, 0x01); 1266 1267 sr12 = hwp->readSeq(hwp, 0x12); 1268 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1269 "SR12: 0x%02X\n", sr12)); 1270 sr13 = hwp->readSeq(hwp, 0x13); 1271 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1272 "SR13: 0x%02X\n", sr13)); 1273 1274 /* 3C5.13[7:6] - Integrated LVDS / DVI Mode Select 1275 * (DVP1D15-14 pin strapping) 1276 * 00: LVDS1 + LVDS2 1277 * 01: DVI + LVDS2 1278 * 10: Dual LVDS Channel (High Resolution Panel) 1279 * 11: One DVI only (decrease the clock jitter) */ 1280 switch (sr13 & 0xC0) { 1281 case 0x00: 1282 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1283 "LVDS1 + LVDS2 detected.\n"); 1284 break; 1285 case 0x40: 1286 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1287 "Single Link DVI + LVDS2 detected.\n"); 1288 break; 1289 case 0x80: 1290 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1291 "Dual Channel LVDS detected.\n"); 1292 break; 1293 case 0xC0: 1294 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1295 "Single Link DVI detected.\n"); 1296 break; 1297 default: 1298 break; 1299 } 1300 1301 hwp->writeSeq(hwp, 0x5A, sr5a); 1302 1303 } 1304 1305 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1306 "Exiting viaProbePinStrapping.\n")); 1307} 1308 1309void 1310viaOutputDetect(ScrnInfoPtr pScrn) 1311{ 1312 VIAPtr pVia = VIAPTR(pScrn); 1313 VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; 1314 1315 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1316 "Entered viaOutputDetect.\n")); 1317 1318 pBIOSInfo->analog = NULL; 1319 1320 /* Read off the VIA Technologies IGP pin strapping for 1321 display detection purposes. */ 1322 viaProbePinStrapping(pScrn); 1323 1324 /* LVDS */ 1325 via_lvds_init(pScrn); 1326 1327 /* VGA */ 1328 via_analog_init(pScrn); 1329 1330 /* TV */ 1331 via_tv_init(pScrn); 1332 1333 /* External TMDS Transmitter (DVI) */ 1334 via_dvi_init(pScrn); 1335 1336 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1337 "Exiting viaOutputDetect.\n")); 1338} 1339 1340#ifdef HAVE_DEBUG 1341/* 1342 * Returns: 1343 * Bit[7] 2nd Path 1344 * Bit[6] 1/0 MHS Enable/Disable 1345 * Bit[5] 0 = Bypass Callback, 1 = Enable Callback 1346 * Bit[4] 0 = Hot-Key Sequence Control (OEM Specific) 1347 * Bit[3] LCD 1348 * Bit[2] TV 1349 * Bit[1] CRT 1350 * Bit[0] DVI 1351 */ 1352static CARD8 1353VIAGetActiveDisplay(ScrnInfoPtr pScrn) 1354{ 1355 vgaHWPtr hwp = VGAHWPTR(pScrn); 1356 CARD8 tmp; 1357 1358 tmp = (hwp->readCrtc(hwp, 0x3E) >> 4); 1359 tmp |= ((hwp->readCrtc(hwp, 0x3B) & 0x18) << 3); 1360 1361 return tmp; 1362} 1363#endif /* HAVE_DEBUG */ 1364 1365/* 1366 * 1367 */ 1368CARD32 1369ViaGetMemoryBandwidth(ScrnInfoPtr pScrn) 1370{ 1371 VIAPtr pVia = VIAPTR(pScrn); 1372 1373 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1374 "ViaGetMemoryBandwidth. Memory type: %d\n", 1375 pVia->MemClk)); 1376 1377 switch (pVia->MemClk) { 1378 case VIA_MEM_SDR66: 1379 case VIA_MEM_SDR100: 1380 case VIA_MEM_SDR133: 1381 return VIA_BW_MIN; 1382 case VIA_MEM_DDR200: 1383 return VIA_BW_DDR200; 1384 case VIA_MEM_DDR266: 1385 case VIA_MEM_DDR333: 1386 case VIA_MEM_DDR400: 1387 return VIA_BW_DDR400; 1388 case VIA_MEM_DDR533: 1389 case VIA_MEM_DDR667: 1390 return VIA_BW_DDR667; 1391 case VIA_MEM_DDR800: 1392 case VIA_MEM_DDR1066: 1393 return VIA_BW_DDR1066; 1394 default: 1395 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1396 "ViaBandwidthAllowed: Unknown memory type: %d\n", 1397 pVia->MemClk); 1398 return VIA_BW_MIN; 1399 } 1400} 1401 1402/* 1403 * 1404 * Some very common abstractions. 1405 * 1406 */ 1407 1408/* 1409 * Standard vga call really. 1410 * Needs to be called to reset the dotclock (after SR40:2/1 reset) 1411 */ 1412void 1413ViaSetUseExternalClock(vgaHWPtr hwp) 1414{ 1415 CARD8 data; 1416 1417 DEBUG(xf86DrvMsg(hwp->pScrn->scrnIndex, X_INFO, 1418 "ViaSetUseExternalClock\n")); 1419 1420 data = hwp->readMiscOut(hwp); 1421 hwp->writeMiscOut(hwp, data | 0x0C); 1422} 1423 1424/* 1425 * 1426 */ 1427static void 1428ViaSetDotclock(ScrnInfoPtr pScrn, CARD32 clock, int base, int probase) 1429{ 1430 vgaHWPtr hwp = VGAHWPTR(pScrn); 1431 VIAPtr pVia = VIAPTR(pScrn); 1432 1433 DEBUG(xf86DrvMsg(hwp->pScrn->scrnIndex, X_INFO, 1434 "ViaSetDotclock to 0x%06x\n", (unsigned)clock)); 1435 1436 if ((pVia->Chipset == VIA_CLE266) || (pVia->Chipset == VIA_KM400)) { 1437 hwp->writeSeq(hwp, base, clock >> 8); 1438 hwp->writeSeq(hwp, base+1, clock & 0xFF); 1439 } else { /* unichrome pro */ 1440 union pllparams pll; 1441 int dtz, dr, dn, dm; 1442 pll.packed = clock; 1443 dtz = pll.params.dtz; 1444 dr = pll.params.dr; 1445 dn = pll.params.dn; 1446 dm = pll.params.dm; 1447 1448 /* The VX855 and VX900 do not modify dm/dn, but earlier chipsets do. */ 1449 if ((pVia->Chipset != VIA_VX855) && (pVia->Chipset != VIA_VX900)) { 1450 dm -= 2; 1451 dn -= 2; 1452 } 1453 1454 hwp->writeSeq(hwp, probase, dm & 0xff); 1455 hwp->writeSeq(hwp, probase+1, 1456 ((dm >> 8) & 0x03) | (dr << 2) | ((dtz & 1) << 7)); 1457 hwp->writeSeq(hwp, probase+2, (dn & 0x7f) | ((dtz & 2) << 6)); 1458 } 1459} 1460 1461/* 1462 * 1463 */ 1464void 1465ViaSetPrimaryDotclock(ScrnInfoPtr pScrn, CARD32 clock) 1466{ 1467 vgaHWPtr hwp = VGAHWPTR(pScrn); 1468 1469 ViaSetDotclock(pScrn, clock, 0x46, 0x44); 1470 1471 ViaSeqMask(hwp, 0x40, 0x02, 0x02); 1472 ViaSeqMask(hwp, 0x40, 0x00, 0x02); 1473} 1474 1475/* 1476 * 1477 */ 1478void 1479ViaSetSecondaryDotclock(ScrnInfoPtr pScrn, CARD32 clock) 1480{ 1481 vgaHWPtr hwp = VGAHWPTR(pScrn); 1482 1483 ViaSetDotclock(pScrn, clock, 0x44, 0x4A); 1484 1485 ViaSeqMask(hwp, 0x40, 0x04, 0x04); 1486 ViaSeqMask(hwp, 0x40, 0x00, 0x04); 1487} 1488 1489/* 1490 * 1491 */ 1492static void 1493ViaSetECKDotclock(ScrnInfoPtr pScrn, CARD32 clock) 1494{ 1495 /* Does the non-pro chip have an ECK clock ? */ 1496 ViaSetDotclock(pScrn, clock, 0, 0x47); 1497} 1498 1499static CARD32 1500ViaComputeDotClock(unsigned clock) 1501{ 1502 double fout, fref, err, minErr; 1503 CARD32 dr, dn, dm, maxdm, maxdn; 1504 CARD32 factual, best; 1505 1506 fref = 14.31818e6; 1507 fout = (double)clock * 1.e3; 1508 1509 factual = ~0; 1510 maxdm = 127; 1511 maxdn = 7; 1512 minErr = 1e10; 1513 best = 0; 1514 1515 for (dr = 0; dr < 4; ++dr) { 1516 for (dn = (dr == 0) ? 2 : 1; dn <= maxdn; ++dn) { 1517 for (dm = 1; dm <= maxdm; ++dm) { 1518 factual = fref * dm; 1519 factual /= (dn << dr); 1520 err = fabs((double)factual / fout - 1.); 1521 if (err < minErr) { 1522 minErr = err; 1523 best = (dm & 127) | ((dn & 31) << 8) | (dr << 14); 1524 } 1525 } 1526 } 1527 } 1528 return best; 1529} 1530 1531static CARD32 1532ViaComputeProDotClock(unsigned clock) 1533{ 1534 double fvco, fout, fref, err, minErr; 1535 CARD32 dr = 0, dn, dm, maxdm, maxdn; 1536 CARD32 factual; 1537 union pllparams bestClock; 1538 1539 fref = 14.318e6; 1540 fout = (double)clock * 1.e3; 1541 1542 factual = ~0; 1543 maxdm = factual / 14318000U; 1544 minErr = 1.e10; 1545 bestClock.packed = 0U; 1546 1547 do { 1548 fvco = fout * (1 << dr); 1549 } while (fvco < 300.e6 && dr++ < 8); 1550 1551 if (dr == 8) { 1552 return 0; 1553 } 1554 1555 if (clock < 30000) 1556 maxdn = 8; 1557 else if (clock < 45000) 1558 maxdn = 7; 1559 else if (clock < 170000) 1560 maxdn = 6; 1561 else 1562 maxdn = 5; 1563 1564 for (dn = 2; dn < maxdn; ++dn) { 1565 for (dm = 2; dm < maxdm; ++dm) { 1566 factual = 14318000U * dm; 1567 factual /= dn << dr; 1568 if ((err = fabs((double)factual / fout - 1.)) < 0.005) { 1569 if (err < minErr) { 1570 minErr = err; 1571 bestClock.params.dtz = 1; 1572 bestClock.params.dr = dr; 1573 bestClock.params.dn = dn; 1574 bestClock.params.dm = dm; 1575 } 1576 } 1577 } 1578 } 1579 1580 return bestClock.packed; 1581} 1582 1583/* 1584 * 1585 */ 1586CARD32 1587ViaModeDotClockTranslate(ScrnInfoPtr pScrn, DisplayModePtr mode) 1588{ 1589 VIAPtr pVia = VIAPTR(pScrn); 1590 int i; 1591 1592 if ((pVia->Chipset == VIA_CLE266) || (pVia->Chipset == VIA_KM400)) { 1593 CARD32 best1 = 0, best2; 1594 1595 for (i = 0; ViaDotClocks[i].DotClock; i++) 1596 if (ViaDotClocks[i].DotClock == mode->Clock) { 1597 best1 = ViaDotClocks[i].UniChrome; 1598 break; 1599 } 1600 1601 best2 = ViaComputeDotClock(mode->Clock); 1602 1603 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1604 "ViaComputeDotClock %d : %04x : %04x\n", 1605 mode->Clock, (unsigned int)best1, 1606 (unsigned int)best2)); 1607 1608 return best2; 1609 } else { 1610 for (i = 0; ViaDotClocks[i].DotClock; i++) 1611 if (ViaDotClocks[i].DotClock == mode->Clock) 1612 return ViaDotClocks[i].UniChromePro.packed; 1613 return ViaComputeProDotClock(mode->Clock); 1614 } 1615 1616 return 0; 1617} 1618 1619void 1620viaTMDSPower(ScrnInfoPtr pScrn, Bool On) 1621{ 1622 1623 vgaHWPtr hwp = VGAHWPTR(pScrn); 1624 1625 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1626 "Entered viaTMDSPower.\n")); 1627 1628 if (On) { 1629 /* Power on TMDS */ 1630 ViaCrtcMask(hwp, 0xD2, 0x00, 0x08); 1631 } else { 1632 /* Power off TMDS */ 1633 ViaCrtcMask(hwp, 0xD2, 0x08, 0x08); 1634 } 1635 1636 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1637 "Integrated TMDS (DVI) Power: %s\n", 1638 On ? "On" : "Off"); 1639 1640 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1641 "Exiting viaTMDSPower.\n")); 1642} 1643