1/* 2 * Copyright 2016 Kevin Brace 3 * Copyright 2005-2016 The OpenChrome Project 4 * [https://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 49/* 50 * Sets IGA1 or IGA2 as the display output source for DIP0 51 * (Digital Interface Port 0) interface for CLE266 only. 52 */ 53void 54viaDIP0SetDisplaySource(ScrnInfoPtr pScrn, CARD8 displaySource) 55{ 56 vgaHWPtr hwp = VGAHWPTR(pScrn); 57 CARD8 temp = displaySource; 58 59 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 60 "Entered viaDIP0SetDisplaySource.\n")); 61 62 /* Set DIP0 display output source. */ 63 /* 3X5.6C[7] - DIP0 (Digital Interface Port 0) Data Source Selection 64 * 0: Primary Display (IGA1) 65 * 1: Secondary Display (IGA2) */ 66 ViaCrtcMask(hwp, 0x6C, temp << 7, 0x80); 67 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 68 "DIP0 Display Output Source: IGA%d\n", 69 (temp & 0x01) + 1); 70 71 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 72 "Exiting viaDIP0SetDisplaySource.\n")); 73} 74 75/* 76 * Sets DIP0 (Digital Interface Port 0) I/O pad state. 77 * This function is for CLE266 chipset only. 78 */ 79void 80viaDIP0EnableIOPads(ScrnInfoPtr pScrn, CARD8 ioPadState) 81{ 82 vgaHWPtr hwp = VGAHWPTR(pScrn); 83 84 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 85 "Entered viaDIP0EnableIOPads.\n")); 86 87 /* Set DIP0 I/O pad state. */ 88 /* 3C5.1E[7:6] - DIP0 Power Control 89 * 0x: Pad always off 90 * 10: Depend on the other control signal 91 * 11: Pad on/off according to the 92 * Power Management Status (PMS) */ 93 ViaSeqMask(hwp, 0x1E, ioPadState << 6, 0xC0); 94 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 95 "DIP0 I/O Pad State: %s\n", 96 (ioPadState & 0x02) ? 97 (ioPadState & 0x01) ? "Automatic On / Off" : "Conditional" 98 : "Off"); 99 100 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 101 "Exiting viaDIP0EnableIOPads.\n")); 102} 103 104/* 105 * Sets DIP0 (Digital Interface Port 0) clock I/O pad drive strength 106 * for CLE266 chipset only. 107 */ 108void 109viaDIP0SetClockDriveStrength(ScrnInfoPtr pScrn, CARD8 clockDriveStrength) 110{ 111 vgaHWPtr hwp = VGAHWPTR(pScrn); 112 113 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 114 "Entered viaDIP0SetClockDriveStrength.\n")); 115 116 /* 3C5.1E[2] - DIP0 Clock Drive Strength Bit [0] */ 117 ViaSeqMask(hwp, 0x1E, clockDriveStrength << 2, 0x04); 118 119 /* 3C5.2A[4] - DIP0 Clock Drive Strength Bit [1] */ 120 ViaSeqMask(hwp, 0x2A, clockDriveStrength << 3, 0x10); 121 122 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 123 "DIP0 Clock I/O Pad Drive Strength: %u\n", 124 clockDriveStrength & 0x03); 125 126 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 127 "Exiting viaDIP0SetClockDriveStrength.\n")); 128} 129 130/* 131 * Sets DIP0 (Digital Interface Port 0) data I/O pads drive strength 132 * for CLE266 chipset only. 133 */ 134void 135viaDIP0SetDataDriveStrength(ScrnInfoPtr pScrn, CARD8 dataDriveStrength) 136{ 137 vgaHWPtr hwp = VGAHWPTR(pScrn); 138 139 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 140 "Entered viaDIP0SetDataDriveStrength.\n")); 141 142 /* 3C5.1B[1] - DIP0 Data Drive Strength Bit [0] */ 143 ViaSeqMask(hwp, 0x1B, dataDriveStrength << 1, 0x02); 144 145 /* 3C5.2A[5] - DIP0 Data Drive Strength Bit [1] */ 146 ViaSeqMask(hwp, 0x2A, dataDriveStrength << 4, 0x20); 147 148 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 149 "DIP0 Data I/O Pads Drive Strength: %u\n", 150 dataDriveStrength); 151 152 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 153 "Exiting viaDIP0SetDataDriveStrength.\n")); 154} 155 156/* 157 * Sets IGA1 or IGA2 as the display output source for DVP0 158 * (Digital Video Port) interface. 159 */ 160void 161viaDVP0SetDisplaySource(ScrnInfoPtr pScrn, CARD8 displaySource) 162{ 163 vgaHWPtr hwp = VGAHWPTR(pScrn); 164 CARD8 temp = displaySource; 165 166 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 167 "Entered viaDVP0SetDisplaySource.\n")); 168 169 /* Set DVP0 display output source. */ 170 /* 3X5.96[4] - DVP0 Data Source Selection 171 * 0: Primary Display 172 * 1: Secondary Display */ 173 ViaCrtcMask(hwp, 0x96, temp << 4, 0x10); 174 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 175 "DVP0 Display Output Source: IGA%d\n", 176 (temp & 0x01) + 1); 177 178 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 179 "Exiting viaDVP0SetDisplaySource.\n")); 180} 181 182/* 183 * Sets DVP0 (Digital Video Port 0) I/O pad state. 184 */ 185void 186viaDVP0EnableIOPads(ScrnInfoPtr pScrn, CARD8 ioPadState) 187{ 188 vgaHWPtr hwp = VGAHWPTR(pScrn); 189 190 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 191 "Entered viaDVP0EnableIOPads.\n")); 192 193 /* Set DVP0 I/O pad state. */ 194 /* 3C5.1E[7:6] - DVP0 Power Control 195 * 0x: Pad always off 196 * 10: Depend on the other control signal 197 * 11: Pad on/off according to the 198 * Power Management Status (PMS) */ 199 ViaSeqMask(hwp, 0x1E, ioPadState << 6, 0xC0); 200 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 201 "DVP0 I/O Pad State: %s\n", 202 (ioPadState & 0x02) ? 203 (ioPadState & 0x01) ? "Automatic On / Off" : "Conditional" 204 : "Off"); 205 206 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 207 "Exiting viaDVP0EnableIOPads.\n")); 208} 209 210/* 211 * Sets DVP0 (Digital Video Port 0) clock I/O pad drive strength. 212 */ 213void 214viaDVP0SetClockDriveStrength(ScrnInfoPtr pScrn, CARD8 clockDriveStrength) 215{ 216 vgaHWPtr hwp = VGAHWPTR(pScrn); 217 218 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 219 "Entered viaDVP0SetClockDriveStrength.\n")); 220 221 /* 3C5.1E[2] - DVP0 Clock Drive Strength Bit [0] */ 222 ViaSeqMask(hwp, 0x1E, clockDriveStrength << 2, 0x04); 223 224 /* 3C5.2A[4] - DVP0 Clock Drive Strength Bit [1] */ 225 ViaSeqMask(hwp, 0x2A, clockDriveStrength << 3, 0x10); 226 227 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 228 "DVP0 Clock I/O Pad Drive Strength: %u\n", 229 clockDriveStrength & 0x03); 230 231 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 232 "Exiting viaDVP0SetClockDriveStrength.\n")); 233} 234 235/* 236 * Sets DVP0 (Digital Video Port 0) data I/O pads drive strength. 237 */ 238void 239viaDVP0SetDataDriveStrength(ScrnInfoPtr pScrn, CARD8 dataDriveStrength) 240{ 241 vgaHWPtr hwp = VGAHWPTR(pScrn); 242 243 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 244 "Entered viaDVP0SetDataDriveStrength.\n")); 245 246 /* 3C5.1B[1] - DVP0 Data Drive Strength Bit [0] */ 247 ViaSeqMask(hwp, 0x1B, dataDriveStrength << 1, 0x02); 248 249 /* 3C5.2A[5] - DVP0 Data Drive Strength Bit [1] */ 250 ViaSeqMask(hwp, 0x2A, dataDriveStrength << 4, 0x20); 251 252 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 253 "DVP0 Data I/O Pads Drive Strength: %u\n", 254 dataDriveStrength); 255 256 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 257 "Exiting viaDVP0SetDataDriveStrength.\n")); 258} 259 260/* 261 * Sets IGA1 or IGA2 as the display output source for DVP1 262 * (Digital Video Port) interface. 263 */ 264void 265viaDVP1SetDisplaySource(ScrnInfoPtr pScrn, CARD8 displaySource) 266{ 267 vgaHWPtr hwp = VGAHWPTR(pScrn); 268 CARD8 temp = displaySource; 269 270 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 271 "Entered viaDVP1SetDisplaySource.\n")); 272 273 /* Set DVP1 display output source. */ 274 /* 3X5.9B[4] - DVP1 Data Source Selection 275 * 0: Primary Display 276 * 1: Secondary Display */ 277 ViaCrtcMask(hwp, 0x9B, temp << 4, 0x10); 278 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 279 "DVP1 Display Output Source: IGA%d\n", 280 (temp & 0x01) + 1); 281 282 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 283 "Exiting viaDVP1SetDisplaySource.\n")); 284} 285 286/* 287 * Sets DVP1 (Digital Video Port 1) I/O pad state. 288 */ 289void 290viaDVP1EnableIOPads(ScrnInfoPtr pScrn, CARD8 ioPadState) 291{ 292 vgaHWPtr hwp = VGAHWPTR(pScrn); 293 294 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 295 "Entered viaDVP1EnableIOPads.\n")); 296 297 /* Set DVP1 I/O pad state. */ 298 /* 3C5.1E[5:4] - DVP1 Power Control 299 * 0x: Pad always off 300 * 10: Depend on the other control signal 301 * 11: Pad on/off according to the 302 * Power Management Status (PMS) */ 303 ViaSeqMask(hwp, 0x1E, ioPadState << 4, 0x30); 304 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 305 "DVP1 I/O Pad State: %s\n", 306 (ioPadState & 0x02) ? 307 (ioPadState & 0x01) ? "Automatic On / Off": "Conditional" 308 : "Off"); 309 310 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 311 "Exiting viaDVP1EnableIOPads.\n")); 312} 313 314/* 315 * Sets DVP1 (Digital Video Port 1) clock I/O pad drive strength. 316 */ 317void 318viaDVP1SetClockDriveStrength(ScrnInfoPtr pScrn, CARD8 clockDriveStrength) 319{ 320 vgaHWPtr hwp = VGAHWPTR(pScrn); 321 322 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 323 "Entered viaDVP1SetClockDriveStrength.\n")); 324 325 /* 3C5.65[3:2] - DVP1 Clock Pads Driving Select 326 * 00: lowest 327 * 01: low 328 * 10: high 329 * 11: highest */ 330 ViaSeqMask(hwp, 0x65, clockDriveStrength << 2, 0x0C); 331 332 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 333 "DVP1 Clock I/O Pad Drive Strength: %u\n", 334 clockDriveStrength & 0x03); 335 336 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 337 "Exiting viaDVP1SetClockDriveStrength.\n")); 338} 339 340/* 341 * Sets DVP1 (Digital Video Port 1) data I/O pads drive strength. 342 */ 343void 344viaDVP1SetDataDriveStrength(ScrnInfoPtr pScrn, CARD8 dataDriveStrength) 345{ 346 vgaHWPtr hwp = VGAHWPTR(pScrn); 347 348 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 349 "Entered viaDVP1SetDataDriveStrength.\n")); 350 351 /* 3C5.65[1:0] - DVP1 Data Pads Driving Select 352 * 00: lowest 353 * 01: low 354 * 10: high 355 * 11: highest */ 356 ViaSeqMask(hwp, 0x65, dataDriveStrength, 0x03); 357 358 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 359 "DVP1 Data I/O Pads Drive Strength: %u\n", 360 dataDriveStrength & 0x03); 361 362 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 363 "Exiting viaDVP1SetDataDriveStrength.\n")); 364} 365 366/* 367 * Sets IGA1 or IGA2 as the display output source for VIA Technologies 368 * Chrome IGP DFP (Digital Flat Panel) Low interface. 369 */ 370void 371viaDFPLowSetDisplaySource(ScrnInfoPtr pScrn, CARD8 displaySource) 372{ 373 vgaHWPtr hwp = VGAHWPTR(pScrn); 374 CARD8 temp = displaySource; 375 376 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 377 "Entered viaDFPLowSetDisplaySource.\n")); 378 379 /* Set DFP Low display output source. */ 380 /* 3X5.99[4] - DFP Low Data Source Selection 381 * 0: Primary Display 382 * 1: Secondary Display */ 383 ViaCrtcMask(hwp, 0x99, temp << 4, 0x10); 384 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 385 "DFP Low Display Output Source: IGA%d\n", 386 (temp & 0x01) + 1); 387 388 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 389 "Exiting viaDFPLowSetDisplaySource.\n")); 390} 391 392/* 393 * Sets DFP (Digital Flat Panel) Low I/O pad state. 394 */ 395void 396viaDFPLowEnableIOPads(ScrnInfoPtr pScrn, CARD8 ioPadState) 397{ 398 vgaHWPtr hwp = VGAHWPTR(pScrn); 399 400 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 401 "Entered viaDFPLowEnableIOPads.\n")); 402 403 /* Set DFP Low I/O pad state. */ 404 /* 3C5.2A[1:0] - DFP Low Power Control 405 * 0x: Pad always off 406 * 10: Depend on the other control signal 407 * 11: Pad on/off according to the 408 * Power Management Status (PMS) */ 409 ViaSeqMask(hwp, 0x2A, ioPadState, 0x03); 410 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 411 "DFP Low I/O Pad State: %s\n", 412 (ioPadState & 0x02) ? 413 (ioPadState & 0x01) ? "Automatic On / Off": "Conditional" 414 : "Off"); 415 416 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 417 "Exiting viaDFPLowEnableIOPads.\n")); 418} 419 420/* 421 * Reads off the VIA Technologies IGP pin strapping for 422 * display detection purposes. 423 */ 424void 425viaProbePinStrapping(ScrnInfoPtr pScrn) 426{ 427 vgaHWPtr hwp = VGAHWPTR(pScrn); 428 VIAPtr pVia = VIAPTR(pScrn); 429 CARD8 sr12, sr13, sr5a; 430 431 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 432 "Entered viaProbePinStrapping.\n")); 433 434 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 435 "Probing VIA Technologies IGP pin strapping . . .\n"); 436 437 if ((pVia->Chipset == VIA_CX700) 438 || (pVia->Chipset == VIA_VX800) 439 || (pVia->Chipset == VIA_VX855) 440 || (pVia->Chipset == VIA_VX900)) { 441 442 sr5a = hwp->readSeq(hwp, 0x5A); 443 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 444 "SR5A: 0x%02X\n", sr5a)); 445 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 446 "Setting 3C5.5A[0] to 0.\n"); 447 ViaSeqMask(hwp, 0x5A, sr5a & 0xFE, 0x01); 448 } 449 450 sr12 = hwp->readSeq(hwp, 0x12); 451 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 452 "SR12: 0x%02X\n", sr12)); 453 sr13 = hwp->readSeq(hwp, 0x13); 454 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 455 "SR13: 0x%02X\n", sr13)); 456 457 switch (pVia->Chipset) { 458 case VIA_CLE266: 459 460 /* 3C5.12[4] - FPD17 pin strapping 461 * 0: TMDS transmitter (DVI) / capture device 462 * 1: Flat panel */ 463 if (sr12 & 0x10) { 464 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 465 "A flat panel is connected to " 466 "flat panel interface.\n"); 467 468 /* 3C5.12[3:0] - FPD16-13 pin strapping 469 * 0 ~ 15: Flat panel code defined 470 * by VIA Technologies */ 471 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 472 "Detected Flat Panel Type from " 473 "Strapping Pins: %d\n", sr12 & 0x0F); 474 } else { 475 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 476 "A TMDS transmitter (DVI) / capture device is " 477 "connected to DIP0.\n"); 478 } 479 480 /* 3C5.12[5] - FPD18 pin strapping 481 * 0: TMDS transmitter (DVI) 482 * 1: TV encoder */ 483 if (sr12 & 0x20) { 484 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 485 "A TV encoder is connected to " 486 "DIP0.\n"); 487 488 /* 3C5.13[4:3] - FPD21-20 pin strapping 489 * 00: PAL 490 * 01: NTSC 491 * 10: PAL-N 492 * 11: PAL-NC */ 493 if ((!(sr13 & 0x08)) && (sr13 & 0x04)) { 494 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 495 "NTSC for the TV encoder.\n"); 496 } else { 497 if (!(sr13 & 0x08)) { 498 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 499 "PAL for the TV encoder.\n"); 500 } else { 501 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 502 "PAL%s for the TV encoder.\n", 503 (sr13 & 0x04) ? "-NC" : "-N"); 504 } 505 } 506 507 /* 3C5.12[6] - FPD19 pin strapping 508 * 0: 525 lines (NTSC) 509 * 1: 625 lines (PAL) */ 510 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 511 "%s lines for the TV encoder.\n", 512 (sr12 & 0x40) ? "625" : "525"); 513 } else { 514 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 515 "A TMDS transmitter (DVI) is connected to " 516 "DIP0.\n"); 517 } 518 519 break; 520 521 case VIA_KM400: 522 case VIA_K8M800: 523 case VIA_PM800: 524 case VIA_P4M800PRO: 525 526 /* 3C5.12[6] - DVP0D6 pin strapping 527 * 0: Disable DVP0 (Digital Video Port 0) for 528 * DVI or TV out use 529 * 1: Enable DVP0 (Digital Video Port 0) for 530 * DVI or TV out use */ 531 if (sr12 & 0x40) { 532 533 /* 3C5.12[5] - DVP0D5 pin strapping 534 * 0: TMDS transmitter (DVI) 535 * 1: TV encoder */ 536 if (sr12 & 0x20) { 537 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 538 "A TV encoder is detected on " 539 "DVP0 (Digital Video Port 0).\n"); 540 } else { 541 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 542 "A TMDS transmitter (DVI) is detected on " 543 "DVP0 (Digital Video Port 0).\n"); 544 } 545 } 546 547 548 /* 3C5.13[3] - DVP0D8 pin strapping 549 * 0: AGP pins are used for AGP 550 * 1: AGP pins are used by FPDP 551 * (Flat Panel Display Port) */ 552 if (sr13 & 0x08) { 553 554 /* 3C5.12[4] - DVP0D4 pin strapping 555 * 0: Dual 12-bit FPDP (Flat Panel Display Port) 556 * 1: 24-bit FPDP (Flat Panel Display Port) */ 557 if (sr12 & 0x10) { 558 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 559 "24-bit FPDP (Flat Panel Display Port) " 560 "detected.\n"); 561 562 /* 3C5.12[3:0] - DVP0D3-0 pin strapping 563 * 0 ~ 15: Flat panel code defined 564 * by VIA Technologies */ 565 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 566 "Detected Flat Panel Type from " 567 "Strapping Pins: %d\n", sr12 & 0x0F); 568 } else { 569 570 /* 3C5.12[6] - DVP0D6 pin strapping 571 * 0: Disable DVP0 (Digital Video Port 0) for 572 * DVI or TV out use 573 * 1: Enable DVP0 (Digital Video Port 0) for 574 * DVI or TV out use 575 * 3C5.12[5] - DVP0D5 pin strapping 576 * 0: TMDS transmitter (DVI) 577 * 1: TV encoder */ 578 if ((!(sr12 & 0x40)) && (!(sr12 & 0x20))) { 579 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 580 "A TV encoder is connected to " 581 "FPDP (Flat Panel Display Port).\n"); 582 } else { 583 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 584 "Dual 12-bit FPDP (Flat Panel Display Port) " 585 "detected.\n"); 586 587 /* 3C5.12[3:0] - DVP0D3-0 pin strapping 588 * 0 ~ 15: Flat panel code defined 589 * by VIA Technologies */ 590 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 591 "Detected Flat Panel Type from " 592 "Strapping Pins: %d\n", sr12 & 0x0F); 593 } 594 } 595 } 596 597 break; 598 599 default: 600 break; 601 } 602 603 if ((pVia->Chipset == VIA_CX700) 604 || (pVia->Chipset == VIA_VX800) 605 || (pVia->Chipset == VIA_VX855) 606 || (pVia->Chipset == VIA_VX900)) { 607 608 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 609 "Setting 3C5.5A[0] to 1.\n"); 610 ViaSeqMask(hwp, 0x5A, sr5a | 0x01, 0x01); 611 612 sr12 = hwp->readSeq(hwp, 0x12); 613 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 614 "SR12: 0x%02X\n", sr12)); 615 sr13 = hwp->readSeq(hwp, 0x13); 616 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 617 "SR13: 0x%02X\n", sr13)); 618 619 /* 3C5.13[7:6] - Integrated LVDS / DVI Mode Select 620 * (DVP1D15-14 pin strapping) 621 * 00: LVDS1 + LVDS2 622 * 01: DVI + LVDS2 623 * 10: Dual LVDS Channel (High Resolution Panel) 624 * 11: One DVI only (decrease the clock jitter) */ 625 switch (sr13 & 0xC0) { 626 case 0x00: 627 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 628 "LVDS1 + LVDS2 detected.\n"); 629 break; 630 case 0x40: 631 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 632 "Single Link DVI + LVDS2 detected.\n"); 633 break; 634 case 0x80: 635 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 636 "Dual Channel LVDS detected.\n"); 637 break; 638 case 0xC0: 639 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 640 "Single Link DVI detected.\n"); 641 break; 642 default: 643 break; 644 } 645 646 hwp->writeSeq(hwp, 0x5A, sr5a); 647 648 } 649 650 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 651 "Exiting viaProbePinStrapping.\n")); 652} 653 654void 655viaOutputDetect(ScrnInfoPtr pScrn) 656{ 657 VIAPtr pVia = VIAPTR(pScrn); 658 VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; 659 660 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 661 "Entered viaOutputDetect.\n")); 662 663 pBIOSInfo->analog = NULL; 664 665 /* Initialize the number of VGA connectors. */ 666 pVia->numberVGA = 0; 667 668 /* Initialize the number of DVI connectors. */ 669 pVia->numberDVI = 0; 670 671 /* Initialize the number of FP connectors. */ 672 pVia->numberFP = 0; 673 674 /* Read off the VIA Technologies IGP pin strapping for 675 display detection purposes. */ 676 viaProbePinStrapping(pScrn); 677 678 /* VGA */ 679 via_analog_init(pScrn); 680 681 /* TV */ 682 via_tv_init(pScrn); 683 684 /* DVI */ 685 via_dvi_init(pScrn); 686 687 /* LVDS */ 688 via_lvds_init(pScrn); 689 690 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 691 "Exiting viaOutputDetect.\n")); 692} 693 694#ifdef HAVE_DEBUG 695/* 696 * Returns: 697 * Bit[7] 2nd Path 698 * Bit[6] 1/0 MHS Enable/Disable 699 * Bit[5] 0 = Bypass Callback, 1 = Enable Callback 700 * Bit[4] 0 = Hot-Key Sequence Control (OEM Specific) 701 * Bit[3] LCD 702 * Bit[2] TV 703 * Bit[1] CRT 704 * Bit[0] DVI 705 */ 706static CARD8 707VIAGetActiveDisplay(ScrnInfoPtr pScrn) 708{ 709 vgaHWPtr hwp = VGAHWPTR(pScrn); 710 CARD8 tmp; 711 712 tmp = (hwp->readCrtc(hwp, 0x3E) >> 4); 713 tmp |= ((hwp->readCrtc(hwp, 0x3B) & 0x18) << 3); 714 715 return tmp; 716} 717#endif /* HAVE_DEBUG */ 718 719/* 720 * 721 */ 722CARD32 723ViaGetMemoryBandwidth(ScrnInfoPtr pScrn) 724{ 725 VIAPtr pVia = VIAPTR(pScrn); 726 727 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 728 "ViaGetMemoryBandwidth. Memory type: %d\n", 729 pVia->MemClk)); 730 731 switch (pVia->MemClk) { 732 case VIA_MEM_SDR66: 733 case VIA_MEM_SDR100: 734 case VIA_MEM_SDR133: 735 return VIA_BW_MIN; 736 case VIA_MEM_DDR200: 737 return VIA_BW_DDR200; 738 case VIA_MEM_DDR266: 739 case VIA_MEM_DDR333: 740 case VIA_MEM_DDR400: 741 return VIA_BW_DDR400; 742 case VIA_MEM_DDR533: 743 case VIA_MEM_DDR667: 744 return VIA_BW_DDR667; 745 case VIA_MEM_DDR800: 746 case VIA_MEM_DDR1066: 747 return VIA_BW_DDR1066; 748 default: 749 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 750 "ViaBandwidthAllowed: Unknown memory type: %d\n", 751 pVia->MemClk); 752 return VIA_BW_MIN; 753 } 754} 755 756/* 757 * 758 * Some very common abstractions. 759 * 760 */ 761 762/* 763 * Standard vga call really. 764 * Needs to be called to reset the dotclock (after SR40:2/1 reset) 765 */ 766void 767ViaSetUseExternalClock(vgaHWPtr hwp) 768{ 769 CARD8 data; 770 771 DEBUG(xf86DrvMsg(hwp->pScrn->scrnIndex, X_INFO, 772 "ViaSetUseExternalClock\n")); 773 774 data = hwp->readMiscOut(hwp); 775 hwp->writeMiscOut(hwp, data | 0x0C); 776} 777 778/* 779 * 780 */ 781static void 782ViaSetDotclock(ScrnInfoPtr pScrn, CARD32 clock, int base, int probase) 783{ 784 vgaHWPtr hwp = VGAHWPTR(pScrn); 785 VIAPtr pVia = VIAPTR(pScrn); 786 787 DEBUG(xf86DrvMsg(hwp->pScrn->scrnIndex, X_INFO, 788 "ViaSetDotclock to 0x%06x\n", (unsigned)clock)); 789 790 if ((pVia->Chipset == VIA_CLE266) || (pVia->Chipset == VIA_KM400)) { 791 hwp->writeSeq(hwp, base, clock >> 8); 792 hwp->writeSeq(hwp, base+1, clock & 0xFF); 793 } else { /* unichrome pro */ 794 union pllparams pll; 795 int dtz, dr, dn, dm; 796 pll.packed = clock; 797 dtz = pll.params.dtz; 798 dr = pll.params.dr; 799 dn = pll.params.dn; 800 dm = pll.params.dm; 801 802 /* The VX855 and VX900 do not modify dm/dn, but earlier chipsets do. */ 803 if ((pVia->Chipset != VIA_VX855) && (pVia->Chipset != VIA_VX900)) { 804 dm -= 2; 805 dn -= 2; 806 } 807 808 hwp->writeSeq(hwp, probase, dm & 0xff); 809 hwp->writeSeq(hwp, probase+1, 810 ((dm >> 8) & 0x03) | (dr << 2) | ((dtz & 1) << 7)); 811 hwp->writeSeq(hwp, probase+2, (dn & 0x7f) | ((dtz & 2) << 6)); 812 } 813} 814 815/* 816 * 817 */ 818void 819ViaSetPrimaryDotclock(ScrnInfoPtr pScrn, CARD32 clock) 820{ 821 vgaHWPtr hwp = VGAHWPTR(pScrn); 822 823 ViaSetDotclock(pScrn, clock, 0x46, 0x44); 824 825 ViaSeqMask(hwp, 0x40, 0x02, 0x02); 826 ViaSeqMask(hwp, 0x40, 0x00, 0x02); 827} 828 829/* 830 * 831 */ 832void 833ViaSetSecondaryDotclock(ScrnInfoPtr pScrn, CARD32 clock) 834{ 835 vgaHWPtr hwp = VGAHWPTR(pScrn); 836 837 ViaSetDotclock(pScrn, clock, 0x44, 0x4A); 838 839 ViaSeqMask(hwp, 0x40, 0x04, 0x04); 840 ViaSeqMask(hwp, 0x40, 0x00, 0x04); 841} 842 843/* 844 * 845 */ 846static void 847ViaSetECKDotclock(ScrnInfoPtr pScrn, CARD32 clock) 848{ 849 /* Does the non-pro chip have an ECK clock ? */ 850 ViaSetDotclock(pScrn, clock, 0, 0x47); 851} 852 853static CARD32 854ViaComputeDotClock(unsigned clock) 855{ 856 double fout, fref, err, minErr; 857 CARD32 dr, dn, dm, maxdm, maxdn; 858 CARD32 factual, best; 859 860 fref = 14.31818e6; 861 fout = (double)clock * 1.e3; 862 863 factual = ~0; 864 maxdm = 127; 865 maxdn = 7; 866 minErr = 1e10; 867 best = 0; 868 869 for (dr = 0; dr < 4; ++dr) { 870 for (dn = (dr == 0) ? 2 : 1; dn <= maxdn; ++dn) { 871 for (dm = 1; dm <= maxdm; ++dm) { 872 factual = fref * dm; 873 factual /= (dn << dr); 874 err = fabs((double)factual / fout - 1.); 875 if (err < minErr) { 876 minErr = err; 877 best = (dm & 127) | ((dn & 31) << 8) | (dr << 14); 878 } 879 } 880 } 881 } 882 return best; 883} 884 885static CARD32 886ViaComputeProDotClock(unsigned clock) 887{ 888 double fvco, fout, err, minErr; 889 CARD32 dr = 0, dn, dm, maxdm, maxdn; 890 CARD32 factual; 891 union pllparams bestClock; 892 893 fout = (double)clock * 1.e3; 894 895 factual = ~0; 896 maxdm = factual / 14318000U; 897 minErr = 1.e10; 898 bestClock.packed = 0U; 899 900 do { 901 fvco = fout * (1 << dr); 902 } while (fvco < 300.e6 && dr++ < 8); 903 904 if (dr == 8) { 905 return 0; 906 } 907 908 if (clock < 30000) 909 maxdn = 8; 910 else if (clock < 45000) 911 maxdn = 7; 912 else if (clock < 170000) 913 maxdn = 6; 914 else 915 maxdn = 5; 916 917 for (dn = 2; dn < maxdn; ++dn) { 918 for (dm = 2; dm < maxdm; ++dm) { 919 factual = 14318000U * dm; 920 factual /= dn << dr; 921 if ((err = fabs((double)factual / fout - 1.)) < 0.005) { 922 if (err < minErr) { 923 minErr = err; 924 bestClock.params.dtz = 1; 925 bestClock.params.dr = dr; 926 bestClock.params.dn = dn; 927 bestClock.params.dm = dm; 928 } 929 } 930 } 931 } 932 933 return bestClock.packed; 934} 935 936/* 937 * 938 */ 939CARD32 940ViaModeDotClockTranslate(ScrnInfoPtr pScrn, DisplayModePtr mode) 941{ 942 VIAPtr pVia = VIAPTR(pScrn); 943 int i; 944 945 if ((pVia->Chipset == VIA_CLE266) || (pVia->Chipset == VIA_KM400)) { 946 CARD32 best1 = 0, best2; 947 948 for (i = 0; ViaDotClocks[i].DotClock; i++) 949 if (ViaDotClocks[i].DotClock == mode->Clock) { 950 best1 = ViaDotClocks[i].UniChrome; 951 break; 952 } 953 954 best2 = ViaComputeDotClock(mode->Clock); 955 956 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 957 "ViaComputeDotClock %d : %04x : %04x\n", 958 mode->Clock, (unsigned int)best1, 959 (unsigned int)best2)); 960 961 return best2; 962 } else { 963 for (i = 0; ViaDotClocks[i].DotClock; i++) 964 if (ViaDotClocks[i].DotClock == mode->Clock) 965 return ViaDotClocks[i].UniChromePro.packed; 966 return ViaComputeProDotClock(mode->Clock); 967 } 968 969 return 0; 970} 971