📄 dalddc.c
字号:
&& ulStdLen < ulLen)
{
ulLen = ulStdLen;
}
}
}
// Stop I2C bus no matter success or failure
//
if (FALSE == DDCStop(lpDisplay))
{
DALDEBUG((DALDBG_ENTRY_EXIT, "DDCRead- Exit"));
return FALSE;
}
DALDEBUG((DALDBG_ENTRY_EXIT, "DDCRead- Exit"));
return bRet;
} // DDCRead()
/******************************Private*Routine*****************************\
* BOOL DDCWrite(LPDEVGDO lpDisplay, LPUCHAR lpucBuf, ULONG ulLen)
*
* Write byte block of EDID data.
*
\**************************************************************************/
static BOOL
DDCWrite(
LPDEVGDO lpDisplay, // Display structure
LPUCHAR lpucBuf, // Buffer to write from
ULONG ulLen) // Buffer length
{
ULONG ulCount;
BOOL bRet;
DALDEBUG((DALDBG_ENTRY_EXIT, "DDCWrite- Entry"));
DALASSERT(NULL != lpucBuf, "lpucBuf is NULL!");
bRet = DDCStart(lpDisplay);
ulCount = DDC_RETRIES;
while ((bRet) && (ulCount > 0))
{
bRet = DDCStart(lpDisplay);
ulCount--;
}
if (bRet == FALSE)
{
DALDEBUG((DALDBG_ENTRY_EXIT, "DDCWrite- Exit"));
return FALSE;
}
for (ulCount = 0; ulCount < ulLen; ulCount++)
{
if (FALSE == (bRet = DDCWriteByte(lpDisplay, lpucBuf[ulCount])))
break;
}
// Stop I2C bus no matter success or failure
//
if (FALSE == DDCStop(lpDisplay))
{
DALDEBUG((DALDBG_ENTRY_EXIT, "DDCWrite- Exit"));
return FALSE;
}
DALDEBUG((DALDBG_ENTRY_EXIT, "DDCWrite- Exit"));
return bRet;
} // DDCWrite()
/******************************Private*Routine*****************************\
* BOOL DDCReadByte(LPDEVGDO lpDisplay, LPUCHAR lpucByte, BOOL bMore)
*
* Read one byte of EDID data.
*
\**************************************************************************/
static BOOL
DDCReadByte(
LPDEVGDO lpDisplay, // Display structure
LPUCHAR lpucByte, // Byte to read
BOOL bMore) // More reads needed?
{
LONG lShift;
LONG lClockWait;
BOOL bAck;
PFNDDCREADLINE pfnReadLine = lpDisplay->lpHWED->pfnDDC_I2C_ReadLine;
PFNDDCWRITELINE pfnWriteLine = lpDisplay->lpHWED->pfnDDC_I2C_WriteLine;
HGDO hGDO = lpDisplay->hGDO;
DALDEBUG((DALDBG_ENTRY_EXIT, "DDCReadByte- Entry"));
*lpucByte = 0;
//
// The data bits are read from MSB to LSB. A data bit is read while the SCL is high.
//
for (lShift = 7; lShift >= 0; lShift--)
{
// Set SCL high
//
pfnWriteLine(hGDO, 1, DAL_DDC_I2C_LINE_SCL);
DDC_I2C_DELAY();
bAck = DDCWaitForClockLineHigh(lpDisplay);
lClockWait = DDC_RETRIES;
// Some monitors take awhile to respond to the fact that
// the clock has been set high. For these monitors we
// simply ask them a few times if think they might be
// ready to talk to us nicely.
//
while ( (!bAck) && (lClockWait > 0))
{
bAck = DDCWaitForClockLineHigh(lpDisplay);
lClockWait--;
DDC_I2C_DELAY();
}
if(bAck == FALSE)
{
DALDEBUG((DALDBG_DETAIL, "DDCReadByte: SCL didn't take"));
DALDEBUG((DALDBG_ENTRY_EXIT, "DDCReadByte- Exit"));
return FALSE;
}
// Read SDA
//
*lpucByte |= pfnReadLine(hGDO,
DAL_DDC_I2C_LINE_SDA) << lShift;
// Set SCL low
//
pfnWriteLine(hGDO, 0, DAL_DDC_I2C_LINE_SCL);
DDC_I2C_DELAY();
}
//
// Send the acknowledge bit. SDA low = ACK, SDA high = NAK.
//
if (TRUE == bMore)
{ // Set SDA low - ACK
pfnWriteLine(hGDO, 0, DAL_DDC_I2C_LINE_SDA);
}
else
{ // Set SDA high - NAK
pfnWriteLine(hGDO, 1, DAL_DDC_I2C_LINE_SDA);
}
DDC_I2C_DELAY();
//
// Send a SCL high->low pulse, then release the SDA by setting it high.
//
// Set SCL high
//
pfnWriteLine(hGDO, 1, DAL_DDC_I2C_LINE_SCL);
DDC_I2C_DELAY();
if (DDCWaitForClockLineHigh(lpDisplay) == FALSE)
{
DALDEBUG((DALDBG_DETAIL, "DDCReadByte: SCL didn't take - ACK failed"));
DALDEBUG((DALDBG_ENTRY_EXIT, "DDCReadByte- Exit"));
return FALSE;
}
// Set SCL low
//
pfnWriteLine(hGDO, 0, DAL_DDC_I2C_LINE_SCL);
DDC_I2C_DELAY();
// Set SDA high
//
pfnWriteLine(hGDO, 1, DAL_DDC_I2C_LINE_SDA);
DDC_I2C_DELAY();
DALDEBUG((DALDBG_ENTRY_EXIT, "DDCReadByte- Exit"));
return TRUE;
} // DDCReadByte()
/******************************Private*Routine*****************************\
* BOOL DDCWriteByte(LPDEVGDO lpDisplay, UCHAR ucByte)
*
* Write one byte of EDID data.
*
\**************************************************************************/
static BOOL
DDCWriteByte(
LPDEVGDO lpDisplay, // Display structure
UCHAR ucByte) // Byte to write
{
LONG lShift;
LONG lClockWait;
BOOL bAck;
PFNDDCREADLINE pfnReadLine = lpDisplay->lpHWED->pfnDDC_I2C_ReadLine;
PFNDDCWRITELINE pfnWriteLine = lpDisplay->lpHWED->pfnDDC_I2C_WriteLine;
HGDO hGDO = lpDisplay->hGDO;
DALDEBUG((DALDBG_ENTRY_EXIT, "DDCWriteByte- Entry"));
//
// Bits are transmitted serially starting with the MSB.
//
for (lShift = 7; lShift >= 0; lShift--)
{
//
// Transmitt data bit.
//
// Set SDA
//
pfnWriteLine(hGDO, (UCHAR)((ucByte >> lShift) & 0x01), DAL_DDC_I2C_LINE_SDA);
DDC_I2C_DELAY();
//
// After each data bit we must send high->low SCL pulse.
//
// Set SCL high
//
pfnWriteLine(hGDO, 1, DAL_DDC_I2C_LINE_SCL);
DDC_I2C_DELAY();
bAck = DDCWaitForClockLineHigh(lpDisplay);
lClockWait = DDC_RETRIES;
// Some monitors take awhile to respond to the fact that
// the clock has been set high. For these monitors we
// simply ask them a few times if think they might be
// ready to talk to us nicely.
//
while ( (!bAck) && (lClockWait > 0))
{
bAck = DDCWaitForClockLineHigh(lpDisplay);
lClockWait--;
DDC_I2C_DELAY();
}
if(bAck == FALSE)
{
DALDEBUG((DALDBG_DETAIL, "DDCWriteByte: SCL didn't take"));
DALDEBUG((DALDBG_ENTRY_EXIT, "DDCWriteByte- Exit"));
return FALSE;
}
// Set SCL low
//
pfnWriteLine(hGDO, 0, DAL_DDC_I2C_LINE_SCL);
DDC_I2C_DELAY();
}
//
// The monitor sends ACK by preventing the SDA from going high after the clock pulse we use
// to send our last data bit. If the SDA goes high after this bit, it is a NAK from the monitor.
//
// Set SDA high
//
pfnWriteLine(hGDO, 1, DAL_DDC_I2C_LINE_SDA);
DDC_I2C_DELAY();
// Set SCL high
//
pfnWriteLine(hGDO, 1, DAL_DDC_I2C_LINE_SCL);
DDC_I2C_DELAY();
if (DDCWaitForClockLineHigh(lpDisplay) == FALSE)
{
DALDEBUG((DALDBG_DETAIL, "DDCWriteByte: SCL didn't take - ACK failed"));
DALDEBUG((DALDBG_ENTRY_EXIT, "DDCWriteByte- Exit"));
return FALSE;
}
// Read ACK bit
//
DDC_I2C_DELAY();
bAck = pfnReadLine(hGDO, DAL_DDC_I2C_LINE_SDA);
// Set SCL low
//
pfnWriteLine(hGDO, 0, DAL_DDC_I2C_LINE_SCL);
DDC_I2C_DELAY();
if (TRUE == bAck)
{ // NAK from the monitor
DALDEBUG((DALDBG_DETAIL, "DDCWriteByte: NAK received"));
DALDEBUG((DALDBG_ENTRY_EXIT, "DDCWriteByte- Exit"));
return FALSE;
}
DALDEBUG((DALDBG_ENTRY_EXIT, "DDCWriteByte- Exit"));
return TRUE;
} // DDCWriteByte()
/******************************Private*Routine*****************************\
* BOOL DDCWaitForClockLineHigh(LPDEVGDO lpDisplay)
*
* Wait for clock line to become high.
*
\**************************************************************************/
static BOOL
DDCWaitForClockLineHigh(
LPDEVGDO lpDisplay) // Display structure
{
ULONG ulCount;
PFNDDCREADLINE pfnReadLine = lpDisplay->lpHWED->pfnDDC_I2C_ReadLine;
DALDEBUG((DALDBG_ENTRY_EXIT, "DDCWaitForClockLineHigh- Entry"));
for (ulCount = 0; ulCount < DDC_I2C_SCL_READ_RETRIES; ulCount++)
{
if (pfnReadLine(lpDisplay->hGDO, DAL_DDC_I2C_LINE_SCL) == TRUE)
{
DALDEBUG((DALDBG_ENTRY_EXIT, "DDCWaitForClockLineHigh- Exit"));
return TRUE;
}
DDC_I2C_DELAY();
}
DALDEBUG((DALDBG_ENTRY_EXIT, "DDCWaitForClockLineHigh- Exit"));
return FALSE;
} // DDCWaitForClockLineHigh()
/******************************Public*Routine******************************\
* BOOL bFakeTvEdidData(LPHW_DAL_EXTENSION lpHDE, LPDEVGDO lpDisplay,
* LPEDID_BUFFER lpEDIDBuf)
*
* Fake TV EDID data.
*
\**************************************************************************/
BOOL
bFakeTvEdidData(
LPDEVGDO lpDisplay,
LPDEVMODE_INFO lpDisplayMaxModeInfo, // Display structure
LPEDID_BUFFER lpEDIDBuf) // Uninitialized EDID buffer structure
{
static EDID_DATA_V1X sTvEdidDataV1X =
{
// Header (8): EDID ver 1 header
{0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00},
// Vendor / Product Identification (10)
{ 0x41, 0xD0, // ID Manufacturer Name: PNP (0 10000 01110 10000)
0xFE, 0x09, // ID Product Code: TV (?)
0x00, 0x00, 0x00, 0x00, // ID Serial Number
0x00, // Week of Manufacture
0x00 // Year of Manufacture: 1990
},
// EDID structure Version / Revision (2)
{0x01, 0x03}, // What revision to use? v1.3
// Basic Display Parameters / Features (5)
{ 0x00, // Vudeo Input Definition
0x00, // Max Horizontal Image Size
0x00, // Max Vertical Image SIze
0x00, // Display Transfer characteristic (Gamma * 100 - 100)
0xF0 // Feature Support (DPMS)
},
// Color Characteristics (10)
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
// Established Timings (3)
{ 0x21, // 640 x 480 @ 60Hz, 800 x 600 @ 60Hz
0x00, // 0x08 = 1024 x 768 @ 60Hz, if supported
0x00
},
// Standard Timing Identification (16)
{ 0, 0, 0, 0, 0, 0, 0, 0},
// Detailed timing (18 x 4)
{ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
},
// Extension Flag (1)
0x00,
// Check Sum (1)
0x00
};
ULONG ulTemp;
ULONG ulChecksum;
// DEVMODE_INFO HighResMode;
DALDEBUG((DALDBG_ENTRY_EXIT, "bFakeTvEdidData - Entry"));
DALASSERT(EDID_VER_1_STDLEN == sizeof(sTvEdidDataV1X),
"EDID_DATA_V11 structure size mismatch - mispacked??");
DALASSERT(EDID_VER_1_STDLEN <= sizeof(lpEDIDBuf->aucEdidDataBuffer),
"Supplied EDID buffer too small");
// Copy fake EDID structure
//
lpEDIDBuf->ulSize = EDID_VER_1_STDLEN;
lpEDIDBuf->ulFormatId = EDID_VER_13;
MOVEMEMORY(lpEDIDBuf->aucEdidDataBuffer, &sTvEdidDataV1X, EDID_VER_1_STDLEN);
// Check if high resolution supported
//
if((lpDisplayMaxModeInfo->ulPelsWidth >= 1024) &&
(lpDisplayMaxModeInfo->ulPelsHeight >= 768)) //Never assume existing code working .
{
LPEDID_DATA_V1X pEdidV1x = ((LPEDID_DATA_V1X)lpEDIDBuf->aucEdidDataBuffer);
pEdidV1x->aucEstablishedTimings[1] = 0x08;
}
// Generate and fill in the checksum byte.
//
for (ulTemp = 0, ulChecksum = 0; ulTemp < EDID_VER_1_STDLEN; ulTemp++)
{
ulChecksum += lpEDIDBuf->aucEdidDataBuffer[ulTemp];
}
if (0x00 != (ulChecksum & 0xFF))
{
lpEDIDBuf->aucEdidDataBuffer[EDID_VER_1_STDLEN - 1]
= (UCHAR)(0x100 - (ulChecksum & 0xFF));
}
DALDEBUG((DALDBG_ENTRY_EXIT, "bFakeTvEdidData - Exit"));
return TRUE;
} // bFakeTvEdidData()
/******************************Public*Routine******************************\
* BOOL bDDCBlockAccess
*
* This function allows caller to access the I2C bus. It writes the input
* and read the data on the bus. The size of data to be read is inputed by
* caller.
\**************************************************************************/
BOOL
bDDCBlockAccess(
LPHW_DAL_EXTENSION lpHDE,
LPDEVGDO lpDisplay,
ULONG ulFunction,
ULONG ulOption,
ULONG ulInputSize,
LPUCHAR lpInputBuf,
LPULONG lpulOutputSize,
LPUCHAR lpOutputBuf )
{
BOOL bRet;
ULONG ulCount;
PFNDDCREADLINE pfnReadLine = lpDisplay->lpHWED->pfnDDC_I2C_ReadLine;
PFNDDCWRITELINE pfnWriteLine = lpDisplay->lpHWED->pfnDDC_I2C_WriteLine;
// in order to support DDC2Ci, GDO must support DDC primitive functions
if (!bUseDalBasedDdc(lpDisplay))
{
*lpulOutputSize = 0;
return FALSE;
}
// We need the establish the correct I2C bus. If it does not, call bGetEdidData
// function to have it established.
if (!(lpDisplay->ulFlags & GDO_CONNECTOR_ESTABLISHED))
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -