AppleTAS3004Audio.cpp [plain text]
#include "AppleTAS3004Audio.h"
#include <IOKit/IOInterruptEventSource.h>
#include <IOKit/IOFilterInterruptEventSource.h>
#include <IOKit/IOWorkLoop.h>
#include <IOKit/IORegistryEntry.h>
#include <IOKit/IOCommandGate.h>
#include <IOKit/IOTimerEventSource.h>
#include "AudioHardwareConstants.h"
#include "AudioHardwareUtilities.h"
#include "AppleDBDMAAudio.h"
#define super IOService
OSDefineMetaClassAndStructors(AppleTAS3004Audio, AudioHardwareObjectInterface)
const UInt8 AppleTAS3004Audio::kDEQAddress = 0x6A;
#pragma mark ---------------------
#pragma mark +UNIX LIKE FUNCTIONS
#pragma mark ---------------------
bool AppleTAS3004Audio::init(OSDictionary *properties)
{
debugIOLog (3, "+ AppleTAS3004Audio::init");
if (!super::init(properties))
return false;
mVolLeft = 0;
mVolRight = 0;
mTAS_WasDead = false;
debugIOLog (3, "- AppleTAS3004Audio::init");
return true;
}
bool AppleTAS3004Audio::start (IOService * provider) {
bool result;
debugIOLog (3, "+ AppleTAS3004Audio[%p]::start(%p)", this, provider);
result = FALSE;
FailIf (!provider, Exit);
mAudioDeviceProvider = (AppleOnboardAudio *)provider;
result = super::start (provider);
result = provider->open (this, kFamilyOption_OpenMultiple);
Exit:
debugIOLog (3, "- AppleTAS3004Audio[%p]::start(%p) returns %s", this, provider, result == true ? "true" : "false");
return result;
}
void AppleTAS3004Audio::free()
{
debugIOLog (3, "+ AppleTAS3004Audio::free");
super::free();
debugIOLog (3, "- AppleTAS3004Audio::free");
}
void AppleTAS3004Audio::initPlugin(PlatformInterface* inPlatformObject)
{
mPlatformInterface = inPlatformObject;
}
bool AppleTAS3004Audio::willTerminate ( IOService * provider, IOOptionBits options )
{
bool result = super::willTerminate( provider, options );
debugIOLog (3, "AppleTAS3004Audio::willTerminate(%p) returns %d, mAudioDeviceProvider = %p", provider, result, mAudioDeviceProvider);
if (provider == mAudioDeviceProvider) {
debugIOLog (3, "closing our provider");
provider->close (this);
}
debugIOLog (3, "- AppleTAS3004Audio[%p]::willTerminate(%p) returns %s", this, provider, result == true ? "true" : "false");
return result;
}
bool AppleTAS3004Audio::requestTerminate ( IOService * provider, IOOptionBits options )
{
bool result = super::requestTerminate( provider, options );
debugIOLog (3, "AppleTAS3004Audio::requestTerminate(%p) returns %d, mAudioDeviceProvider = %p", provider, result, mAudioDeviceProvider);
return result;
}
bool AppleTAS3004Audio::preDMAEngineInit()
{
IOReturn err;
IORegistryEntry *sound;
UInt32 loopCnt;
UInt8 data[kTAS3004BIQwidth];
debugIOLog (3, "+ AppleTAS3004Audio::preDMAEngineInit");
debugIOLog (3, "ourProvider's name is %s", mAudioDeviceProvider->getName ());
sound = mAudioDeviceProvider->getParentEntry (gIOServicePlane);
FailIf (!sound, Exit);
debugIOLog (3, "sound's name is %s", sound->getName ());
data[0] = ( kNormalLoad << kFL ) | ( k64fs << kSC ) | TAS_I2S_MODE | ( TAS_WORD_LENGTH << kW0 );
CODEC_WriteRegister( kTAS3004MainCtrl1Reg, data, kUPDATE_SHADOW );
data[DRC_AboveThreshold] = kDisableDRC;
data[DRC_BelowThreshold] = 0;
data[DRC_Threshold] = 0;
data[DRC_Integration] = 0;
data[DRC_Attack] = 0;
data[DRC_Decay] = 0;
CODEC_WriteRegister( kTAS3004DynamicRangeCtrlReg, data, kUPDATE_SHADOW );
for( loopCnt = 0; loopCnt < kTAS3004VOLwidth; loopCnt++ ) data[loopCnt] = 0;
CODEC_WriteRegister( kTAS3004VolumeCtrlReg, data, kUPDATE_SHADOW );
data[0] = 0x72; CODEC_WriteRegister( kTAS3004TrebleCtrlReg, data, kUPDATE_SHADOW );
CODEC_WriteRegister( kTAS3004BassCtrlReg, data, kUPDATE_SHADOW );
data[0] = 0x10; data[1] = 0x00;
data[2] = 0x00;
data[3] = 0x00; data[4] = 0x00;
data[5] = 0x00;
data[6] = 0x00; data[7] = 0x00;
data[8] = 0x00;
CODEC_WriteRegister( kTAS3004MixerLeftGainReg, data, kUPDATE_SHADOW ); CODEC_WriteRegister( kTAS3004MixerRightGainReg, data, kUPDATE_SHADOW );
for( loopCnt = 1; loopCnt < kTAS3004BIQwidth; loopCnt++ ) data[loopCnt] = 0x00;
data[0] = 0x10;
CODEC_WriteRegister( kTAS3004LeftBiquad0CtrlReg, data, kUPDATE_SHADOW );
CODEC_WriteRegister( kTAS3004LeftBiquad1CtrlReg, data, kUPDATE_SHADOW );
CODEC_WriteRegister( kTAS3004LeftBiquad2CtrlReg, data, kUPDATE_SHADOW );
CODEC_WriteRegister( kTAS3004LeftBiquad3CtrlReg, data, kUPDATE_SHADOW );
CODEC_WriteRegister( kTAS3004LeftBiquad4CtrlReg, data, kUPDATE_SHADOW );
CODEC_WriteRegister( kTAS3004LeftBiquad5CtrlReg, data, kUPDATE_SHADOW );
CODEC_WriteRegister( kTAS3004LeftBiquad6CtrlReg, data, kUPDATE_SHADOW );
CODEC_WriteRegister( kTAS3004LeftLoudnessBiquadReg, data, kUPDATE_SHADOW );
CODEC_WriteRegister( kTAS3004RightBiquad0CtrlReg, data, kUPDATE_SHADOW );
CODEC_WriteRegister( kTAS3004RightBiquad1CtrlReg, data, kUPDATE_SHADOW );
CODEC_WriteRegister( kTAS3004RightBiquad2CtrlReg, data, kUPDATE_SHADOW );
CODEC_WriteRegister( kTAS3004RightBiquad3CtrlReg, data, kUPDATE_SHADOW );
CODEC_WriteRegister( kTAS3004RightBiquad4CtrlReg, data, kUPDATE_SHADOW );
CODEC_WriteRegister( kTAS3004RightBiquad5CtrlReg, data, kUPDATE_SHADOW );
CODEC_WriteRegister( kTAS3004RightLoudnessBiquadReg, data, kUPDATE_SHADOW );
data[0] = 0x00; data[3] = 0x10;
CODEC_WriteRegister( kTAS3004RightBiquad6CtrlReg, data, kUPDATE_SHADOW );
data[0] = 0x00; CODEC_WriteRegister( kTAS3004LeftLoudnessBiquadGainReg, data, kUPDATE_SHADOW );
CODEC_WriteRegister( kTAS3004RightLoudnessBiquadGainReg, data, kUPDATE_SHADOW );
data[0] = ( kADMNormal << kADM ) | ( kDeEmphasisOFF << kADM ) | ( kPowerDownAnalog << kAPD );
CODEC_WriteRegister( kTAS3004AnalogControlReg, data, kUPDATE_SHADOW );
data[0] = ( kNormalFilter << kAP ) | ( kNormalBassTreble << kDL );
CODEC_WriteRegister( kTAS3004MainCtrl2Reg, data, kUPDATE_SHADOW );
err = CODEC_Initialize(); IOSleep (1);
ToggleAnalogPowerDownWake();
memcpy (&standbyTAS3004Regs, &shadowTAS3004Regs, sizeof (TAS3004_ShadowReg));
minVolume = kMinimumVolume;
maxVolume = kMaximumVolume;
Exit:
debugIOLog (3, "- AppleTAS3004Audio::preDMAEngineInit");
return true;
}
IOReturn AppleTAS3004Audio::SetAnalogPowerDownMode( UInt8 mode )
{
IOReturn err;
UInt8 dataBuffer[kTAS3004ANALOGCTRLREGwidth];
err = kIOReturnSuccess;
if ( kPowerDownAnalog == mode || kPowerNormalAnalog == mode )
{
err = CODEC_ReadRegister( kTAS3004AnalogControlReg, dataBuffer );
if ( kIOReturnSuccess == err )
{
dataBuffer[0] &= ~( kAPD_MASK << kAPD );
dataBuffer[0] |= ( mode << kAPD );
err = CODEC_WriteRegister( kTAS3004AnalogControlReg, dataBuffer, kUPDATE_ALL );
}
}
return err;
}
IOReturn AppleTAS3004Audio::ToggleAnalogPowerDownWake( void )
{
IOReturn err;
err = SetAnalogPowerDownMode (kPowerDownAnalog);
if (kIOReturnSuccess == err) {
err = SetAnalogPowerDownMode (kPowerNormalAnalog);
}
return err;
}
#pragma mark ---------------------
#pragma mark +HARDWARE IO ACTIVATION
#pragma mark ---------------------
UInt32 AppleTAS3004Audio::getActiveOutput(void)
{
debugIOLog (3, "+ AppleTAS3004Audio::sndHWGetActiveOutputExclusive");
debugIOLog (3, "- AppleTAS3004Audio::sndHWGetActiveOutputExclusive");
return 0;
}
IOReturn AppleTAS3004Audio::setActiveOutput(UInt32 outputPort )
{
debugIOLog (3, "+ AppleTAS3004Audio::sndHWSetActiveOutputExclusive");
IOReturn myReturn = kIOReturnSuccess;
debugIOLog (3, "- AppleTAS3004Audio::sndHWSetActiveOutputExclusive");
return(myReturn);
}
UInt32 AppleTAS3004Audio::getActiveInput(void)
{
debugIOLog (3, "+ AppleTAS3004Audio::sndHWGetActiveInputExclusive");
debugIOLog (3, "- AppleTAS3004Audio::sndHWGetActiveInputExclusive");
return 0;
}
IOReturn AppleTAS3004Audio::setActiveInput (UInt32 input)
{
UInt8 data[kTAS3004MaximumRegisterWidth];
IOReturn result = kIOReturnSuccess;
debugIOLog (3, "+ AppleTAS3004Audio::setActiveInput (%4s)", (char *)&input);
CODEC_ReadRegister (kTAS3004AnalogControlReg, data);
data[0] &= ~((1 << kADM) | (1 << kLRB) | (1 << kINP));
switch (input) {
case kIOAudioInputPortSubTypeLine:
data[0] |= ((kADMNormal << kADM) | (kLeftInputForMonaural << kLRB) | (kAnalogInputA << kINP));
result = CODEC_WriteRegister (kTAS3004AnalogControlReg, data, kUPDATE_ALL);
break;
case kIOAudioInputPortSubTypeInternalMicrophone:
data[0] |= ((kADMBInputsMonaural << kADM) | (kRightInputForMonaural << kLRB) | (kAnalogInputB << kINP));
result = CODEC_WriteRegister (kTAS3004AnalogControlReg, data, kUPDATE_ALL);
break;
default:
result = kIOReturnError;
break;
}
debugIOLog (3, "- AppleTAS3004Audio::setActiveInput");
return(result);
}
#pragma mark ---------------------
#pragma mark +CONTROL FUNCTIONS
#pragma mark ---------------------
IOReturn AppleTAS3004Audio::setCodecMute(bool mutestate)
{
return setMute ( mutestate, kAnalogAudioSelector ); }
IOReturn AppleTAS3004Audio::setCodecMute (bool muteState, UInt32 streamType) {
IOReturn result = kIOReturnSuccess;
debugIOLog (3, "+ AppleTAS3004Audio::setMute (%d, %4s)", muteState, (char*)&streamType);
switch ( streamType ) {
case kAnalogAudioSelector:
if (true == muteState) {
result = SetVolumeCoefficients (0, 0);
} else {
result = SetVolumeCoefficients (volumeTable[(UInt32)mVolLeft], volumeTable[(UInt32)mVolRight]);
}
break;
default:
result = kIOReturnError;
break;
}
debugIOLog (3, "- AppleTAS3004Audio::setMute (%d, %4s) returns %X", muteState, (char*)&streamType, result);
return result;
}
bool AppleTAS3004Audio::hasAnalogMute ()
{
return true;
}
UInt32 AppleTAS3004Audio::getMinimumdBVolume () {
return volumedBTable[minVolume];
}
UInt32 AppleTAS3004Audio::getMaximumdBVolume () {
return volumedBTable[maxVolume];
}
UInt32 AppleTAS3004Audio::getMinimumVolume () {
return minVolume;
}
UInt32 AppleTAS3004Audio::getMaximumVolume () {
return maxVolume;
}
UInt32 AppleTAS3004Audio::getMaximumdBGain (void) {
return kTAS3004_Plus_12dB;
}
UInt32 AppleTAS3004Audio::getMinimumdBGain (void) {
return kTAS3004_Minus_12dB;
}
UInt32 AppleTAS3004Audio::getMaximumGain (void) {
return kTAS3004_MaxGainSteps;
}
UInt32 AppleTAS3004Audio::getMinimumGain (void) {
return 0;
}
bool AppleTAS3004Audio::setCodecVolume(UInt32 leftVolume, UInt32 rightVolume)
{
bool result;
result = false;
debugIOLog (3, "+ AppleTAS3004Audio::sndHWSetSystemVolume (left: %ld, right %ld)", leftVolume, rightVolume);
mVolLeft = leftVolume;
mVolRight = rightVolume;
result = SetVolumeCoefficients (volumeTable[(UInt32)mVolLeft], volumeTable[(UInt32)mVolRight]);
debugIOLog (3, "- AppleTAS3004Audio::sndHWSetSystemVolume");
return (result == kIOReturnSuccess);
}
IOReturn AppleTAS3004Audio::setPlayThrough(bool playthroughstate)
{
UInt8 leftMixerGain[kTAS3004MIXERGAINwidth];
UInt8 rightMixerGain[kTAS3004MIXERGAINwidth];
IOReturn err;
debugIOLog (3, "+ AppleTAS3004Audio::sndHWSetPlayThrough");
err = CODEC_ReadRegister ( kTAS3004MixerLeftGainReg, leftMixerGain );
FailIf ( kIOReturnSuccess != err, Exit );
err = CODEC_ReadRegister ( kTAS3004MixerRightGainReg, rightMixerGain );
FailIf ( kIOReturnSuccess != err, Exit );
if ( playthroughstate ) {
leftMixerGain[3] = rightMixerGain[3] = 0x10;
} else {
leftMixerGain[3] = rightMixerGain[3] = 0x00;
}
err = CODEC_WriteRegister ( kTAS3004MixerLeftGainReg, leftMixerGain, kUPDATE_ALL );
err = CODEC_WriteRegister ( kTAS3004MixerRightGainReg, rightMixerGain, kUPDATE_ALL );
Exit:
debugIOLog (3, "- AppleTAS3004Audio::sndHWSetPlayThrough");
return err;
}
IOReturn AppleTAS3004Audio::setSampleRate ( UInt32 sampleRate ) {
IOReturn result = kIOReturnBadArgument;
FailIf ( ( 50000 < sampleRate ) || ( sampleRate < 30000 ), Exit );
CODEC_Initialize();
result = kIOReturnSuccess;
Exit:
return result;
}
IOReturn AppleTAS3004Audio::setSampleDepth ( UInt32 sampleDepth ) {
UInt8 data;
IOReturn result = kIOReturnBadArgument;
debugIOLog (3, "+ AppleTAS3004Audio:: setSampleDepth ( %d )", (unsigned int) sampleDepth );
FailIf ( !( 16 == sampleDepth || 24 == sampleDepth ), Exit );
CODEC_Initialize ();
result = CODEC_ReadRegister ( kTAS3004MainCtrl1Reg, &data );
FailIf ( kIOReturnSuccess != result, Exit );
data &= ~( kSerialWordLengthMASK << kW0 );
if ( 16 == sampleDepth ) {
data |= ( kSerialWordLength16 << kW0 );
} else {
data |= ( kSerialWordLength24 << kW0 );
}
result = CODEC_WriteRegister ( kTAS3004MainCtrl1Reg, &data, kFORCE_UPDATE_ALL );
Exit:
debugIOLog (3, "+ AppleTAS3004Audio::setSampleWidth ( %d ) returns %d", (unsigned int)sampleDepth, (unsigned int)result );
return result;
}
IOReturn AppleTAS3004Audio::breakClockSelect ( UInt32 clockSource ) {
IOReturn result;
debugIOLog (3, "+ AppleTAS3004Audio::breakClockSelect ( %ld )", clockSource );
result = kIOReturnError;
FailIf ( !( kTRANSPORT_MASTER_CLOCK == clockSource || kTRANSPORT_SLAVE_CLOCK == clockSource ), Exit );
mPlatformInterface->setCodecReset ( kCODEC_RESET_Analog, kGPIO_Reset );
result = kIOReturnSuccess;
Exit:
debugIOLog (3, "+ AppleTAS3004Audio::breakClockSelect ( %ld ) returns %X", clockSource, result );
return result;
}
IOReturn AppleTAS3004Audio::makeClockSelect ( UInt32 clockSource ) {
IOReturn result;
debugIOLog (3, "+ AppleTAS3004Audio::makeClockSelect ( %ld )", clockSource );
result = kIOReturnError;
FailIf ( !( kTRANSPORT_MASTER_CLOCK == clockSource || kTRANSPORT_SLAVE_CLOCK == clockSource ), Exit );
CODEC_Initialize();
result = kIOReturnSuccess;
Exit:
debugIOLog (3, "- AppleTAS3004Audio::makeClockSelect ( %ld ) returns %X", clockSource, result );
return result;
}
IOReturn AppleTAS3004Audio::recoverFromFatalError ( FatalRecoverySelector selector ) {
FailIf ( NULL == mPlatformInterface, Exit );
switch ( selector ) {
case kControlBusFatalErrorRecovery:
CODEC_Initialize();
break;
case kClockSourceInterruptedRecovery:
CODEC_Initialize();
break;
default:
debugIOLog (3, "*** Requested recovery from unknown condition!" );
break;
}
Exit:
debugIOLog (3, "± AppleTAS3004Audio::recoverFromFatalError ( %d )", (unsigned int)selector );
return kIOReturnSuccess;
}
#pragma mark ---------------------
#pragma mark +POWER MANAGEMENT
#pragma mark ---------------------
IOReturn AppleTAS3004Audio::performDeviceSleep () {
debugIOLog (3, "+ AppleTAS3004Audio::performDeviceSleep");
SetAnalogPowerDownMode (kPowerDownAnalog);
debugIOLog (3, "- AppleTAS3004Audio::performDeviceSleep");
return kIOReturnSuccess;
}
IOReturn AppleTAS3004Audio::performDeviceWake () {
IOReturn err;
debugIOLog (3, "+ AppleTAS3004Audio::performDeviceWake");
err = kIOReturnSuccess;
SetAnalogPowerDownMode (kPowerNormalAnalog);
err = CODEC_Initialize ();
debugIOLog (3, "- AppleTAS3004Audio::performDeviceWake" );
return err;
}
#pragma mark ---------------------
#pragma mark + HARDWARE MANIPULATION
#pragma mark ---------------------
IOReturn AppleTAS3004Audio::GetShadowRegisterInfo( TAS3004_ShadowReg * shadowRegsPtr, UInt8 regAddr, UInt8 ** shadowPtr, UInt8* registerSize ) {
IOReturn err;
err = kIOReturnSuccess;
FailWithAction( NULL == shadowPtr, err = kIOReturnError, Exit );
FailWithAction( NULL == registerSize, err = kIOReturnError, Exit );
switch( regAddr )
{
case kTAS3004MainCtrl1Reg: *shadowPtr = (UInt8*)&shadowRegsPtr->sMC1R; *registerSize = kTAS3004MC1Rwidth; break;
case kTAS3004DynamicRangeCtrlReg: *shadowPtr = (UInt8*)&shadowRegsPtr->sDRC; *registerSize = kTAS3004DRCwidth; break;
case kTAS3004VolumeCtrlReg: *shadowPtr = (UInt8*)&shadowRegsPtr->sVOL; *registerSize = kTAS3004VOLwidth; break;
case kTAS3004TrebleCtrlReg: *shadowPtr = (UInt8*)&shadowRegsPtr->sTRE; *registerSize = kTAS3004TREwidth; break;
case kTAS3004BassCtrlReg: *shadowPtr = (UInt8*)&shadowRegsPtr->sBAS; *registerSize = kTAS3004BASwidth; break;
case kTAS3004MixerLeftGainReg: *shadowPtr = (UInt8*)&shadowRegsPtr->sMXL; *registerSize = kTAS3004MIXERGAINwidth; break;
case kTAS3004MixerRightGainReg: *shadowPtr = (UInt8*)&shadowRegsPtr->sMXR; *registerSize = kTAS3004MIXERGAINwidth; break;
case kTAS3004LeftBiquad0CtrlReg: *shadowPtr = (UInt8*)&shadowRegsPtr->sLB0; *registerSize = kTAS3004BIQwidth; break;
case kTAS3004LeftBiquad1CtrlReg: *shadowPtr = (UInt8*)&shadowRegsPtr->sLB1; *registerSize = kTAS3004BIQwidth; break;
case kTAS3004LeftBiquad2CtrlReg: *shadowPtr = (UInt8*)&shadowRegsPtr->sLB2; *registerSize = kTAS3004BIQwidth; break;
case kTAS3004LeftBiquad3CtrlReg: *shadowPtr = (UInt8*)&shadowRegsPtr->sLB3; *registerSize = kTAS3004BIQwidth; break;
case kTAS3004LeftBiquad4CtrlReg: *shadowPtr = (UInt8*)&shadowRegsPtr->sLB4; *registerSize = kTAS3004BIQwidth; break;
case kTAS3004LeftBiquad5CtrlReg: *shadowPtr = (UInt8*)&shadowRegsPtr->sLB5; *registerSize = kTAS3004BIQwidth; break;
case kTAS3004LeftBiquad6CtrlReg: *shadowPtr = (UInt8*)&shadowRegsPtr->sLB6; *registerSize = kTAS3004BIQwidth; break;
case kTAS3004RightBiquad0CtrlReg: *shadowPtr = (UInt8*)&shadowRegsPtr->sRB0; *registerSize = kTAS3004BIQwidth; break;
case kTAS3004RightBiquad1CtrlReg: *shadowPtr = (UInt8*)&shadowRegsPtr->sRB1; *registerSize = kTAS3004BIQwidth; break;
case kTAS3004RightBiquad2CtrlReg: *shadowPtr = (UInt8*)&shadowRegsPtr->sRB2; *registerSize = kTAS3004BIQwidth; break;
case kTAS3004RightBiquad3CtrlReg: *shadowPtr = (UInt8*)&shadowRegsPtr->sRB3; *registerSize = kTAS3004BIQwidth; break;
case kTAS3004RightBiquad4CtrlReg: *shadowPtr = (UInt8*)&shadowRegsPtr->sRB4; *registerSize = kTAS3004BIQwidth; break;
case kTAS3004RightBiquad5CtrlReg: *shadowPtr = (UInt8*)&shadowRegsPtr->sRB5; *registerSize = kTAS3004BIQwidth; break;
case kTAS3004RightBiquad6CtrlReg: *shadowPtr = (UInt8*)&shadowRegsPtr->sRB6; *registerSize = kTAS3004BIQwidth; break;
case kTAS3004LeftLoudnessBiquadReg: *shadowPtr = (UInt8*)&shadowRegsPtr->sLLB; *registerSize = kTAS3004BIQwidth; break;
case kTAS3004RightLoudnessBiquadReg: *shadowPtr = (UInt8*)&shadowRegsPtr->sRLB; *registerSize = kTAS3004BIQwidth; break;
case kTAS3004LeftLoudnessBiquadGainReg: *shadowPtr = (UInt8*)&shadowRegsPtr->sLLBG; *registerSize = kTAS3004LOUDNESSBIQUADGAINwidth; break;
case kTAS3004RightLoudnessBiquadGainReg: *shadowPtr = (UInt8*)&shadowRegsPtr->sRLBG; *registerSize = kTAS3004LOUDNESSBIQUADGAINwidth; break;
case kTAS3004AnalogControlReg: *shadowPtr = (UInt8*)&shadowRegsPtr->sACR; *registerSize = kTAS3004ANALOGCTRLREGwidth; break;
case kTAS3004MainCtrl2Reg: *shadowPtr = (UInt8*)&shadowRegsPtr->sMC2R; *registerSize = kTAS3004MC2Rwidth; break;
default: err = kIOReturnError; break;
}
Exit:
return err;
}
IOReturn AppleTAS3004Audio::InitEQSerialMode (UInt32 mode)
{
IOReturn err;
UInt8 data;
err = CODEC_ReadRegister (kTAS3004MainCtrl1Reg, &data);
if ( kIOReturnSuccess == err ) {
data &= ~( 1 << kFL );
if ( kNormalLoad == mode ) {
data |= (kNormalLoad << kFL);
} else {
data |= (kFastLoad << kFL);
}
err = CODEC_WriteRegister (kTAS3004MainCtrl1Reg, &data, kFORCE_UPDATE_ALL);
}
return err;
}
IOReturn AppleTAS3004Audio::SetVolumeCoefficients( UInt32 left, UInt32 right )
{
UInt8 volumeData[kTAS3004VOLwidth];
IOReturn err;
debugIOLog (3, "SetVolumeCoefficients: L=%lX R=%lX", left, right);
volumeData[2] = left;
volumeData[1] = left >> 8;
volumeData[0] = left >> 16;
volumeData[5] = right;
volumeData[4] = right >> 8;
volumeData[3] = right >> 16;
err = CODEC_WriteRegister( kTAS3004VolumeCtrlReg, volumeData, kUPDATE_ALL );
return err;
}
IOReturn AppleTAS3004Audio::CODEC_Initialize() {
IOReturn err;
UInt32 retryCount;
UInt32 initMode;
UInt8 oldMode;
UInt8 *shadowPtr;
UInt8 registerSize;
Boolean done;
err = kIOReturnError;
done = false;
oldMode = 0;
initMode = kUPDATE_HW;
retryCount = 0;
if (!mSemaphores)
{
mSemaphores = 1;
do{
debugIOLog (3, "... Resetting TAS3004" );
CODEC_Reset();
if( 0 == oldMode )
CODEC_ReadRegister( kTAS3004MainCtrl1Reg, &oldMode );
err = InitEQSerialMode( kSetFastLoadMode ); FailIf( kIOReturnSuccess != err, AttemptToRetry );
GetShadowRegisterInfo ( &shadowTAS3004Regs, kTAS3004LeftBiquad0CtrlReg, &shadowPtr, ®isterSize );
err = CODEC_WriteRegister( kTAS3004LeftBiquad0CtrlReg, shadowPtr, initMode );
FailIf( kIOReturnSuccess != err, AttemptToRetry );
GetShadowRegisterInfo ( &shadowTAS3004Regs, kTAS3004LeftBiquad1CtrlReg, &shadowPtr, ®isterSize );
err = CODEC_WriteRegister( kTAS3004LeftBiquad1CtrlReg, shadowPtr, initMode );
FailIf( kIOReturnSuccess != err, AttemptToRetry );
GetShadowRegisterInfo ( &shadowTAS3004Regs, kTAS3004LeftBiquad2CtrlReg, &shadowPtr, ®isterSize );
err = CODEC_WriteRegister( kTAS3004LeftBiquad2CtrlReg, shadowPtr, initMode );
FailIf( kIOReturnSuccess != err, AttemptToRetry );
GetShadowRegisterInfo ( &shadowTAS3004Regs, kTAS3004LeftBiquad3CtrlReg, &shadowPtr, ®isterSize );
err = CODEC_WriteRegister( kTAS3004LeftBiquad3CtrlReg, shadowPtr, initMode );
FailIf( kIOReturnSuccess != err, AttemptToRetry );
GetShadowRegisterInfo ( &shadowTAS3004Regs, kTAS3004LeftBiquad4CtrlReg, &shadowPtr, ®isterSize );
err = CODEC_WriteRegister( kTAS3004LeftBiquad4CtrlReg, shadowPtr, initMode );
FailIf( kIOReturnSuccess != err, AttemptToRetry );
GetShadowRegisterInfo ( &shadowTAS3004Regs, kTAS3004LeftBiquad5CtrlReg, &shadowPtr, ®isterSize );
err = CODEC_WriteRegister( kTAS3004LeftBiquad5CtrlReg, shadowPtr, initMode );
FailIf( kIOReturnSuccess != err, AttemptToRetry );
GetShadowRegisterInfo ( &shadowTAS3004Regs, kTAS3004LeftBiquad6CtrlReg, &shadowPtr, ®isterSize );
err = CODEC_WriteRegister( kTAS3004LeftBiquad6CtrlReg, shadowPtr, initMode );
FailIf( kIOReturnSuccess != err, AttemptToRetry );
GetShadowRegisterInfo ( &shadowTAS3004Regs, kTAS3004LeftLoudnessBiquadReg, &shadowPtr, ®isterSize );
err = CODEC_WriteRegister( kTAS3004LeftLoudnessBiquadReg, shadowPtr, initMode );
FailIf( kIOReturnSuccess != err, AttemptToRetry );
GetShadowRegisterInfo ( &shadowTAS3004Regs, kTAS3004RightBiquad0CtrlReg, &shadowPtr, ®isterSize );
err = CODEC_WriteRegister( kTAS3004RightBiquad0CtrlReg, shadowPtr, initMode );
FailIf( kIOReturnSuccess != err, AttemptToRetry );
GetShadowRegisterInfo ( &shadowTAS3004Regs, kTAS3004RightBiquad1CtrlReg, &shadowPtr, ®isterSize );
err = CODEC_WriteRegister( kTAS3004RightBiquad1CtrlReg, shadowPtr, initMode );
FailIf( kIOReturnSuccess != err, AttemptToRetry );
GetShadowRegisterInfo ( &shadowTAS3004Regs, kTAS3004RightBiquad2CtrlReg, &shadowPtr, ®isterSize );
err = CODEC_WriteRegister( kTAS3004RightBiquad2CtrlReg, shadowPtr, initMode );
FailIf( kIOReturnSuccess != err, AttemptToRetry );
GetShadowRegisterInfo ( &shadowTAS3004Regs, kTAS3004RightBiquad3CtrlReg, &shadowPtr, ®isterSize );
err = CODEC_WriteRegister( kTAS3004RightBiquad3CtrlReg, shadowPtr, initMode );
FailIf( kIOReturnSuccess != err, AttemptToRetry );
GetShadowRegisterInfo ( &shadowTAS3004Regs, kTAS3004RightBiquad4CtrlReg, &shadowPtr, ®isterSize );
err = CODEC_WriteRegister( kTAS3004RightBiquad4CtrlReg, shadowPtr, initMode );
FailIf( kIOReturnSuccess != err, AttemptToRetry );
GetShadowRegisterInfo ( &shadowTAS3004Regs, kTAS3004RightBiquad5CtrlReg, &shadowPtr, ®isterSize );
err = CODEC_WriteRegister( kTAS3004RightBiquad5CtrlReg, shadowPtr, initMode );
FailIf( kIOReturnSuccess != err, AttemptToRetry );
GetShadowRegisterInfo ( &shadowTAS3004Regs, kTAS3004RightBiquad6CtrlReg, &shadowPtr, ®isterSize );
err = CODEC_WriteRegister( kTAS3004RightBiquad6CtrlReg, shadowPtr, initMode );
FailIf( kIOReturnSuccess != err, AttemptToRetry );
GetShadowRegisterInfo ( &shadowTAS3004Regs, kTAS3004RightLoudnessBiquadReg, &shadowPtr, ®isterSize );
err = CODEC_WriteRegister( kTAS3004RightLoudnessBiquadReg, shadowPtr, initMode );
FailIf( kIOReturnSuccess != err, AttemptToRetry );
err = InitEQSerialMode( kSetNormalLoadMode ); FailIf( kIOReturnSuccess != err, AttemptToRetry );
GetShadowRegisterInfo ( &shadowTAS3004Regs, kTAS3004DynamicRangeCtrlReg, &shadowPtr, ®isterSize );
err = CODEC_WriteRegister( kTAS3004DynamicRangeCtrlReg, shadowPtr, initMode );
FailIf( kIOReturnSuccess != err, AttemptToRetry );
GetShadowRegisterInfo ( &shadowTAS3004Regs, kTAS3004VolumeCtrlReg, &shadowPtr, ®isterSize );
err = CODEC_WriteRegister( kTAS3004VolumeCtrlReg, shadowPtr, initMode );
FailIf( kIOReturnSuccess != err, AttemptToRetry );
GetShadowRegisterInfo ( &shadowTAS3004Regs, kTAS3004TrebleCtrlReg, &shadowPtr, ®isterSize );
err = CODEC_WriteRegister( kTAS3004TrebleCtrlReg, shadowPtr, initMode );
FailIf( kIOReturnSuccess != err, AttemptToRetry );
GetShadowRegisterInfo ( &shadowTAS3004Regs, kTAS3004BassCtrlReg, &shadowPtr, ®isterSize );
err = CODEC_WriteRegister( kTAS3004BassCtrlReg, shadowPtr, initMode );
FailIf( kIOReturnSuccess != err, AttemptToRetry );
GetShadowRegisterInfo ( &shadowTAS3004Regs, kTAS3004MixerLeftGainReg, &shadowPtr, ®isterSize );
err = CODEC_WriteRegister( kTAS3004MixerLeftGainReg, shadowPtr, initMode );
FailIf( kIOReturnSuccess != err, AttemptToRetry );
GetShadowRegisterInfo ( &shadowTAS3004Regs, kTAS3004MixerRightGainReg, &shadowPtr, ®isterSize );
err = CODEC_WriteRegister( kTAS3004MixerRightGainReg, shadowPtr, initMode );
FailIf( kIOReturnSuccess != err, AttemptToRetry );
GetShadowRegisterInfo ( &shadowTAS3004Regs, kTAS3004LeftLoudnessBiquadGainReg, &shadowPtr, ®isterSize );
err = CODEC_WriteRegister( kTAS3004LeftLoudnessBiquadGainReg, shadowPtr, initMode );
FailIf( kIOReturnSuccess != err, AttemptToRetry );
GetShadowRegisterInfo ( &shadowTAS3004Regs, kTAS3004RightLoudnessBiquadGainReg, &shadowPtr, ®isterSize );
err = CODEC_WriteRegister( kTAS3004RightLoudnessBiquadGainReg, shadowPtr, initMode );
FailIf( kIOReturnSuccess != err, AttemptToRetry );
GetShadowRegisterInfo ( &shadowTAS3004Regs, kTAS3004AnalogControlReg, &shadowPtr, ®isterSize );
err = CODEC_WriteRegister( kTAS3004AnalogControlReg, shadowPtr, initMode );
FailIf( kIOReturnSuccess != err, AttemptToRetry );
GetShadowRegisterInfo ( &shadowTAS3004Regs, kTAS3004MainCtrl2Reg, &shadowPtr, ®isterSize );
err = CODEC_WriteRegister( kTAS3004MainCtrl2Reg, shadowPtr, initMode );
FailIf( kIOReturnSuccess != err, AttemptToRetry );
GetShadowRegisterInfo ( &shadowTAS3004Regs, kTAS3004MainCtrl1Reg, &shadowPtr, ®isterSize );
err = CODEC_WriteRegister( kTAS3004MainCtrl1Reg, &oldMode, initMode ); FailIf( kIOReturnSuccess != err, AttemptToRetry );
AttemptToRetry:
if( kIOReturnSuccess == err ) {
done = true;
mTAS_WasDead = false;
}
retryCount++;
} while ( !done && ( kTAS3004_MAX_RETRY_COUNT != retryCount ) );
mSemaphores = 0;
if( kTAS3004_MAX_RETRY_COUNT == retryCount ) {
mTAS_WasDead = true;
debugIOLog (5, "\n\n\n\n TAS3004 IS DEAD: Check %s\n\n\n", "ChooseAudio in fcr1" );
mPlatformInterface->LogFCR ();
mPlatformInterface->LogGPIO ();
mPlatformInterface->LogI2S ();
}
}
if( kIOReturnSuccess != err )
debugIOLog (7, "[AppleTAS3004Audio] CODEC_Initialize() err = %d ***** FATAL *****", err );
return err;
}
void AppleTAS3004Audio::CODEC_Reset ( void ) {
mPlatformInterface->setCodecReset ( kCODEC_RESET_Analog, kGPIO_Run );
IOSleep ( kCodec_RESET_SETUP_TIME ); mPlatformInterface->setCodecReset ( kCODEC_RESET_Analog, kGPIO_Reset );
IOSleep ( kCodec_RESET_HOLD_TIME );
mPlatformInterface->setCodecReset ( kCODEC_RESET_Analog, kGPIO_Run );
IOSleep ( kCodec_RESET_RELEASE_TIME );
}
IOReturn AppleTAS3004Audio::CODEC_ReadRegister(UInt8 regAddr, UInt8* registerData) {
UInt8 registerSize;
UInt32 regByteIndex;
UInt8 *shadowPtr;
IOReturn err;
err = kIOReturnSuccess;
registerSize = 0;
shadowPtr = NULL;
err = GetShadowRegisterInfo( &shadowTAS3004Regs, regAddr, &shadowPtr, ®isterSize );
if( kIOReturnSuccess == err )
{
for( regByteIndex = 0; regByteIndex < registerSize; regByteIndex++ )
{
registerData[regByteIndex] = shadowPtr[regByteIndex];
}
}
if( kIOReturnSuccess != err )
debugIOLog (3, "[AppleTAS3004Audio] %d notEnoughHardware = CODEC_ReadRegister( 0x%2.0X, 0x%8.0X )", err, regAddr, (unsigned int)registerData );
return err;
}
IOReturn AppleTAS3004Audio::CODEC_WriteRegister(UInt8 regAddr, UInt8* registerData, UInt8 mode){
UInt8 registerSize;
UInt32 regByteIndex;
UInt8 *shadowPtr;
IOReturn err;
Boolean updateRequired;
Boolean success;
err = kIOReturnSuccess;
updateRequired = false;
success = false;
registerSize = 0;
shadowPtr = NULL;
err = GetShadowRegisterInfo( &shadowTAS3004Regs, regAddr, &shadowPtr, ®isterSize );
if( kIOReturnSuccess == err )
{
if( kUPDATE_SHADOW == mode || kUPDATE_ALL == mode || kFORCE_UPDATE_ALL == mode )
{
success = true;
for( regByteIndex = 0; regByteIndex < registerSize; regByteIndex++ )
{
shadowPtr[regByteIndex] = registerData[regByteIndex];
}
}
if( kUPDATE_HW == mode || kUPDATE_ALL == mode || kFORCE_UPDATE_ALL == mode )
{
success = mPlatformInterface->writeCodecRegister(kDEQAddress, regAddr, registerData, registerSize, kI2C_StandardSubMode);
if ( !success ) { err = kIOReturnError; }
if ( success ) {
if ( mTAS_WasDead ) {
mAudioDeviceProvider->interruptEventHandler ( kRequestCodecRecoveryStatus, (UInt32)kControlBusFatalErrorRecovery );
}
}
if ( !success && !mSemaphores ) { debugIOLog (7, "AppleTAS3004Audio::CODEC_WriteRegister mPlatformInterface->writeCodecRegister ( %x, %p, %x ) %d POSTS A FATAL ERROR!", regAddr, registerData, kI2C_StandardSubMode, success );
mAudioDeviceProvider->interruptEventHandler ( kRequestCodecRecoveryStatus, (UInt32)kControlBusFatalErrorRecovery );
}
}
}
if( kIOReturnSuccess != err || !success ) {
debugIOLog (7, "error 0x%X returned, success == %d in AppleTAS3004Audio::CODEC_WriteRegister", err, success);
}
return err;
}
#pragma mark ---------------------
#pragma mark +UTILITY FUNCTIONS
#pragma mark ---------------------
IORegistryEntry *AppleTAS3004Audio::FindEntryByNameAndProperty (const IORegistryEntry * start, const char * name, const char * key, UInt32 value) {
OSIterator *iterator;
IORegistryEntry *theEntry;
IORegistryEntry *tmpReg;
OSNumber *tmpNumber;
theEntry = NULL;
iterator = NULL;
FailIf (NULL == start, Exit);
iterator = start->getChildIterator (gIOServicePlane);
FailIf (NULL == iterator, Exit);
while (NULL == theEntry && (tmpReg = OSDynamicCast (IORegistryEntry, iterator->getNextObject ())) != NULL) {
if (strcmp (tmpReg->getName (), name) == 0) {
tmpNumber = OSDynamicCast (OSNumber, tmpReg->getProperty (key));
if (NULL != tmpNumber && tmpNumber->unsigned32BitValue () == value) {
theEntry = tmpReg;
theEntry->retain();
}
}
}
Exit:
if (NULL != iterator) {
iterator->release ();
}
return theEntry;
}
IORegistryEntry *AppleTAS3004Audio::FindEntryByProperty (const IORegistryEntry * start, const char * key, const char * value) {
OSIterator *iterator;
IORegistryEntry *theEntry;
IORegistryEntry *tmpReg;
OSData *tmpData;
theEntry = NULL;
iterator = start->getChildIterator (gIODTPlane);
FailIf (NULL == iterator, Exit);
while (NULL == theEntry && (tmpReg = OSDynamicCast (IORegistryEntry, iterator->getNextObject ())) != NULL) {
tmpData = OSDynamicCast (OSData, tmpReg->getProperty (key));
if (NULL != tmpData && tmpData->isEqualTo (value, strlen (value))) {
theEntry = tmpReg;
}
}
Exit:
if (NULL != iterator) {
iterator->release ();
}
return theEntry;
}
Boolean AppleTAS3004Audio::HasInput (void) {
IORegistryEntry *sound;
OSData *tmpData;
UInt32 *numInputs = NULL;
Boolean hasInput;
debugIOLog (3, "+ AppleTAS3004Audio::HasInput" );
hasInput = false;
sound = mAudioDeviceProvider->getParentEntry (gIOServicePlane);
FailIf (!sound, Exit);
tmpData = OSDynamicCast (OSData, sound->getProperty (kNumInputs));
FailIf (!tmpData, Exit);
numInputs = (UInt32*)tmpData->getBytesNoCopy ();
if (*numInputs > 1) {
hasInput = true;
}
Exit:
debugIOLog (3, "- AppleTAS3004Audio::HasInput returns %d, numInputs %ld", hasInput, NULL == numInputs ? 0 : *numInputs );
return hasInput;
}
IOReturn AppleTAS3004Audio::setBiquadCoefficients ( void * biquadCoefficients )
{
IOReturn err;
IOReturn totalErr = kIOReturnError;
totalErr = kIOReturnSuccess;
for ( UInt32 index = 0; index < ( kTAS3004NumBiquads * kTAS3004MaxStreamCnt ); index ++ ) {
if ( kTAS3004NumBiquads > index ) {
err = SndHWSetOutputBiquad ( kStreamFrontLeft, index, (FourDotTwenty*)biquadCoefficients );
} else {
err = SndHWSetOutputBiquad ( kStreamFrontRight, index - kTAS3004NumBiquads, (FourDotTwenty*)biquadCoefficients );
}
(( EQFilterCoefficients*)biquadCoefficients)++;
if ( err ) { totalErr = err; }
}
return totalErr;
}
void AppleTAS3004Audio::disableProcessing ( Boolean inRealtime ) {
UInt32 index;
UInt8 data[kTAS3004BIQwidth*2];
debugIOLog (3, "+ AppleTAS3004Audio::disableProcessing, already disabled = %s", mEQDisabled ? "true" : "false" );
if (FALSE == mEQDisabled) {
if (FALSE == inRealtime) {
SetVolumeCoefficients (0, 0); IODelay ( 70000 ); SetAnalogPowerDownMode (kPowerDownAnalog); IODelay ( 10000 );
InitEQSerialMode ( kSetFastLoadMode ); }
for( index = 0; index < sizeof ( data ); index++ ) { data[index] = 0x00; }
data[3] = 0x10;
for ( index = 0; index < kTAS3004BIQwidth; index++ ) {
standbyTAS3004Regs.sLB0[index] = shadowTAS3004Regs.sLB0[index];
standbyTAS3004Regs.sLB1[index] = shadowTAS3004Regs.sLB1[index];
standbyTAS3004Regs.sLB2[index] = shadowTAS3004Regs.sLB2[index];
standbyTAS3004Regs.sLB3[index] = shadowTAS3004Regs.sLB3[index];
standbyTAS3004Regs.sLB4[index] = shadowTAS3004Regs.sLB4[index];
standbyTAS3004Regs.sLB5[index] = shadowTAS3004Regs.sLB5[index];
standbyTAS3004Regs.sLB6[index] = shadowTAS3004Regs.sLB6[index];
standbyTAS3004Regs.sRB0[index] = shadowTAS3004Regs.sRB0[index];
standbyTAS3004Regs.sRB1[index] = shadowTAS3004Regs.sRB1[index];
standbyTAS3004Regs.sRB2[index] = shadowTAS3004Regs.sRB2[index];
standbyTAS3004Regs.sRB3[index] = shadowTAS3004Regs.sRB3[index];
standbyTAS3004Regs.sRB4[index] = shadowTAS3004Regs.sRB4[index];
standbyTAS3004Regs.sRB5[index] = shadowTAS3004Regs.sRB5[index];
standbyTAS3004Regs.sRB6[index] = shadowTAS3004Regs.sRB6[index];
}
for( index = 0; index < kTAS3004DRCwidth; index++ ) {
standbyTAS3004Regs.sDRC[index] = shadowTAS3004Regs.sDRC[index];
}
for ( index = kTAS3004LeftBiquad0CtrlReg; index < kTAS3004LeftBiquad6CtrlReg; index++ ) {
CODEC_WriteRegister( index, &data[3], kUPDATE_ALL );
CODEC_WriteRegister( index + ( kTAS3004RightBiquad0CtrlReg - kTAS3004LeftBiquad0CtrlReg ), &data[3], kUPDATE_ALL );
}
CODEC_WriteRegister( kTAS3004LeftBiquad6CtrlReg, &data[3], kUPDATE_ALL );
CODEC_WriteRegister( kTAS3004RightBiquad6CtrlReg, &data[0], kUPDATE_ALL );
if (FALSE == inRealtime) {
InitEQSerialMode ( kSetNormalLoadMode ); IODelay ( 10000 );
SetAnalogPowerDownMode (kPowerNormalAnalog);
IODelay ( 10000 );
if ( !mAnalogMuteState ) {
SetVolumeCoefficients (volumeTable[(UInt32)mVolLeft], volumeTable[(UInt32)mVolRight]);
}
}
mEQDisabled = TRUE;
}
debugIOLog (3, "- AppleTAS3004Audio::disableProcessing" );
}
void AppleTAS3004Audio::enableProcessing (void) {
UInt8 mcr2Data[kTAS3004DRCwidth];
UInt32 index;
UInt8 data[kTAS3004BIQwidth*2];
debugIOLog (3, "+ AppleTAS3004Audio::enableEQ" );
SetVolumeCoefficients (0, 0); IODelay ( 70000 ); SetAnalogPowerDownMode (kPowerDownAnalog); IODelay ( 10000 );
InitEQSerialMode ( kSetFastLoadMode );
for( index = 0; index < sizeof ( data ); index++ ) { data[index] = 0x00; }
data[3] = 0x10;
CODEC_WriteRegister( kTAS3004LeftBiquad0CtrlReg, standbyTAS3004Regs.sLB0, kUPDATE_ALL );
CODEC_WriteRegister( kTAS3004LeftBiquad1CtrlReg, standbyTAS3004Regs.sLB1, kUPDATE_ALL );
CODEC_WriteRegister( kTAS3004LeftBiquad2CtrlReg, standbyTAS3004Regs.sLB2, kUPDATE_ALL );
CODEC_WriteRegister( kTAS3004LeftBiquad3CtrlReg, standbyTAS3004Regs.sLB3, kUPDATE_ALL );
CODEC_WriteRegister( kTAS3004LeftBiquad4CtrlReg, standbyTAS3004Regs.sLB4, kUPDATE_ALL );
CODEC_WriteRegister( kTAS3004LeftBiquad5CtrlReg, standbyTAS3004Regs.sLB5, kUPDATE_ALL );
CODEC_WriteRegister( kTAS3004LeftBiquad6CtrlReg, &data[3], kUPDATE_ALL );
CODEC_WriteRegister( kTAS3004RightBiquad0CtrlReg, standbyTAS3004Regs.sRB0, kUPDATE_ALL );
CODEC_WriteRegister( kTAS3004RightBiquad1CtrlReg, standbyTAS3004Regs.sRB1, kUPDATE_ALL );
CODEC_WriteRegister( kTAS3004RightBiquad2CtrlReg, standbyTAS3004Regs.sRB2, kUPDATE_ALL );
CODEC_WriteRegister( kTAS3004RightBiquad3CtrlReg, standbyTAS3004Regs.sRB3, kUPDATE_ALL );
CODEC_WriteRegister( kTAS3004RightBiquad4CtrlReg, standbyTAS3004Regs.sRB4, kUPDATE_ALL );
CODEC_WriteRegister( kTAS3004RightBiquad5CtrlReg, standbyTAS3004Regs.sRB5, kUPDATE_ALL );
CODEC_WriteRegister( kTAS3004RightBiquad6CtrlReg, &data[0], kUPDATE_ALL );
for( index = 0; index < kTAS3004DRCwidth; index++ ) {
mcr2Data[index] = standbyTAS3004Regs.sDRC[index];
}
CODEC_WriteRegister( kTAS3004DynamicRangeCtrlReg, mcr2Data, kFORCE_UPDATE_ALL );
InitEQSerialMode ( kSetNormalLoadMode ); IODelay ( 10000 );
SetAnalogPowerDownMode (kPowerNormalAnalog); IODelay ( 10000 );
if ( !mAnalogMuteState ) {
SetVolumeCoefficients (volumeTable[(UInt32)mVolLeft], volumeTable[(UInt32)mVolRight]);
}
mEQDisabled = FALSE;
debugIOLog (3, "- AppleTAS3004Audio::enableEQ" );
}
IOReturn AppleTAS3004Audio::SndHWSetOutputBiquad( UInt32 streamID, UInt32 biquadRefNum, FourDotTwenty *biquadCoefficients )
{
IOReturn err;
UInt32 coefficientIndex;
UInt32 TAS3004BiquadIndex;
UInt32 biquadGroupIndex;
UInt8 TAS3004Biquad[kTAS3004CoefficientsPerBiquad * kTAS3004NumBiquads];
err = kIOReturnSuccess;
FailWithAction( kTAS3004MaxBiquadRefNum < biquadRefNum || NULL == biquadCoefficients, err = kIOReturnError, Exit );
FailWithAction( kStreamStereo != streamID && kStreamFrontLeft != streamID && kStreamFrontRight != streamID, err = kIOReturnError, Exit );
TAS3004BiquadIndex = 0;
biquadGroupIndex = biquadRefNum * kTAS3004CoefficientsPerBiquad;
if( kStreamFrontRight == streamID )
biquadGroupIndex += kNumberOfTAS3004BiquadCoefficientsPerChannel;
for( coefficientIndex = 0; coefficientIndex < kTAS3004CoefficientsPerBiquad; coefficientIndex++ )
{
TAS3004Biquad[TAS3004BiquadIndex++] = biquadCoefficients[coefficientIndex].integerAndFraction1;
TAS3004Biquad[TAS3004BiquadIndex++] = biquadCoefficients[coefficientIndex].fraction2;
TAS3004Biquad[TAS3004BiquadIndex++] = biquadCoefficients[coefficientIndex].fraction3;
}
err = SetOutputBiquadCoefficients( streamID, biquadRefNum, TAS3004Biquad );
Exit:
return err;
}
IOReturn AppleTAS3004Audio::SndHWSetOutputBiquadGroup( UInt32 biquadFilterCount, FourDotTwenty *biquadCoefficients )
{
UInt32 index;
IOReturn err;
FailWithAction( 0 == biquadFilterCount || NULL == biquadCoefficients, err = kIOReturnError, Exit );
err = kIOReturnSuccess;
InitEQSerialMode( kSetFastLoadMode );
index = 0;
do {
if( index >= ( biquadFilterCount / 2 ) ) {
err = SndHWSetOutputBiquad( kStreamFrontRight, index - ( biquadFilterCount / 2 ), biquadCoefficients );
} else {
err = SndHWSetOutputBiquad( kStreamFrontLeft, index, biquadCoefficients );
}
index++;
biquadCoefficients += kNumberOfCoefficientsPerBiquad;
} while ( ( index < biquadFilterCount ) && ( kIOReturnSuccess == err ) );
InitEQSerialMode( kSetNormalLoadMode );
Exit:
return err;
}
IOReturn AppleTAS3004Audio::SetOutputBiquadCoefficients( UInt32 streamID, UInt32 biquadRefNum, UInt8 *biquadCoefficients )
{
UInt32 index;
UInt8 data[kTAS3004BIQwidth*2];
IOReturn err;
err = kIOReturnSuccess;
FailWithAction ( kTAS3004MaxBiquadRefNum < biquadRefNum || NULL == biquadCoefficients, err = kIOReturnError, Exit );
FailWithAction ( kStreamStereo != streamID && kStreamFrontLeft != streamID && kStreamFrontRight != streamID, err = kIOReturnError, Exit );
switch ( biquadRefNum )
{
case kBiquadRefNum_0:
switch( streamID )
{
case kStreamFrontLeft: err = CODEC_WriteRegister( kTAS3004LeftBiquad0CtrlReg, biquadCoefficients, kUPDATE_ALL ); break;
case kStreamFrontRight: err = CODEC_WriteRegister( kTAS3004RightBiquad0CtrlReg, biquadCoefficients, kUPDATE_ALL ); break;
case kStreamStereo: err = CODEC_WriteRegister( kTAS3004LeftBiquad0CtrlReg, biquadCoefficients, kUPDATE_ALL );
err = CODEC_WriteRegister( kTAS3004RightBiquad0CtrlReg, biquadCoefficients, kUPDATE_ALL ); break;
}
break;
case kBiquadRefNum_1:
switch( streamID )
{
case kStreamFrontLeft: err = CODEC_WriteRegister( kTAS3004LeftBiquad1CtrlReg, biquadCoefficients, kUPDATE_ALL ); break;
case kStreamFrontRight: err = CODEC_WriteRegister( kTAS3004RightBiquad1CtrlReg, biquadCoefficients, kUPDATE_ALL ); break;
case kStreamStereo: err = CODEC_WriteRegister( kTAS3004LeftBiquad1CtrlReg, biquadCoefficients, kUPDATE_ALL );
err = CODEC_WriteRegister( kTAS3004RightBiquad1CtrlReg, biquadCoefficients, kUPDATE_ALL ); break;
}
break;
case kBiquadRefNum_2:
switch( streamID )
{
case kStreamFrontLeft: err = CODEC_WriteRegister( kTAS3004LeftBiquad2CtrlReg, biquadCoefficients, kUPDATE_ALL ); break;
case kStreamFrontRight: err = CODEC_WriteRegister( kTAS3004RightBiquad2CtrlReg, biquadCoefficients, kUPDATE_ALL ); break;
case kStreamStereo: err = CODEC_WriteRegister( kTAS3004LeftBiquad2CtrlReg, biquadCoefficients, kUPDATE_ALL );
err = CODEC_WriteRegister( kTAS3004RightBiquad2CtrlReg, biquadCoefficients, kUPDATE_ALL ); break;
}
break;
case kBiquadRefNum_3:
switch( streamID )
{
case kStreamFrontLeft: err = CODEC_WriteRegister( kTAS3004LeftBiquad3CtrlReg, biquadCoefficients, kUPDATE_ALL ); break;
case kStreamFrontRight: err = CODEC_WriteRegister( kTAS3004RightBiquad3CtrlReg, biquadCoefficients, kUPDATE_ALL ); break;
case kStreamStereo: err = CODEC_WriteRegister( kTAS3004LeftBiquad3CtrlReg, biquadCoefficients, kUPDATE_ALL );
err = CODEC_WriteRegister( kTAS3004RightBiquad3CtrlReg, biquadCoefficients, kUPDATE_ALL ); break;
}
break;
case kBiquadRefNum_4:
switch( streamID )
{
case kStreamFrontLeft: err = CODEC_WriteRegister( kTAS3004LeftBiquad4CtrlReg, biquadCoefficients, kUPDATE_ALL ); break;
case kStreamFrontRight: err = CODEC_WriteRegister( kTAS3004RightBiquad4CtrlReg, biquadCoefficients, kUPDATE_ALL ); break;
case kStreamStereo: err = CODEC_WriteRegister( kTAS3004LeftBiquad4CtrlReg, biquadCoefficients, kUPDATE_ALL );
err = CODEC_WriteRegister( kTAS3004RightBiquad4CtrlReg, biquadCoefficients, kUPDATE_ALL ); break;
}
break;
case kBiquadRefNum_5:
switch( streamID )
{
case kStreamFrontLeft: err = CODEC_WriteRegister( kTAS3004LeftBiquad5CtrlReg, biquadCoefficients, kUPDATE_ALL ); break;
case kStreamFrontRight: err = CODEC_WriteRegister( kTAS3004RightBiquad5CtrlReg, biquadCoefficients, kUPDATE_ALL ); break;
case kStreamStereo: err = CODEC_WriteRegister( kTAS3004LeftBiquad5CtrlReg, biquadCoefficients, kUPDATE_ALL );
err = CODEC_WriteRegister( kTAS3004RightBiquad5CtrlReg, biquadCoefficients, kUPDATE_ALL ); break;
}
break;
case kBiquadRefNum_6:
#if 1 // hardware phase correction
for( index = 0; index < sizeof ( data ); index++ ) { data[index] = 0x00; }
data[3] = 0x10;
switch( streamID )
{
case kStreamFrontLeft:
case kStreamFrontRight:
case kStreamStereo: err = CODEC_WriteRegister( kTAS3004LeftBiquad6CtrlReg, &data[3], kUPDATE_ALL );
err = CODEC_WriteRegister( kTAS3004RightBiquad6CtrlReg, &data[0], kUPDATE_ALL ); break;
}
break;
#else
switch( streamID )
{
case kStreamFrontLeft: err = CODEC_WriteRegister( kTAS3004LeftBiquad6CtrlReg, biquadCoefficients, kUPDATE_ALL ); break;
case kStreamFrontRight: err = CODEC_WriteRegister( kTAS3004RightBiquad6CtrlReg, biquadCoefficients, kUPDATE_ALL ); break;
case kStreamStereo: err = CODEC_WriteRegister( kTAS3004LeftBiquad6CtrlReg, biquadCoefficients, kUPDATE_ALL );
err = CODEC_WriteRegister( kTAS3004RightBiquad6CtrlReg, biquadCoefficients, kUPDATE_ALL ); break;
}
#endif
break;
}
Exit:
debugIOLog (3, "± AppleTAS3004Audio::SetOutputBiquadCoefficients (%4s, %ld,%p) returns %x", (char*)&streamID, biquadRefNum, biquadCoefficients, err);
return err;
}
#pragma mark ---------------------
#pragma mark ¥ USER CLIENT SUPPORT
#pragma mark ---------------------
IOReturn AppleTAS3004Audio::getPluginState ( HardwarePluginDescriptorPtr outState ) {
IOReturn result = kIOReturnBadArgument;
UInt8 * shadowRegs;
FailIf ( NULL == outState, Exit );
outState->hardwarePluginType = getPluginType();
outState->registerCacheSize = sizeof ( shadowTAS3004Regs );
shadowRegs = (UInt8*)&shadowTAS3004Regs.sMC1R;
for ( UInt32 registerAddress = 0; registerAddress < outState->registerCacheSize; registerAddress++ ) {
outState->registerCache[registerAddress] = shadowRegs[registerAddress];
}
outState->recoveryRequest = 0;
result = kIOReturnSuccess;
Exit:
return result;
}
IOReturn AppleTAS3004Audio::setPluginState ( HardwarePluginDescriptorPtr inState ) {
TAS3004_ShadowReg * newRegValues;
UInt8 * shadowPtr;
UInt8 * inStateShadowPtr;
UInt8 registerSize;
UInt8 outRegisterSize;
IOReturn result;
UInt8 regAddrList[] = { kTAS3004MainCtrl1Reg,
kTAS3004DynamicRangeCtrlReg,
kTAS3004VolumeCtrlReg,
kTAS3004TrebleCtrlReg,
kTAS3004BassCtrlReg,
kTAS3004MixerLeftGainReg,
kTAS3004MixerRightGainReg,
kTAS3004LeftBiquad0CtrlReg,
kTAS3004LeftBiquad1CtrlReg,
kTAS3004LeftBiquad2CtrlReg,
kTAS3004LeftBiquad3CtrlReg,
kTAS3004LeftBiquad4CtrlReg,
kTAS3004LeftBiquad5CtrlReg,
kTAS3004LeftBiquad6CtrlReg,
kTAS3004RightBiquad0CtrlReg,
kTAS3004RightBiquad1CtrlReg,
kTAS3004RightBiquad2CtrlReg,
kTAS3004RightBiquad3CtrlReg,
kTAS3004RightBiquad4CtrlReg,
kTAS3004RightBiquad5CtrlReg,
kTAS3004RightBiquad6CtrlReg,
kTAS3004LeftLoudnessBiquadReg,
kTAS3004RightLoudnessBiquadReg,
kTAS3004LeftLoudnessBiquadGainReg,
kTAS3004RightLoudnessBiquadGainReg,
kTAS3004AnalogControlReg,
kTAS3004MainCtrl2Reg
};
result = kIOReturnBadArgument;
FailIf ( NULL == inState, Exit );
FailIf ( sizeof ( shadowTAS3004Regs ) != inState->registerCacheSize, Exit );
result = kIOReturnSuccess;
newRegValues = (TAS3004_ShadowReg*)&inState->registerCache;
for ( UInt32 index = 0; ( index < ( sizeof ( regAddrList ) / sizeof ( UInt8 ) ) ) && ( kIOReturnSuccess == result ); index++ ) {
if ( kIOReturnSuccess == GetShadowRegisterInfo ( &shadowTAS3004Regs, regAddrList[index], &shadowPtr, ®isterSize ) ) {
if ( kIOReturnSuccess == GetShadowRegisterInfo ( newRegValues, regAddrList[index], &inStateShadowPtr, &outRegisterSize ) ) {
for ( UInt8 registerByteAddress = 0; registerByteAddress < registerSize; registerByteAddress++ ) {
if ( inStateShadowPtr[registerByteAddress] != shadowPtr[registerByteAddress] ) {
result = CODEC_WriteRegister ( regAddrList[index], inStateShadowPtr, kUPDATE_ALL );
break;
}
}
}
}
}
Exit:
return result;
}
HardwarePluginType AppleTAS3004Audio::getPluginType ( void ) {
return kCodec_TAS3004;
}