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