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