1/* Jong 03/12/2009; added for supporting Xorg 7.0 */ 2#ifdef HAVE_CONFIG_H 3#include "config.h" 4#endif 5 6#include <unistd.h> 7#include "osdef.h" 8#include "vgatypes.h" 9/* #include "vb_util.h" */ /* Jong@08032009 */ 10#include "vb_def.h" 11 12#ifdef WIN2000 13#include <dderror.h> 14#include <devioctl.h> 15#include <miniport.h> 16#include <ntddvdeo.h> 17#include <video.h> 18#include "xgiv.h" 19#include "dd_i2c.h" 20#include "tools.h" 21#endif /* WIN2000 */ 22 23#ifdef LINUX_XF86 24#include "xf86.h" 25#include "xf86PciInfo.h" 26#include "xgi.h" 27#include "xgi_regs.h" 28#include "vb_i2c.h" 29#endif 30 31#ifdef LINUX_KERNEL 32#include <linux/version.h> 33#include <asm/io.h> 34#include <linux/types.h> 35#include "vb_i2c.h" 36 37/* Jong@08052009 */ 38/* #include <linux/delay.h> */ /* udelay */ 39 40#include "XGIfb.h" 41 42#endif 43 44 45 46/*char I2CAccessBuffer(PXGI_HW_DEVICE_INFO pHWDE, PI2CControl I2CCntl, ULONG DevAddr, ULONG Offset, PUCHAR pBuffer, ULONG ulSize); */ 47char vGetEDIDExtensionBlocks(PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2C, PUCHAR pjBuffer, ULONG ulBufferSize); 48char vGetEnhancedEDIDBlock(PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2C, ULONG ulBlockID, ULONG ulBlockTag, PUCHAR pjBuffer, ULONG ulBufferSize); 49 50char I2COpen (PXGI_HW_DEVICE_INFO pHWDE,ULONG ulI2CEnable, ULONG ulChannelID, PI2CControl pI2CControl); 51char I2CAccess(PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2CControl); 52BOOLEAN I2CNull( PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2CControl); 53BOOLEAN I2CRead(PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2CControl); 54BOOLEAN I2CWrite(PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2CControl); 55BOOLEAN ResetI2C(PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2CControl); 56BOOLEAN I2CRead(PXGI_HW_DEVICE_INFO pHWDE,PI2CControl pI2CControl); 57BOOLEAN I2CWrite(PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2CControl); 58BOOLEAN ResetI2C(PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2CControl); 59BOOLEAN Ack (PXGI_HW_DEVICE_INFO pHWDE, bool fPut); 60BOOLEAN NoAck(PXGI_HW_DEVICE_INFO pHWDE); 61BOOLEAN Start( PXGI_HW_DEVICE_INFO pHWDE); 62BOOLEAN Stop(PXGI_HW_DEVICE_INFO pHWDE); 63BOOLEAN WriteUCHARI2C(PXGI_HW_DEVICE_INFO pHWDE, UCHAR cData); 64BOOLEAN ReadUCHARI2C(PXGI_HW_DEVICE_INFO pHWDE, PUCHAR pBuffer); 65UCHAR ReverseUCHAR(UCHAR data); 66 67VOID vWriteClockLineDVI(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data); 68VOID vWriteDataLineDVI(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data); 69BOOLEAN bReadClockLineDVI(PXGI_HW_DEVICE_INFO pHWDE); 70BOOLEAN bReadDataLineDVI(PXGI_HW_DEVICE_INFO pHWDE); 71 72BOOLEAN bEDIDCheckSum(PUCHAR pjEDIDBuf,ULONG ulBufSize); 73 74VOID vWriteClockLineCRT(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data); 75VOID vWriteDataLineCRT(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data); 76BOOLEAN bReadClockLineCRT(PXGI_HW_DEVICE_INFO pHWDE); 77BOOLEAN bReadDataLineCRT(PXGI_HW_DEVICE_INFO pHWDE); 78 79/* Jong@08102009 */ 80VOID vWriteClockLineFCNT(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data); 81VOID vWriteDataLineFCNT(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data); 82BOOLEAN bReadClockLineFCNT(PXGI_HW_DEVICE_INFO pHWDE); 83BOOLEAN bReadDataLineFCNT(PXGI_HW_DEVICE_INFO pHWDE); 84 85/* #define CRT_I2C */ 86VOID vWriteClockLine(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data); 87VOID vWriteDataLine(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data); 88BOOLEAN bReadClockLine(PXGI_HW_DEVICE_INFO pHWDE); 89BOOLEAN bReadDataLine(PXGI_HW_DEVICE_INFO pHWDE); 90 91/* Jong@08052009 */ 92extern UCHAR XGI_GetRegByte(XGIIOADDRESS port); 93 94/* Jong@08052009 */ 95void I2C_DelayUS(ULONG MicroSeconds) 96{ 97 ErrorF(""); 98 /* udelay(MicroSeconds); */ 99} 100 101 102typedef enum _I2C_ACCESS_CMD 103{ 104 I2C_WRITE = 0, 105 I2C_READ 106/* Jong 08/18/2008; for XFree86 */ 107 /* WRITE = 0, 108 READ */ 109} I2C_ACCESS_CMD; 110 111/* For XG21 */ 112 113#define ENABLE_GPIOA 0x01 114#define ENABLE_GPIOB 0x02 115#define ENABLE_GPIOC 0x04 116VOID 117EnableGPIOA( 118XGIIOADDRESS pjIOPort, I2C_ACCESS_CMD CmdType) 119{ 120 PDEBUGI2C(ErrorF("EnableGPIOA()-pjIOPort=0x%x...\n", pjIOPort)); 121 122 UCHAR ujCR4A = XGI_GetReg(pjIOPort, IND_CR4A_GPIO_REG_III); 123 124 if (CmdType == I2C_WRITE) 125 { 126 ujCR4A &= ~ENABLE_GPIOA; 127 } 128 else 129 { 130 ujCR4A |= ENABLE_GPIOA; 131 } 132 133 XGI_SetReg(pjIOPort, IND_CR4A_GPIO_REG_III, ujCR4A); 134} 135 136VOID 137EnableGPIOB( 138XGIIOADDRESS pjIOPort, I2C_ACCESS_CMD CmdType) 139{ 140 UCHAR ujCR4A = XGI_GetReg(pjIOPort, IND_CR4A_GPIO_REG_III); 141 142 if (CmdType == I2C_WRITE) 143 { 144 ujCR4A &= ~ENABLE_GPIOB; 145 } 146 else 147 { 148 ujCR4A |= ENABLE_GPIOB; 149 } 150 151 XGI_SetReg(pjIOPort, IND_CR4A_GPIO_REG_III, ujCR4A); 152} 153 154VOID 155EnableGPIOC( 156XGIIOADDRESS pjIOPort, I2C_ACCESS_CMD CmdType) 157{ 158 UCHAR ujCR4A = XGI_GetReg(pjIOPort, IND_CR4A_GPIO_REG_III); 159 160 if (CmdType == I2C_WRITE) 161 { 162 ujCR4A &= ~ENABLE_GPIOC; 163 } 164 else 165 { 166 ujCR4A |= ENABLE_GPIOC; 167 } 168 169 XGI_SetReg(pjIOPort, IND_CR4A_GPIO_REG_III, ujCR4A); 170} 171 172 173 174 175/** 176* Function: getGPIORWTranser() 177* 178* Description: This function is used based on Z9. Because of wrongly wired deployment by HW 179* the CR4A and CR48 for GPIO pins have reverse sequence. For example, 180* D[7:0] for read function is ordered as GPIOA to GPIOH, but D[7:0] for read 181* is as GPIOH~GPIOA 182*/ 183UCHAR 184getGPIORWTransfer( 185UCHAR ujDate) 186{ 187 UCHAR ujRet = 0; 188 UCHAR i = 0; 189 190 for (i=0; i<8; i++) 191 { 192 ujRet = ujRet << 1; 193 ujRet |= GETBITS(ujDate >> i, 0:0); 194 } 195 196 return ujRet; 197} 198 199 200 201char I2CAccessBuffer(PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2CControl, ULONG ulDevAddr, 202 ULONG ulOffset, PUCHAR pBuffer,ULONG ulSize) 203{ 204 205 I2CControl I2C; 206 ULONG i; 207 208 if ((ulSize == 0) || (pBuffer == NULL)) { 209 return -1; 210 } 211 if (ulDevAddr & 1) { 212 return -1; 213 } 214 if ((ulDevAddr > 0xFF) || (ulOffset > 0xFF)) { 215 return -1; 216 } 217 218 I2C.Command = pI2CControl->Command; 219 I2C.dwCookie = pI2CControl->dwCookie; 220 I2C.Data = pI2CControl->Data; 221 I2C. Flags = pI2CControl->Flags; 222 I2C.Status = pI2CControl->Status; 223 I2C.ClockRate = pI2CControl->ClockRate; 224 switch (pI2CControl->Command) { 225 case I2C_COMMAND_READ: 226 /* Reset I2C Bus */ 227 I2C.Command = I2C_COMMAND_RESET; 228 I2CAccess(pHWDE, &I2C); 229 if (I2C.Status != I2C_STATUS_NOERROR) { 230 pI2CControl->Status = I2C.Status; 231 break; 232 } 233 234 /* Write Device Address */ 235 I2C.Command = I2C_COMMAND_WRITE; 236 I2C.Flags = I2C_FLAGS_START | I2C_FLAGS_ACK; 237 I2C.Data = (UCHAR)ulDevAddr; 238 I2CAccess(pHWDE, &I2C); 239 if (I2C.Status != I2C_STATUS_NOERROR) { 240 pI2CControl->Status = I2C.Status; 241 break; 242 } 243 244 /* Write Register Offset */ 245 I2C.Command = I2C_COMMAND_WRITE; 246 I2C.Flags = I2C_FLAGS_ACK | I2C_FLAGS_STOP; 247 I2C.Data = (UCHAR)ulOffset; 248 I2CAccess(pHWDE, &I2C); 249 if (I2C.Status != I2C_STATUS_NOERROR) { 250 pI2CControl->Status = I2C.Status; 251 break; 252 } 253 254 /* Write Device Read Address */ 255 I2C.Command = I2C_COMMAND_WRITE; 256 I2C.Flags = I2C_FLAGS_START | I2C_FLAGS_ACK; 257 I2C.Data = (UCHAR)ulDevAddr + 1; 258 I2CAccess(pHWDE, &I2C); 259 if (I2C.Status != I2C_STATUS_NOERROR) { 260 pI2CControl->Status = I2C.Status; 261 break; 262 } 263 264 /* Read Data */ 265 for (i=0; i< ulSize; i++) { 266 I2C.Command = I2C_COMMAND_READ; 267 I2C.Flags = I2C_FLAGS_ACK; 268 if (i == ulSize - 1) { /* Read Last UCHAR */ 269 I2C.Flags |= I2C_FLAGS_STOP; 270 } 271 I2CAccess(pHWDE, &I2C); 272 if (I2C.Status != I2C_STATUS_NOERROR) { 273 pI2CControl->Status = I2C.Status; 274 break; 275 } 276 *pBuffer = I2C.Data; 277 pBuffer++; 278 } 279 pI2CControl->Status = I2C.Status; 280 break; 281 282 case I2C_COMMAND_WRITE: 283 /* Reset I2C Bus */ 284 I2C.Command = I2C_COMMAND_RESET; 285 I2CAccess(pHWDE, &I2C); 286 if (I2C.Status != I2C_STATUS_NOERROR) { 287 pI2CControl->Status = I2C.Status; 288 break; 289 } 290 291 /* Write Device Address */ 292 I2C.Command = I2C_COMMAND_WRITE; 293 I2C.Flags = I2C_FLAGS_START | I2C_FLAGS_ACK; 294 I2C.Data = (UCHAR)ulDevAddr; 295 I2CAccess(pHWDE, &I2C); 296 if (I2C.Status != I2C_STATUS_NOERROR) { 297 pI2CControl->Status = I2C.Status; 298 break; 299 } 300 301 /* Write Register Offset */ 302 I2C.Command = I2C_COMMAND_WRITE; 303 I2C.Flags = I2C_FLAGS_ACK; 304 I2C.Data = (UCHAR)ulOffset; 305 I2CAccess(pHWDE, &I2C); 306 if (I2C.Status != I2C_STATUS_NOERROR) { 307 pI2CControl->Status = I2C.Status; 308 break; 309 } 310 311 /* Write Data */ 312 for (i=0; i< ulSize; i++) { 313 I2C.Command = I2C_COMMAND_WRITE; 314 I2C.Flags = I2C_FLAGS_ACK; 315 if (i == ulSize - 1) { /* Read Last UCHAR */ 316 I2C.Flags |= I2C_FLAGS_STOP; 317 } 318 I2C.Data = *pBuffer; 319 I2CAccess(pHWDE, &I2C); 320 if (I2C.Status != I2C_STATUS_NOERROR) { 321 pI2CControl->Status = I2C.Status; 322 break; 323 } 324 pBuffer++; 325 } 326 pI2CControl->Status = I2C.Status; 327 break; 328 } 329 330 if (pI2CControl->Status == I2C_STATUS_NOERROR) 331 { 332 return 0; 333 } 334 else 335 { 336 return -1; 337 } 338} 339 340 341/************************************************************************* 342// char vGetEDIDExtensionBlocks 343// 344// Routine Description: 345// Reads the extension part behind a 128KB block of EDID which is in 1.3 346// format. The extension part can be distributed into 128KB-blocks. 347// 348// Arguments: 349// pHWDE - Hardware extension object pointer 350// pI2C - I2C pointer 351// pjBuffer - EDID Buffer 352// ulBufferSize - Buffer size 353// 354// 355// Return Value: 356// Status of returning EDID. 357// NO_ERROR - success 358// ERROR_INVALID_PARAMETER - failed 359// 360****************************************************************************/ 361char vGetEDIDExtensionBlocks( 362 PXGI_HW_DEVICE_INFO pHWDE, 363 PI2CControl pI2C, 364 PUCHAR pjBuffer, 365 ULONG ulBufferSize) 366{ 367 char status; 368 ULONG ulBlockTag; 369 ULONG i; 370 PUCHAR pBlockMap; 371 372 373 if ((ulBufferSize < 128) || (pjBuffer == NULL)) 374 { 375 return -1; 376 } 377 378 pI2C->Command = I2C_COMMAND_READ; 379 status = I2CAccessBuffer(pHWDE, pI2C, 0xA0, 128, pjBuffer, 128); 380 if ((status != 0) || (pI2C->Status != I2C_STATUS_NOERROR)) 381 { 382 return status; 383 } 384 385 if (bEDIDCheckSum(pjBuffer, 128) != 0) { 386 return -1; 387 } 388 389 if (*pjBuffer == 0xF0) 390 { /* A Block Map, we should read other extension blocks*/ 391 pBlockMap = pjBuffer; 392 for (i=1; i<=126; i++) 393 { 394 ulBlockTag = *(pBlockMap + i); 395 if (ulBlockTag) 396 { 397 pjBuffer += 128; 398 ulBufferSize -= 128; 399 status = vGetEnhancedEDIDBlock(pHWDE, pI2C, i+1, ulBlockTag, pjBuffer, ulBufferSize); 400 if ((status != 0) || (pI2C->Status != I2C_STATUS_NOERROR)) 401 { 402 return -1; 403 } 404 } 405 else 406 { 407 if (i > 1) 408 { 409 return 0; /* All Extension blocks must be sequential, no holes allowed. (VESA E-EDID)*/ 410 } 411 else 412 { 413 return -1; 414 } 415 } 416 } 417 /* We should read block # 128 */ 418 pjBuffer += 128; 419 ulBufferSize -= 128; 420 ulBlockTag = 0xF0; 421 status = vGetEnhancedEDIDBlock(pHWDE, pI2C, 128, ulBlockTag, pjBuffer, ulBufferSize); 422 if ((status != 0) || (pI2C->Status != I2C_STATUS_NOERROR)) 423 { 424 return 0; /* Monitor may has only 128 blocks (0~127) */ 425 } 426 427 pBlockMap = pjBuffer; 428 for (i=1; i<=126; i++) 429 { /* Read Block # 128 ~ 254 */ 430 ulBlockTag = *(pBlockMap + i); 431 if (ulBlockTag) 432 { 433 pjBuffer += 128; 434 ulBufferSize -= 128; 435 status = vGetEnhancedEDIDBlock(pHWDE, pI2C, i+128, ulBlockTag, pjBuffer, ulBufferSize); 436 if ((status != 0) || (pI2C->Status != I2C_STATUS_NOERROR)) 437 { 438 return -1; 439 } 440 } 441 else 442 { 443 if (i > 1) 444 { 445 return 0; /* All Extension blocks must be sequential, no holes allowed. (VESA E-EDID) */ 446 } 447 else 448 { 449 return -1; 450 } 451 } 452 } 453 } 454 455 return 0; 456} 457 458/************************************************************************* 459// char vGetEnhancedEDIDBlock 460// 461// Routine Description: 462// Get the EDID which is in Enhanced-EDID format via I2C. The parse-in block 463// tag(ulBlockTag) and the first UCHAR of the retrieved buffer should be identical. 464// Returns error when they are not, otherwise return NO_ERROR. 465// 466// Arguments: 467// pHWDE - Hardware extension object pointer 468// pI2C - I2C pointer 469// ulBlockID - Block ID 470// ulBlockTag - Block Tag 471// pjBuffer - EDID Buffer 472// ulBufferSize - Buffer size 473// 474// 475// Return Value: 476// Status of returning EDID. 477// NO_ERROR - success 478// ERROR_INVALID_PARAMETER - failed 479// 480****************************************************************************/ 481char vGetEnhancedEDIDBlock( 482 PXGI_HW_DEVICE_INFO pHWDE, 483 PI2CControl pI2C, 484 ULONG ulBlockID, 485 ULONG ulBlockTag, 486 PUCHAR pjBuffer, 487 ULONG ulBufferSize) 488{ 489 ULONG ulOffset, SegmentID; 490 char status; 491 492 if ((ulBufferSize < 128) || (pjBuffer == NULL)) 493 { 494 return -1; 495 } 496 497 SegmentID = ulBlockID / 2; 498 ulOffset = (ulBlockID % 2) * 128; 499 500 pI2C->Command = I2C_COMMAND_WRITE; 501 status = I2CAccessBuffer(pHWDE, pI2C, 0x60, 0, (PUCHAR)&SegmentID, 1); 502 if ((status == NO_ERROR) && (pI2C->Status == I2C_STATUS_NOERROR)) 503 { 504 pI2C->Command = I2C_COMMAND_READ; 505 status = I2CAccessBuffer(pHWDE, pI2C, 0xA0, ulOffset, pjBuffer, 128); 506 if ((status == 0) && (pI2C->Status == I2C_STATUS_NOERROR)) 507 { 508 if (*pjBuffer != (UCHAR)ulBlockTag) 509 { 510 return -1; 511 } 512 513 if (bEDIDCheckSum(pjBuffer, 128) != 0) 514 { 515 return -1; 516 } 517 } 518 else 519 { 520 return ERROR_INVALID_PARAMETER; 521 } 522 } 523 else 524 { 525 return ERROR_INVALID_PARAMETER; 526 } 527 528 529 return NO_ERROR; 530} 531char I2COpen (PXGI_HW_DEVICE_INFO pHWDE, ULONG ulI2CEnable, ULONG ulChannelID, PI2CControl pI2CControl) 532{ 533/* 534// printk("\nI2COpen(%d) : Channel ID = %d\n", ulI2CEnable, ulChannelID); 535 // we need to determine the Context area for each command we receive 536 // i.e. which hardware I2C bus is the command for. 537 // this is unimplemented here! 538*/ 539 if (ulChannelID >= MAX_I2C_CHANNEL) 540 { 541 return ERROR_INVALID_PARAMETER; 542 } 543 if (ulI2CEnable) /* Open I2C Port */ 544 { 545/* // verify clock rate. If you cannot implement the given rate, 546 // enable a lower clock rate closest to the request clock rate. 547 // 548 // put a better check here if your device can only do discrete 549 // clock rate values. 550*/ 551 if (pI2CControl->ClockRate > I2C_MAX_CLOCK_RATE) 552 { 553 pI2CControl->ClockRate = I2C_MAX_CLOCK_RATE; 554 } 555 pI2CControl->Status = I2C_STATUS_NOERROR; 556 } 557 else /* Close I2C Port*/ 558 { 559 /* Set Acquired state to FALSE */ 560 561 pI2CControl->dwCookie = 0; 562 /* Set status */ 563 pI2CControl->Status = I2C_STATUS_NOERROR; 564 } 565 566 567 568 return 0; 569} 570/* end of I2COpen */ 571char I2CAccess(PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2CControl) 572{ 573 ULONG ulChannel = pI2CControl->dwCookie % MAX_I2C_CHANNEL; 574 575 576 if (pI2CControl->ClockRate > I2C_MAX_CLOCK_RATE) 577 { 578 pI2CControl->ClockRate = I2C_MAX_CLOCK_RATE; 579 } 580 if (pI2CControl->ClockRate == 0) { 581 pI2CControl->ClockRate = 20000; 582 } 583 584 pHWDE->I2CDelay = (1000000 / pI2CControl->ClockRate) * 10 * 2; /* in 100ns */ 585 /* pHWDE->I2CDelay = (1000000 / pI2CControl->ClockRate) * 10; */ /* in 100ns */ 586 /* pHWDE->I2CDelay = 100; */ 587 /* PDEBUG(ErrorF("I2CAccess()-I2CDelay = %d...\n", pHWDE->I2CDelay)); */ 588 589 /* pHWDE->I2CDelay = 100; */ /* Jong@08032009 */ 590 591 switch (pI2CControl->Command) 592 { 593 /* Issue a STOP or START without a READ or WRITE Command */ 594 case I2C_COMMAND_NULL: 595 if (I2CNull(pHWDE, pI2CControl) == FALSE) break; 596/* if (pI2CControl->Flags & I2C_FLAGS_STOP) { 597 pI2CContext->dwI2CPortAcquired = FALSE; 598 } 599*/ break; 600 601 /* READ or WRITE Command */ 602 case I2C_COMMAND_READ: 603 if (I2CRead(pHWDE, pI2CControl) == FALSE) break; 604/* if (pI2CControl->Flags & I2C_FLAGS_STOP) { 605 pI2CContext->dwI2CPortAcquired = FALSE; 606 } 607*/ break; 608 609 case I2C_COMMAND_WRITE: 610 if (I2CWrite(pHWDE, pI2CControl) == FALSE) break; 611/* if (pI2CControl->Flags & I2C_FLAGS_STOP) { 612 pI2CContext->dwI2CPortAcquired = FALSE; 613 } 614*/ break; 615 616 case I2C_COMMAND_STATUS: 617 pI2CControl->Status = I2C_STATUS_NOERROR; 618 break; 619 620 case I2C_COMMAND_RESET: 621 /* Reset I2C bus */ 622 if (ResetI2C(pHWDE, pI2CControl) == FALSE) break; 623 break; 624 625 default: 626 /* Invalid Command */ 627 return ERROR_INVALID_PARAMETER; 628 } 629 630 631/* printk("\nI2CAccess(): I2C Cmd = 0x%X I2C Flags = 0x%X I2C Status = 0x%X I2C Data = 0x%X", pI2CControl->Command, pI2CControl->Flags, pI2CControl->Status, pI2CControl->Data); */ 632 633 return NO_ERROR; 634} 635 636 637/*^^* 638 * Function: I2CNull 639 * 640 * Purpose: To complete an I2C instruction. 641 * 642 * Inputs: lpI2C_ContextData : PI2C_CONTEXT, pointer to data struct associated 643 * with card being accessed 644 * I2CCntl : PI2CControl, pointer to I2C control structure 645 * 646 * Outputs: void. 647 *^^*/ 648BOOLEAN I2CNull( PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2CControl) 649{ 650 pI2CControl->Status = I2C_STATUS_ERROR; 651 652/*///// Issue STOP - START, if I2C_FLAGS_DATACHAINING ////////*/ 653 if (pI2CControl->Flags & I2C_FLAGS_DATACHAINING) 654 { 655 if (Stop(pHWDE) == FALSE) return FALSE; 656 if (Start(pHWDE) == FALSE) return FALSE; 657 } 658 659/*///// Issue START ////////*/ 660 if (pI2CControl->Flags & I2C_FLAGS_START) 661 { 662 if (Start(pHWDE) == FALSE) return FALSE; 663 } 664 665/*////// Issue STOP /////////*/ 666 if (pI2CControl->Flags & I2C_FLAGS_STOP) 667 { 668 if (Stop(pHWDE) == FALSE) return FALSE; 669 } 670 671 pI2CControl->Status = I2C_STATUS_NOERROR; 672 return TRUE; 673}/* end of I2CNull()*/ 674 675/*^^* 676 * Function: I2CRead 677 * 678 * Purpose: To complete an I2C instruction. 679 * 680 * Inputs: lpI2C_ContextData : PI2C_CONTEXT, pointer to data struct associated 681 * with card being accessed 682 * I2CCntl : PI2CControl, pointer to I2C control structure 683 * 684 * Outputs: void. 685 *^^*/ 686BOOLEAN I2CRead(PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2CControl) 687{ 688 pI2CControl->Status = I2C_STATUS_ERROR; 689 690/*///// Issue STOP - START, if I2C_FLAGS_DATACHAINING ////////*/ 691 if (pI2CControl->Flags & I2C_FLAGS_DATACHAINING) 692 { 693 if (Stop(pHWDE) == FALSE) return FALSE; 694 if (Start(pHWDE) == FALSE) return FALSE; 695 } 696 697/*///// Issue START ////////*/ 698 if (pI2CControl->Flags & I2C_FLAGS_START) 699 { 700 if (Start(pHWDE) == FALSE) return FALSE; 701 } 702 703/*///// Read Command ///////*/ 704 if (ReadUCHARI2C(pHWDE, &pI2CControl->Data) == FALSE) 705 return FALSE; 706 707 if (pI2CControl->Flags & I2C_FLAGS_STOP) { 708 if (NoAck(pHWDE) == FALSE) return FALSE; 709 } 710 else { /* Should we issue ACK*/ 711 if (pI2CControl->Flags & I2C_FLAGS_ACK) { 712 if (Ack(pHWDE, SEND_ACK) == FALSE) return FALSE; 713 } 714 } 715 716/*////// Issue STOP /////////*/ 717 if (pI2CControl->Flags & I2C_FLAGS_STOP) 718 { 719 if (Stop(pHWDE) == FALSE) return FALSE; 720 } 721 722 pI2CControl->Status = I2C_STATUS_NOERROR; 723 return TRUE; 724} /* end of I2CRead() */ 725 726/*^^* 727 * Function: I2CWrite 728 * 729 * Purpose: To complete an I2C instruction. 730 * 731 * Inputs: lpI2C_ContextData : PI2C_CONTEXT, pointer to data struct associated 732 * with card being accessed 733 * I2CCntl : PI2CControl, pointer to I2C control structure 734 * 735 * Outputs: void. 736 *^^*/ 737BOOLEAN I2CWrite(PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2CControl) 738{ 739 pI2CControl->Status = I2C_STATUS_ERROR; 740 741/*///// Issue STOP - START, if I2C_FLAGS_DATACHAINING ////////*/ 742 if (pI2CControl->Flags & I2C_FLAGS_DATACHAINING) 743 { 744 if (Stop(pHWDE) == FALSE) 745 { 746 747 return FALSE; 748 } 749 if (Start(pHWDE) == FALSE) 750 { 751 752 753 return FALSE; 754 } 755 } 756 757/*///// Issue START ////////*/ 758 if (pI2CControl->Flags & I2C_FLAGS_START) 759 { 760 if (Start(pHWDE) == FALSE) 761 { 762 return FALSE; 763 } 764 } 765 766/*///// Write Command ///////*/ 767 if (WriteUCHARI2C(pHWDE, pI2CControl->Data) == FALSE) 768 { 769 770 return FALSE; 771 } 772 773 if (pI2CControl->Flags & I2C_FLAGS_ACK) { 774 if (Ack(pHWDE, RECV_ACK) == FALSE) 775 { 776 return FALSE; 777 } 778 } 779 780/*////// Issue STOP /////////*/ 781 if (pI2CControl->Flags & I2C_FLAGS_STOP) 782 { 783 if (Stop(pHWDE) == FALSE) 784 { 785 return FALSE; 786 } 787 } 788 789 pI2CControl->Status = I2C_STATUS_NOERROR; 790 return TRUE; 791} /* end of I2CWrite() */ 792 793/*^^* 794 * Function: ResetI2C 795 * 796 * Purpose: To reset I2CBus 797 * 798 * Inputs: lpI2C_ContextData : PI2C_CONTEXT, pointer to data struct associated with 799 * lpI2C_ContextData being accessed 800 * 801 * Outputs: UCHAR, the data that was read. 802 *^^*/ 803BOOLEAN ResetI2C(PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2CControl) 804{ 805 806 if (Stop(pHWDE) == TRUE) { 807 pI2CControl->Status = I2C_STATUS_NOERROR; 808 return TRUE; 809 } 810 else { 811 pI2CControl->Status = I2C_STATUS_ERROR; 812 return FALSE; 813 } 814} /* ResetI2C() */ 815 816 817 818 819/*^^* 820 * Function: Ack 821 * 822 * Purpose: To ask the I2C bus for an acknowledge. 823 * 824 * Inputs: lpI2C_ContextData : PI2C_CONTEXT, pointer to data struct associated with 825 * lpI2C_ContextData being accessed 826 * 827 * Outputs: char, ack status. 828 *^^*/ 829BOOLEAN Ack (PXGI_HW_DEVICE_INFO pHWDE, bool fPut) 830{ 831 BOOLEAN status = FALSE; 832 ULONG i, delay, delay2; 833 ULONG ack; 834 835 delay = pHWDE->I2CDelay / 10 / 2; 836 if (fPut == SEND_ACK) /* Send Ack into I2C bus */ 837 { 838 vWriteDataLine(pHWDE, LODAT); 839 I2C_DelayUS(delay); 840 841 vWriteClockLine(pHWDE, HICLK); 842 I2C_DelayUS(delay); 843 if (bReadClockLine(pHWDE) != HICLK) { 844 i = 0; 845 delay2 = delay * 2; 846 I2C_DelayUS(delay2); /* Jong@08052008 */ 847 do { 848 vWriteClockLine(pHWDE, HICLK); 849 I2C_DelayUS(delay2); 850 if (bReadClockLine(pHWDE) == HICLK) break; 851 i++; 852 delay2 *= 2; 853 if (i >= I2C_RETRY_COUNT) return FALSE; 854 } while (1); 855 } 856 857 858 I2C_DelayUS(delay); /* Jong@08052008 */ 859 vWriteClockLine(pHWDE, LOCLK); 860 I2C_DelayUS(delay); 861 862 return TRUE; 863 } 864 else 865 { 866 /* Receive Ack from I2C bus */ 867 vWriteDataLine(pHWDE, HIDAT); 868 I2C_DelayUS(delay); 869 ack = bReadDataLine(pHWDE); 870 871 I2C_DelayUS(delay); /* Jong@08052008 */ 872 vWriteClockLine(pHWDE, HICLK); 873 I2C_DelayUS(delay); 874 if (bReadClockLine(pHWDE) != HICLK) { 875 i = 0; 876 delay2 = delay * 2; 877 do { 878 I2C_DelayUS(delay2); /* Jong@08052008 */ 879 vWriteClockLine(pHWDE, HICLK); 880 I2C_DelayUS(delay2); 881 if (bReadClockLine(pHWDE) == HICLK) break; 882 i++; 883 delay2 *= 2; 884 if (i >= I2C_RETRY_COUNT) return FALSE; 885 } while (1); 886 } 887 888 I2C_DelayUS(delay); /* Jong@08052008 */ 889 status = bReadDataLine(pHWDE); 890 891 I2C_DelayUS(delay); /* Jong@08052008 */ 892 vWriteClockLine(pHWDE, LOCLK); 893 I2C_DelayUS(delay); 894 895 if (status != LODAT) { 896 if (ack == LODAT) { 897 status = LODAT; 898 } 899 900 else { 901 902 } 903 904 } 905 return (BOOLEAN)(status == LODAT); 906 } 907}/* end of Ack() */ 908 909 910BOOLEAN NoAck(PXGI_HW_DEVICE_INFO pHWDE) 911{ 912 ULONG i, delay, delay2; 913 914 delay = pHWDE->I2CDelay / 10 / 2; 915 916 vWriteDataLine(pHWDE, HIDAT); 917 I2C_DelayUS(delay); 918 919 vWriteClockLine(pHWDE, HICLK); 920 I2C_DelayUS(delay); 921 if (bReadClockLine(pHWDE) != HICLK) { 922 delay2 = delay * 2; 923 i = 0; 924 do { 925 I2C_DelayUS(delay2); /* Jong@08052008 */ 926 vWriteClockLine(pHWDE, HICLK); 927 I2C_DelayUS(delay2); 928 if (bReadClockLine(pHWDE) == HICLK) break; 929 i++; 930 delay2 *= 2; 931 if (i >= I2C_RETRY_COUNT) return FALSE; 932 } while (1); 933 } 934 935 I2C_DelayUS(delay); /* Jong@08052008 */ 936 vWriteClockLine(pHWDE, LOCLK); 937 I2C_DelayUS(delay); 938 939 return TRUE; 940} 941 942 943/*^^* 944 * Function: Start 945 * 946 * Purpose: To start a transfer on the I2C bus. 947 * 948 * Inputs: lpI2C_ContextData : PI2C_CONTEXT, pointer to data struct associated with 949 * lpI2C_ContextData being accessed 950 * 951 * Outputs: void. 952 *^^*/ 953BOOLEAN Start( PXGI_HW_DEVICE_INFO pHWDE) 954{ 955 ULONG i, delay, delay2; 956 957 delay = pHWDE->I2CDelay / 10 / 2; 958 959 vWriteDataLine(pHWDE, HIDAT); 960 I2C_DelayUS(delay); 961 if (bReadDataLine(pHWDE) != HIDAT) { 962 delay2 = delay * 2; 963 i = 0; 964 do { 965 I2C_DelayUS(delay2); /* Jong@08052008 */ 966 vWriteDataLine(pHWDE, HIDAT); 967 I2C_DelayUS(delay2); 968 if (bReadDataLine(pHWDE) == HIDAT) break; 969 i++; 970 delay2 *= 2; 971 if (i >= I2C_RETRY_COUNT) return FALSE; 972 } while (1); 973 } 974 975 I2C_DelayUS(delay); /* Jong@08052008 */ 976 vWriteClockLine(pHWDE, HICLK); 977 I2C_DelayUS(delay); 978 if (bReadClockLine(pHWDE) != HICLK) { 979 delay2 = delay * 2; 980 i = 0; 981 do { 982 I2C_DelayUS(delay2); /* Jong@08052008 */ 983 vWriteClockLine(pHWDE, HICLK); 984 I2C_DelayUS(delay2); 985 if (bReadClockLine(pHWDE) == HICLK) break; 986 i++; 987 delay2 *= 2; 988 if (i >= I2C_RETRY_COUNT) return FALSE; 989 } while (1); 990 } 991 992 I2C_DelayUS(delay); /* Jong@08052008 */ 993 vWriteDataLine(pHWDE, LODAT); 994 I2C_DelayUS(delay); 995 996 vWriteClockLine(pHWDE, LOCLK); 997 I2C_DelayUS(delay); 998 999 return TRUE; 1000}/* end of Start */ 1001 1002/*^^* 1003 * Function: Stop 1004 * 1005 * Purpose: To stop a transfer on the I2C bus. 1006 * 1007 * Inputs: lpI2C_ContextData : PI2C_CONTEXT, pointer to data struct associated with 1008 * lpI2C_ContextData being accessed 1009 * 1010 * Outputs: void. 1011 *^^*/ 1012BOOLEAN Stop(PXGI_HW_DEVICE_INFO pHWDE) 1013{ 1014 ULONG i, delay, delay2; 1015 1016 delay = pHWDE->I2CDelay / 10 / 2; 1017 PDEBUGI2C(ErrorF("Stop()-begin-pHWDE->I2CDelay=%d, delay=%d...\n", pHWDE->I2CDelay, delay)); 1018 1019 vWriteDataLine(pHWDE, LODAT); 1020 I2C_DelayUS(delay); 1021 1022 vWriteClockLine(pHWDE, HICLK); 1023 I2C_DelayUS(delay); 1024 if (bReadClockLine(pHWDE) != HICLK) { 1025 i = 0; 1026 delay2 = delay * 2; 1027 do { 1028 I2C_DelayUS(delay2); /* Jong@08052008 */ 1029 vWriteClockLine(pHWDE, HICLK); 1030 I2C_DelayUS(delay2); 1031 if (bReadClockLine(pHWDE) == HICLK) break; 1032 i++; 1033 delay2 *= 2; 1034 if (i >= I2C_RETRY_COUNT) return FALSE; 1035 } while (1); 1036 } 1037 1038 I2C_DelayUS(delay); /* Jong@08052008 */ 1039 vWriteDataLine(pHWDE, HIDAT); 1040 I2C_DelayUS(delay); 1041 1042 return (BOOLEAN)(bReadDataLine(pHWDE) == HIDAT); 1043}/* end of Stop*/ 1044 1045/*^^* 1046 * Function: WriteUCHARI2C 1047 * 1048 * Purpose: To write a UCHAR of data to the I2C bus. 1049 * 1050 * Inputs: lpI2C_ContextData : PI2C_CONTEXT, pointer to data struct associated with 1051 * lpI2C_ContextData being accessed 1052 * cData: UCHAR, the data to write 1053 * 1054 * Outputs: void. 1055 *^^*/ 1056BOOLEAN WriteUCHARI2C(PXGI_HW_DEVICE_INFO pHWDE, UCHAR cData) 1057{ 1058 ULONG i, j, delay, delay2; 1059 1060 cData = ReverseUCHAR(cData); 1061 1062 delay = pHWDE->I2CDelay / 10 / 2; 1063 1064 for (j=0; j<8; j++, cData>>=1) 1065 { 1066 I2C_DelayUS(delay); /* Jong@08052008 */ 1067 vWriteDataLine(pHWDE, cData); 1068 I2C_DelayUS(delay); 1069 1070 vWriteClockLine(pHWDE, HICLK); 1071 I2C_DelayUS(delay); 1072 if (bReadClockLine(pHWDE) != HICLK) { 1073 i = 0; 1074 delay2 = delay * 2; 1075 do { 1076 I2C_DelayUS(delay2); /* Jong@08052008 */ 1077 vWriteClockLine(pHWDE, HICLK); 1078 I2C_DelayUS(delay2); 1079 if (bReadClockLine(pHWDE) == HICLK) break; 1080 i++; 1081 delay2 *= 2; 1082 if (i >= I2C_RETRY_COUNT) return FALSE; 1083 } while (1); 1084 } 1085 1086 I2C_DelayUS(delay); /* Jong@08052008 */ 1087 vWriteClockLine(pHWDE, LOCLK); 1088 I2C_DelayUS(delay); 1089 } 1090 return TRUE; 1091}/* end of WriteUCHARI2C */ 1092 1093/*^^* 1094 * Function: ReadUCHARI2C 1095 * 1096 * Purpose: To read a UCHAR of data from the I2C bus. 1097 * 1098 * Inputs: lpI2C_ContextData : PI2C_CONTEXT, pointer to data struct associated with 1099 * lpI2C_ContextData being accessed 1100 * 1101 * Outputs: UCHAR, the data that was read. 1102 *^^*/ 1103BOOLEAN ReadUCHARI2C(PXGI_HW_DEVICE_INFO pHWDE, PUCHAR pBuffer) 1104{ 1105 ULONG ulReadData, data, i, j, delay, delay2; 1106 1107 delay = pHWDE->I2CDelay / 10 / 2; 1108 1109 vWriteDataLine(pHWDE, HIDAT); 1110 I2C_DelayUS(delay); 1111 1112 ulReadData = 0; 1113 for (j = 0; j < 8; j++) 1114 { 1115 vWriteClockLine(pHWDE, HICLK); 1116 I2C_DelayUS(delay); 1117 if (bReadClockLine(pHWDE) != HICLK) { 1118 i = 0; 1119 delay2 = delay * 2; 1120 do { 1121 I2C_DelayUS(delay2); /* Jong@08052008 */ 1122 vWriteClockLine(pHWDE, HICLK); 1123 I2C_DelayUS(delay2); 1124 if (bReadClockLine(pHWDE) == HICLK) break; 1125 i++; 1126 delay2 *= 2; 1127 if (i >= I2C_RETRY_COUNT) return FALSE; 1128 } while (1); 1129 } 1130 1131 I2C_DelayUS(delay); /* Jong@08052008 */ 1132 data = bReadDataLine(pHWDE); 1133 ulReadData = (ulReadData << 1) | (data & 1); 1134 1135 I2C_DelayUS(delay); /* Jong@08052008 */ 1136 vWriteClockLine(pHWDE, LOCLK); 1137 I2C_DelayUS(delay); 1138 1139 vWriteDataLine(pHWDE, HIDAT); 1140 I2C_DelayUS(delay); 1141 } 1142 1143 *pBuffer = (UCHAR) ulReadData; 1144 return TRUE; 1145} 1146 1147 1148UCHAR ReverseUCHAR(UCHAR data) 1149{ 1150 UCHAR rdata = 0; 1151 int i; 1152 1153 for (i=0; i<8; i++) 1154 { 1155 rdata <<= 1; 1156 rdata |= (data & 1); 1157 data >>= 1; 1158 } 1159 1160 return(rdata); 1161} 1162 1163/************************************************************************************ 1164 For DVI I2C Interface 1165***************************************************************************************/ 1166 1167/************************************************************************* 1168// VOID vWriteClockLineDVI() 1169// IOReg xx14, index 0F is defined as follows: 1170// 1171// ... 1 0 1172// --------|------|-------| 1173// ...| Data | Clock | 1174// ------------------------ 1175*************************************************************************/ 1176VOID vWriteClockLineDVI(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data) 1177{ 1178 UCHAR temp; 1179 XGIIOADDRESS pjI2cIOBase; 1180 1181 PDEBUGI2C(ErrorF("vWriteClockLineDVI()...begin\n")); 1182 1183 if ((pHWDE->jChipType < XG21)&&(pHWDE->jChipType != XG27)) 1184 { 1185 ErrorF("vWriteClockLineDVI()...0\n"); 1186 } 1187 else 1188 { 1189 PDEBUGI2C(ErrorF("vWriteClockLineDVI()...1\n")); 1190 pjI2cIOBase = pHWDE->pjIOAddress + CRTC_ADDRESS_PORT_COLOR; 1191 1192 /* Enable GPIOA Write */ 1193 1194 EnableGPIOA(pjI2cIOBase, I2C_WRITE); 1195 1196 PDEBUGI2C(ErrorF("*1 - pHWDE->ucI2cDVI = %d\n", pHWDE->ucI2cDVI)); 1197 pHWDE->ucI2cDVI = (pHWDE->ucI2cDVI & MASK(1:1)) | SETBITS(data, 0:0); 1198 PDEBUGI2C(ErrorF("*2 - pHWDE->ucI2cDVI = %d\n", pHWDE->ucI2cDVI)); 1199 1200 temp = XGI_GetReg(pjI2cIOBase, IND_CR48_GPIO_REG_I); 1201 PDEBUGI2C(ErrorF("IND_CR48_GPIO_REG_I = %d\n", temp)); 1202 1203 { 1204 UCHAR temp2 = getGPIORWTransfer(temp); 1205 PDEBUGI2C(ErrorF("temp2 = %d\n", temp2)); 1206 temp = temp2; 1207 } 1208 1209 temp = (temp & (~MASK(1:0))) | pHWDE->ucI2cDVI; 1210 PDEBUGI2C(ErrorF("temp= %d\n", temp)); 1211 XGI_SetReg(pjI2cIOBase,IND_CR48_GPIO_REG_I, temp); 1212 } 1213 1214 PDEBUGI2C(ErrorF("vWriteClockLineDVI()...end\n")); 1215} 1216 1217/************************************************************************* 1218// VOID vWriteDataLineDVI() 1219// IOReg xx14, index 0F is defined as follows: 1220// 1221// ... 1 0 1222// --------|------|-------| 1223// ...| Data | Clock | 1224// ------------------------ 1225*************************************************************************/ 1226VOID vWriteDataLineDVI(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data) 1227{ 1228 UCHAR temp; 1229 XGIIOADDRESS pjI2cIOBase; 1230 1231 PDEBUGI2C(ErrorF("vWriteDataLineDVI()...begin\n")); 1232 1233 if ((pHWDE->jChipType < XG21)&&(pHWDE->jChipType != XG27)) 1234 { 1235 ErrorF("vWriteDataLineDVI()...0\n"); 1236 } 1237 else 1238 { 1239 PDEBUGI2C(ErrorF("vWriteDataLineDVI()...1\n")); 1240 pjI2cIOBase = pHWDE->pjIOAddress + CRTC_ADDRESS_PORT_COLOR; 1241 1242 1243 /* Enable GPIOB Write */ 1244 1245 EnableGPIOB(pjI2cIOBase, I2C_WRITE); 1246 1247 PDEBUGI2C(ErrorF("*1 - pHWDE->ucI2cDVI = %d\n", pHWDE->ucI2cDVI)); 1248 pHWDE->ucI2cDVI = (pHWDE->ucI2cDVI & MASK(0:0)) | SETBITS(data, 1:1); 1249 PDEBUGI2C(ErrorF("*2 - pHWDE->ucI2cDVI = %d\n", pHWDE->ucI2cDVI)); 1250 1251 temp = XGI_GetReg(pjI2cIOBase, IND_CR48_GPIO_REG_I); 1252 PDEBUGI2C(ErrorF("IND_CR48_GPIO_REG_I = %d\n", temp)); 1253 1254 { 1255 UCHAR temp2 = getGPIORWTransfer(temp); 1256 PDEBUGI2C(ErrorF("temp2 = %d\n", temp2)); 1257 1258 temp = temp2; 1259 } 1260 1261 temp = (temp & (~MASK(1:0))) | pHWDE->ucI2cDVI; 1262 PDEBUGI2C(ErrorF("temp = %d\n", temp)); 1263 1264 XGI_SetReg(pjI2cIOBase,IND_CR48_GPIO_REG_I, temp); 1265 } 1266 1267 PDEBUGI2C(ErrorF("vWriteDataLineDVI()...end\n")); 1268} 1269 1270/************************************************************************* 1271// BOOLEAN bReadClockLineDVI() 1272// IOReg xx14, index 0F is defined as follows: 1273// 1274// ... 1 0 1275// --------|------|-------| 1276// ...| Data | Clock | 1277// ------------------------ 1278*************************************************************************/ 1279BOOLEAN bReadClockLineDVI(PXGI_HW_DEVICE_INFO pHWDE) 1280{ 1281 UCHAR cPortData; 1282 XGIIOADDRESS pjI2cIOBase; 1283 1284 PDEBUGI2C(ErrorF("bReadClockLineDVI()...begin\n")); 1285 1286 if ((pHWDE->jChipType != XG21)&&(pHWDE->jChipType != XG27)) 1287 { 1288 ErrorF("bReadClockLineDVI()...0\n"); 1289 } 1290 else 1291 { 1292 PDEBUGI2C(ErrorF("bReadClockLineDVI()...1\n")); 1293 pjI2cIOBase = pHWDE->pjIOAddress + CRTC_ADDRESS_PORT_COLOR; 1294 1295 /* Enable GPIOA READ */ 1296 1297 EnableGPIOA(pjI2cIOBase, I2C_READ); 1298 1299 cPortData = XGI_GetReg(pjI2cIOBase, IND_CR48_GPIO_REG_I); 1300 PDEBUGI2C(ErrorF("*1 - cPortData = %d...\n", cPortData)); 1301 1302 cPortData = GETBITS(cPortData, 7:7); 1303 PDEBUGI2C(ErrorF("*2 - cPortData = %d...\n", cPortData)); 1304 } 1305 1306 PDEBUGI2C(ErrorF("bReadClockLineDVI()...return(cPortData=%d)\n", cPortData)); 1307 return cPortData; 1308} 1309 1310/************************************************************************* 1311// BOOLEAN bReadDataLineDVI() 1312// IOReg xx14, index 0F is defined as follows: 1313// 1314// ... 1 0 1315// --------|------|-------| 1316// ...| Data | Clock | 1317// ------------------------ 1318*************************************************************************/ 1319BOOLEAN bReadDataLineDVI(PXGI_HW_DEVICE_INFO pHWDE) 1320{ 1321 UCHAR cPortData; 1322 XGIIOADDRESS pjI2cIOBase; 1323 1324 PDEBUGI2C(ErrorF("bReadDataLineDVI()...begin\n")); 1325 1326 if ((pHWDE->jChipType != XG21)&&(pHWDE->jChipType != XG27)) 1327 { 1328 ErrorF("bReadDataLineDVI()...0\n"); 1329 } 1330 else 1331 { 1332 PDEBUGI2C(ErrorF("bReadDataLineDVI()...1\n")); 1333 pjI2cIOBase = pHWDE->pjIOAddress + CRTC_ADDRESS_PORT_COLOR; 1334 1335 1336 /* Enable GPIOB Write */ 1337 1338 EnableGPIOB(pjI2cIOBase, I2C_READ); 1339 1340 cPortData = XGI_GetReg(pjI2cIOBase, IND_CR48_GPIO_REG_I); 1341 PDEBUGI2C(ErrorF("*1 - cPortData = %d...\n", cPortData)); 1342 cPortData = GETBITS(cPortData, 6:6); 1343 PDEBUGI2C(ErrorF("*2 - cPortData = %d...\n", cPortData)); 1344 } 1345 1346 1347 PDEBUGI2C(ErrorF("bReadDataLineDVI()...return(cPortData=%d)\n", cPortData)); 1348 return cPortData; 1349} 1350 1351//*************************************************************************// 1352// VOID vWaitForCRT1VsyncActive() 1353// IoReg 3DA 1354// ... 3 ... 1355// --------|--------------|-------| 1356// ...| Vertical Sync| | 1357// -------------------------------- 1358//*************************************************************************// 1359VOID vWaitForCRT1HsyncActive(PXGI_HW_DEVICE_INFO pHWDE) 1360{ 1361 XGIIOADDRESS pjPort = pHWDE->pjIOAddress + INPUT_STATUS_1_COLOR; 1362 ULONG i; 1363 1364 for (i = 0; i < 0x00FFFF; i++) 1365 { 1366 if ( (XGI_GetRegByte(pjPort) & 0x01) == 0) 1367 { 1368 // Inactive 1369 break; 1370 } //if 1371 } //for-loop 1372 1373 for (i = 0; i < 0x00FFFF; i++) 1374 { 1375 if ( (XGI_GetRegByte(pjPort) & 0x01) != 0) 1376 { 1377 // active 1378 break; 1379 } //if 1380 } //for-loop 1381 1382} //vWaitForCRT1HsyncActive() 1383 1384//////////////////////////////////////////////////////////////////////////////////// 1385// 1386// For CRT I2C Interface 1387// 1388//////////////////////////////////////////////////////////////////////////////////// 1389 1390//*************************************************************************// 1391// VOID vWriteClockLineCRT() 1392// IOReg SR11 is defined as follows: 1393// 1394// ... 1 0 1395// --------|------|-------| 1396// ...| Data | Clock | 1397// ------------------------ 1398//*************************************************************************// 1399VOID vWriteClockLineCRT(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data) 1400{ 1401 UCHAR temp, ujSR1F; 1402 XGIIOADDRESS pjI2cIOBase = pHWDE->pjIOAddress + SEQ_ADDRESS_PORT; 1403 1404 PDEBUGI2C(ErrorF("I2C:Write CRT clock = %x\n", data & 1)); 1405 1406 ujSR1F = XGI_GetReg(pjI2cIOBase, IND_SR1F_POWER_MANAGEMENT); 1407 1408 pHWDE->ucI2cCRT = (pHWDE->ucI2cCRT & MASK(1:1)) | SETBITS(data, 0:0); 1409 1410 temp = XGI_GetReg(pjI2cIOBase, IND_SR11_DDC_REG); 1411 temp = (temp & (~MASK(1:0))) | pHWDE->ucI2cCRT; 1412 1413 //wait for CRT1 retrace only when CRT1 is enabled! 1414 /* if (pHWDE->bMonitorPoweredOn) */ /* jong@08042009; ignore here */ 1415 { 1416 if(!(data & 1) && ((ujSR1F & 0xC0)==0) ) 1417 { 1418 vWaitForCRT1HsyncActive(pHWDE); 1419 } 1420 } 1421 1422 XGI_SetReg(pjI2cIOBase, IND_SR11_DDC_REG, temp); 1423} 1424 1425//*************************************************************************// 1426// VOID vWriteDataLineCRT() 1427// IOReg SR11 is defined as follows: 1428// 1429// ... 1 0 1430// --------|------|-------| 1431// ...| Data | Clock | 1432// ------------------------ 1433//*************************************************************************// 1434VOID vWriteDataLineCRT(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data) 1435{ 1436 UCHAR temp, ujSR1F; 1437 XGIIOADDRESS pjI2cIOBase = pHWDE->pjIOAddress + SEQ_ADDRESS_PORT; 1438 1439 PDEBUGI2C(ErrorF("I2C:Write CRT data = %x\n", data & 1)); 1440 1441 ujSR1F = XGI_GetReg(pHWDE->pjIOAddress + SEQ_ADDRESS_PORT, IND_SR1F_POWER_MANAGEMENT); 1442 1443 pHWDE->ucI2cCRT = (pHWDE->ucI2cCRT & MASK(0:0)) | SETBITS(data, 1:1); 1444 temp = XGI_GetReg(pjI2cIOBase, IND_SR11_DDC_REG); 1445 temp = (temp & (~MASK(1:0))) | pHWDE->ucI2cCRT; 1446 1447 //wait for CRT1 retrace only when CRT1 is enabled! 1448 /* if (pHWDE->bMonitorPoweredOn) */ /* Jong@08042009; ignore checking */ 1449 { 1450 if(!(data & 1) && ((ujSR1F & 0xC0)==0) ) 1451 { 1452 vWaitForCRT1HsyncActive(pHWDE); 1453 } 1454 } 1455 1456 XGI_SetReg(pjI2cIOBase, IND_SR11_DDC_REG, temp); 1457} 1458 1459//*************************************************************************// 1460// BOOLEAN bReadClockLineCRT() 1461// IOReg SR11 is defined as follows: 1462// 1463// ... 1 0 1464// --------|------|-------| 1465// ...| Data | Clock | 1466// ------------------------ 1467//*************************************************************************// 1468BOOLEAN bReadClockLineCRT(PXGI_HW_DEVICE_INFO pHWDE) 1469{ 1470 UCHAR cPortData; 1471 XGIIOADDRESS pjI2cIOBase = pHWDE->pjIOAddress + SEQ_ADDRESS_PORT; 1472 1473 cPortData = XGI_GetReg(pjI2cIOBase, IND_SR11_DDC_REG); 1474 cPortData = GETBITS(cPortData, 0:0); 1475 1476 PDEBUGI2C(ErrorF("I2C:Read Channel CRT clock = %x\n", cPortData)); 1477 1478 return cPortData; 1479} 1480 1481//*************************************************************************// 1482// BOOLEAN bReadDataLineCRT() 1483// IOReg SR11 is defined as follows: 1484// 1485// ... 1 0 1486// --------|------|-------| 1487// ...| Data | Clock | 1488// ------------------------ 1489//*************************************************************************// 1490BOOLEAN bReadDataLineCRT(PXGI_HW_DEVICE_INFO pHWDE) 1491{ 1492 UCHAR cPortData; 1493 XGIIOADDRESS pjI2cIOBase = pHWDE->pjIOAddress + SEQ_ADDRESS_PORT; 1494 1495 cPortData = XGI_GetReg(pjI2cIOBase, IND_SR11_DDC_REG); 1496 cPortData = GETBITS(cPortData, 1:1); 1497 1498 PDEBUGI2C(ErrorF("I2C:Read Channel CRT data = %x\n", cPortData)); 1499 1500 return cPortData; 1501} 1502 1503//////////////////////////////////////////////////////////////////////////////////// 1504// 1505// For Feature Connector I2C Interface 1506// 1507//////////////////////////////////////////////////////////////////////////////////// 1508 1509//*************************************************************************// 1510// VOID vWriteClockLineFCNT() 1511// IOReg SR11 is defined as follows: 1512// 1513// ... 3 2 ... 1514// --------|------|-------|-------| 1515// ...| Data | Clock | | 1516// -------------------------------- 1517//*************************************************************************// 1518VOID vWriteClockLineFCNT(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data) 1519{ 1520 UCHAR temp; 1521 XGIIOADDRESS pjI2cIOBase = pHWDE->pjIOAddress + SEQ_ADDRESS_PORT; 1522 1523 PDEBUGI2C(ErrorF("I2C:Write FCNT clock = %x\n", data & 1)); 1524 1525 pHWDE->ucI2cFCNT = (pHWDE->ucI2cFCNT & MASK(3:3)) | SETBITS(data, 2:2); 1526 1527 temp = XGI_GetReg(pjI2cIOBase, IND_SR11_DDC_REG); 1528 temp = (temp & (~MASK(3:2))) | pHWDE->ucI2cFCNT; 1529 1530 XGI_SetReg(pjI2cIOBase, IND_SR11_DDC_REG, temp); 1531} 1532 1533//*************************************************************************// 1534// VOID vWriteDataLineFCNT() 1535// IOReg SR11 is defined as follows: 1536// 1537// ... 3 2 ... 1538// --------|------|-------|-------| 1539// ...| Data | Clock | | 1540// -------------------------------- 1541//*************************************************************************// 1542VOID vWriteDataLineFCNT(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data) 1543{ 1544 UCHAR temp, temp2, temp3; 1545 XGIIOADDRESS pjI2cIOBase = pHWDE->pjIOAddress + SEQ_ADDRESS_PORT; 1546 1547 PDEBUGI2C(ErrorF("I2C:Write FCNT data = %x\n", data & 1)); 1548 1549 pHWDE->ucI2cFCNT = (pHWDE->ucI2cFCNT & MASK(2:2)) | SETBITS(data, 3:3); 1550 1551 temp = XGI_GetReg(pjI2cIOBase, IND_SR11_DDC_REG); 1552 temp = (temp & (~MASK(3:2))) | pHWDE->ucI2cFCNT; 1553 1554 XGI_SetReg(pjI2cIOBase, IND_SR11_DDC_REG, temp); 1555} 1556 1557//*************************************************************************// 1558// BOOLEAN bReadClockLineFCNT() 1559// IOReg SR11 is defined as follows: 1560// 1561// ... 3 2 ... 1562// --------|------|-------|-------| 1563// ...| Data | Clock | | 1564// -------------------------------- 1565//*************************************************************************// 1566BOOLEAN bReadClockLineFCNT(PXGI_HW_DEVICE_INFO pHWDE) 1567{ 1568 UCHAR cPortData; 1569 XGIIOADDRESS pjI2cIOBase = pHWDE->pjIOAddress + SEQ_ADDRESS_PORT; 1570 1571 cPortData = XGI_GetReg(pjI2cIOBase, IND_SR11_DDC_REG); 1572 cPortData = GETBITS(cPortData, 2:2); 1573 1574 PDEBUGI2C(ErrorF("I2C:Read Channel FCNT clock = %x\n", cPortData)); 1575 1576 return cPortData; 1577} 1578 1579//*************************************************************************// 1580// BOOLEAN bReadDataLineFCNT() 1581// IOReg SR11 is defined as follows: 1582// 1583// ... 3 2 ... 1584// --------|------|-------|-------| 1585// ...| Data | Clock | | 1586// -------------------------------- 1587//*************************************************************************// 1588BOOLEAN bReadDataLineFCNT(PXGI_HW_DEVICE_INFO pHWDE) 1589{ 1590 UCHAR cPortData; 1591 XGIIOADDRESS pjI2cIOBase = pHWDE->pjIOAddress + SEQ_ADDRESS_PORT; 1592 1593 cPortData = XGI_GetReg(pjI2cIOBase, IND_SR11_DDC_REG); 1594 cPortData = GETBITS(cPortData, 3:3); 1595 1596 PDEBUGI2C(ErrorF("I2C:Read Channel FCNT data = %x\n", cPortData)); 1597 1598 return cPortData; 1599} 1600 1601/*=======================================================*/ 1602VOID vWriteClockLine(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data) 1603{ 1604 if(pHWDE->crtno == 0) 1605 vWriteClockLineCRT(pHWDE, data); 1606 else if(pHWDE->crtno == 1) 1607 vWriteClockLineDVI(pHWDE, data); 1608 else if(pHWDE->crtno == 2) 1609 vWriteClockLineFCNT(pHWDE, data); 1610 else 1611 ErrorF("Error(XGI) : Unkonwn output device! \n"); 1612} 1613 1614VOID vWriteDataLine(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data) 1615{ 1616 if(pHWDE->crtno == 0) 1617 vWriteDataLineCRT(pHWDE, data); 1618 else if(pHWDE->crtno == 1) 1619 vWriteDataLineDVI(pHWDE, data); 1620 else if(pHWDE->crtno == 2) 1621 vWriteDataLineFCNT(pHWDE, data); 1622 else 1623 ErrorF("Error(XGI) : Unkonwn output device! \n"); 1624} 1625 1626BOOLEAN bReadClockLine(PXGI_HW_DEVICE_INFO pHWDE) 1627{ 1628 if(pHWDE->crtno == 0) 1629 return(bReadClockLineCRT(pHWDE)); 1630 else if(pHWDE->crtno == 1) 1631 return(bReadClockLineDVI(pHWDE)); 1632 else if(pHWDE->crtno == 2) 1633 return(bReadClockLineFCNT(pHWDE)); 1634 else { 1635 ErrorF("Error(XGI) : Unkonwn output device! \n"); 1636 return FALSE; 1637 } 1638} 1639 1640BOOLEAN bReadDataLine(PXGI_HW_DEVICE_INFO pHWDE) 1641{ 1642 if(pHWDE->crtno == 0) 1643 return(bReadDataLineCRT(pHWDE)); 1644 else if(pHWDE->crtno == 1) 1645 return(bReadDataLineDVI(pHWDE)); 1646 else if(pHWDE->crtno == 2) 1647 return(bReadDataLineFCNT(pHWDE)); 1648 else { 1649 ErrorF("Error(XGI) : Unkonwn output device! \n"); 1650 return FALSE; 1651 } 1652} 1653 1654BOOLEAN bEDIDCheckSum(PUCHAR pjEDIDBuf,ULONG ulBufSize) 1655{ 1656 ULONG i; 1657 UCHAR ujSum = 0; 1658 PUCHAR pujPtr; 1659 1660 pujPtr = pjEDIDBuf; 1661 1662 for (i = 0; i < ulBufSize; i++) 1663 { 1664 /* printk("pujPtr=%x, ",*pujPtr); */ 1665 ujSum += *(pujPtr++); 1666 } /*for-loop */ 1667 1668 return(ujSum); 1669 1670} 1671 1672/* Jong 08/03/2009; Get EDID functions; ported from MS Windows */ 1673//*************************************************************************\\ 1674// VP_STATUS vGetEDID_1 1675// 1676// Routine Description: 1677// Get the EDID which is in version 1.x format via I2C. 1678// 1679// Arguments: 1680// pHWDE - Hardware extension object pointer 1681// pI2C - I2C pointer 1682// pjBuffer - EDID Buffer 1683// ulBufferSize - Buffer size 1684// 1685// 1686// Return Value: 1687// Status of returning EDID. 1688// NO_ERROR - success 1689// ERROR_INVALID_PARAMETER - failed 1690// 1691//**************************************************************************** 1692VP_STATUS vGetEDID_1( 1693 PXGI_HW_DEVICE_INFO pHWDE, 1694 PI2CControl pI2C, 1695 PUCHAR pjBuffer, 1696 ULONG ulBufferSize) 1697{ 1698 VP_STATUS status; 1699 1700 PDEBUGI2C(ErrorF("vGetEDID_1()\n")); 1701 1702 if ((ulBufferSize < 128) || (pjBuffer == NULL)) { 1703 return ERROR_INVALID_PARAMETER; 1704 } 1705 1706 // Set Segment Block ID as 0 if Monitor support Enhanced-EDID 1707 /* 1708 pI2C->Command = I2C_COMMAND_WRITE_SEGMENT; // to replace I2C_COMMAND_WRITE 1709 pI2C->Data = 0; 1710 I2CAccessBuffer(pHWDE, pI2C, 0x60, 0, &(pI2C->Data), 0); 1711 */ 1712 pI2C->Command = I2C_COMMAND_WRITE; 1713 pI2C->Data = 0; 1714 I2CAccessBuffer(pHWDE, pI2C, 0x60, 0, &(pI2C->Data), 0); 1715 1716 pI2C->Command = I2C_COMMAND_READ; 1717 status = I2CAccessBuffer(pHWDE, pI2C, 0xA0, 0, pjBuffer, 128); 1718 if ((status == NO_ERROR) && (pI2C->Status == I2C_STATUS_NOERROR)) 1719 { 1720 // Check Block 0 EDID Header and its checksum 1721 if ((*((PULONG)(pjBuffer )) != 0xFFFFFF00) || 1722 (*((PULONG)(pjBuffer+4)) != 0x00FFFFFF)) 1723 { 1724 PDEBUGI2C(ErrorF("vGetEDID_1(): EDID Header Incorrect!!\n")); 1725 return ERROR_INVALID_PARAMETER; 1726 } 1727 1728 if (bEDIDCheckSum(pjBuffer, 128) != 0) 1729 { 1730 if ((*((PULONG)(pjBuffer+0x60)) ==0x4d636e79)&& (*((PULONG)(pjBuffer+0x64)) ==0x65747361)) 1731 { 1732 return NO_ERROR; //To Fix SyncMaster Checksum error issue 1733 } 1734 1735 PDEBUGI2C(ErrorF("vGetEDID_1(): EDID Checksum Error!!\n")); 1736 return ERROR_INVALID_PARAMETER; 1737 } 1738 1739 } 1740 else 1741 { 1742 PDEBUGI2C(ErrorF("vGetEDID_1 : call I2CAccessBuffer(0xA0) fail !!!\n")); 1743 return status; 1744 } 1745 1746 return NO_ERROR; 1747} 1748 1749//*************************************************************************\\ 1750// VP_STATUS vGetEDID_2 1751// 1752// Routine Description: 1753// Get the EDID which is in version 2.0 format via I2C. 1754// 1755// Arguments: 1756// pHWDE - Hardware extension object pointer 1757// pI2C - I2C pointer 1758// pjBuffer - EDID Buffer 1759// ulBufferSize - Buffer size 1760// 1761// 1762// Return Value: 1763// Status of returning EDID. 1764// NO_ERROR - success 1765// ERROR_INVALID_PARAMETER - failed 1766// 1767//**************************************************************************** 1768VP_STATUS vGetEDID_2( 1769 PXGI_HW_DEVICE_INFO pHWDE, 1770 PI2CControl pI2C, 1771 PUCHAR pjBuffer, 1772 ULONG ulBufferSize) 1773{ 1774 VP_STATUS status; 1775 1776 PDEBUGI2C(ErrorF("vGetEDID_2()\n")); 1777 1778 if ((ulBufferSize < 256) || (pjBuffer == NULL)) { 1779 return ERROR_INVALID_PARAMETER; 1780 } 1781 1782 pI2C->Command = I2C_COMMAND_READ; 1783 status = I2CAccessBuffer(pHWDE, pI2C, 0xA2, 0, pjBuffer, 256); 1784 if ((status != NO_ERROR) || (pI2C->Status != I2C_STATUS_NOERROR)) { 1785 PDEBUGI2C(ErrorF("vGetEDID_2 : call I2CAccessBuffer(0xA2) fail !!!\n")); 1786 usleep(5); 1787 status = I2CAccessBuffer(pHWDE, pI2C, 0xA6, 0, pjBuffer, 256); 1788 if ((status != NO_ERROR) || (pI2C->Status != I2C_STATUS_NOERROR)) { 1789 PDEBUGI2C(ErrorF("vGetEDID_2 : call I2CAccessBuffer(0xA6) fail !!!\n")); 1790 return ERROR_INVALID_PARAMETER; 1791 } 1792 } 1793 1794 if (*pjBuffer != 0x20) 1795 { 1796 return ERROR_INVALID_PARAMETER; 1797 } 1798 1799 if (bEDIDCheckSum(pjBuffer, 256) != 0) 1800 { 1801 return ERROR_INVALID_PARAMETER; 1802 } 1803 1804 return NO_ERROR; 1805} 1806 1807//*************************************************************************\\ 1808// BOOLEAN bGetEDID 1809// 1810// Routine Description: 1811// For driver to get the monitor EDID through I2C. This function works similar 1812// with VideoPortDDCMonitorHelper() does. 1813// 1814// 1815// Arguments: 1816// pHWDE - Hardware extension object pointer 1817// ulChannelID - Channel ID 1818// pjEDIDBuffer - EDID Buffer 1819// ulBufferSize - Buffer size 1820// 1821// 1822// Return Value: 1823// Status of returning EDID. 1824// TRUE - success 1825// FALSE - failed 1826// 1827//**************************************************************************** 1828BOOLEAN bGetEDID( 1829 PXGI_HW_DEVICE_INFO pHWDE, 1830 ULONG ulChannelID, 1831 PUCHAR pjEDIDBuffer, 1832 ULONG ulBufferSize) 1833{ 1834 I2CControl I2C; 1835 VP_STATUS status; 1836 1837 PDEBUGI2C(ErrorF("bGetEDID() is called.\n")); 1838 1839 if ((ulBufferSize != 0) && (pjEDIDBuffer != NULL)) 1840 { 1841 memset(pjEDIDBuffer, 0, ulBufferSize); 1842 } 1843 else 1844 { 1845 PDEBUGI2C(ErrorF("bGetEDID()-(ulBufferSize == 0) || (pjEDIDBuffer == NULL)\n")); 1846 return FALSE; 1847 } 1848 1849 if (I2COpen(pHWDE, I2C_OPEN, ulChannelID, &I2C) != NO_ERROR) 1850 { 1851 PDEBUGI2C(ErrorF("bGetEDID()-I2COpen()-fail!\n")); 1852 return FALSE; 1853 } 1854 1855 // Force Monitor using DDC2 protocal... 1856 I2C.ClockRate = I2C_MAX_CLOCK_RATE; 1857 I2C.Command = I2C_COMMAND_WRITE; 1858 I2C.Flags = I2C_FLAGS_STOP; 1859 I2C.Data = 0xFF; 1860 I2CAccess(pHWDE, &I2C); 1861 1862 // Reset I2C bus 1863 I2C.Command = I2C_COMMAND_RESET; 1864 I2CAccess(pHWDE, &I2C); 1865 if (I2C.Status != I2C_STATUS_NOERROR) 1866 { 1867 PDEBUGI2C(ErrorF("bGetEDID() fail: Reset I2C bus fail.\n")); 1868 return FALSE; 1869 } 1870 1871 status = vGetEDID_2(pHWDE, &I2C, pjEDIDBuffer, ulBufferSize); 1872 PDEBUGI2C(ErrorF("bGetEDID()-vGetEDID_2-status=%d\n", status == NO_ERROR ? 1:0)); 1873 1874 if (status != NO_ERROR) 1875 { 1876 usleep(5); 1877 status = vGetEDID_1(pHWDE, &I2C, pjEDIDBuffer, ulBufferSize); 1878 PDEBUGI2C(ErrorF("bGetEDID()-vGetEDID_1-status=%d\n", status == NO_ERROR ? 1:0)); 1879 1880 if (status == NO_ERROR) 1881 { 1882 if (*(pjEDIDBuffer+0x7E) != 0) 1883 { 1884 vGetEDIDExtensionBlocks(pHWDE, &I2C, pjEDIDBuffer+128, ulBufferSize-128); 1885 PDEBUGI2C(ErrorF("bGetEDID()-vGetEDIDExtensionBlocks()\n")); 1886 } 1887 } 1888 else 1889 { 1890 ErrorF( "bGetEDID() fail !!\n"); 1891 } 1892 } 1893 1894 I2COpen(pHWDE, I2C_CLOSE, ulChannelID, &I2C); 1895 1896 PDEBUGI2C(ErrorF("bGetEDID()-return(%d)\n", status == NO_ERROR ? 1:0)); 1897 return (status == NO_ERROR); 1898} 1899