📄 dalddc.c
字号:
// this senario should not happen very offen unless there is no display
// device connected before to the connector. In this case, should
// bDDCBlockAccess be called????
EDID_BUFFER sEDIDBuf;
if (!bGetEdidData(lpHDE, lpDisplay, (LPEDID_BUFFER)&sEDIDBuf))
{
*lpulOutputSize = 0;
return FALSE;
}
}
switch (ulFunction)
{
case CWDDEDI_DISPLAY_DDCFN_READCLOCKLINE:
{
lpOutputBuf[0] = 0;
if (pfnReadLine(lpDisplay->hGDO, DAL_DDC_I2C_LINE_SCL))
{
lpOutputBuf[0] = 1;
}
*lpulOutputSize = 1;
break;
}
case CWDDEDI_DISPLAY_DDCFN_WRITECLOCKLINE:
{
if (lpInputBuf[0])
{
pfnWriteLine(lpDisplay->hGDO, 1, DAL_DDC_I2C_LINE_SCL);
}
else
{
pfnWriteLine(lpDisplay->hGDO, 0, DAL_DDC_I2C_LINE_SCL);
}
break;
}
case CWDDEDI_DISPLAY_DDCFN_READDATALINE:
{
lpOutputBuf[0] = 0;
if (pfnReadLine(lpDisplay->hGDO, DAL_DDC_I2C_LINE_SDA))
{
lpOutputBuf[0] = 1;
}
*lpulOutputSize = 1;
break;
}
case CWDDEDI_DISPLAY_DDCFN_WRITEDATALINE:
{
if (lpInputBuf[0])
{
pfnWriteLine(lpDisplay->hGDO, 1, DAL_DDC_I2C_LINE_SDA);
}
else
{
pfnWriteLine(lpDisplay->hGDO, 0, DAL_DDC_I2C_LINE_SDA);
}
break;
}
case CWDDEDI_DISPLAY_DDCFN_BLOCKACCESS:
{
if (CWDDEDI_DISPLAY_DDCOPT_SWITCHDDC2 & ulOption)
{
// This is a little fix that gets some older DDC monitors to respond
// properly to DDC queries. Set the clock line low, wait 15 ms then set
// the clock line high.
//
pfnWriteLine(lpDisplay->hGDO, 0, DAL_DDC_I2C_LINE_SCL);
DDC_DELAY_MILLISECONDS(15);
pfnWriteLine(lpDisplay->hGDO, 1, DAL_DDC_I2C_LINE_SCL);
// Initialize SDA and SCL lines to default state of released high (input).
// Drive SCL low for 15ms to switch DDC2-capable monitor to DDC2 mode.
//
pfnWriteLine(lpDisplay->hGDO, 1, DAL_DDC_I2C_LINE_SDA);
pfnWriteLine(lpDisplay->hGDO, 0, DAL_DDC_I2C_LINE_SCL);
DDC_DELAY_MILLISECONDS(15);
pfnWriteLine(lpDisplay->hGDO, 1, DAL_DDC_I2C_LINE_SCL);
if (DDCWaitForClockLineHigh(lpDisplay) == FALSE)
{
DALDEBUG((DALDBG_DETAIL, "bDDCBlockAccess: Can't switch to DDC2"));
return FALSE;
}
}
// send start
// Try to start I2C bus a number of times. Should succeed every time,
// otherwise fail. Really paranoid.
bRet = DDCStart(lpDisplay);
ulCount = DDC_RETRIES;
while ((bRet) && (ulCount > 0))
{
bRet = DDCStart(lpDisplay);
ulCount--;
}
if (bRet == FALSE)
{
DDCStop(lpDisplay);
return FALSE;
}
// send the body
for (ulCount = 0; ulCount < ulInputSize; ulCount++)
{
if (FALSE == DDCWriteByte(lpDisplay, lpInputBuf[ulCount]))
{
DDCStop(lpDisplay);
return FALSE;
}
DDC_I2C_DELAY();
DDC_I2C_DELAY();
DDC_I2C_DELAY();
DDC_I2C_DELAY();
}
// check to see if we have to receive any data
if (lpOutputBuf != NULL)
{
// read the data on I2C bus
for (ulCount = 0; ulCount < *lpulOutputSize; ulCount++)
{
if (FALSE == (bRet = DDCReadByte(lpDisplay,
lpOutputBuf + ulCount,
ulCount < *lpulOutputSize - 1)))
{
break;
}
DDC_I2C_DELAY();
DDC_I2C_DELAY();
DDC_I2C_DELAY();
DDC_I2C_DELAY();
}
}
*lpulOutputSize = ulCount;
// send stop
DDCStop(lpDisplay);
break;
}
default:
{
return FALSE;
}
}
return TRUE;
}
/******************************Public*Routine******************************\
* BOOL bInformCVModChange
*
* This function allows caller to access the I2C bus. It writes the input
* and read the data on the bus. Since the dongle for Component video needs
* set the I2C bus to outputs to HDTV/SDTV.
\**************************************************************************/
BOOL
bInformCVModChange(
LPHW_DAL_EXTENSION lpHDE,
LPDEVGDO lpDisplay,
LPDEVMODE_INFO lpMI
)
{
BOOL bRet ;
UCHAR ucInput[DDC_NUM_BYTES];
ULONG ulLength;
UCHAR ucOutput;
ULONG ulOutputSize =1;
if (GDO_HOOK2_I2C_SUPPORT & lpDisplay->lpHWED->ulFunctionHooks2)
{
//ulLength is the actual Number of bytes for Get function.
ulLength = (*lpDisplay->lpHWED->pfnGetSetI2CData)(lpDisplay->hGDO, &ucInput[0], DDC_NUM_BYTES, DAL_I2C_GET_DATA_FROM_GDO);
if(0 ==ulLength)
return FALSE;
}
else
return FALSE; //Not support dongle.
bRet = bDDCBlockAccess(lpHDE,
lpDisplay,
CWDDEDI_DISPLAY_DDCFN_BLOCKACCESS,
CWDDEDI_DISPLAY_DDCOPT_SWITCHDDC2,
ulLength,
&ucInput[0],
&ulOutputSize,
&ucOutput);
return bRet;
}
/******************************Public*Routine******************************\
* BOOL FAR R6LCDGetEdidData(lpDisplayMaxModeInfo->ulPelsWidth,
* LPEDID_BUFFER lpEdidBuffer)
* This function is used to get emulated EDID data only for LCD.
*
\**************************************************************************/
BOOL FAR bLCDGetFakeEdid(LPDEVGDO lpDisplay,
LPDEVMODE_INFO lpDisplayMaxModeInfo,
LPEDID_BUFFER lpEDIDBuf)
{
ULONG ulTemp,ulChecksum;
LPEDID_STANDARD_TIMING lpStandardTiming;
LPDEVMODE_INFO lpMI;
EDID_DETAILED_V1X sDetailedTiming;
BOOL bNeedAddDetailedTiming;
LPEDID_DATA_V1X lpEDID = (LPEDID_DATA_V1X)&lpEDIDBuf->aucEdidDataBuffer[0];
ULONG i = 0;
//MS supported Standard EDID mode
DEVMODE_INFO aStandardModes[] =
{
{0, 640, 480, 0, 60},
{0, 800, 600, 0, 60},
{0, 1024, 768, 0, 60},
{0, 1152, 864, 0, 60},
{0, 1280, 1024, 0, 60},
{0, 1600, 1200, 0, 60}
};
DALDEBUG((DALDBG_ENTRY_EXIT, "bLCDGetFakeEdid - Entry"));
ZEROMEMORY((LPVOID)&lpEDIDBuf->aucEdidDataBuffer[0],sizeof(lpEDIDBuf->aucEdidDataBuffer));
ZEROMEMORY((LPVOID)&sDetailedTiming, sizeof(EDID_DETAILED_V1X));
bNeedAddDetailedTiming = TRUE;
lpEDIDBuf->ulSize = sizeof(lpEDIDBuf->aucEdidDataBuffer);
lpEDIDBuf->ulFormatId = EDID_VERSION_13;
// Fill in EDID header.
for (ulTemp = 1; ulTemp < 7; ulTemp++)
lpEDID->aucHeader[ulTemp] = 0xFF;
// Fill in necessary EDID fields.
lpEDID->aucVendorID[0] = 0x36; // MS_
lpEDID->aucVendorID[1] = 0x7F;
if(lpDisplayMaxModeInfo->ulDisplayFrequency == 60) //don't output standard timing if it is non_standard refresh rate panel.
{
switch (lpDisplayMaxModeInfo->ulPelsWidth)
{
case 1600:
if (1200 == lpDisplayMaxModeInfo->ulPelsHeight)
{
lpEDID->aucVendorID[2] = 0x06; // LCD 1600x1200
}
break;
case 1280:
if (1024 == lpDisplayMaxModeInfo->ulPelsHeight)
{
lpEDID->aucVendorID[2] = 0x05; // LCD 1280x1024
}
break;
case 1152:
if(864 == lpDisplayMaxModeInfo->ulPelsHeight)
{
lpEDID->aucVendorID[2] = 0x04; // LCD 1152x864
}
break;
case 1024:
if (768 == lpDisplayMaxModeInfo->ulPelsHeight)
{
lpEDID->aucVendorID[2] = 0x03; // LCD 1024x768
}
break;
case 800:
if (600 == lpDisplayMaxModeInfo->ulPelsHeight)
{
lpEDID->aucVendorID[2] = 0x02; // LCD 800x600
}
break;
case 640:
if (480 == lpDisplayMaxModeInfo->ulPelsHeight)
{
lpEDID->aucVendorID[2] = 0x01; // LCD 640x480
}
break;
default: //No entry in MS's.inf, but we still have support it!!
break ;
}
}
lpEDID->aucVersion[0] = 0x01; //Version 1
lpEDID->aucVersion[1] = 0x03; //Revision 3
lpEDID->aucBasicDisplayParameters [0] = 1; // VideoInputDefinition - Digital
lpEDID->aucBasicDisplayParameters [1] = 40; // MaxHzImageSize in cm
lpEDID->aucBasicDisplayParameters [2] = 30; // MaxVtImageSize in cm
lpEDID->aucBasicDisplayParameters [4] = 0xF0; // FeatureSupport - DPMS and color display,
if(lpDisplayMaxModeInfo->ulDisplayFrequency ==60)
{
// Fill in established timings.
lpStandardTiming = (LPEDID_STANDARD_TIMING)&lpEDID->ausStandardTimings[0];
lpMI = &aStandardModes[0];
while((lpMI->ulPelsWidth <= lpDisplayMaxModeInfo->ulPelsWidth)&&
(lpMI->ulPelsHeight <= lpDisplayMaxModeInfo->ulPelsHeight)&&
(i < sizeof(aStandardModes)/sizeof(DEVMODE_INFO)))
{
lpStandardTiming ->ucHorizontalActive = (UCHAR)(lpMI->ulPelsWidth/8 -31);
lpStandardTiming ->ucAspectAndRefreshRate = (UCHAR)(EDID_STANDARD_ASPECT_4_X_3 |
(lpDisplayMaxModeInfo->ulDisplayFrequency - 60));
lpStandardTiming++;
lpMI++;
i++;
}
//Fill in established timings , here we assume LCD panel are all 60Hz!
//if(lpDisplayMaxModeInfo->ulDisplayFrequency ==60)
//{
lpEDID->aucEstablishedTimings[0] |= EDID_ESTABLISHED_640_60;
if(lpDisplayMaxModeInfo->ulPelsWidth >= 800)
{
lpEDID->aucEstablishedTimings[0] |= EDID_ESTABLISHED_800_60;
}
if(lpDisplayMaxModeInfo->ulPelsWidth >= 1024)
{
lpEDID->aucEstablishedTimings[1] |= EDID_ESTABLISHED_1024_60;
}
}
//Fill in detailed timing for weired panel if Panel native mode is not supported by MS.
for ( i = 0; i < sizeof(aStandardModes)/sizeof(DEVMODE_INFO); i++)
{
lpMI = &aStandardModes[i];
if((lpDisplayMaxModeInfo ->ulPelsWidth == lpMI->ulPelsWidth)&&
(lpDisplayMaxModeInfo ->ulPelsHeight== lpMI->ulPelsHeight)&&
(lpDisplayMaxModeInfo->ulDisplayFrequency == lpMI->ulDisplayFrequency))
{
//Panel native mode is in the MS supported list, do noting.
bNeedAddDetailedTiming = FALSE;
break;
}
}
if(bNeedAddDetailedTiming)
{
DAL_CRTC_TIMING sTiming;
ZEROMEMORY((LPDAL_CRTC_TIMING)&sTiming, sizeof(DAL_CRTC_TIMING));
if(lpDisplay->lpHWED ->ulFunctionHooks2 & GDO_HOOK2_GETFIXEDDISPLAYMODETIMING)
{
if((*lpDisplay->lpHWED->pfnGetFixedDisplayModeTiming)(lpDisplay->hGDO,
(LPDEVMODE_INFO)lpDisplayMaxModeInfo,
(LPDAL_CRTC_TIMING)&sTiming))
{
vDALTimingToDetailedTiming((LPDAL_CRTC_TIMING)&sTiming, (LPEDID_DETAILED_V1X)&sDetailedTiming);
lpEDID->aucBasicDisplayParameters [4] |= 0x02; // perferred timing mode required for V1.3.
//Only fill in the detailed timing when Panel mode is not MS supported
MOVEMEMORY((LPEDID_DETAILED_V1X) &lpEDID->EDIDDetailedTimings[0] ,(LPEDID_DETAILED_V1X)&sDetailedTiming, sizeof(EDID_DETAILED_V1X));
}
}
}
// Generate and fill in the checksum byte.
for (ulTemp = 0, ulChecksum = 0; ulTemp < sizeof (EDID_DATA_V11); ulTemp++)
{
ulChecksum += lpEDIDBuf->aucEdidDataBuffer[ulTemp];
}
if (0x00 != (ulChecksum & 0xFF))
lpEDIDBuf->aucEdidDataBuffer[--ulTemp] = (UCHAR)(0x100 - (ulChecksum & 0xFF));
DALDEBUG((DALDBG_ENTRY_EXIT, "bLCDGetFakeEdid - Exit"));
return TRUE;
} // bLCDGetFakeEdid()
/******************************Public*Routine******************************\
* VOID vDALTimingToDetailedTiming
* INPUT: lpCrtcTiming
* OUTPUT: lpEdidDetailedTiming
* RETURN: NONE
\**************************************************************************/
VOID vDALTimingToDetailedTiming(LPDAL_CRTC_TIMING lpCrtcTiming, LPEDID_DETAILED_V1X lpEdidDetailedTiming)
{
USHORT usHBlank;
USHORT usVBlank;
USHORT usHSyncOffset;
USHORT usVSyncOffset;
DALDEBUG((DALDBG_ENTRY_EXIT, "vDALTimingToDetailedTiming - Entry"));
usHBlank = lpCrtcTiming->usHorizontalTotal -lpCrtcTiming->usHorizontalDisplay;
usVBlank = lpCrtcTiming->usVerticalTotal -lpCrtcTiming->usVerticalDisplay;
usHSyncOffset = lpCrtcTiming->usHorizontalSyncStart - lpCrtcTiming->usHorizontalDisplay;
usVSyncOffset = lpCrtcTiming->usVerticalSyncStart - lpCrtcTiming->usVerticalDisplay;
//Translate to Edid Detailed timing.
lpEdidDetailedTiming ->usPixelClock = lpCrtcTiming->usPixelClock;
lpEdidDetailedTiming ->ucHActiveL8 = (UCHAR) (lpCrtcTiming->usHorizontalDisplay & 0x00FF);
lpEdidDetailedTiming ->ucHBlankingL8 = (UCHAR) (usHBlank & 0x00FF);
lpEdidDetailedTiming ->ucHActive_HBlankU4 = (UCHAR) ((lpCrtcTiming->usHorizontalDisplay & 0x0F00)>>4|
(usHBlank & 0x0F00)>>8);
lpEdidDetailedTiming ->ucVActiveL8 = (UCHAR) (lpCrtcTiming->usVerticalDisplay & 0x00FF);
lpEdidDetailedTiming ->ucVBlankingL8 = (UCHAR) (usVBlank & 0x00FF);
lpEdidDetailedTiming ->ucVActive_VBlankU4 = (UCHAR) ((lpCrtcTiming->usVerticalDisplay & 0x0F00)>>4|
(usVBlank & 0x0F00)>>8);
lpEdidDetailedTiming ->ucHSyncOffsetL8 = (UCHAR) (usHSyncOffset & 0x00FF);
lpEdidDetailedTiming ->ucHSyncWidthL8 = (UCHAR) (lpCrtcTiming->usHorizontalSyncWidth & 0x00FF);
lpEdidDetailedTiming ->ucVSyncOffset_VSyncWidthL4 = (UCHAR)((usVSyncOffset & 0x0F00)>>4|
(lpCrtcTiming->usVerticalSyncWidth & 0x0F00)>>8);
lpEdidDetailedTiming ->ucHSyncOffset_HSyncWidth_VSyncOffset_VSyncWidth = (UCHAR)((usHSyncOffset & 0x0300) >>2|
(lpCrtcTiming->usHorizontalSyncWidth & 0x0300) >>4|
(usVSyncOffset & 0x0300) >>6|
(lpCrtcTiming->usVerticalSyncWidth & 0x0300) >>8);
lpEdidDetailedTiming ->ucHImageSize = 0;
lpEdidDetailedTiming ->ucVImageSize = 0;
lpEdidDetailedTiming ->ucHVImageSizeU4 = 0;
lpEdidDetailedTiming ->ucHBorder = (UCHAR)lpCrtcTiming->usHorizontalOverscanRight; //For overscan
lpEdidDetailedTiming ->ucVBorder = (UCHAR)lpCrtcTiming->usVerticalOverscanBottom;
if(lpCrtcTiming->usFlags &USE_DEFAULT_POLARITY)
{
if(lpCrtcTiming->usFlags & CRTC_H_SYNC_POLARITY)
{
lpEdidDetailedTiming ->ucFlags |= EDID_DETAILED_V1x_FLAG_BIT1;
}
if(lpCrtcTiming->usFlags & CRTC_V_SYNC_POLARITY )
{
lpEdidDetailedTiming ->ucFlags |= EDID_DETAILED_V1x_FLAG_BIT1;
}
lpEdidDetailedTiming ->ucFlags |= EDID_DETAILED_V1x_FLAG_BIT3|EDID_DETAILED_V1x_FLAG_BIT4; //Digital seperated.
}
if(lpCrtcTiming->usFlags & CRTC_INTERLACED)
{
lpEdidDetailedTiming ->ucFlags |= EDID_DETAILED_V1x_FLAG_INTERLACED;
}
DALDEBUG((DALDBG_ENTRY_EXIT, "vDALTimingToDetailedTiming - Entry"));
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -