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