|
|
//==========================================================================;
//
// ATIConfg.CPP
// WDM MiniDrivers development.
// ATIHwConfiguration class implementation.
// Copyright (c) 1996 - 1997 ATI Technologies Inc. All Rights Reserved.
//
// $Date: 10 Jun 1999 09:54:42 $
// $Revision: 1.21 $
// $Author: KLEBANOV $
//
//==========================================================================;
extern"C" { #include "conio.h"
#include "strmini.h"
#include "wdmdebug.h"
#include "ksmedia.h" //Paul
}
#include "aticonfg.h"
#include "wdmdrv.h"
#include "atigpio.h"
#include "mmconfig.h"
/*^^*
* CATIHwConfiguration() * Purpose : CATIHwConfiguration Class constructor * Determines I2CExpander address and all possible hardware IDs and addresses * * Inputs : PDEVICE_OBJECT pDeviceObject : pointer to the creator DeviceObject * CI2CScript * pCScript : pointer to the I2CScript class object * PUINT puiError : pointer to return Error code * * Outputs : none * Author : IKLEBANOV *^^*/ CATIHwConfiguration::CATIHwConfiguration( PPORT_CONFIGURATION_INFORMATION pConfigInfo, CI2CScript * pCScript, PUINT puiError) {
ENSURE { m_VideoInStandardsSupported = 0; m_CrystalIDInMMTable = 0xF; // invalid entry, needs to be set when set with the value from MMTable
m_gpioProviderInterface.gpioOpen = NULL; m_gpioProviderInterface.gpioAccess = NULL; m_pdoDriver = NULL; m_usE2PROMValidation = ( USHORT)-1;
if( InitializeAttachGPIOProvider( &m_gpioProviderInterface, pConfigInfo->PhysicalDeviceObject)) // there was no error to get GPIOInterface from the MiniVDD
m_pdoDriver = pConfigInfo->RealPhysicalDeviceObject; else { * puiError = WDMMINI_ERROR_NOGPIOPROVIDER; FAIL; }
if( !FindI2CExpanderAddress( pCScript)) { * puiError = WDMMINI_NOHARDWARE; FAIL; } if( !FindHardwareProperties( pConfigInfo->RealPhysicalDeviceObject, pCScript)) { * puiError = WDMMINI_NOHARDWARE; FAIL; }
* puiError = WDMMINI_NOERROR;
OutputDebugTrace(( "CATIHwConfig:CATIHwConfiguration() exit\n"));
} END_ENSURE;
if( * puiError != WDMMINI_NOERROR) OutputDebugError(( "CATIHwConfig:CATIHwConfiguration() uiError=%x\n", * puiError)); }
/*^^*
* FindHardwareProperties() * Purpose : Determines hardware properties : I2C address and the type * * Inputs : PDEVICEOBJECT pDeviceObject: pointer to device object * CI2CScript * pCScript : pointer to the I2CScript object * * Outputs : BOOL, TRUE if a valid ATI hardware Configuration was found * Author : IKLEBANOV *^^*/ BOOL CATIHwConfiguration::FindHardwareProperties( PDEVICE_OBJECT pDeviceObject, CI2CScript * pCScript) { UCHAR uchI2CValue; UCHAR uchORMask = 0x00; UCHAR uchANDMask = 0xFF; BOOL bResult = TRUE; I2CPacket i2cPacket;
m_VideoInStandardsSupported = 0; //Paul
m_uchTunerAddress = 0; m_usTunerId = 0; m_usTunerPowerConfiguration = ATI_TUNER_POWER_CONFIG_0;
m_uchDecoderAddress = 0; m_usDecoderId = VIDEODECODER_TYPE_NOTINSTALLED; m_usDecoderConfiguration = 0;
m_uchAudioAddress = 0; m_uiAudioConfiguration = 0;
switch( m_uchI2CExpanderAddress) { case 0x70: // a standard external tuner board
m_uchTunerAddress = 0xC0; m_uchDecoderAddress = 0x88; // we need to determine actual Decoder ID, implement later
m_usDecoderId = VIDEODECODER_TYPE_BT829;
if( GetI2CExpanderConfiguration( pCScript, &uchI2CValue)) { m_usTunerId = uchI2CValue & 0x0F;
m_usDecoderConfiguration = ATI_VIDEODECODER_CONFIG_1;
if( uchI2CValue & 0x10) { m_uiAudioConfiguration = ATI_AUDIO_CONFIG_4; m_uchAudioAddress = 0x82; } else m_uiAudioConfiguration = ATI_AUDIO_CONFIG_3; }
m_VideoInStandardsSupported = SetVidStdBasedOnI2CExpander( uchI2CValue ); //Paul
break;
case 0x78: // FM tuner
m_uchTunerAddress = 0xC0; m_uchDecoderAddress = 0x88; // we need to determine actual Decoder ID, implement later
m_usDecoderId = VIDEODECODER_TYPE_BT829;
if( GetI2CExpanderConfiguration( pCScript, &uchI2CValue)) { m_usTunerId = uchI2CValue & 0x0F;
m_usDecoderConfiguration = ATI_VIDEODECODER_CONFIG_1; m_uiAudioConfiguration = ATI_AUDIO_CONFIG_5; }
m_VideoInStandardsSupported = SetVidStdBasedOnI2CExpander( uchI2CValue ); //Paul
break;
case 0x76: // AllInWonder, configuration is in the BIOS
{ CATIMultimediaTable CMultimediaInfo( pDeviceObject, &m_gpioProviderInterface, &bResult);
if( bResult) { // tuner and decoder Info is included
m_uchTunerAddress = 0xC6; m_uchDecoderAddress = 0x8A; m_usDecoderConfiguration = ATI_VIDEODECODER_CONFIG_1; m_uiAudioConfiguration = ATI_AUDIO_CONFIG_1;
if( !CMultimediaInfo.GetTVTunerId( &m_usTunerId) || !CMultimediaInfo.GetVideoDecoderId( &m_usDecoderId)) bResult = FALSE; else m_VideoInStandardsSupported = SetVidStdBasedOnMMTable( &CMultimediaInfo ); //Paul
} break; }
case 0x7C: ENSURE { i2cPacket.uchChipAddress = m_uchI2CExpanderAddress; i2cPacket.cbReadCount = 1; i2cPacket.cbWriteCount = 0; i2cPacket.puchReadBuffer = &uchI2CValue; i2cPacket.puchWriteBuffer = NULL; i2cPacket.usFlags = 0; pCScript->ExecuteI2CPacket( &i2cPacket); if( i2cPacket.uchI2CResult != I2C_STATUS_NOERROR) { bResult = FALSE; FAIL; }
uchI2CValue |= 0x0F;
i2cPacket.uchChipAddress = m_uchI2CExpanderAddress; i2cPacket.cbReadCount = 0; i2cPacket.cbWriteCount = 1; i2cPacket.puchReadBuffer = NULL; i2cPacket.puchWriteBuffer = &uchI2CValue; i2cPacket.usFlags = 0; pCScript->ExecuteI2CPacket( &i2cPacket); if (i2cPacket.uchI2CResult != I2C_STATUS_NOERROR) { bResult = FALSE; FAIL; }
// information should be correct now
if( GetI2CExpanderConfiguration( pCScript, &uchI2CValue)) { m_usTunerId = uchI2CValue & 0x0F; }
m_VideoInStandardsSupported = SetVidStdBasedOnI2CExpander( uchI2CValue ); //Paul
} END_ENSURE;
if (!bResult) break; // For IO Expander address == 0x7c there might be more information in the BIOS Table sto do not return
// or break at this point
case 0xFF: // AllInWonder PRO, configuration is in the BIOS
ENSURE { CATIMultimediaTable CMultimediaInfo( pDeviceObject, &m_gpioProviderInterface, &bResult); USHORT nOEMId, nOEMRevision, nATIProductType; BOOL bATIProduct; if( !bResult) FAIL;
// OEM Id information is included
if( !CMultimediaInfo.IsATIProduct( &bATIProduct)) { bResult = FALSE; FAIL; }
m_uchDecoderAddress = 0x8A; m_uchTunerAddress = 0xC6;
if( bATIProduct) { if( !CMultimediaInfo.GetATIProductId( &nATIProductType)) { bResult = FALSE; FAIL; }
if( CMultimediaInfo.GetTVTunerId( &m_usTunerId) && CMultimediaInfo.GetVideoDecoderId( &m_usDecoderId)) { switch( nATIProductType) { case ATI_PRODUCT_TYPE_AIW_PRO_NODVD: case ATI_PRODUCT_TYPE_AIW_PRO_DVD: m_usDecoderConfiguration = ATI_VIDEODECODER_CONFIG_2; m_uiAudioConfiguration = ATI_AUDIO_CONFIG_2; m_usTunerPowerConfiguration = ATI_TUNER_POWER_CONFIG_1;
m_uchAudioAddress = 0xB4;
break;
case ATI_PRODUCT_TYPE_AIW_PLUS: m_uiAudioConfiguration = ATI_AUDIO_CONFIG_6; m_usDecoderConfiguration = ATI_VIDEODECODER_CONFIG_2;
m_uchAudioAddress = 0xB6; break;
case ATI_PRODUCT_TYPE_AIW_PRO_R128_KITCHENER: m_uiAudioConfiguration = ATI_AUDIO_CONFIG_7; m_usDecoderConfiguration = ATI_VIDEODECODER_CONFIG_2;
m_uchAudioAddress = 0xB4; break;
case ATI_PRODUCT_TYPE_AIW_PRO_R128_TORONTO: m_uiAudioConfiguration = ATI_AUDIO_CONFIG_8; m_usDecoderConfiguration = ATI_VIDEODECODER_CONFIG_UNDEFINED;
m_uchAudioAddress = 0x80; break;
default: bResult = FALSE; break; } } else bResult = FALSE; } else { // non ATI Product
if( !CMultimediaInfo.GetOEMId( &nOEMId) || !CMultimediaInfo.GetOEMRevisionId( &nOEMRevision)) { bResult = FALSE; FAIL; }
m_uchDecoderAddress = 0x8A; m_uchTunerAddress = 0xC6; switch( nOEMId) { case OEM_ID_INTEL: switch( nOEMRevision) { case INTEL_ANCHORAGE: if( CMultimediaInfo.GetVideoDecoderId( &m_usDecoderId) && CMultimediaInfo.GetTVTunerId( &m_usTunerId)) { m_uiAudioConfiguration = ATI_AUDIO_CONFIG_1; switch( m_usDecoderId) { case VIDEODECODER_TYPE_BT829: m_usDecoderConfiguration = ATI_VIDEODECODER_CONFIG_3; break;
case VIDEODECODER_TYPE_BT829A: m_usDecoderConfiguration = ATI_VIDEODECODER_CONFIG_2; break;
default: bResult = FALSE; break; } } else bResult = FALSE; break;
default: bResult = FALSE; break; } break;
case OEM_ID_APRICOT: switch( nOEMRevision) { case REVISION1: case REVISION2: if( CMultimediaInfo.GetTVTunerId( &m_usTunerId)) { switch( m_usDecoderId) { case VIDEODECODER_TYPE_BT829: m_usDecoderConfiguration = ATI_VIDEODECODER_CONFIG_4; break;
case VIDEODECODER_TYPE_BT829A: m_usDecoderConfiguration = ATI_VIDEODECODER_CONFIG_2; break; } } else bResult = FALSE; break;
default: bResult = FALSE; break; } break;
case OEM_ID_FUJITSU: m_uchDecoderAddress = 0x88; switch( nOEMRevision) { case REVISION1: if( CMultimediaInfo.GetVideoDecoderId( &m_usDecoderId)) { switch( m_usDecoderId) { case VIDEODECODER_TYPE_BT829A: m_usDecoderConfiguration = ATI_VIDEODECODER_CONFIG_2; break;
default: bResult = FALSE; break; } } else bResult = FALSE; break;
default: bResult = FALSE; break; } break;
case OEM_ID_COMPAQ: switch( nOEMRevision) { case REVISION1: if( CMultimediaInfo.GetVideoDecoderId( &m_usDecoderId)) { switch( m_usDecoderId) { case VIDEODECODER_TYPE_BT829: m_usDecoderConfiguration = ATI_VIDEODECODER_CONFIG_3; break;
case VIDEODECODER_TYPE_BT829A: m_usDecoderConfiguration = ATI_VIDEODECODER_CONFIG_2; break;
default: bResult = FALSE; break; } } else bResult = FALSE; break;
default: bResult = FALSE; break; } break;
case OEM_ID_BCM: case OEM_ID_SAMSUNG: switch( nOEMRevision) { case REVISION0: if( CMultimediaInfo.GetVideoDecoderId( &m_usDecoderId)) { switch( m_usDecoderId) { case VIDEODECODER_TYPE_BT829A: m_usDecoderConfiguration = ATI_VIDEODECODER_CONFIG_2; break;
default: bResult = FALSE; } } else bResult = FALSE; break;
default: bResult = FALSE; break; } break;
case OEM_ID_SAMREX: switch( nOEMRevision) { case REVISION0: if( CMultimediaInfo.GetVideoDecoderId( &m_usDecoderId)) { switch( m_usDecoderId) { case VIDEODECODER_TYPE_BT829A: m_usDecoderConfiguration = ATI_VIDEODECODER_CONFIG_2; break;
default: bResult = FALSE; break; } } else bResult = FALSE; break;
default: bResult = FALSE; break; } break;
case OEM_ID_NEC: switch( nOEMRevision) { case REVISION0: case REVISION1: if( CMultimediaInfo.GetVideoDecoderId( &m_usDecoderId)) { switch( m_usDecoderId) { case VIDEODECODER_TYPE_BT829A: m_usDecoderConfiguration = ATI_VIDEODECODER_CONFIG_2; break;
default: bResult = FALSE; break; } } else bResult = FALSE; break;
default: bResult = FALSE; break; } break;
default: if( CMultimediaInfo.GetVideoDecoderId( &m_usDecoderId)) { if( m_usDecoderId == VIDEODECODER_TYPE_RTHEATER) { // default the configuration to Toronto board
m_uiAudioConfiguration = ATI_AUDIO_CONFIG_8; m_usDecoderConfiguration = ATI_VIDEODECODER_CONFIG_UNDEFINED;
m_uchAudioAddress = 0x80; } else { // default the configuration to Kitchener board
m_uiAudioConfiguration = ATI_AUDIO_CONFIG_7; m_usDecoderConfiguration = ATI_VIDEODECODER_CONFIG_2;
m_uchAudioAddress = 0xB4; }
bResult = TRUE; } else bResult = FALSE;
break; } }
m_VideoInStandardsSupported = SetVidStdBasedOnMMTable( &CMultimediaInfo ); //Paul
} END_ENSURE;
break; } OutputDebugInfo(( "CATIHwConfig:FindHardwareConfiguration() found:\n")); OutputDebugInfo(( "Tuner: Id = %d, I2CAddress = 0x%x\n", m_usTunerId, m_uchTunerAddress)); OutputDebugInfo(( "Decoder: Id = %d, I2CAddress = 0x%x, Configuration = %d\n", m_usDecoderId, m_uchDecoderAddress, m_usDecoderConfiguration)); OutputDebugInfo(( "Audio: I2CAddress = 0x%x, Configuration = %d\n", m_uchAudioAddress, m_uiAudioConfiguration));
return( bResult); }
/*^^*
* GetTunerConfiguration() * Purpose : Gets tuner Id and i2C address * Inputs : PUINT puiTunerId : pointer to return tuner Id * PUCHAR puchTunerAddress : pointer to return tuner I2C address * * Outputs : BOOL : returns TRUE * also sets the requested values into the input pointers * Author : IKLEBANOV *^^*/ BOOL CATIHwConfiguration::GetTunerConfiguration( PUINT puiTunerId, PUCHAR puchTunerAddress) {
if(( puiTunerId != NULL) && ( puchTunerAddress != NULL)) { * puiTunerId = ( UINT)m_usTunerId; * puchTunerAddress = m_uchTunerAddress;
return( TRUE); } else return( FALSE); }
/*^^*
* GetDecoderConfiguration() * Purpose : Gets decoder Id and i2C address * * Inputs : puiDecoderId : pointer to return Decoder Id * * Outputs : BOOL : returns TRUE * also sets the requested values into the input pointer * Author : IKLEBANOV *^^*/ BOOL CATIHwConfiguration::GetDecoderConfiguration( PUINT puiDecoderId, PUCHAR puchDecoderAddress) {
if(( puiDecoderId != NULL) && ( puchDecoderAddress != NULL)) { * puiDecoderId = ( UINT)m_usDecoderId; * puchDecoderAddress = m_uchDecoderAddress;
return( TRUE); } else return( FALSE); }
/*^^*
* GetAudioConfiguration() * Purpose : Gets Audio solution Id and i2C address * * Inputs : PUINT puiAudioConfiguration : pointer to return Audio configuration Id * PUCHAR puchAudioAddress : pointer to return audio hardware * I2C address * * Outputs : BOOL : returns TRUE * also sets the requested values into the input pointer * Author : IKLEBANOV *^^*/ BOOL CATIHwConfiguration::GetAudioConfiguration( PUINT puiAudioConfiguration, PUCHAR puchAudioAddress) {
if(( puiAudioConfiguration != NULL) && ( puchAudioAddress != NULL)) { * puiAudioConfiguration = ( UINT)m_uiAudioConfiguration; * puchAudioAddress = m_uchAudioAddress;
return( TRUE); } else return( FALSE); }
/*^^*
* InitializeAudioConfiguration() * Purpose : Initializes Audio Chip with default / power up values. This function will * be called at Low priority with i2CProvider locked * * Inputs : CI2CScript * pCScript : pointer to the I2CScript object * UINT uiAudioConfigurationId : detected Audio configuration * UCHAR uchAudioChipAddress : detected Audio chip I2C address * Outputs : none * Author : IKLEBANOV *^^*/ BOOL CATIHwConfiguration::InitializeAudioConfiguration( CI2CScript * pCScript, UINT uiAudioConfigurationId, UCHAR uchAudioChipAddress) { I2CPacket i2cPacket; UCHAR uchWrite16Value[5]; #ifdef I2S_CAPTURE
UCHAR uchRead16Value[5]; #endif // I2S_CAPTURE
BOOL bResult;
switch( uiAudioConfigurationId) { case ATI_AUDIO_CONFIG_2: case ATI_AUDIO_CONFIG_7: // TDA9850 has to be initialized with the values from I2C EEPROM, if
// those answers the CheckSum. If not, take hardcoded default values
{ UINT nIndex, nNumberOfRegs; PUCHAR puchInitializationBuffer = NULL; UCHAR uchWriteBuffer[2]; bResult = FALSE;
nNumberOfRegs = AUDIO_TDA9850_Reg_Align3 - AUDIO_TDA9850_Reg_Control1 + 1;
puchInitializationBuffer = ( PUCHAR) \ ::ExAllocatePool( NonPagedPool, nNumberOfRegs * sizeof( PUCHAR));
if( puchInitializationBuffer == NULL) return( bResult);
// fill in the Initialization buffer with the defaults values
puchInitializationBuffer[0] = AUDIO_TDA9850_Control1_DefaultValue; puchInitializationBuffer[1] = AUDIO_TDA9850_Control2_DefaultValue; puchInitializationBuffer[2] = AUDIO_TDA9850_Control3_DefaultValue; puchInitializationBuffer[3] = AUDIO_TDA9850_Control4_DefaultValue; puchInitializationBuffer[4] = AUDIO_TDA9850_Align1_DefaultValue; puchInitializationBuffer[5] = AUDIO_TDA9850_Align2_DefaultValue; puchInitializationBuffer[6] = AUDIO_TDA9850_Align3_DefaultValue;
// we have to see if anything in I2C EEPROM is waiting for us to
// overwrite the default values
if( ValidateConfigurationE2PROM( pCScript)) { // The configuration E2PROM kept its integrity. Let's read the
// initialization values from the device
ReadConfigurationE2PROM( pCScript, 3, &puchInitializationBuffer[4]); ReadConfigurationE2PROM( pCScript, 4, &puchInitializationBuffer[5]); }
// write the power-up defaults values into the chip
i2cPacket.uchChipAddress = uchAudioChipAddress; i2cPacket.cbReadCount = 0; i2cPacket.cbWriteCount = 2; i2cPacket.puchReadBuffer = NULL; i2cPacket.puchWriteBuffer = uchWriteBuffer; i2cPacket.usFlags = I2COPERATION_WRITE;
for( nIndex = 0; nIndex < nNumberOfRegs; nIndex ++) { uchWriteBuffer[0] = AUDIO_TDA9850_Reg_Control1 + nIndex; uchWriteBuffer[1] = puchInitializationBuffer[nIndex]; if( !( bResult = pCScript->ExecuteI2CPacket( &i2cPacket))) break; }
if( puchInitializationBuffer != NULL) ::ExFreePool( puchInitializationBuffer);
return( bResult); } break;
case ATI_AUDIO_CONFIG_4: // TDA8425 volume control should be initialized
return( SetDefaultVolumeControl( pCScript)); break;
case ATI_AUDIO_CONFIG_6: { UCHAR uchWriteBuffer;
// write the power-up defaults values into the chip
i2cPacket.uchChipAddress = uchAudioChipAddress; i2cPacket.cbReadCount = 0; i2cPacket.cbWriteCount = 1; i2cPacket.puchReadBuffer = NULL; i2cPacket.puchWriteBuffer = &uchWriteBuffer; i2cPacket.usFlags = I2COPERATION_WRITE; uchWriteBuffer = AUDIO_TDA9851_DefaultValue;
return( pCScript->ExecuteI2CPacket( &i2cPacket)); } break;
case ATI_AUDIO_CONFIG_8: //Reset MSP3430
i2cPacket.uchChipAddress = m_uchAudioAddress; i2cPacket.cbReadCount = 0; i2cPacket.usFlags = I2COPERATION_WRITE; i2cPacket.puchWriteBuffer = uchWrite16Value;
//Write 0x80 - 00 to Subaddr 0x00
i2cPacket.cbWriteCount = 3; uchWrite16Value[0] = 0x00; uchWrite16Value[1] = 0x80; uchWrite16Value[2] = 0x00;
bResult = pCScript->PerformI2CPacketOperation( &i2cPacket); if(bResult) { if( i2cPacket.uchI2CResult != I2CSCRIPT_NOERROR) return(FALSE); } else return(FALSE);
//Write 0x00 - 00 to Subaddr 0x00
i2cPacket.cbWriteCount = 3; uchWrite16Value[0] = 0x00; uchWrite16Value[1] = 0x00; uchWrite16Value[2] = 0x00;
bResult = pCScript->PerformI2CPacketOperation( &i2cPacket); if(bResult) { if( i2cPacket.uchI2CResult != I2CSCRIPT_NOERROR) return(FALSE); } else return(FALSE);
//SubAddr 0x12 Reg 0x13 Val 0x3f60
i2cPacket.cbWriteCount = 5; uchWrite16Value[0] = 0x12; uchWrite16Value[1] = 0x00; uchWrite16Value[2] = 0x13; uchWrite16Value[3] = 0x3f; uchWrite16Value[4] = 0x60;
bResult = pCScript->PerformI2CPacketOperation( &i2cPacket); if(bResult) { if( i2cPacket.uchI2CResult != I2CSCRIPT_NOERROR) return(FALSE); } else return(FALSE);
//SubAddr 0x12 Reg 0x00 Val 0x0000
i2cPacket.cbWriteCount = 5; uchWrite16Value[0] = 0x12; uchWrite16Value[1] = 0x00; uchWrite16Value[2] = 0x00; uchWrite16Value[3] = 0x00; uchWrite16Value[4] = 0x00;
bResult = pCScript->PerformI2CPacketOperation( &i2cPacket); if(bResult) { if( i2cPacket.uchI2CResult != I2CSCRIPT_NOERROR) return(FALSE); } else return(FALSE); #ifdef I2S_CAPTURE
#pragma message ("\n!!! PAY ATTENTION: Driver has been build with ITT CHIP I2S CAPTURE CONFIGURED !!!\n")
i2cPacket.uchChipAddress = m_uchAudioAddress; i2cPacket.usFlags = I2COPERATION_WRITE; i2cPacket.puchWriteBuffer = uchWrite16Value; i2cPacket.puchReadBuffer = uchRead16Value;
//Setup I2S Source Select and Output Channel Matrix
//SubAddr 0x12 Reg 0x0b Val 0x0320
i2cPacket.cbWriteCount = 5; i2cPacket.cbReadCount = 0; uchWrite16Value[0] = 0x12; uchWrite16Value[1] = 0x00; uchWrite16Value[2] = 0x0b; uchWrite16Value[3] = 0x03; uchWrite16Value[4] = 0x20;
bResult = pCScript->PerformI2CPacketOperation( &i2cPacket); if(bResult) { if( i2cPacket.uchI2CResult != I2CSCRIPT_NOERROR) return(FALSE); } else return(FALSE);
//Setup MODUS
i2cPacket.cbWriteCount = 5; i2cPacket.cbReadCount = 0; uchWrite16Value[0] = 0x10; uchWrite16Value[1] = 0x00; uchWrite16Value[2] = 0x30; uchWrite16Value[3] = 0x20; uchWrite16Value[4] = 0xe3;
bResult = pCScript->PerformI2CPacketOperation( &i2cPacket); if(bResult) { if( i2cPacket.uchI2CResult != I2CSCRIPT_NOERROR) return(FALSE); } else return(FALSE);
#endif // I2S_CAPTURE
break;
default: break; }
return( TRUE); }
/*^^*
* GetTVAudioSignalProperties() * Purpose : Gets Audio signal properties readable from ATI dependand hardware, * like I2C expander. This call is always synchronous. * * Inputs : CI2CScript * pCScript : pointer to the I2CScript object * PBOOL pbStereo : pointer to the Stereo Indicator * PBOOL pbSAP : pointer to the SAP Indicator * * Outputs : BOOL, returns TRUE, if successful * Author : IKLEBANOV *^^*/ BOOL CATIHwConfiguration::GetTVAudioSignalProperties( CI2CScript * pCScript, PBOOL pbStereo, PBOOL pbSAP) { I2CPacket i2cPacket; UCHAR uchReadValue, uchWriteValue; BOOL bResult;
switch( m_uiAudioConfiguration) { case ATI_AUDIO_CONFIG_1: case ATI_AUDIO_CONFIG_5: // Stereo property is read back from I2C expander
i2cPacket.uchChipAddress = m_uchI2CExpanderAddress; i2cPacket.cbReadCount = 1; i2cPacket.cbWriteCount = 1; i2cPacket.puchReadBuffer = &uchReadValue; i2cPacket.puchWriteBuffer = &uchWriteValue; i2cPacket.usFlags = I2COPERATION_READWRITE; i2cPacket.uchORValue = 0x40; i2cPacket.uchANDValue = 0xFF;
bResult = FALSE;
ENSURE { if( !pCScript->LockI2CProviderEx()) FAIL;
pCScript->ExecuteI2CPacket( &i2cPacket); if( !( bResult = ( i2cPacket.uchI2CResult == I2C_STATUS_NOERROR))) FAIL;
i2cPacket.puchWriteBuffer = NULL; i2cPacket.usFlags = I2COPERATION_READ;
pCScript->ExecuteI2CPacket( &i2cPacket); if( !( bResult = ( i2cPacket.uchI2CResult == I2C_STATUS_NOERROR))) FAIL;
* pbStereo = uchReadValue & 0x40;
bResult = TRUE;
} END_ENSURE;
pCScript->ReleaseI2CProvider();
break;
default: bResult = FALSE; break; }
if( bResult) // no case, where SAP property is read back from ATI's hardware
* pbSAP = FALSE;
return( bResult); }
/*^^*
* GetDecoderOutputEnableLevel() * Purpose : Retrieves ATI dependent hardware configuration property of the logical level * should be applied on OUTEN field of Bt829x decoder in order to enable * output stream * * Inputs : none * * Outputs : UINT, * UINT( -1) value is returned if an error occures * Author : IKLEBANOV *^^*/ UINT CATIHwConfiguration::GetDecoderOutputEnableLevel( void) { UINT uiEnableLevel;
switch( m_usDecoderConfiguration) { case ATI_VIDEODECODER_CONFIG_1: case ATI_VIDEODECODER_CONFIG_3: case ATI_VIDEODECODER_CONFIG_4: uiEnableLevel = 0; break;
case ATI_VIDEODECODER_CONFIG_2: uiEnableLevel = 1; break;
default: uiEnableLevel = UINT( -1); break; }
return( uiEnableLevel); }
/*^^*
* EnableDecoderI2CAccess() * Purpose : Enables/disables I2C access to the decoder chip * * Inputs : CI2CScript * pCScript : pointer to the I2CScript object * BOOL bEnable : defines what to do - enable/disable the decoder's outputs * * Outputs : none * Author : IKLEBANOV *^^*/ void CATIHwConfiguration::EnableDecoderI2CAccess( CI2CScript * pCScript, BOOL bEnable) { UCHAR uchORMask = 0; UCHAR uchANDMask = 0xFF; UCHAR uchReadValue, uchWriteValue; I2CPacket i2cPacket;
switch( m_usDecoderConfiguration) { case ATI_VIDEODECODER_CONFIG_1: // Add-On TV Tuner board - ATI TV requires certain actions to be taken
i2cPacket.uchChipAddress = m_uchI2CExpanderAddress; i2cPacket.cbReadCount = 1; i2cPacket.cbWriteCount = 1; if( bEnable) uchANDMask &= 0x7F; else uchORMask |= 0x80;
i2cPacket.puchReadBuffer = &uchReadValue; i2cPacket.puchWriteBuffer = &uchWriteValue; i2cPacket.usFlags = I2COPERATION_READWRITE; i2cPacket.uchORValue = uchORMask; i2cPacket.uchANDValue = uchANDMask;
pCScript->PerformI2CPacketOperation( &i2cPacket);
break;
#ifdef _X86_
case ATI_VIDEODECODER_CONFIG_3: _outp( 0x7D, ( _inp( 0x7D) | 0x80)); if( bEnable) _outp( 0x7C, ( _inp( 0x7C) & 0x7F)); else _outp( 0x7C, ( _inp( 0x7C) | 0x80)); return;
case ATI_VIDEODECODER_CONFIG_4: if( bEnable) _outp( 0x78, ( _inp( 0x78) & 0xF7)); else _outp( 0x78, ( _inp( 0x78) | 0x08)); return; #endif
default: break; } }
/*^^*
* GetI2CExpanderConfiguration() * Purpose : Gets board configuration via I2C expander * Reads the configuration registers back * Inputs : CI2CScript * pCScript : pointer to CI2CScript object * PUCHAR puchI2CValue : pointer to read the I2C value into * * Outputs : BOOL : returns TRUE * also sets the requested values into the input pointers * Author : IKLEBANOV *^^*/ BOOL CATIHwConfiguration::GetI2CExpanderConfiguration( CI2CScript * pCScript, PUCHAR puchI2CValue) { I2CPacket i2cPacket;
if( puchI2CValue == NULL) return( FALSE);
i2cPacket.uchChipAddress = m_uchI2CExpanderAddress; i2cPacket.cbReadCount = 1; i2cPacket.cbWriteCount = 0; i2cPacket.puchReadBuffer = puchI2CValue; i2cPacket.puchWriteBuffer = NULL; i2cPacket.usFlags = 0;
pCScript->ExecuteI2CPacket( &i2cPacket);
return(( i2cPacket.uchI2CResult == I2C_STATUS_NOERROR) ? TRUE : FALSE); }
/*^^*
* FindI2CExpanderAddress() * Purpose : Determines I2C expander address. * * Inputs : CI2CScript * pCScript : pointer to the I2CScript class object * * Outputs : BOOL : returns TRUE, if no I2C access error; * also sets m_uchI2CExpanderAddress class member. If any was not found, set it as 0xFF * Author : IKLEBANOV *^^*/ BOOL CATIHwConfiguration::FindI2CExpanderAddress( CI2CScript * pCScript) { USHORT nIndex; UCHAR uchI2CValue; I2CPacket i2cPacket; // table of the possible I2C expender addresses
UCHAR auchI2CExpenderAddress[] = { 0x70, 0x78, 0x7c, 0x76};
// unknown I2C expender address
m_uchI2CExpanderAddress = 0xFF; for( nIndex = 0; nIndex < sizeof( auchI2CExpenderAddress); nIndex ++) { i2cPacket.uchChipAddress = auchI2CExpenderAddress[nIndex]; i2cPacket.cbReadCount = 1; i2cPacket.cbWriteCount = 0; i2cPacket.puchReadBuffer = &uchI2CValue; i2cPacket.puchWriteBuffer = NULL; i2cPacket.usFlags = 0;
pCScript->ExecuteI2CPacket( &i2cPacket); if( i2cPacket.uchI2CResult == I2C_STATUS_NOERROR) { m_uchI2CExpanderAddress = auchI2CExpenderAddress[nIndex]; break; } }
OutputDebugInfo(( "CATIHwConfig:FindI2CExpanderAddress() exit address = %x\n", m_uchI2CExpanderAddress));
return( TRUE); }
/*^^*
* GetAudioProperties() * Purpose : Gets numbers of Audio inputs and outputs * Inputs : PULONG pulNumberOfInputs : pointer to return number of Audio inputs * PULONG pulNumberOfOutputs : pointer to return number of Audio outputs * * Outputs : BOOL : returns TRUE * also sets the requested values into the input pointers * Author : IKLEBANOV *^^*/ BOOL CATIHwConfiguration::GetAudioProperties( PULONG pulNumberOfInputs, PULONG pulNumberOfOutputs) {
if(( pulNumberOfInputs != NULL) && ( pulNumberOfOutputs != NULL)) { // Hardcoded for AIW with no FM support - FM stuff has not been defined by Microsoft yet
* pulNumberOfInputs = 2; * pulNumberOfOutputs = 1;
return( TRUE); } else return( FALSE); }
/*^^*
* CanConnectAudioSource() * Purpose : Determines possibility to connect the specified Audio source to the audio output. * * Inputs : int nAudioSource : the audio source the function is asked about * * Outputs : BOOL : returns TRUE, the connection is possible; * Author : IKLEBANOV *^^*/ BOOL CATIHwConfiguration::CanConnectAudioSource( int nAudioSource) { BOOL bResult;
if( nAudioSource != AUDIOSOURCE_MUTE) bResult = nAudioSource < AUDIOSOURCE_LASTSUPPORTED; else switch( m_uiAudioConfiguration) { case ATI_AUDIO_CONFIG_1: case ATI_AUDIO_CONFIG_2: case ATI_AUDIO_CONFIG_4: case ATI_AUDIO_CONFIG_5: case ATI_AUDIO_CONFIG_6: case ATI_AUDIO_CONFIG_7: case ATI_AUDIO_CONFIG_8: bResult = TRUE; break;
case ATI_AUDIO_CONFIG_3: default: bResult = FALSE; break; }
return( bResult); }
/*^^*
* SetDefaultVolumeControl() * Purpose : Set the default volume level, if the hardware support volume control * * Inputs : CI2CScript * pCScript : pointer to I2CScript class object * * Outputs : BOOL : returns FALSE, if either unknown audio source or I2C access error; * Author : IKLEBANOV *^^*/ BOOL CATIHwConfiguration::SetDefaultVolumeControl( CI2CScript * pCScript) { BOOL bResult; I2CPacket i2cPacket; UCHAR uchWriteBuffer[3];
switch( m_uiAudioConfiguration) { case ATI_AUDIO_CONFIG_4:
ENSURE { i2cPacket.uchChipAddress = m_uchAudioAddress; i2cPacket.cbReadCount = 0; i2cPacket.cbWriteCount = 3; i2cPacket.puchReadBuffer = NULL; i2cPacket.puchWriteBuffer = uchWriteBuffer; i2cPacket.usFlags = I2COPERATION_WRITE;
uchWriteBuffer[0] = 0x00; // volume left + right
uchWriteBuffer[1] = 0xFA; uchWriteBuffer[2] = 0xFA;
bResult = pCScript->PerformI2CPacketOperation( &i2cPacket);
} END_ENSURE;
break;
default: bResult = TRUE; break; }
return( bResult); }
/*^^*
* ConnectAudioSource() * Purpose : Connects the specified Audio input to the Audio output. * * Inputs : CI2CScript * pCScript : pointer to I2CScript class object * int nAudioSource : the audio source to be connected to the audio output * * Outputs : BOOL : returns FALSE, if either unknown audio source or I2C access error; * Author : IKLEBANOV *^^*/ BOOL CATIHwConfiguration::ConnectAudioSource( CI2CScript * pCScript, int nAudioSource) { UCHAR uchORMask = 0; UCHAR uchANDMask = 0xFF; UCHAR uchReadValue, uchWriteValue[2]; UCHAR uchWrite16Value[5]; I2CPacket i2cPacket; BOOL bI2CAccess, bResult; GPIOControl gpioAccessBlock; UCHAR uchI2CAddr; USHORT cbWRCount; USHORT cbRDCount; USHORT usI2CMode;
switch( m_uiAudioConfiguration) { case ATI_AUDIO_CONFIG_1: bI2CAccess = TRUE; uchI2CAddr = m_uchI2CExpanderAddress; cbWRCount = 1; cbRDCount = 1; usI2CMode = I2COPERATION_READWRITE;
uchANDMask &= 0xAF; switch( nAudioSource) { case AUDIOSOURCE_MUTE: uchORMask |= 0x00; break; case AUDIOSOURCE_TVAUDIO: uchORMask |= 0x10; break; case AUDIOSOURCE_LINEIN: uchORMask |= 0x50; break; case AUDIOSOURCE_FMAUDIO: // no FM is supported
default: return( FALSE); } break;
case ATI_AUDIO_CONFIG_2: bI2CAccess = FALSE; uchANDMask &= 0xFC; switch( nAudioSource) { case AUDIOSOURCE_MUTE: uchORMask |= 0x02; break; case AUDIOSOURCE_TVAUDIO: uchORMask |= 0x01; break; case AUDIOSOURCE_LINEIN: uchORMask |= 0x00; break; case AUDIOSOURCE_FMAUDIO: uchORMask |= 0x03;
default: return( FALSE); } break;
case ATI_AUDIO_CONFIG_3: bI2CAccess = TRUE; uchI2CAddr = m_uchI2CExpanderAddress; cbWRCount = 1; cbRDCount = 1; usI2CMode = I2COPERATION_READWRITE;
uchANDMask &= 0xDF; switch( nAudioSource) { case AUDIOSOURCE_TVAUDIO: uchORMask |= 0x00; break; case AUDIOSOURCE_LINEIN: uchORMask |= 0x40; break; case AUDIOSOURCE_FMAUDIO: // no FM is supported
case AUDIOSOURCE_MUTE: // no mute is supported
default: return( FALSE); } break;
case ATI_AUDIO_CONFIG_4: bI2CAccess = TRUE; uchI2CAddr = m_uchAudioAddress; cbWRCount = 2; cbRDCount = 0; usI2CMode = I2COPERATION_WRITE;
uchWriteValue[0] = 0x08; switch( nAudioSource) { case AUDIOSOURCE_MUTE: uchWriteValue[1] = 0xF7; break;
case AUDIOSOURCE_TVAUDIO: SetDefaultVolumeControl( pCScript); uchWriteValue[1] = 0xD7; break; case AUDIOSOURCE_LINEIN: SetDefaultVolumeControl( pCScript); uchWriteValue[1] = 0xCE; break; case AUDIOSOURCE_FMAUDIO: // no FM is supported
default: return( FALSE); } break;
case ATI_AUDIO_CONFIG_5: bI2CAccess = TRUE; uchI2CAddr = m_uchI2CExpanderAddress; cbWRCount = 1; cbRDCount = 1; usI2CMode = I2COPERATION_READWRITE;
uchANDMask &= 0xAF; switch( nAudioSource) { case AUDIOSOURCE_MUTE: uchORMask |= 0x50; break; case AUDIOSOURCE_TVAUDIO: uchORMask |= 0x00; break; case AUDIOSOURCE_LINEIN: uchORMask |= 0x40; break; case AUDIOSOURCE_FMAUDIO: uchORMask |= 0x10;
default: return( FALSE); } break;
case ATI_AUDIO_CONFIG_6: case ATI_AUDIO_CONFIG_7: bI2CAccess = TRUE; uchI2CAddr = m_uchDecoderAddress; cbWRCount = 2; cbRDCount = 1; usI2CMode = I2COPERATION_READWRITE; uchWriteValue[0] = 0x3F;
uchANDMask &= 0xFC; switch( nAudioSource) { case AUDIOSOURCE_MUTE: uchORMask |= 0x02; break; case AUDIOSOURCE_TVAUDIO: uchORMask |= 0x01; break; case AUDIOSOURCE_LINEIN: uchORMask |= 0x00; break; case AUDIOSOURCE_FMAUDIO: uchORMask |= 0x03;
default: return( FALSE); } break;
case ATI_AUDIO_CONFIG_8:
switch( nAudioSource) {
case AUDIOSOURCE_MUTE:
i2cPacket.uchChipAddress = m_uchAudioAddress; i2cPacket.cbReadCount = 0; i2cPacket.cbWriteCount = 5; i2cPacket.usFlags = I2COPERATION_WRITE; i2cPacket.puchWriteBuffer = uchWrite16Value;
//SubAddr 0x12 Reg 0x13 Val 0x3f60
uchWrite16Value[0] = 0x12; uchWrite16Value[1] = 0x00; uchWrite16Value[2] = 0x13; uchWrite16Value[3] = 0x3f; uchWrite16Value[4] = 0x60;
bResult = pCScript->PerformI2CPacketOperation( &i2cPacket); if(bResult) { if( i2cPacket.uchI2CResult != I2CSCRIPT_NOERROR) return(FALSE); } else return(FALSE);
//SubAddr 0x12 Reg 0xD Val 0x0000
uchWrite16Value[0] = 0x12; uchWrite16Value[1] = 0x00; uchWrite16Value[2] = 0x0d; uchWrite16Value[3] = 0x00; uchWrite16Value[4] = 0x00;
bResult = pCScript->PerformI2CPacketOperation( &i2cPacket); if(bResult) { if( i2cPacket.uchI2CResult != I2CSCRIPT_NOERROR) return(FALSE); } else return(FALSE);
//SubAddr 0x12 Reg 0x8 Val 0x0220
uchWrite16Value[0] = 0x12; uchWrite16Value[1] = 0x00; uchWrite16Value[2] = 0x08; uchWrite16Value[3] = 0x02; uchWrite16Value[4] = 0x20;
bResult = pCScript->PerformI2CPacketOperation( &i2cPacket); if(bResult) { if( i2cPacket.uchI2CResult != I2CSCRIPT_NOERROR) return(FALSE); } else return(FALSE);
//SubAddr 0x12 Reg 0x00 Val 0x0000
uchWrite16Value[0] = 0x12; uchWrite16Value[1] = 0x00; uchWrite16Value[2] = 0x00; uchWrite16Value[3] = 0x00; uchWrite16Value[4] = 0x00;
bResult = pCScript->PerformI2CPacketOperation( &i2cPacket); if(bResult) { if( i2cPacket.uchI2CResult != I2CSCRIPT_NOERROR) return(FALSE); } else return(FALSE);
break;
case AUDIOSOURCE_LINEIN:
i2cPacket.uchChipAddress = m_uchAudioAddress; i2cPacket.cbReadCount = 0; i2cPacket.cbWriteCount = 5; i2cPacket.usFlags = I2COPERATION_WRITE; i2cPacket.puchWriteBuffer = uchWrite16Value;
//SubAddr 0x10 Reg 0x30 Val 0x0000
uchWrite16Value[0] = 0x10; uchWrite16Value[1] = 0x00; uchWrite16Value[2] = 0x30; uchWrite16Value[3] = 0x00; #ifdef I2S_CAPTURE
#pragma message ("\n!!! PAY ATTENTION: Driver has been build with ITT CHIP I2S CAPTURE CONFIGURED !!!\n")
uchWrite16Value[4] = 0xe0; #else
uchWrite16Value[4] = 0x00; #endif
bResult = pCScript->PerformI2CPacketOperation( &i2cPacket); if(bResult) { if( i2cPacket.uchI2CResult != I2CSCRIPT_NOERROR) return(FALSE); } else return(FALSE);
//SubAddr 0x10 Reg 0x20 Val 0x0000
uchWrite16Value[0] = 0x10; uchWrite16Value[1] = 0x00; uchWrite16Value[2] = 0x20; uchWrite16Value[3] = 0x00; uchWrite16Value[4] = 0x00;
bResult = pCScript->PerformI2CPacketOperation( &i2cPacket); if(bResult) { if( i2cPacket.uchI2CResult != I2CSCRIPT_NOERROR) return(FALSE); } else return(FALSE);
//SubAddr 0x12 Reg 0xe Val 0x0000
uchWrite16Value[0] = 0x12; uchWrite16Value[1] = 0x00; uchWrite16Value[2] = 0x0e; uchWrite16Value[3] = 0x00; uchWrite16Value[4] = 0x00;
bResult = pCScript->PerformI2CPacketOperation( &i2cPacket); if(bResult) { if( i2cPacket.uchI2CResult != I2CSCRIPT_NOERROR) return(FALSE); } else return(FALSE);
//SubAddr 0x12 Reg 0x13 Val 0x3c40
uchWrite16Value[0] = 0x12; uchWrite16Value[1] = 0x00; uchWrite16Value[2] = 0x13; uchWrite16Value[3] = 0x3c; uchWrite16Value[4] = 0x40;
bResult = pCScript->PerformI2CPacketOperation( &i2cPacket); if(bResult) { if( i2cPacket.uchI2CResult != I2CSCRIPT_NOERROR) return(FALSE); } else return(FALSE);
//SubAddr 0x12 Reg 0x8 Val 0x3c40
uchWrite16Value[0] = 0x12; uchWrite16Value[1] = 0x00; uchWrite16Value[2] = 0x08; uchWrite16Value[3] = 0x02; uchWrite16Value[4] = 0x20;
bResult = pCScript->PerformI2CPacketOperation( &i2cPacket); if(bResult) { if( i2cPacket.uchI2CResult != I2CSCRIPT_NOERROR) return(FALSE); } else return(FALSE);
//SubAddr 0x12 Reg 0xd Val 0x1900
uchWrite16Value[0] = 0x12; uchWrite16Value[1] = 0x00; uchWrite16Value[2] = 0x0d; uchWrite16Value[3] = 0x19; uchWrite16Value[4] = 0x00;
bResult = pCScript->PerformI2CPacketOperation( &i2cPacket); if(bResult) { if( i2cPacket.uchI2CResult != I2CSCRIPT_NOERROR) return(FALSE); } else return(FALSE);
//SubAddr 0x12 Reg 0x00 Val 0x7300
uchWrite16Value[0] = 0x12; uchWrite16Value[1] = 0x00; uchWrite16Value[2] = 0x00; uchWrite16Value[3] = 0x73; uchWrite16Value[4] = 0x00;
bResult = pCScript->PerformI2CPacketOperation( &i2cPacket); if(bResult) { if( i2cPacket.uchI2CResult != I2CSCRIPT_NOERROR) return(FALSE); } else return(FALSE);
break;
case AUDIOSOURCE_TVAUDIO: i2cPacket.uchChipAddress = m_uchAudioAddress; i2cPacket.cbReadCount = 0; i2cPacket.cbWriteCount = 5; i2cPacket.usFlags = I2COPERATION_WRITE; i2cPacket.puchWriteBuffer = uchWrite16Value;
//SubAddr 0x12 Reg 0x13 Val 0x3f60
uchWrite16Value[0] = 0x12; uchWrite16Value[1] = 0x00; uchWrite16Value[2] = 0x13; uchWrite16Value[3] = 0x3f; uchWrite16Value[4] = 0x60;
bResult = pCScript->PerformI2CPacketOperation( &i2cPacket); if(bResult) { if( i2cPacket.uchI2CResult != I2CSCRIPT_NOERROR) return(FALSE); } else return(FALSE);
//SubAddr 0x12 Reg 0xD Val 0x0000
uchWrite16Value[0] = 0x12; uchWrite16Value[1] = 0x00; uchWrite16Value[2] = 0x0d; uchWrite16Value[3] = 0x00; uchWrite16Value[4] = 0x00;
bResult = pCScript->PerformI2CPacketOperation( &i2cPacket); if(bResult) { if( i2cPacket.uchI2CResult != I2CSCRIPT_NOERROR) return(FALSE); } else return(FALSE);
//SubAddr 0x10 Reg 0x30 Val 0x2003
uchWrite16Value[0] = 0x10; uchWrite16Value[1] = 0x00; uchWrite16Value[2] = 0x30; uchWrite16Value[3] = 0x20; #ifdef I2S_CAPTURE
#pragma message ("\n!!! PAY ATTENTION: Driver has been build with ITT CHIP I2S CAPTURE CONFIGURED !!!\n")
uchWrite16Value[4] = 0xe3; #else
uchWrite16Value[4] = 0x03; #endif
bResult = pCScript->PerformI2CPacketOperation( &i2cPacket); if(bResult) { if( i2cPacket.uchI2CResult != I2CSCRIPT_NOERROR) return(FALSE); } else return(FALSE);
//SubAddr 0x10 Reg 0x20 Val 0x0020
uchWrite16Value[0] = 0x10; uchWrite16Value[1] = 0x00; uchWrite16Value[2] = 0x20; uchWrite16Value[3] = 0x00; uchWrite16Value[4] = 0x20;
bResult = pCScript->PerformI2CPacketOperation( &i2cPacket); if(bResult) { if( i2cPacket.uchI2CResult != I2CSCRIPT_NOERROR) return(FALSE); } else return(FALSE);
//SubAddr 0x12 Reg 0xE Val 0x2403
uchWrite16Value[0] = 0x12; uchWrite16Value[1] = 0x00; uchWrite16Value[2] = 0x0e; uchWrite16Value[3] = 0x24; uchWrite16Value[4] = 0x03;
bResult = pCScript->PerformI2CPacketOperation( &i2cPacket); if(bResult) { if( i2cPacket.uchI2CResult != I2CSCRIPT_NOERROR) return(FALSE); } else return(FALSE);
//SubAddr 0x12 Reg 0x08 Val 0x0320
uchWrite16Value[0] = 0x12; uchWrite16Value[1] = 0x00; uchWrite16Value[2] = 0x08; uchWrite16Value[3] = 0x03; uchWrite16Value[4] = 0x20;
bResult = pCScript->PerformI2CPacketOperation( &i2cPacket); if(bResult) { if( i2cPacket.uchI2CResult != I2CSCRIPT_NOERROR) return(FALSE); } else return(FALSE);
//SubAddr 0x12 Reg 0x00 Val 0x7300
uchWrite16Value[0] = 0x12; uchWrite16Value[1] = 0x00; uchWrite16Value[2] = 0x00; uchWrite16Value[3] = 0x73; uchWrite16Value[4] = 0x00;
bResult = pCScript->PerformI2CPacketOperation( &i2cPacket); if(bResult) { if( i2cPacket.uchI2CResult != I2CSCRIPT_NOERROR) return(FALSE); } else return(FALSE);
break;
default: return(FALSE); }//switch
return(TRUE); //break;
default : return( FALSE); }
if( bI2CAccess) { if( pCScript == NULL) return( FALSE);
i2cPacket.uchChipAddress = uchI2CAddr; i2cPacket.cbReadCount = cbRDCount; i2cPacket.cbWriteCount = cbWRCount; i2cPacket.puchReadBuffer = &uchReadValue; i2cPacket.puchWriteBuffer = uchWriteValue; i2cPacket.usFlags = usI2CMode; i2cPacket.uchORValue = uchORMask; i2cPacket.uchANDValue = uchANDMask;
// synchronous execution
bResult = pCScript->PerformI2CPacketOperation( &i2cPacket); OutputDebugInfo(( "CATIHwConfig: ConnectAudioSource( %d) = %d\n", nAudioSource, bResult));
if( bResult) bResult = ( i2cPacket.uchI2CResult == I2CSCRIPT_NOERROR);
return( bResult); } else { // use GPIO interface to switch Audio source
bResult = FALSE;
ENSURE { if(( m_gpioProviderInterface.gpioOpen == NULL) || ( m_gpioProviderInterface.gpioAccess == NULL)) FAIL;
uchReadValue = AUDIO_MUX_PINS; // use as a PinMask
gpioAccessBlock.Pins = &uchReadValue; gpioAccessBlock.Flags = GPIO_FLAGS_BYTE; gpioAccessBlock.nBytes = 1; gpioAccessBlock.nBufferSize = 1; gpioAccessBlock.AsynchCompleteCallback = NULL;
// lock GPIO provider
if( !LockGPIOProviderEx( &gpioAccessBlock)) FAIL;
uchReadValue = AUDIO_MUX_PINS; // use as a PinMask
gpioAccessBlock.Command = GPIO_COMMAND_READ_BUFFER; gpioAccessBlock.Flags = GPIO_FLAGS_BYTE; gpioAccessBlock.dwCookie = m_dwGPIOAccessKey; gpioAccessBlock.nBytes = 1; gpioAccessBlock.nBufferSize = 1; gpioAccessBlock.Pins = &uchReadValue; gpioAccessBlock.Buffer = uchWriteValue; gpioAccessBlock.AsynchCompleteCallback = NULL;
if( !AccessGPIOProvider( m_pdoDriver, &gpioAccessBlock)) FAIL;
uchWriteValue[0] &= uchANDMask; uchWriteValue[0] |= uchORMask;
gpioAccessBlock.Command = GPIO_COMMAND_WRITE_BUFFER;
if( !AccessGPIOProvider( m_pdoDriver, &gpioAccessBlock)) FAIL;
bResult = TRUE;
}END_ENSURE;
// nothing bad will happen if we try to release the provider even we
// have not obtained it at the first place
uchReadValue = AUDIO_MUX_PINS; // use as a PinMask
gpioAccessBlock.Pins = &uchReadValue; gpioAccessBlock.Flags = GPIO_FLAGS_BYTE; gpioAccessBlock.nBytes = 1; gpioAccessBlock.nBufferSize = 1; gpioAccessBlock.AsynchCompleteCallback = NULL;
ReleaseGPIOProvider( &gpioAccessBlock);
return( bResult); } }
/*^^*
* GPIOIoSynchCompletionRoutine() * Purpose : This routine is for use with synchronous IRP processing. * All it does is signal an event, so the driver knows it and can continue. * * Inputs : PDEVICE_OBJECT DriverObject : Pointer to driver object created by system * PIRP pIrp : Irp that just completed * PVOID Event : Event we'll signal to say Irp is done * * Outputs : none * Author : IKLEBANOV *^^*/ extern "C" NTSTATUS GPIOIoSynchCompletionRoutine( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PVOID Event) {
KeSetEvent(( PKEVENT)Event, 0, FALSE); return( STATUS_MORE_PROCESSING_REQUIRED); }
/*^^*
* InitializeAttachGPIOProvider() * Purpose : determines the pointer to the parent GPIO Provider interface * This function will be called at Low priority * * Inputs : GPIOINTERFACE * pGPIOInterface : pointer to the Interface to be filled in * PDEVICE_OBJECT pDeviceObject : MiniDriver device object, which is a child of GPIO Master * * Outputs : BOOL - returns TRUE, if the interface was found * Author : IKLEBANOV *^^*/ BOOL CATIHwConfiguration::InitializeAttachGPIOProvider( GPIOINTERFACE * pGPIOInterface, PDEVICE_OBJECT pDeviceObject) { BOOL bResult;
bResult = LocateAttachGPIOProvider( pGPIOInterface, pDeviceObject, IRP_MJ_PNP); if(( pGPIOInterface->gpioOpen == NULL) || ( pGPIOInterface->gpioAccess == NULL)) { OutputDebugError(( "CATIHwConfig(): GPIO interface has NULL pointers\n")); bResult = FALSE; }
return( bResult); }
/*^^*
* LocateAttachGPIOProvider() * Purpose : gets the pointer to the parent GPIO Provider interface * This function will be called at Low priority * * Inputs : GPIOINTERFACE * pGPIOInterface : pointer to the Interface to be filled in * PDEVICE_OBJECT pDeviceObject : MiniDriver device object, which is a child of I2C Master * int nIrpMajorFunction : IRP major function to query the GPIO Interface * * Outputs : BOOL - returns TRUE, if the interface was found * Author : IKLEBANOV *^^*/ BOOL CATIHwConfiguration::LocateAttachGPIOProvider( GPIOINTERFACE * pGPIOInterface, PDEVICE_OBJECT pDeviceObject, UCHAR nIrpMajorFunction) { PIRP pIrp; BOOL bResult = FALSE;
ENSURE { PIO_STACK_LOCATION pNextStack; NTSTATUS ntStatus; KEVENT Event; pIrp = IoAllocateIrp( pDeviceObject->StackSize, FALSE); if( pIrp == NULL) { OutputDebugError(( "CATIHwConfig(): can not allocate IRP\n")); FAIL; }
pNextStack = IoGetNextIrpStackLocation( pIrp); if( pNextStack == NULL) { OutputDebugError(( "CATIHwConfig(): can not allocate NextStack\n")); FAIL; }
pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED; pNextStack->MajorFunction = nIrpMajorFunction; pNextStack->MinorFunction = IRP_MN_QUERY_INTERFACE; KeInitializeEvent( &Event, NotificationEvent, FALSE);
IoSetCompletionRoutine( pIrp, GPIOIoSynchCompletionRoutine, &Event, TRUE, TRUE, TRUE);
pNextStack->Parameters.QueryInterface.InterfaceType = ( struct _GUID *)&GUID_GPIO_INTERFACE; pNextStack->Parameters.QueryInterface.Size = sizeof( GPIOINTERFACE); pNextStack->Parameters.QueryInterface.Version = 1; pNextStack->Parameters.QueryInterface.Interface = ( PINTERFACE)pGPIOInterface; pNextStack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
ntStatus = IoCallDriver( pDeviceObject, pIrp);
if( ntStatus == STATUS_PENDING) KeWaitForSingleObject( &Event, Suspended, KernelMode, FALSE, NULL); if(( pGPIOInterface->gpioOpen == NULL) || ( pGPIOInterface->gpioAccess == NULL)) FAIL;
bResult = TRUE;
} END_ENSURE; if( pIrp != NULL) IoFreeIrp( pIrp);
return( bResult); }
/*^^*
* LockGPIOProviderEx() * Purpose : locks the GPIOProvider for exclusive use * * Inputs : PGPIOControl pgpioAccessBlock : pointer to GPIO control structure * * Outputs : BOOL : retunrs TRUE, if the GPIOProvider is locked * Author : IKLEBANOV *^^*/ BOOL CATIHwConfiguration::LockGPIOProviderEx( PGPIOControl pgpioAccessBlock) { NTSTATUS ntStatus; LARGE_INTEGER liStartTime, liCurrentTime;
KeQuerySystemTime( &liStartTime);
ENSURE { if(( m_gpioProviderInterface.gpioOpen == NULL) || ( m_gpioProviderInterface.gpioAccess == NULL) || ( m_pdoDriver == NULL)) FAIL;
pgpioAccessBlock->Status = GPIO_STATUS_NOERROR; pgpioAccessBlock->Command = GPIO_COMMAND_OPEN_PINS;
while( TRUE) { KeQuerySystemTime( &liCurrentTime);
if(( liCurrentTime.QuadPart - liStartTime.QuadPart) >= GPIO_TIMELIMIT_OPENPROVIDER) { // time has expired for attempting to lock GPIO provider
return (FALSE); }
ntStatus = m_gpioProviderInterface.gpioOpen( m_pdoDriver, TRUE, pgpioAccessBlock);
if(( NT_SUCCESS( ntStatus)) && ( pgpioAccessBlock->Status == GPIO_STATUS_NOERROR)) break; }
// the GPIO Provider has granted access - save dwCookie for further use
m_dwGPIOAccessKey = pgpioAccessBlock->dwCookie;
return( TRUE);
} END_ENSURE;
return( FALSE); }
/*^^*
* ReleaseGPIOProvider() * Purpose : releases the GPIOProvider for other clients' use * * Inputs : PGPIOControl pgpioAccessBlock : pointer to a composed GPIO access block * * Outputs : BOOL : retunrs TRUE, if the GPIOProvider is released * Author : IKLEBANOV *^^*/ BOOL CATIHwConfiguration::ReleaseGPIOProvider( PGPIOControl pgpioAccessBlock) { NTSTATUS ntStatus;
ENSURE { if(( m_gpioProviderInterface.gpioOpen == NULL) || ( m_gpioProviderInterface.gpioAccess == NULL) || ( m_pdoDriver == NULL)) FAIL;
pgpioAccessBlock->Status = GPIO_STATUS_NOERROR; pgpioAccessBlock->Command = GPIO_COMMAND_CLOSE_PINS; pgpioAccessBlock->dwCookie = m_dwGPIOAccessKey;
ntStatus = m_gpioProviderInterface.gpioOpen( m_pdoDriver, FALSE, pgpioAccessBlock);
if( !NT_SUCCESS( ntStatus)) { OutputDebugError(( "CATIHwConfig: ReleaseGPIOProvider() NTSTATUS = %x\n", ntStatus)); FAIL; }
if( pgpioAccessBlock->Status != GPIO_STATUS_NOERROR) { OutputDebugError(( "CATIHwConfig: ReleaseGPIOProvider() Status = %x\n", pgpioAccessBlock->Status)); FAIL; }
m_dwGPIOAccessKey = 0; return ( TRUE);
} END_ENSURE;
return( FALSE); }
/*^^*
* AccessGPIOProvider() * Purpose : provide synchronous type of access to GPIOProvider * * Inputs : PDEVICE_OBJECT pdoDriver : pointer to the client's device object * PGPIOControl pgpioAccessBlock : pointer to a composed GPIO access block * * Outputs : BOOL, TRUE if acsepted by the GPIO Provider * * Author : IKLEBANOV *^^*/ BOOL CATIHwConfiguration::AccessGPIOProvider( PDEVICE_OBJECT pdoClient, PGPIOControl pgpioAccessBlock) { NTSTATUS ntStatus;
ENSURE {
if(( m_gpioProviderInterface.gpioOpen == NULL) || ( m_gpioProviderInterface.gpioAccess == NULL) || ( m_pdoDriver == NULL)) FAIL;
ntStatus = m_gpioProviderInterface.gpioAccess( pdoClient, pgpioAccessBlock);
if( !NT_SUCCESS( ntStatus)) { OutputDebugError(( "CATIHwConfig: AccessGPIOProvider() NTSTATUS = %x\n", ntStatus)); FAIL; }
if( pgpioAccessBlock->Status != GPIO_STATUS_NOERROR) { OutputDebugError(( "CATIHwConfig: AccessGPIOProvider() Status = %x\n", pgpioAccessBlock->Status)); FAIL; }
return TRUE;
} END_ENSURE;
return( FALSE); }
/*^^*
* SetTunerPowerState * Purpose : Sets Tuner power mode * Inputs : CI2CScript * pCScript : pointer to the I2C Provider class * BOOL bPowerState : TRUE, if turne the power on * * Outputs : BOOL, TRUE if successfull * Author : TOM *^^*/ BOOL CATIHwConfiguration::SetTunerPowerState( CI2CScript * pCScript, BOOL bPowerState) { UCHAR uchORMask = 0x0; UCHAR uchANDMask = 0xFF; UCHAR uchPinsMask, uchValue; BOOL bResult; GPIOControl gpioAccessBlock;
switch( m_usTunerPowerConfiguration) { case ATI_TUNER_POWER_CONFIG_1:
if( bPowerState) uchANDMask &= 0xF7; else uchORMask |= 0x08; break;
default : return( FALSE); }
// use GPIO interface to turn Tuner power ON / OFF
bResult = FALSE;
ENSURE { if(( m_gpioProviderInterface.gpioOpen == NULL) || ( m_gpioProviderInterface.gpioAccess == NULL)) FAIL;
uchPinsMask = TUNER_PM_PINS; // use as a PinMask
gpioAccessBlock.Pins = &uchPinsMask; gpioAccessBlock.Flags = GPIO_FLAGS_BYTE; gpioAccessBlock.nBytes = 1; gpioAccessBlock.nBufferSize = 1; gpioAccessBlock.AsynchCompleteCallback = NULL;
// try to get GPIO Provider
if( !LockGPIOProviderEx( &gpioAccessBlock)) FAIL;
uchPinsMask = TUNER_PM_PINS; // use as a PinMask
gpioAccessBlock.Command = GPIO_COMMAND_READ_BUFFER; gpioAccessBlock.Flags = GPIO_FLAGS_BYTE; gpioAccessBlock.dwCookie = m_dwGPIOAccessKey; gpioAccessBlock.nBytes = 1; gpioAccessBlock.nBufferSize = 1; gpioAccessBlock.Pins = &uchPinsMask; gpioAccessBlock.Buffer = &uchValue; gpioAccessBlock.AsynchCompleteCallback = NULL;
if( !AccessGPIOProvider( m_pdoDriver, &gpioAccessBlock)) FAIL;
uchValue &= uchANDMask; uchValue |= uchORMask;
gpioAccessBlock.Command = GPIO_COMMAND_WRITE_BUFFER;
if( !AccessGPIOProvider( m_pdoDriver, &gpioAccessBlock)) FAIL;
bResult = TRUE;
} END_ENSURE;
// nothing bad will happen if we try to release the provider even we
// have not obtained it at the first place
uchValue = TUNER_PM_PINS; // use as a PinMask
gpioAccessBlock.Pins = &uchValue; gpioAccessBlock.Flags = GPIO_FLAGS_BYTE; gpioAccessBlock.nBytes = 1; gpioAccessBlock.nBufferSize = 1; gpioAccessBlock.AsynchCompleteCallback = NULL; ReleaseGPIOProvider( &gpioAccessBlock);
return( bResult); }
/*^^*
* ValidateConfigurationE2PROM * Purpose : Checks the integrity ( check-sum) of I2C driven configuration EEPROM * Inputs : CI2CScript * pCScript : pointer to the I2C Provider class * * Outputs : BOOL, TRUE if the information inside EEPROM is valid * Author : TOM *^^*/ BOOL CATIHwConfiguration::ValidateConfigurationE2PROM( CI2CScript * pCScript) { I2CPacket i2cPacket; UCHAR uchReadValue=0, uchWriteValue, uchCheckSum=0; UINT nIndex; BOOL bResult = ( BOOL)m_usE2PROMValidation;
if( m_usE2PROMValidation == ( USHORT)-1) { // the validation has not been done yet.
bResult = FALSE;
ENSURE { // Let's always start from byte 0.
i2cPacket.uchChipAddress = AIWPRO_CONFIGURATIONE2PROM_ADDRESS; i2cPacket.cbWriteCount = 1; i2cPacket.cbReadCount = 1; i2cPacket.puchReadBuffer = &uchCheckSum; uchWriteValue = 0; i2cPacket.puchWriteBuffer = &uchWriteValue; i2cPacket.usFlags = I2COPERATION_READ | I2COPERATION_RANDOMACCESS;
if( !pCScript->ExecuteI2CPacket( &i2cPacket)) FAIL;
for( nIndex = 1; nIndex < AIWPRO_CONFIGURATIONE2PROM_LENGTH; nIndex ++) { // let's use auto-increment address mode
i2cPacket.usFlags = I2COPERATION_READ; i2cPacket.cbWriteCount = 0; i2cPacket.puchWriteBuffer = NULL; i2cPacket.puchReadBuffer = &uchReadValue;
if( !pCScript->ExecuteI2CPacket( &i2cPacket)) FAIL;
uchCheckSum ^= uchReadValue; }
if( nIndex != AIWPRO_CONFIGURATIONE2PROM_LENGTH) FAIL;
bResult = ( uchCheckSum == 0);
} END_ENSURE;
m_usE2PROMValidation = ( USHORT)bResult; }
return( bResult); }
/*^^*
* ReadConfigurationE2PROM * Purpose : Reads a single byte from I2C driver configuration EEPROM by offset * Inputs : CI2CScript * pCScript : pointer to the I2C Provider class * ULONG ulOffset : byte offset within the EEPROM * PUCHAR puchValue : pointer to the buffer to read into * * Outputs : BOOL, TRUE if I2C read operation succeeded * Author : TOM *^^*/ BOOL CATIHwConfiguration::ReadConfigurationE2PROM( CI2CScript * pCScript, ULONG ulOffset, PUCHAR puchValue) { I2CPacket i2cPacket; UCHAR uchReadValue=0, uchWriteValue;
ENSURE { if( ulOffset >= AIWPRO_CONFIGURATIONE2PROM_LENGTH) FAIL;
uchWriteValue = ( UCHAR)ulOffset; i2cPacket.uchChipAddress = AIWPRO_CONFIGURATIONE2PROM_ADDRESS; i2cPacket.cbWriteCount = 1; i2cPacket.cbReadCount = 1; i2cPacket.puchReadBuffer = &uchReadValue; i2cPacket.puchWriteBuffer = &uchWriteValue; i2cPacket.usFlags = I2COPERATION_READ | I2COPERATION_RANDOMACCESS;
if( !pCScript->ExecuteI2CPacket( &i2cPacket)) FAIL;
* puchValue = uchReadValue;
return( TRUE);
} END_ENSURE;
return( FALSE); }
//Paul
ULONG CATIHwConfiguration::ReturnTunerVideoStandard( USHORT usTunerId ) //Paul: For PAL support
{ switch( usTunerId ) { case 1: return KS_AnalogVideo_NTSC_M; break; case 2: return KS_AnalogVideo_NTSC_M_J; break; case 3: return KS_AnalogVideo_PAL_B | KS_AnalogVideo_PAL_G; break; case 4: return KS_AnalogVideo_PAL_I; break; case 5: return KS_AnalogVideo_PAL_B | KS_AnalogVideo_PAL_G | KS_AnalogVideo_SECAM_L | KS_AnalogVideo_SECAM_L1; break; case 6: return KS_AnalogVideo_NTSC_M; break; case 7: return KS_AnalogVideo_SECAM_D | KS_AnalogVideo_SECAM_K; break; case 8: return KS_AnalogVideo_NTSC_M; break; case 9: return KS_AnalogVideo_PAL_B | KS_AnalogVideo_PAL_G; break; case 10: return KS_AnalogVideo_PAL_I; break; case 11: return KS_AnalogVideo_PAL_B | KS_AnalogVideo_PAL_G | KS_AnalogVideo_SECAM_L | KS_AnalogVideo_SECAM_L1; break; case 12: return KS_AnalogVideo_NTSC_M; break; case 13: return KS_AnalogVideo_PAL_B | KS_AnalogVideo_PAL_D | KS_AnalogVideo_PAL_G | KS_AnalogVideo_PAL_I | KS_AnalogVideo_SECAM_D | KS_AnalogVideo_SECAM_K; break; case 14: return 0; break; case 15: return 0; break; case 16: return KS_AnalogVideo_NTSC_M; break; case 17: return KS_AnalogVideo_NTSC_M; break; case 18: return KS_AnalogVideo_NTSC_M; break; default: return 0; // if we don't recognize the tuner, we say that no video standard is supported
} }
//Paul
// bit 5 indicates the number of crystals installed. 0 means we have 2 crystals,
// 1 means we only have 1, so the tuner determines the standard
ULONG CATIHwConfiguration::SetVidStdBasedOnI2CExpander( UCHAR ucI2CValue ) { if ( ucI2CValue & 0x20 ) // only 1 crystal
{ ULONG ulTunerStd = ReturnTunerVideoStandard( ucI2CValue & 0x0F ); if ( ulTunerStd & ( KS_AnalogVideo_NTSC_Mask & ~KS_AnalogVideo_NTSC_433 | KS_AnalogVideo_PAL_60 ) ) // Then we should have NTSC-type crystal
{ return KS_AnalogVideo_NTSC_Mask & ~KS_AnalogVideo_NTSC_433 | KS_AnalogVideo_PAL_60 | KS_AnalogVideo_PAL_M | KS_AnalogVideo_PAL_N; } else { return KS_AnalogVideo_PAL_Mask & ~KS_AnalogVideo_PAL_60 & ~KS_AnalogVideo_PAL_M & ~KS_AnalogVideo_PAL_N | KS_AnalogVideo_SECAM_Mask | KS_AnalogVideo_NTSC_433; } } else return KS_AnalogVideo_NTSC_Mask | KS_AnalogVideo_PAL_Mask | KS_AnalogVideo_SECAM_Mask; // we support all standards (is this testable?)
}
//Paul
// The Video In crystal type in MMTable will tell us whether we support NTSC, PAL/SECAM, or both
ULONG CATIHwConfiguration::SetVidStdBasedOnMMTable( CATIMultimediaTable * pCMultimediaInfo ) { if ( pCMultimediaInfo ) { if ( pCMultimediaInfo->GetVideoInCrystalId( &m_CrystalIDInMMTable ) ) { switch ( m_CrystalIDInMMTable ) { // "NTSC and PAL Crystals Installed (for Bt8xx)"
case 0: return KS_AnalogVideo_NTSC_Mask | KS_AnalogVideo_PAL_Mask; // may need to add SECAM. We will see
break; // "NTSC Crystal Only (for Bt8xx)"
case 1: return KS_AnalogVideo_NTSC_Mask & ~KS_AnalogVideo_NTSC_433 | KS_AnalogVideo_PAL_60 | KS_AnalogVideo_PAL_M | KS_AnalogVideo_PAL_N; // standards that use "NTSC" clock
break; // "PAL Crystal Only (for Bt8xx)"
case 2: return KS_AnalogVideo_PAL_Mask & ~KS_AnalogVideo_PAL_60 & ~KS_AnalogVideo_PAL_M & ~KS_AnalogVideo_PAL_N | KS_AnalogVideo_SECAM_Mask | KS_AnalogVideo_NTSC_433; // standards that use "PAL" clock
break; // "NTSC, PAL, SECAM (for Bt829)"
case 3: return KS_AnalogVideo_NTSC_Mask | KS_AnalogVideo_PAL_Mask | KS_AnalogVideo_SECAM_Mask; break; } } } return 0;
}
//Paul: Used by RT WDM to determine the VIN PLL
BOOL CATIHwConfiguration::GetMMTableCrystalID( PUCHAR pucCrystalID ) { if ( ( m_uchI2CExpanderAddress==0xFF ) || ( !pucCrystalID ) ) { return FALSE; } else { *pucCrystalID = m_CrystalIDInMMTable; return TRUE; } }
|