AppleOnboardAudio.cpp [plain text]
#include <IOKit/IOCommandGate.h>
#include <IOKit/IOMessage.h>
#include <IOKit/pwr_mgt/RootDomain.h>
#include <IOKit/IOTimerEventSource.h>
#include "IOKit/audio/IOAudioDevice.h"
#include "AppleOnboardAudio.h"
#include "AudioHardwareUtilities.h"
#include "AudioHardwareObjectInterface.h"
#include "PlatformFactory.h"
#include "PlatformInterface.h"
#include "TransportFactory.h"
OSDefineMetaClassAndStructors(AppleOnboardAudio, IOAudioDevice)
UInt32 AppleOnboardAudio::sInstanceCount = 0;
#define super IOAudioDevice
#define LOCALIZABLE 1
#define FORCE_MULTIPLE_DEVICES_TO_LOAD
#define ONLY_PUBLISH_ONE_BUILIT_DEVICE
#define DONT_THREAD_INIT
#pragma mark +UNIX LIKE FUNCTIONS
bool AppleOnboardAudio::init (OSDictionary *properties)
{
debugIOLog (3, "+ AppleOnboardAudio[%p]::init", this);
if (!super::init(properties)) return false;
currentDevices = 0xFFFF;
mHasHardwareInputGain = true;
mInternalMicDualMonoMode = e_Mode_Disabled;
mSampleRateSelectInProcessSemaphore = false;
mClockSelectInProcessSemaphore = false;
mCurrentProcessingOutputString = OSString::withCString ("none");
mCurrentProcessingInputString = OSString::withCString ("none");
mUCState.ucPowerState = kIOAudioDeviceActive;
debugIOLog (3, "- AppleOnboardAudio[%p]::init", this);
return true;
}
bool AppleOnboardAudio::start (IOService * provider) {
bool result;
debugIOLog (3, "+ AppleOnboardAudio[%ld]::start (%p)", mInstanceIndex, provider);
result = FALSE;
AppleOnboardAudio::sInstanceCount++;
mInstanceIndex = AppleOnboardAudio::sInstanceCount;
mProvider = provider;
provider->open (this);
mPowerThread = thread_call_allocate ((thread_call_func_t)AppleOnboardAudio::performPowerStateChangeThread, (thread_call_param_t)this);
FailIf (NULL == mPowerThread, Exit);
mInitHardwareThread = thread_call_allocate ((thread_call_func_t)AppleOnboardAudio::initHardwareThread, (thread_call_param_t)this);
FailIf (NULL == mInitHardwareThread, Exit);
debugIOLog (3, "- AppleOnboardAudio[%ld]::start (%p)", mInstanceIndex, provider);
result = super::start (provider);
Exit:
return result;
}
bool AppleOnboardAudio::handleOpen (IOService * forClient, IOOptionBits options, void * arg )
{
bool result;
debugIOLog (3, "AppleOnboardAudio[%ld]::handleOpen(%p)", mInstanceIndex, forClient);
if (kFamilyOption_OpenMultiple == options) {
result = true;
} else {
result = super::handleOpen ( forClient, options, arg );
FailIf (!result, Exit);
}
registerPlugin ( (AudioHardwareObjectInterface *)forClient );
Exit:
debugIOLog (3, "AppleOnboardAudio[%ld]::handleOpen(%p) returns %s", mInstanceIndex, forClient, result == true ? "true" : "false");
return result;
}
void AppleOnboardAudio::handleClose (IOService * forClient, IOOptionBits options )
{
debugIOLog (3, "AppleOnboardAudio[%ld]::handleClose(%p)", mInstanceIndex, forClient);
unRegisterPlugin ( (AudioHardwareObjectInterface *)forClient );
if (options != kFamilyOption_OpenMultiple) {
super::handleClose ( forClient, options );
}
return;
}
bool AppleOnboardAudio::willTerminate ( IOService * provider, IOOptionBits options )
{
bool result = super::willTerminate ( provider, options );
provider->close(this);
debugIOLog (3, "AppleOnboardAudio[%ld]::willTerminate(%p) returns %d", mInstanceIndex, provider, result);
return result;
}
void AppleOnboardAudio::registerPlugin (AudioHardwareObjectInterface *thePlugin) {
debugIOLog (3, "AppleOnboardAudio[%ld]::registerPlugin (%p)", mInstanceIndex, thePlugin);
FailIf ( NULL == mPluginObjects, Exit );
mPluginObjects->setObject (thePlugin);
Exit:
return;
}
void AppleOnboardAudio::stop (IOService * provider) {
if ( NULL != aoaNotifier ) {
aoaNotifier->remove();
}
FailIf ( mProvider != provider, Exit );
if (NULL != mSysPowerDownNotifier) {
mSysPowerDownNotifier->remove ();
mSysPowerDownNotifier = NULL;
}
mTerminating = TRUE;
if (idleTimer) {
if (workLoop) {
workLoop->removeEventSource (idleTimer);
}
idleTimer->release ();
idleTimer = NULL;
}
if (mSoftwareInterruptHandler) {
if (workLoop) {
workLoop->removeEventSource (mSoftwareInterruptHandler);
mSoftwareInterruptHandler->release ();
}
}
if ( pollTimer ) {
if ( workLoop ) {
workLoop->removeEventSource ( pollTimer );
}
pollTimer->release ();
pollTimer = NULL;
}
callPluginsInOrder ( kSetMuteState, TRUE );
if (mPowerThread) {
thread_call_cancel (mPowerThread);
}
debugIOLog (3, "AppleOnboardAudio[%ld]::stop(), audioEngines = %p, isInactive() = %d", mInstanceIndex, audioEngines, isInactive());
Exit:
super::stop (provider);
}
void AppleOnboardAudio::unRegisterPlugin (AudioHardwareObjectInterface *inPlugin) {
AudioHardwareObjectInterface * thePluginObject;
UInt32 index;
UInt32 count;
debugIOLog (3, "AppleOnboardAudio[%ld]::unRegisterPlugin (%p)", mInstanceIndex, inPlugin);
if (NULL != mPluginObjects) {
count = mPluginObjects->getCount ();
for (index = 0; index < count; index++) {
thePluginObject = getIndexedPluginObject (index);
if ((NULL != thePluginObject) && (inPlugin == thePluginObject)) {
mPluginObjects->removeObject(index);
debugIOLog (3, "removed (%p)", inPlugin);
}
}
}
return;
}
IOReturn AppleOnboardAudio::registerPluginAction (OSObject *owner, void *arg1, void *arg2, void *arg3, void *arg4) {
AppleOnboardAudio * device;
device = OSDynamicCast (AppleOnboardAudio, owner);
debugIOLog (3, "AppleOnboardAudio[%ld]::plugin %p registering", device->mInstanceIndex, arg1);
if (NULL == device->mPluginObjects) {
device->mPluginObjects = OSArray::withCapacity (1);
}
FailIf (NULL == device->mPluginObjects, Exit);
device->mPluginObjects->setObject ((AudioHardwareObjectInterface *)arg1);
Exit:
return kIOReturnSuccess;
}
OSObject * AppleOnboardAudio::getLayoutEntry (const char * entryID, AppleOnboardAudio * theAOA) {
OSArray * layouts;
OSDictionary * layoutEntry;
OSObject * entry;
entry = NULL;
layouts = OSDynamicCast (OSArray, theAOA->getProperty (kLayouts));
FailIf (NULL == layouts, Exit);
#ifdef REMOVE_LAYOUTS
layoutEntry = OSDynamicCast (OSDictionary, layouts->getObject (0));
#else
layoutEntry = OSDynamicCast (OSDictionary, layouts->getObject (theAOA->mMatchingIndex));
#endif
FailIf (NULL == layoutEntry, Exit);
entry = OSDynamicCast (OSObject, layoutEntry->getObject (entryID));
Exit:
return entry;
}
bool AppleOnboardAudio::hasMasterVolumeControl (const UInt32 inCode) {
char * connectionString;
connectionString = getConnectionKeyFromCharCode (inCode, kIOAudioStreamDirectionOutput);
return hasMasterVolumeControl (connectionString);
}
bool AppleOnboardAudio::hasMasterVolumeControl (const char * outputEntry) {
OSDictionary * dictEntry;
OSArray * controlsArray;
OSString * controlString;
UInt32 controlsCount;
UInt32 index;
bool hasMasterVolControl;
debugIOLog ( 3, "+ AppleOnboardAudio[%ld]::hasMasterVolumeControl('%4s')", mInstanceIndex, outputEntry );
hasMasterVolControl = FALSE;
dictEntry = OSDynamicCast (OSDictionary, getLayoutEntry (outputEntry, this));
FailIf (NULL == dictEntry, Exit);
controlsArray = OSDynamicCast (OSArray, dictEntry->getObject (kControls));
FailIf (NULL == controlsArray, Exit);
controlsCount = controlsArray->getCount ();
for (index = 0; index < controlsCount; index++) {
controlString = OSDynamicCast (OSString, controlsArray->getObject (index));
if ((NULL != controlString) && controlString->isEqualTo (kMasterVolControlString)) {
hasMasterVolControl = TRUE;
}
}
Exit:
debugIOLog ( 3, "- AppleOnboardAudio[%ld]::hasMasterVolumeControl('%4s') returns %d", mInstanceIndex, outputEntry, hasMasterVolControl );
return hasMasterVolControl;
}
bool AppleOnboardAudio::hasLeftVolumeControl (const UInt32 inCode) {
char * connectionString;
connectionString = getConnectionKeyFromCharCode (inCode, kIOAudioStreamDirectionOutput);
return hasLeftVolumeControl (connectionString);
}
bool AppleOnboardAudio::hasLeftVolumeControl (const char * outputEntry) {
OSDictionary * dictEntry;
OSArray * controlsArray;
OSString * controlString;
UInt32 controlsCount;
UInt32 index;
bool hasLeftVolControl;
debugIOLog ( 3, "+ AppleOnboardAudio[%ld]::hasLeftVolumeControl('%4s')", mInstanceIndex, outputEntry );
hasLeftVolControl = FALSE;
dictEntry = OSDynamicCast (OSDictionary, getLayoutEntry (outputEntry, this));
FailIf (NULL == dictEntry, Exit);
controlsArray = OSDynamicCast (OSArray, dictEntry->getObject (kControls));
FailIf (NULL == controlsArray, Exit);
controlsCount = controlsArray->getCount ();
for (index = 0; index < controlsCount; index++) {
controlString = OSDynamicCast (OSString, controlsArray->getObject (index));
if ((NULL != controlString) && controlString->isEqualTo (kLeftVolControlString)) {
hasLeftVolControl = TRUE;
}
}
Exit:
debugIOLog ( 3, "- AppleOnboardAudio[%ld]::hasLeftVolumeControl('%4s') returns %d", mInstanceIndex, outputEntry, hasLeftVolControl );
return hasLeftVolControl;
}
bool AppleOnboardAudio::hasRightVolumeControl (const UInt32 inCode) {
char * connectionString;
connectionString = getConnectionKeyFromCharCode (inCode, kIOAudioStreamDirectionOutput);
return hasRightVolumeControl (connectionString);
}
bool AppleOnboardAudio::hasRightVolumeControl (const char * outputEntry) {
OSDictionary * dictEntry;
OSArray * controlsArray;
OSString * controlString;
UInt32 controlsCount;
UInt32 index;
bool hasRightVolControl;
debugIOLog ( 3, "+ AppleOnboardAudio[%ld]::hasRightVolumeControl('%4s')", mInstanceIndex, outputEntry );
hasRightVolControl = FALSE;
dictEntry = OSDynamicCast (OSDictionary, getLayoutEntry (outputEntry, this));
FailIf (NULL == dictEntry, Exit);
controlsArray = OSDynamicCast (OSArray, dictEntry->getObject (kControls));
FailIf (NULL == controlsArray, Exit);
controlsCount = controlsArray->getCount ();
for (index = 0; index < controlsCount; index++) {
controlString = OSDynamicCast (OSString, controlsArray->getObject (index));
if ((NULL != controlString) && controlString->isEqualTo (kRightVolControlString)) {
hasRightVolControl = TRUE;
}
}
Exit:
debugIOLog ( 3, "- AppleOnboardAudio[%ld]::hasRightVolumeControl('%4s') returns %d", mInstanceIndex, outputEntry, hasRightVolControl );
return hasRightVolControl;
}
void AppleOnboardAudio::setUseInputGainControls (const char * inputEntry) {
OSDictionary * dictEntry;
OSArray * controlsArray;
OSString * controlString;
UInt32 controlsCount;
UInt32 index;
debugIOLog (3, "AppleOnboardAudio[%ld]::setUseInputGainControls(%s)", mInstanceIndex, inputEntry);
mUseInputGainControls = kNoInputGainControls;
dictEntry = OSDynamicCast (OSDictionary, getLayoutEntry (inputEntry, this));
FailIf (NULL == dictEntry, Exit);
controlsArray = OSDynamicCast (OSArray, dictEntry->getObject (kControls));
FailIf (NULL == controlsArray, Exit);
controlsCount = controlsArray->getCount ();
for (index = 0; index < controlsCount; index++) {
controlString = OSDynamicCast (OSString, controlsArray->getObject (index));
if ((NULL != controlString) && (controlString->isEqualTo (kLeftVolControlString) || controlString->isEqualTo (kRightVolControlString))) {
mUseInputGainControls = kStereoInputGainControls;
debugIOLog (3, "mUseInputGainControls = kStereoInputGainControls");
} else if ((NULL != controlString) && (controlString->isEqualTo (kMasterVolControlString))) {
mUseInputGainControls = kMonoInputGainControl;
debugIOLog (3, "mUseInputGainControls = kMonoInputGainControl");
}
}
Exit:
return;
}
void AppleOnboardAudio::setUsePlaythroughControl (const char * inputEntry) {
OSDictionary * dictEntry;
OSBoolean * playthroughOSBoolean;
debugIOLog (3, "+ AppleOnboardAudio[%ld]::setUsePlaythroughControl(%s)", mInstanceIndex, inputEntry );
mUsePlaythroughControl = FALSE;
dictEntry = OSDynamicCast ( OSDictionary, getLayoutEntry ( inputEntry, this) );
FailIf ( NULL == dictEntry, Exit );
playthroughOSBoolean = OSDynamicCast ( OSBoolean, dictEntry->getObject ( kPlaythroughControlString ) );
FailIf ( NULL == playthroughOSBoolean, Exit );
mUsePlaythroughControl = playthroughOSBoolean->getValue ();
Exit:
debugIOLog (3, "- AppleOnboardAudio[%ld]::setUsePlaythroughControl(%s), mUsePlaythroughControl = %d", mInstanceIndex, inputEntry, mUsePlaythroughControl );
return;
}
IOReturn AppleOnboardAudio::formatChangeRequest (const IOAudioStreamFormat * inFormat, const IOAudioSampleRate * inRate) {
IOReturn result;
OSNumber * connectionCodeNumber;
result = kIOReturnError;
callPluginsInOrder ( kSetMuteState, TRUE );
if (NULL != inFormat) {
debugIOLog (3, "AppleOnboardAudio[%ld]::formatChangeRequest with bit width %d", mInstanceIndex, inFormat->fBitWidth);
result = mTransportInterface->transportSetSampleWidth (inFormat->fBitDepth, inFormat->fBitWidth);
callPluginsInOrder (kSetSampleBitDepth, inFormat->fBitDepth);
if (kIOAudioStreamSampleFormat1937AC3 == inFormat->fSampleFormat) {
if (NULL != mOutputSelector) {
connectionCodeNumber = OSNumber::withNumber (kIOAudioOutputPortSubTypeSPDIF, 32);
mOutputSelector->setValue (connectionCodeNumber);
connectionCodeNumber->release ();
mEncodedOutputFormat = true;
}
} else {
mEncodedOutputFormat = false;
}
result = callPluginsInOrder ( kSetSampleType, inFormat->fSampleFormat );
}
if (NULL != inRate) {
mSampleRateSelectInProcessSemaphore = true;
debugIOLog (3, "AppleOnboardAudio[%ld]::formatChangeRequest with rate %ld", mInstanceIndex, inRate->whole);
result = mTransportInterface->transportSetSampleRate (inRate->whole);
callPluginsInOrder (kSetSampleRate, inRate->whole);
if ( kIOReturnSuccess == result ) {
mTransportSampleRate.whole = inRate->whole;
mTransportSampleRate.fraction = inRate->fraction;
mSampleRateSelectInProcessSemaphore = false;
}
}
if ( NULL != mOutputSelector ) {
selectOutput (mOutputSelector->getIntValue (), mIsMute);
}
return result;
}
IOReturn AppleOnboardAudio::callPluginsInReverseOrder (UInt32 inSelector, UInt32 newValue) {
AudioHardwareObjectInterface * thePluginObject;
OSArray * pluginOrderArray;
OSString * pluginName;
SInt32 index;
UInt32 pluginOrderArrayCount;
IOReturn result;
debugIOLog (3, "AppleOnboardAudio[%ld]::callPluginsInReverseOrder (%lX, %lX)", mInstanceIndex, inSelector, newValue);
result = kIOReturnBadArgument;
pluginOrderArray = OSDynamicCast (OSArray, getLayoutEntry (kPluginRecoveryOrder, this));
FailIf (NULL == pluginOrderArray, Exit);
pluginOrderArrayCount = pluginOrderArray->getCount ();
for (index = pluginOrderArrayCount - 1; index >= 0; index--) {
pluginName = OSDynamicCast(OSString, pluginOrderArray->getObject(index));
if (NULL == pluginName) {
debugIOLog (3, "Corrupt %s entry in AppleOnboardAudio[%ld] Info.plist", kPluginRecoveryOrder, mInstanceIndex);
continue;
}
thePluginObject = getPluginObjectWithName (pluginName);
if (NULL == thePluginObject) {
debugIOLog (3, "Can't find required AppleOnboardAudio plugin from %s entry loaded", kPluginRecoveryOrder);
continue;
}
switch (inSelector) {
case kRequestCodecRecoveryStatus:
result = thePluginObject->recoverFromFatalError ((FatalRecoverySelector)newValue);
break;
case kBreakClockSelect:
result = thePluginObject->breakClockSelect (newValue);
break;
case kMakeClockSelect:
result = thePluginObject->makeClockSelect (newValue);
break;
case kSetSampleRate:
result = thePluginObject->setSampleRate (newValue);
break;
case kSetSampleBitDepth:
result = thePluginObject->setSampleDepth (newValue);
break;
case kPowerStateChange:
if (kIOAudioDeviceSleep == newValue) {
result = thePluginObject->performDeviceSleep ();
} else if (kIOAudioDeviceActive == newValue) {
result = thePluginObject->performDeviceWake ();
} else if (kIOAudioDeviceIdle == newValue) {
}
break;
default:
break;
}
}
Exit:
return result;
}
IOReturn AppleOnboardAudio::callPluginsInOrder (UInt32 inSelector, UInt32 newValue) {
AudioHardwareObjectInterface * thePluginObject;
OSArray * pluginOrderArray;
OSString * pluginName;
UInt32 index;
UInt32 pluginOrderArrayCount;
IOReturn tempResult;
IOReturn result;
bool boolResult;
debugIOLog (7, "AppleOnboardAudio[%ld]::callPluginsInOrder (%lX, %lX)", mInstanceIndex, inSelector, newValue);
result = kIOReturnBadArgument;
pluginOrderArray = OSDynamicCast (OSArray, getLayoutEntry (kPluginRecoveryOrder, this));
FailIf (NULL == pluginOrderArray, Exit);
pluginOrderArrayCount = pluginOrderArray->getCount ();
result = kIOReturnSuccess;
for (index = 0; index < pluginOrderArrayCount; index++) {
pluginName = OSDynamicCast(OSString, pluginOrderArray->getObject(index));
if (NULL == pluginName) {
debugIOLog (3, "Corrupt %s entry in AppleOnboardAudio[%ld] Info.plist", kPluginRecoveryOrder, mInstanceIndex);
continue;
}
thePluginObject = getPluginObjectWithName (pluginName);
if (NULL == thePluginObject) {
debugIOLog (3, "Can't find required AppleOnboardAudio plugin from %s entry loaded", kPluginRecoveryOrder);
continue;
}
tempResult = kIOReturnSuccess;
switch (inSelector) {
case kRequestCodecRecoveryStatus:
tempResult = thePluginObject->recoverFromFatalError ((FatalRecoverySelector)newValue);
break;
case kClockInterruptedRecovery:
tempResult = thePluginObject->recoverFromFatalError ((FatalRecoverySelector)newValue);
break;
case kBreakClockSelect:
tempResult = thePluginObject->breakClockSelect (newValue);
break;
case kMakeClockSelect:
tempResult = thePluginObject->makeClockSelect (newValue);
break;
case kSetSampleRate:
tempResult = thePluginObject->setSampleRate (newValue);
break;
case kSetSampleBitDepth:
tempResult = thePluginObject->setSampleDepth (newValue);
break;
case kSetSampleType:
tempResult = thePluginObject->setSampleType ( newValue );
break;
case kPreDMAEngineInit:
boolResult = thePluginObject->preDMAEngineInit ();
if ( !boolResult ) {
debugIOLog (1, "AppleOnboardAudio[%ld]::callPluginsInOrder: preDMAEngineInit on thePluginObject %p failed!\n", mInstanceIndex, thePluginObject);
mPluginObjects->removeObject ( index );
index--;
tempResult = kIOReturnError;
}
break;
case kPostDMAEngineInit:
boolResult = thePluginObject->postDMAEngineInit ();
if ( !boolResult ) {
debugIOLog (1, "AppleOnboardAudio[%ld]::callPluginsInOrder: postDMAEngineInit on thePluginObject %p failed!\n", mInstanceIndex, thePluginObject);
mPluginObjects->removeObject ( index );
index--;
tempResult = kIOReturnError;
}
break;
case kPowerStateChange:
if (kIOAudioDeviceSleep == newValue) {
debugIOLog (3, "AppleOnboardAudio[%ld]::callPluginsInOrder ### Telling %s to sleep", mInstanceIndex, pluginName->getCStringNoCopy ());
tempResult = thePluginObject->performDeviceSleep ();
} else if (kIOAudioDeviceActive == newValue) {
debugIOLog (3, "AppleOnboardAudio[%ld]::callPluginsInOrder ### Telling %s to wake", mInstanceIndex, pluginName->getCStringNoCopy ());
tempResult = thePluginObject->performDeviceWake ();
} else if (kIOAudioDeviceIdle == newValue) {
}
break;
case kCodecErrorInterruptStatus:
thePluginObject->notifyHardwareEvent ( inSelector, newValue );
break;
case kCodecInterruptStatus:
thePluginObject->notifyHardwareEvent ( inSelector, newValue );
break;
case kRunPollTask:
thePluginObject->poll ();
break;
case kSetMuteState:
debugIOLog (3, "callPluginsInOrder calls thePluginObject->setMute ( %ld )", newValue );
tempResult = thePluginObject->setMute ( newValue );
break;
case kSetAnalogMuteState: debugIOLog (3, "callPluginsInOrder calls thePluginObject->setMute ( %ld, kAnalogAudioSelector )", newValue );
tempResult = thePluginObject->setMute ( newValue, kAnalogAudioSelector );
break;
case kSetDigitalMuteState: debugIOLog (3, "callPluginsInOrder calls thePluginObject->setMute ( %ld, kDigitalAudioSelector )", newValue );
tempResult = thePluginObject->setMute ( newValue, kDigitalAudioSelector );
break;
default:
tempResult = kIOReturnBadArgument;
break;
}
if ( kIOReturnSuccess != tempResult ) {
result = tempResult;
}
}
Exit:
return result;
}
AudioHardwareObjectInterface * AppleOnboardAudio::findPluginForType ( HardwarePluginType pluginType ) {
AudioHardwareObjectInterface * thePluginObject;
AudioHardwareObjectInterface * result;
OSArray * pluginOrderArray;
OSString * pluginName;
UInt32 index;
UInt32 pluginOrderArrayCount;
result = NULL;
pluginOrderArray = OSDynamicCast (OSArray, getLayoutEntry (kPluginRecoveryOrder, this));
FailIf (NULL == pluginOrderArray, Exit);
pluginOrderArrayCount = pluginOrderArray->getCount ();
for (index = 0; index < pluginOrderArrayCount && NULL == result; index++) {
thePluginObject = NULL;
pluginName = OSDynamicCast(OSString, pluginOrderArray->getObject(index));
if ( NULL != pluginName ) {
thePluginObject = getPluginObjectWithName (pluginName);
if ( NULL != thePluginObject ) {
if ( pluginType == thePluginObject->getPluginType() ) {
result = thePluginObject;
}
}
}
}
Exit:
return result;
}
void AppleOnboardAudio::setPollTimer () {
AbsoluteTime fireTime;
UInt64 nanos;
if ( pollTimer ) {
clock_get_uptime (&fireTime);
absolutetime_to_nanoseconds (fireTime, &nanos);
nanos += NSEC_PER_SEC;
nanoseconds_to_absolutetime (nanos, &fireTime);
pollTimer->wakeAtTime (fireTime);
}
}
void AppleOnboardAudio::pollTimerCallback ( OSObject *owner, IOTimerEventSource *device ) {
AppleOnboardAudio * audioDevice;
audioDevice = OSDynamicCast ( AppleOnboardAudio, owner );
FailIf ( NULL == audioDevice, Exit );
audioDevice->runPolledTasks ();
Exit:
return;
}
void AppleOnboardAudio::runPolledTasks ( void ) {
IOReturn err;
UInt32 errorCount = 0;
if ( kIOAudioDeviceActive == ourPowerState ) {
if ( !mClockSelectInProcessSemaphore && !mSampleRateSelectInProcessSemaphore ) {
IOAudioSampleRate transportSampleRate;
transportSampleRate.whole = mTransportInterface->transportGetSampleRate ();
transportSampleRate.fraction = 0;
if ( 0 != transportSampleRate.whole ) {
if ( mTransportSampleRate.whole != transportSampleRate.whole || mTransportSampleRate.fraction != transportSampleRate.fraction ) {
do {
err = callPluginsInOrder ( kSetSampleRate, transportSampleRate.whole );
if ( kIOReturnSuccess != err ) {
IOSleep(1);
errorCount++;
}
} while ( ( errorCount < 3 ) && ( kIOReturnSuccess != err ) );
if ( kIOReturnSuccess == err ) {
mTransportSampleRate.whole = transportSampleRate.whole;
mTransportSampleRate.fraction = transportSampleRate.fraction;
mDriverDMAEngine->hardwareSampleRateChanged ( &mTransportSampleRate );
} else {
clockSelectorChanged ( kClockSourceSelectionInternal );
if ( NULL != mExternalClockSelector ) {
OSNumber * clockSourceSelector;
clockSourceSelector = OSNumber::withNumber (kClockSourceSelectionInternal, 32);
mExternalClockSelector->hardwareValueChanged (clockSourceSelector);
clockSourceSelector->release ();
err = callPluginsInOrder ( kSetSampleRate, mTransportSampleRate.whole );
}
}
}
}
if ( ( kTRANSPORT_MASTER_CLOCK != mTransportInterface->transportGetClockSelect() ) && mDriverDMAEngine->engineDied() ) {
ConfigChangeHelper theConfigeChangeHelper(mDriverDMAEngine);
UInt32 currentBitDepth = mTransportInterface->transportGetSampleWidth();
mTransportInterface->transportSetSampleWidth ( currentBitDepth, mTransportInterface->transportGetDMAWidth() );
callPluginsInOrder ( kSetSampleBitDepth, currentBitDepth );
}
}
mPlatformInterface->poll ();
mTransportInterface->poll ();
callPluginsInOrder ( kRunPollTask, 0 );
}
setPollTimer ();
}
UInt32 AppleOnboardAudio::parseOutputDetectCollection ( void ) {
UInt32 result;
debugIOLog (3, "+ AppleOnboardAudio[%ld]::ParseDetectCollection() detectCollection 0x%lX", mInstanceIndex, mDetectCollection );
if ( kGPIO_Selector_NotAssociated == mPlatformInterface->getComboOutAssociation() ) { if ( mDetectCollection & kSndHWLineOutput ) {
result = kIOAudioOutputPortSubTypeLine;
} else if ( mDetectCollection & kSndHWDigitalOutput ) {
result = kIOAudioOutputPortSubTypeSPDIF;
} else if ( mDetectCollection & kSndHWCPUHeadphone ) {
result = kIOAudioOutputPortSubTypeHeadphones;
} else if ( mDetectCollection & kSndHWCPUExternalSpeaker ) {
result = kIOAudioOutputPortSubTypeExternalSpeaker;
} else {
result = kIOAudioOutputPortSubTypeInternalSpeaker;
}
} else {
if ( mDetectCollection & kSndHWLineOutput ) {
result = kIOAudioOutputPortSubTypeLine;
} else if ( mDetectCollection & kSndHWCPUHeadphone ) {
result = kIOAudioOutputPortSubTypeHeadphones;
} else if ( mDetectCollection & kSndHWCPUExternalSpeaker ) {
result = kIOAudioOutputPortSubTypeExternalSpeaker;
} else {
result = kIOAudioOutputPortSubTypeInternalSpeaker;
}
}
debugIOLog (3, "- AppleOnboardAudio[%ld]::ParseDetectCollection returns %4s", mInstanceIndex, (char*)&result );
return result;
}
UInt32 AppleOnboardAudio::parseInputDetectCollection ( void ) {
UInt32 result;
debugIOLog (3, "+ AppleOnboardAudio[%ld]::parseInputDetectCollection() detectCollection 0x%lX", mInstanceIndex, mDetectCollection );
if ( mDetectCollection & kSndHWLineInput ) {
result = kIOAudioOutputPortSubTypeLine;
} else {
result = kIOAudioInputPortSubTypeInternalMicrophone;
}
debugIOLog (3, "- AppleOnboardAudio[%ld]::parseInputDetectCollection returns %lX", mInstanceIndex, result );
return result;
}
void AppleOnboardAudio::initializeDetectCollection ( void ) {
debugIOLog (3, "+ AppleOnboardAudio[%ld]::initializeDetectCollection() ", mInstanceIndex);
if ( kGPIO_Connected == mPlatformInterface->getHeadphoneConnected() ) {
if ( kGPIO_Selector_HeadphoneDetect == mPlatformInterface->getComboOutAssociation() ) {
if ( kGPIO_Unknown == mPlatformInterface->getComboOutJackTypeConnected () ) {
mDetectCollection |= kSndHWCPUHeadphone;
debugIOLog (3, "AppleOnboardAudio[%ld]::initializeDetectCollection() - headphones are connected.", mInstanceIndex);
} else {
if ( kGPIO_TypeIsAnalog == mPlatformInterface->getComboOutJackTypeConnected () ) {
mDetectCollection |= kSndHWCPUHeadphone;
debugIOLog (3, "AppleOnboardAudio[%ld]::initializeDetectCollection() - headphones are connected.", mInstanceIndex);
} else {
mDetectCollection |= kSndHWDigitalOutput;
debugIOLog (3, "AppleOnboardAudio[%ld]::initializeDetectCollection() - digital output is connected.", mInstanceIndex);
}
}
} else {
mDetectCollection |= kSndHWCPUHeadphone;
debugIOLog (3, "AppleOnboardAudio[%ld]::initializeDetectCollection() - headphones are connected.", mInstanceIndex);
}
}
if ( kGPIO_Connected == mPlatformInterface->getLineOutConnected() ) {
if ( kGPIO_Selector_LineOutDetect == mPlatformInterface->getComboOutAssociation() ) {
if ( kGPIO_Unknown == mPlatformInterface->getComboOutJackTypeConnected () ) {
mDetectCollection |= kSndHWLineOutput;
debugIOLog (3, "AppleOnboardAudio[%ld]::initializeDetectCollection() - line output is connected.", mInstanceIndex);
} else {
if ( kGPIO_TypeIsAnalog == mPlatformInterface->getComboOutJackTypeConnected () ) {
mDetectCollection |= kSndHWLineOutput;
debugIOLog (3, "AppleOnboardAudio[%ld]::initializeDetectCollection() - line output is connected.", mInstanceIndex);
} else {
mDetectCollection |= kSndHWDigitalOutput;
debugIOLog (3, "AppleOnboardAudio[%ld]::initializeDetectCollection() - digital output is connected.", mInstanceIndex);
}
}
} else {
mDetectCollection |= kSndHWLineOutput;
debugIOLog (3, "AppleOnboardAudio[%ld]::initializeDetectCollection() - line output is connected.", mInstanceIndex);
}
}
if ( kGPIO_Connected == mPlatformInterface->getDigitalOutConnected() ) {
debugIOLog (3, "AppleOnboardAudio[%ld]::initializeDetectCollection() - digital out is connected.", mInstanceIndex);
mDetectCollection |= kSndHWDigitalOutput;
}
if ( kGPIO_Connected == mPlatformInterface->getLineInConnected() ) {
mDetectCollection |= kSndHWLineInput;
}
if ( kGPIO_Connected == mPlatformInterface->getDigitalInConnected() ) {
mDetectCollection |= kSndHWDigitalInput;
}
if ( kGPIO_Connected == mPlatformInterface->getSpeakerConnected() ) { debugIOLog (3, "AppleOnboardAudio[%ld]::initializeDetectCollection() - external speakers are connected.", mInstanceIndex);
mDetectCollection |= kSndHWCPUExternalSpeaker;
mDetectCollection &= ~kSndHWInternalSpeaker;
} else {
debugIOLog (3, "AppleOnboardAudio[%ld]::initializeDetectCollection() - in internal speakers are connected.", mInstanceIndex);
mDetectCollection |= kSndHWInternalSpeaker;
mDetectCollection &= ~kSndHWCPUExternalSpeaker;
}
debugIOLog (3, "- AppleOnboardAudio[%ld]::initializeDetectCollection(), mDetectCollection = %lX", mInstanceIndex, mDetectCollection );
return;
}
void AppleOnboardAudio::updateOutputDetectCollection (UInt32 statusSelector, UInt32 newValue) {
debugIOLog ( 5, "+ AppleOnboardAudio[%ld]::updateOutputDetectCollection ( %ld, %ld )", mInstanceIndex, statusSelector, newValue );
switch (statusSelector) {
case kHeadphoneStatus:
debugIOLog (6, "kHeadphoneStatus mDetectCollection prior to modification %lX", mDetectCollection );
if (newValue == kInserted) {
mDetectCollection |= kSndHWCPUHeadphone;
mDetectCollection &= ~kSndHWInternalSpeaker;
debugIOLog (6, "headphones inserted, mDetectCollection = %lX", mDetectCollection);
} else if (newValue == kRemoved) {
mDetectCollection &= ~kSndHWCPUHeadphone;
mDetectCollection |= kSndHWInternalSpeaker;
debugIOLog (6, "headphones removed, mDetectCollection = %lX", mDetectCollection);
} else {
debugIOLog (6, "Unknown headphone jack status, mDetectCollection = %lX", mDetectCollection);
}
break;
case kLineOutStatus:
debugIOLog (6, "kLineOutStatus mDetectCollection prior to modification %lX", mDetectCollection );
if (newValue == kInserted) {
mDetectCollection |= kSndHWLineOutput;
mDetectCollection &= ~kSndHWInternalSpeaker;
debugIOLog (6, "line out inserted.");
if ( kGPIO_Selector_LineOutDetect == mPlatformInterface->getComboOutAssociation() ) {
if ( NULL != mLineOutputString ) {
ConfigChangeHelper theConfigeChangeHelper(mDriverDMAEngine);
mOutputSelector->removeAvailableSelection ( kIOAudioOutputPortSubTypeInternalSpeaker );
debugIOLog (6, "removed internal speaker from output selector **");
mOutputSelector->removeAvailableSelection ( kIOAudioOutputPortSubTypeSPDIF );
debugIOLog (6, "removed SPDIF from output selector");
mOutputSelector->addAvailableSelection (kIOAudioOutputPortSubTypeLine, mLineOutputString);
}
}
} else if (newValue == kRemoved) {
mDetectCollection &= ~kSndHWLineOutput;
mDetectCollection |= kSndHWInternalSpeaker;
debugIOLog (6, "line out removed.");
if ( (kGPIO_Unknown != mPlatformInterface->getComboOutJackTypeConnected ()) ) {
ConfigChangeHelper theConfigeChangeHelper(mDriverDMAEngine);
mOutputSelector->removeAvailableSelection ( kIOAudioOutputPortSubTypeLine );
debugIOLog (6, "removed Line from output selector");
mOutputSelector->removeAvailableSelection ( kIOAudioOutputPortSubTypeSPDIF );
debugIOLog (6, "removed SPDIF from output selector");
mOutputSelector->addAvailableSelection (kIOAudioOutputPortSubTypeInternalSpeaker, mInternalSpeakerOutputString);
debugIOLog (6, "added internal speaker to output selector");
}
} else {
debugIOLog (6, "Unknown line out jack status.");
}
break;
case kDigitalOutStatus:
debugIOLog (6, "kDigitalOutStatus mDetectCollection prior to modification %lX", mDetectCollection );
if (newValue == kInserted) {
mDetectCollection |= kSndHWDigitalOutput;
mDetectCollection &= ~kSndHWInternalSpeaker;
debugIOLog (6, "digital out inserted.");
debugIOLog (6, "mDigitalOutputString = %p, getComboOutJackTypeConnected = %ld", mDigitalOutputString, mPlatformInterface->getComboOutJackTypeConnected ());
if ( ( NULL != mDigitalOutputString ) && (kGPIO_Unknown != mPlatformInterface->getComboOutJackTypeConnected ()) ) {
ConfigChangeHelper theConfigeChangeHelper(mDriverDMAEngine);
if ( kGPIO_Selector_LineOutDetect == mPlatformInterface->getComboOutAssociation() ) {
mOutputSelector->removeAvailableSelection ( kIOAudioOutputPortSubTypeInternalSpeaker );
debugIOLog (6, "removed internal speaker from output selector *");
mOutputSelector->removeAvailableSelection ( kIOAudioOutputPortSubTypeLine );
debugIOLog (6, "removed line output from output selector");
} else if ( kGPIO_Selector_HeadphoneDetect == mPlatformInterface->getComboOutAssociation() ) {
mOutputSelector->removeAvailableSelection ( kIOAudioOutputPortSubTypeInternalSpeaker );
debugIOLog (6, "removed internal speaker from output selector **");
mOutputSelector->removeAvailableSelection ( kIOAudioOutputPortSubTypeHeadphones );
debugIOLog (6, "removed headphone from output selector");
}
mOutputSelector->addAvailableSelection (kIOAudioOutputPortSubTypeSPDIF, mDigitalOutputString);
debugIOLog (6, "added SPDIF to output selector");
}
} else if (newValue == kRemoved) {
mDetectCollection &= ~kSndHWDigitalOutput;
mDetectCollection |= kSndHWInternalSpeaker;
debugIOLog (6, "digital out removed.");
if ( (kGPIO_Unknown != mPlatformInterface->getComboOutJackTypeConnected ()) ) {
ConfigChangeHelper theConfigeChangeHelper(mDriverDMAEngine);
if ( kGPIO_Selector_LineOutDetect == mPlatformInterface->getComboOutAssociation() ) {
mOutputSelector->removeAvailableSelection ( kIOAudioOutputPortSubTypeLine );
debugIOLog (6, "removed Line from output selector");
mOutputSelector->addAvailableSelection (kIOAudioOutputPortSubTypeInternalSpeaker, mInternalSpeakerOutputString);
debugIOLog (6, "added internal speaker to output selector");
} else if ( kGPIO_Selector_HeadphoneDetect == mPlatformInterface->getComboOutAssociation() ) {
mOutputSelector->removeAvailableSelection ( kIOAudioOutputPortSubTypeHeadphones );
debugIOLog (6, "removed headphone from output selector");
mOutputSelector->addAvailableSelection (kIOAudioOutputPortSubTypeInternalSpeaker, mInternalSpeakerOutputString);
debugIOLog (6, "added internal speaker to output selector");
}
mOutputSelector->removeAvailableSelection ( kIOAudioOutputPortSubTypeSPDIF );
debugIOLog (6, "removed SPDIF from output selector");
}
} else {
debugIOLog (6, "Unknown digital out jack status.");
}
break;
case kLineInStatus:
debugIOLog (6, "kLineInStatus mDetectCollection prior to modification %lX", mDetectCollection );
if (newValue == kInserted) {
mDetectCollection |= kSndHWLineInput;
} else if (newValue == kRemoved) {
mDetectCollection &= ~kSndHWLineInput;
} else {
debugIOLog (6, "Unknown line in status.");
}
break;
case kExtSpeakersStatus: debugIOLog (6, "kExtSpeakersStatus mDetectCollection prior to modification %lX", mDetectCollection );
if (newValue == kInserted) {
mDetectCollection &= ~kSndHWInternalSpeaker;
mDetectCollection |= kSndHWCPUExternalSpeaker;
if ( ( NULL != mInternalSpeakerOutputString ) && ( NULL != mExternalSpeakerOutputString ) ) {
ConfigChangeHelper theConfigeChangeHelper(mDriverDMAEngine);
mOutputSelector->removeAvailableSelection ( kIOAudioOutputPortSubTypeInternalSpeaker );
debugIOLog (6, "removed internal speaker from output selector ***");
mOutputSelector->addAvailableSelection (kIOAudioOutputPortSubTypeExternalSpeaker, mExternalSpeakerOutputString);
}
debugIOLog (6, "external speakers inserted, mDetectCollection = %lX", mDetectCollection);
} else if (newValue == kRemoved) {
mDetectCollection &= ~kSndHWCPUExternalSpeaker;
mDetectCollection |= kSndHWInternalSpeaker;
if ( ( NULL != mInternalSpeakerOutputString ) && ( NULL != mExternalSpeakerOutputString ) ) {
ConfigChangeHelper theConfigeChangeHelper(mDriverDMAEngine);
mOutputSelector->removeAvailableSelection ( kIOAudioOutputPortSubTypeExternalSpeaker );
debugIOLog (6, "removed External Speaker from output selector");
mOutputSelector->addAvailableSelection (kIOAudioOutputPortSubTypeInternalSpeaker, mInternalSpeakerOutputString);
}
debugIOLog (6, "external speakers removed, mDetectCollection = %lX", mDetectCollection);
} else {
debugIOLog (6, "Unknown external speakers jack status, mDetectCollection = %lX", mDetectCollection);
}
break; }
debugIOLog ( 5, "- AppleOnboardAudio[%ld]::updateOutputDetectCollection ( %ld, %ld ), mDetectCollection = %lX", mInstanceIndex, statusSelector, newValue, mDetectCollection );
}
UInt32 AppleOnboardAudio::getSelectorCodeForOutputEvent (UInt32 eventSelector) {
UInt32 selectorCode;
debugIOLog ( 5, "+ AppleOnboardAudio[%ld]::getSelectorCodeForOutputEvent ( %ld )", mInstanceIndex, eventSelector );
selectorCode = kIOAudioOutputPortSubTypeInternalSpeaker;
if (kLineOutStatus == eventSelector) {
if ( mDetectCollection & kSndHWLineOutput ) {
selectorCode = kIOAudioOutputPortSubTypeLine;
} else if ( mDetectCollection & kSndHWCPUHeadphone ) {
selectorCode = kIOAudioOutputPortSubTypeHeadphones;
} else if ( mDetectCollection & kSndHWDigitalOutput ) {
selectorCode = kIOAudioOutputPortSubTypeSPDIF;
} else if ( mDetectCollection & kSndHWCPUExternalSpeaker ) { selectorCode = kIOAudioOutputPortSubTypeExternalSpeaker;
} else if ( mDetectCollection & kSndHWInternalSpeaker ) {
selectorCode = kIOAudioOutputPortSubTypeInternalSpeaker;
} else {
debugIOLog (3, "UNKNOWN device so selecting INTERNAL SPEAKER" );
selectorCode = kIOAudioOutputPortSubTypeInternalSpeaker;
mDetectCollection |= kSndHWInternalSpeaker;
} } else if (kHeadphoneStatus == eventSelector) {
if ( mDetectCollection & kSndHWCPUHeadphone ) {
selectorCode = kIOAudioOutputPortSubTypeHeadphones;
} else if ( mDetectCollection & kSndHWLineOutput ) {
selectorCode = kIOAudioOutputPortSubTypeLine;
} else if ( mDetectCollection & kSndHWDigitalOutput ) {
selectorCode = kIOAudioOutputPortSubTypeSPDIF;
} else if ( mDetectCollection & kSndHWCPUExternalSpeaker ) { selectorCode = kIOAudioOutputPortSubTypeExternalSpeaker;
} else if ( mDetectCollection & kSndHWInternalSpeaker ) {
selectorCode = kIOAudioOutputPortSubTypeInternalSpeaker;
} else { debugIOLog (3, "UNKNOWN device so selecting INTERNAL SPEAKER" );
selectorCode = kIOAudioOutputPortSubTypeInternalSpeaker;
mDetectCollection |= kSndHWInternalSpeaker;
}
} else if (kExtSpeakersStatus == eventSelector) { if ( mDetectCollection & kSndHWLineOutput ) {
selectorCode = kIOAudioOutputPortSubTypeLine;
} else if ( mDetectCollection & kSndHWCPUHeadphone ) {
selectorCode = kIOAudioOutputPortSubTypeHeadphones;
} else if ( mDetectCollection & kSndHWDigitalOutput ) {
selectorCode = kIOAudioOutputPortSubTypeSPDIF;
} else if ( mDetectCollection & kSndHWCPUExternalSpeaker ) {
selectorCode = kIOAudioOutputPortSubTypeExternalSpeaker;
} else if ( mDetectCollection & kSndHWInternalSpeaker ) {
selectorCode = kIOAudioOutputPortSubTypeInternalSpeaker;
} else {
debugIOLog (3, "UNKNOWN device so selecting INTERNAL SPEAKER" );
selectorCode = kIOAudioOutputPortSubTypeInternalSpeaker;
mDetectCollection |= kSndHWInternalSpeaker;
}
} else if (kDigitalOutStatus == eventSelector) { if ( mDetectCollection & kSndHWDigitalOutput ) {
selectorCode = kIOAudioOutputPortSubTypeSPDIF;
} else if ( mDetectCollection & kSndHWLineOutput ) {
selectorCode = kIOAudioOutputPortSubTypeLine;
} else if ( mDetectCollection & kSndHWCPUHeadphone ) {
selectorCode = kIOAudioOutputPortSubTypeHeadphones;
} else if ( mDetectCollection & kSndHWCPUExternalSpeaker ) {
selectorCode = kIOAudioOutputPortSubTypeExternalSpeaker;
} else if ( mDetectCollection & kSndHWInternalSpeaker ) {
selectorCode = kIOAudioOutputPortSubTypeInternalSpeaker;
} else {
debugIOLog (3, "UNKNOWN device so selecting INTERNAL SPEAKER" );
selectorCode = kIOAudioOutputPortSubTypeInternalSpeaker;
mDetectCollection |= kSndHWInternalSpeaker;
}
} debugIOLog ( 5, "- AppleOnboardAudio[%ld]::getSelectorCodeForOutputEvent ( %ld ), mDetectCollection %lX, selectorCode '%4s'", mInstanceIndex, eventSelector, mDetectCollection, (char*)&selectorCode );
return selectorCode;
}
void AppleOnboardAudio::selectOutput (const UInt32 inSelection, const bool inMuteState, const bool inUpdateAll)
{
bool needToWaitForAmps;
debugIOLog (3, "+ AppleOnboardAudio[%ld]::selectOutput %4s, inMuteState = %d", mInstanceIndex, (char *)&(inSelection), inMuteState );
needToWaitForAmps = true;
switch (inSelection) {
case kIOAudioOutputPortSubTypeHeadphones:
debugIOLog (3, "[AOA] switching amps to headphones. mEncodedOutputFormat %d", mEncodedOutputFormat );
mPlatformInterface->setSpeakerMuteState ( kGPIO_Muted );
outputMuteChange( inMuteState ); if (!mEncodedOutputFormat) {
mPlatformInterface->setHeadphoneMuteState ( kGPIO_Unmuted );
}
if ((mDetectCollection & kSndHWLineOutput) && !mEncodedOutputFormat) {
mPlatformInterface->setLineOutMuteState ( kGPIO_Unmuted );
}
break;
case kIOAudioOutputPortSubTypeLine:
debugIOLog (3, "[AOA] switching amps to line output. mEncodedOutputFormat %d", mEncodedOutputFormat );
mPlatformInterface->setSpeakerMuteState ( kGPIO_Muted );
outputMuteChange( inMuteState ); if (!mEncodedOutputFormat) {
mPlatformInterface->setLineOutMuteState ( kGPIO_Unmuted );
}
if ((mDetectCollection & kSndHWCPUHeadphone) && !mEncodedOutputFormat) {
mPlatformInterface->setHeadphoneMuteState ( kGPIO_Unmuted );
}
break;
case kIOAudioOutputPortSubTypeExternalSpeaker: case kIOAudioOutputPortSubTypeInternalSpeaker:
debugIOLog (3, "[AOA] switching amps to speakers. mEncodedOutputFormat %d", mEncodedOutputFormat );
outputMuteChange( inMuteState ); if (!mEncodedOutputFormat) {
mPlatformInterface->setSpeakerMuteState ( kGPIO_Unmuted );
mPlatformInterface->setLineOutMuteState ( kGPIO_Muted );
mPlatformInterface->setHeadphoneMuteState ( kGPIO_Muted );
}
break;
case kIOAudioOutputPortSubTypeSPDIF:
mPlatformInterface->setSpeakerMuteState ( kGPIO_Muted );
outputMuteChange( inMuteState ); if (mEncodedOutputFormat) {
needToWaitForAmps = false;
} else {
if (inUpdateAll) {
if ((mDetectCollection & kSndHWCPUHeadphone) && !inMuteState) {
mPlatformInterface->setHeadphoneMuteState ( kGPIO_Unmuted );
if ( mDetectCollection & kSndHWLineOutput ) {
mPlatformInterface->setLineOutMuteState ( kGPIO_Unmuted );
}
} else if (mDetectCollection & kSndHWLineOutput && !inMuteState) {
mPlatformInterface->setLineOutMuteState ( kGPIO_Unmuted );
}
}
}
break;
default:
debugIOLog (3, "Amplifier not changed, selection = %ld", inSelection);
needToWaitForAmps = false;
break;
}
if (needToWaitForAmps) {
IOSleep (mAmpRecoveryMuteDuration);
}
mCurrentOutputSelection = inSelection;
debugIOLog (3, "- AppleOnboardAudio[%ld]::selectOutput %4s, inMuteState = %d", mInstanceIndex, (char *)&(inSelection), inMuteState );
return;
}
void AppleOnboardAudio::free()
{
debugIOLog (3, "+ AppleOnboardAudio[%ld]::free", mInstanceIndex);
removeTimerEvent ( this );
if (mDriverDMAEngine) {
debugIOLog (3, " AppleOnboardAudio[%ld]::free - mDriverDMAEngine retain count = %d", mInstanceIndex, mDriverDMAEngine->getRetainCount());
mDriverDMAEngine->release();
mDriverDMAEngine = NULL;
}
if (NULL != mPowerThread) {
thread_call_free (mPowerThread);
}
CLEAN_RELEASE(mOutMuteControl);
CLEAN_RELEASE(mHeadphoneConnected);
CLEAN_RELEASE(mOutLeftVolumeControl);
CLEAN_RELEASE(mOutRightVolumeControl);
CLEAN_RELEASE(mOutMasterVolumeControl);
CLEAN_RELEASE(mInLeftGainControl);
CLEAN_RELEASE(mInRightGainControl);
CLEAN_RELEASE(mInMasterGainControl);
CLEAN_RELEASE(mOutputSelector);
CLEAN_RELEASE(mInputSelector);
CLEAN_RELEASE(mPluginObjects);
CLEAN_RELEASE(mTransportInterface);
CLEAN_RELEASE(mPlatformInterface);
CLEAN_RELEASE(mSignal);
super::free();
debugIOLog (3, "- AppleOnboardAudio[%ld]::free, (void)", mInstanceIndex);
}
#pragma mark +PORT HANDLER FUNCTIONS
void AppleOnboardAudio::setCurrentDevices(UInt32 devices){
UInt32 odevice;
odevice = 0;
if (devices != currentDevices) {
odevice = currentDevices;
currentDevices = devices;
}
debugIOLog (3, "currentDevices = %ld", currentDevices);
if (devices & kSndHWInputDevices || odevice & kSndHWInputDevices) {
if (NULL != mInputConnectionControl) {
OSNumber * inputState;
UInt32 active;
active = devices & kSndHWInputDevices ? 1 : 0; inputState = OSNumber::withNumber ((long long unsigned int)active, 32);
(void)mInputConnectionControl->hardwareValueChanged (inputState);
inputState->release ();
}
}
}
AudioHardwareObjectInterface * AppleOnboardAudio::getIndexedPluginObject (UInt32 index) {
AudioHardwareObjectInterface * thePluginObject;
OSObject * theObject;
thePluginObject = NULL;
theObject = mPluginObjects->getObject(index);
if (NULL != theObject) {
thePluginObject = (AudioHardwareObjectInterface *)(theObject->metaCast("AudioHardwareObjectInterface"));
}
return thePluginObject;
}
PlatformInterface * AppleOnboardAudio::getPlatformInterfaceObject () {
return mPlatformInterface;
}
#pragma mark +INTERRUPTS
void AppleOnboardAudio::softwareInterruptHandler (OSObject *object, IOInterruptEventSource *source, int count) {
AppleOnboardAudio * aoa;
UInt16 cachedProducerCount;
aoa = OSDynamicCast (AppleOnboardAudio, object);
debugIOLog (2, "+ AppleOnboardAudio[%ld]::softwareInterruptHandler ( %p, %p %d )", aoa->mInstanceIndex, object, source, count );
for ( UInt32 index = 0; index < kNumberOfActionSelectors; index++ ) {
cachedProducerCount = aoa->mInterruptProduced[index];
if ( 0 != cachedProducerCount - aoa->mInterruptConsumed[index] ) {
aoa->protectedInterruptEventHandler ( index, 0 );
aoa->mInterruptConsumed[index] = cachedProducerCount;
debugIOLog (2, "Processed interrupt at index %d", index );
}
}
}
void AppleOnboardAudio::interruptEventHandler (UInt32 statusSelector, UInt32 newValue) {
IOCommandGate * cg;
cg = getCommandGate ();
if (NULL != cg) {
cg->runAction (interruptEventHandlerAction, (void *)statusSelector, (void *)newValue);
}
return;
}
IOReturn AppleOnboardAudio::interruptEventHandlerAction (OSObject * owner, void * arg1, void * arg2, void * arg3, void * arg4) {
IOReturn result;
AppleOnboardAudio * aoa;
result = kIOReturnError;
aoa = (AppleOnboardAudio *)owner;
FailIf (NULL == aoa, Exit);
debugIOLog (7, "AppleOnboardAudio[%ld]:: interruptEventAction - (%p, %ld, %ld, %ld, %ld)", aoa->mInstanceIndex, owner, (UInt32)arg1, (UInt32)arg2, (UInt32)arg3, (UInt32)arg4);
aoa->protectedInterruptEventHandler ((UInt32)arg1, (UInt32)arg2);
result = kIOReturnSuccess;
Exit:
return result;
}
bool AppleOnboardAudio::isTargetForMessage ( UInt32 actionSelector, AppleOnboardAudio * theAOA ) {
OSArray * swInterruptsArray;
OSString * theInterruptString;
UInt32 interruptCount;
bool result = FALSE;
debugIOLog (3, "+ AppleOnboardAudio[%ld]::isTargetForMessage (%ld, %p)", mInstanceIndex, actionSelector, theAOA);
swInterruptsArray = OSDynamicCast ( OSArray, getLayoutEntry ( kSWInterrupts, theAOA ) );
FailIf (NULL == swInterruptsArray, Exit);
interruptCount = swInterruptsArray->getCount ();
debugIOLog (3, "interruptCount = %p", interruptCount);
for ( UInt32 index = 0; index < interruptCount; index++ ) {
theInterruptString = OSDynamicCast ( OSString, swInterruptsArray->getObject ( index ) );
debugIOLog (3, "theInterruptString = %p", theInterruptString);
if ( NULL != theInterruptString ) {
debugIOLog (3, "theInterruptString = %s", theInterruptString->getCStringNoCopy());
switch ( actionSelector ) {
case kClockLockStatus:
debugIOLog (3, "testing kClockLockStatus");
if ( !strcmp ( kClockLockIntMessage, theInterruptString->getCStringNoCopy() ) ) {
result = TRUE;
}
break;
case kClockUnLockStatus:
debugIOLog (3, "testing kClockUnLockStatus");
if ( !strcmp ( kClockUnLockIntMessage, theInterruptString->getCStringNoCopy() ) ) {
result = TRUE;
}
break;
case kDigitalInInsertStatus:
debugIOLog (3, "testing kDigitalInInsertStatus");
if ( !strcmp ( kDigitalInInsertIntMessage, theInterruptString->getCStringNoCopy() ) ) {
result = TRUE;
}
break;
case kDigitalInRemoveStatus:
debugIOLog (3, "testing kDigitalInRemoveStatus");
if ( !strcmp ( kDigitalInRemoveIntMessage, theInterruptString->getCStringNoCopy() ) ) {
result = TRUE;
}
break;
default:
debugIOLog (3, "useless actionSelector = %ld", actionSelector);
}
}
}
Exit:
debugIOLog (3, "- AppleOnboardAudio[%ld]::isTargetForMessage (%ld, %p) result = %d", mInstanceIndex, actionSelector, theAOA, result);
return result;
}
void AppleOnboardAudio::protectedInterruptEventHandler (UInt32 statusSelector, UInt32 newValue) {
AudioHardwareObjectInterface * thePlugin;
OSNumber * connectionCodeNumber;
char * pluginString;
UInt32 selectorCode;
debugIOLog ( 5, "+ AppleOnboardAudio[%ld]::protectedInterruptEventHandler ( %ld, %ld )", mInstanceIndex, statusSelector, newValue );
selectorCode = getCharCodeForIntCode (statusSelector);
switch ( statusSelector ) {
case kInternalSpeakerStatus: debugIOLog (7, "AppleOnboardAudio[%ld]::protectedInterruptEventHandler ( kInternalSpeakerStatus, '%4s', %ld )", mInstanceIndex, (char*)&selectorCode, newValue); break;
case kHeadphoneStatus: debugIOLog (5, "AppleOnboardAudio[%ld]::protectedInterruptEventHandler ( kHeadphoneStatus, '%4s', %ld )", mInstanceIndex, (char*)&selectorCode, newValue); break;
case kExtSpeakersStatus: debugIOLog (5, "AppleOnboardAudio[%ld]::protectedInterruptEventHandler ( kExtSpeakersStatus, '%4s', %ld )", mInstanceIndex, (char*)&selectorCode, newValue); break;
case kLineOutStatus: debugIOLog (5, "AppleOnboardAudio[%ld]::protectedInterruptEventHandler ( kLineOutStatus, '%4s', %ld )", mInstanceIndex, (char*)&selectorCode, newValue); break;
case kDigitalOutStatus: debugIOLog (5, "AppleOnboardAudio[%ld]::protectedInterruptEventHandler ( kDigitalOutStatus, '%4s', %ld )", mInstanceIndex, (char*)&selectorCode, newValue); break;
case kLineInStatus: debugIOLog (5, "AppleOnboardAudio[%ld]::protectedInterruptEventHandler ( kLineInStatus, '%4s', %ld )", mInstanceIndex, (char*)&selectorCode, newValue); break;
case kInputMicStatus: debugIOLog (7, "AppleOnboardAudio[%ld]::protectedInterruptEventHandler ( kInputMicStatus, '%4s', %ld )", mInstanceIndex, (char*)&selectorCode, newValue); break;
case kExternalMicInStatus: debugIOLog (7, "AppleOnboardAudio[%ld]::protectedInterruptEventHandler ( kExternalMicInStatus, '%4s', %ld )", mInstanceIndex, (char*)&selectorCode, newValue); break;
case kDigitalInInsertStatus: debugIOLog (5, "AppleOnboardAudio[%ld]::protectedInterruptEventHandler ( kDigitalInInsertStatus, '%4s', %ld )", mInstanceIndex, (char*)&selectorCode, newValue); break;
case kDigitalInRemoveStatus: debugIOLog (5, "AppleOnboardAudio[%ld]::protectedInterruptEventHandler ( kDigitalInRemoveStatus, '%4s', %ld )", mInstanceIndex, (char*)&selectorCode, newValue); break;
case kRequestCodecRecoveryStatus: debugIOLog (7, "AppleOnboardAudio[%ld]::protectedInterruptEventHandler ( kRequestCodecRecoveryStatus, '%4s', %ld )", mInstanceIndex, (char*)&selectorCode, newValue); break;
case kClockInterruptedRecovery: debugIOLog (7, "AppleOnboardAudio[%ld]::protectedInterruptEventHandler ( kClockInterruptedRecovery, '%4s', %ld )", mInstanceIndex, (char*)&selectorCode, newValue); break;
case kClockUnLockStatus: debugIOLog (7, "AppleOnboardAudio[%ld]::protectedInterruptEventHandler ( kClockUnLockStatus, '%4s', %ld )", mInstanceIndex, (char*)&selectorCode, newValue); break;
case kClockLockStatus: debugIOLog (7, "AppleOnboardAudio[%ld]::protectedInterruptEventHandler ( kClockLockStatus, '%4s', %ld )", mInstanceIndex, (char*)&selectorCode, newValue); break;
case kAES3StreamErrorStatus: debugIOLog (7, "AppleOnboardAudio[%ld]::protectedInterruptEventHandler ( kAES3StreamErrorStatus, '%4s', %ld )", mInstanceIndex, (char*)&selectorCode, newValue); break;
case kCodecErrorInterruptStatus: debugIOLog (7, "AppleOnboardAudio[%ld]::protectedInterruptEventHandler ( kCodecErrorInterruptStatus, '%4s', %ld )", mInstanceIndex, (char*)&selectorCode, newValue); break;
case kCodecInterruptStatus: debugIOLog (7, "AppleOnboardAudio[%ld]::protectedInterruptEventHandler ( kCodecInterruptStatus, '%4s', %ld )", mInstanceIndex, (char*)&selectorCode, newValue); break;
case kBreakClockSelect: debugIOLog (7, "AppleOnboardAudio[%ld]::protectedInterruptEventHandler ( kBreakClockSelect, '%4s', %ld )", mInstanceIndex, (char*)&selectorCode, newValue); break;
case kMakeClockSelect: debugIOLog (7, "AppleOnboardAudio[%ld]::protectedInterruptEventHandler ( kMakeClockSelect, '%4s', %ld )", mInstanceIndex, (char*)&selectorCode, newValue); break;
case kSetSampleRate: debugIOLog (7, "AppleOnboardAudio[%ld]::protectedInterruptEventHandler ( kSetSampleRate, '%4s', %ld )", mInstanceIndex, (char*)&selectorCode, newValue); break;
case kSetSampleBitDepth: debugIOLog (7, "AppleOnboardAudio[%ld]::protectedInterruptEventHandler ( kSetSampleBitDepth, '%4s', %ld )", mInstanceIndex, (char*)&selectorCode, newValue); break;
case kPowerStateChange: debugIOLog (7, "AppleOnboardAudio[%ld]::protectedInterruptEventHandler ( kPreDMAEngineInit, '%4s', %ld )", mInstanceIndex, (char*)&selectorCode, newValue); break;
case kPreDMAEngineInit: debugIOLog (7, "AppleOnboardAudio[%ld]::protectedInterruptEventHandler ( kPreDMAEngineInit, '%4s', %ld )", mInstanceIndex, (char*)&selectorCode, newValue); break;
case kPostDMAEngineInit: debugIOLog (7, "AppleOnboardAudio[%ld]::protectedInterruptEventHandler ( kPostDMAEngineInit, '%4s', %ld )", mInstanceIndex, (char*)&selectorCode, newValue); break;
case kRestartTransport: debugIOLog (7, "AppleOnboardAudio[%ld]::protectedInterruptEventHandler ( kRestartTransport, '%4s', %ld )", mInstanceIndex, (char*)&selectorCode, newValue); break;
}
updateOutputDetectCollection (statusSelector, newValue);
switch (statusSelector) {
case kHeadphoneStatus:
case kLineOutStatus:
case kExtSpeakersStatus: case kDigitalOutStatus:
selectorCode = getSelectorCodeForOutputEvent (statusSelector);
connectionCodeNumber = OSNumber::withNumber (selectorCode, 32);
debugIOLog ( 5, " selectorCode = '%4s', connectionCodeNumber = %ld", &selectorCode, connectionCodeNumber );
pluginString = getConnectionKeyFromCharCode (selectorCode, kIOAudioStreamDirectionOutput);
debugIOLog (3, "pluginString updated to %s.", pluginString);
thePlugin = getPluginObjectForConnection (pluginString);
FailIf (NULL == thePlugin, Exit);
cacheOutputVolumeLevels (mCurrentOutputPlugin);
mCurrentOutputPlugin = thePlugin;
setClipRoutineForOutput (pluginString);
selectOutput (selectorCode, mIsMute);
if ( kGPIO_Unknown != mPlatformInterface->getDigitalOutConnected() ) {
if ( kGPIO_Connected == mPlatformInterface->getDigitalOutConnected() ) {
callPluginsInOrder ( kSetDigitalMuteState, mIsMute );
} else {
callPluginsInOrder ( kSetDigitalMuteState, TRUE );
}
} else if ( kGPIO_Unknown != mPlatformInterface->getComboOutJackTypeConnected() ) {
if ( kGPIO_TypeIsDigital == mPlatformInterface->getComboOutJackTypeConnected() ) {
callPluginsInOrder ( kSetDigitalMuteState, mIsMute );
} else {
callPluginsInOrder ( kSetDigitalMuteState, TRUE );
}
} else {
callPluginsInOrder ( kSetDigitalMuteState, mIsMute );
}
if (NULL == mOutputSelector) debugIOLog (3, "\n!!!mOutputSelector = NULL!!!");
FailIf (NULL == mOutputSelector, Exit);
mOutputSelector->hardwareValueChanged (connectionCodeNumber);
setSoftwareOutputDSP (pluginString);
connectionCodeNumber->release();
AdjustOutputVolumeControls (thePlugin, selectorCode);
OSNumber * headphoneState;
if (mDetectCollection & kSndHWCPUHeadphone) {
headphoneState = OSNumber::withNumber (1, 32);
} else {
headphoneState = OSNumber::withNumber ((long long unsigned int)0, 32);
}
mHeadphoneConnected->hardwareValueChanged (headphoneState);
headphoneState->release ();
break;
case kLineInStatus:
pluginString = getConnectionKeyFromCharCode (selectorCode, kIOAudioStreamDirectionInput);
debugIOLog (3, "AppleOnboardAudio[%ld]::protectedInterruptEventHandler - pluginString = %s.", mInstanceIndex, pluginString);
thePlugin = getPluginObjectForConnection (pluginString);
FailIf (NULL == thePlugin, Exit);
debugIOLog (3, "AppleOnboardAudio[%ld]::protectedInterruptEventHandler - thePlugin = %p.", mInstanceIndex, thePlugin);
FailIf (NULL == mInputSelector, Exit);
selectorCode = mInputSelector->getIntValue ();
debugIOLog (3, "mInputSelector->getIntValue () returns %4s", (char *)&selectorCode);
if ((mDetectCollection & kSndHWLineInput) && (kIOAudioInputPortSubTypeLine == selectorCode)) {
thePlugin->setInputMute (FALSE);
} else if (!(mDetectCollection & kSndHWLineInput) && (kIOAudioInputPortSubTypeLine == selectorCode)) {
thePlugin->setInputMute (TRUE);
}
break;
case kExternalMicInStatus:
break;
case kDigitalInInsertStatus:
case kDigitalInRemoveStatus:
if ( !broadcastSoftwareInterruptMessage ( statusSelector ) ) {
debugIOLog (2, "kDigitalInRemoveStatus NOT BROADCASTED" );
}
break;
case kRequestCodecRecoveryStatus:
callPluginsInOrder (kRequestCodecRecoveryStatus, newValue);
break;
case kRestartTransport:
if (NULL != mTransportInterface) {
mTransportInterface->transportSetSampleRate ( mTransportInterface->transportGetSampleRate() );
}
break;
case kCodecErrorInterruptStatus:
callPluginsInOrder ( kCodecErrorInterruptStatus, 0 );
break;
case kCodecInterruptStatus:
callPluginsInOrder ( kCodecInterruptStatus, 0 );
break;
case kClockUnLockStatus:
case kClockLockStatus:
if ( !mClockSelectInProcessSemaphore ) {
if ( kClockLockStatus == statusSelector ) {
clockSelectorChanged ( kClockSourceSelectionInternal );
if ( NULL != mExternalClockSelector ) {
OSNumber * clockSourceSelector;
clockSourceSelector = OSNumber::withNumber (kClockSourceSelectionInternal, 32);
mExternalClockSelector->hardwareValueChanged (clockSourceSelector);
clockSourceSelector->release ();
}
} else {
callPluginsInOrder ( kSetMuteState, mIsMute );
}
} else {
debugIOLog (3, "Attempted to post kClockLockStatus blocked by semaphore" );
}
broadcastSoftwareInterruptMessage ( statusSelector );
break;
case kAES3StreamErrorStatus:
debugIOLog (7, "... kAES3StreamErrorStatus %d", (unsigned int)newValue );
if ( newValue ) {
}
break;
default:
break;
}
Exit:
debugIOLog ( 5, "- AppleOnboardAudio[%ld]::protectedInterruptEventHandler ( %ld, %ld )", mInstanceIndex, statusSelector, newValue );
return;
}
bool AppleOnboardAudio::broadcastSoftwareInterruptMessage ( UInt32 actionSelector ) {
AppleOnboardAudio * theAOA;
UInt32 numInstances;
bool result = FALSE;
debugIOLog (3, "AppleOnboardAudio[%ld]::broadcastSoftwareInterruptMessage (0x%x)", mInstanceIndex, actionSelector);
if ( NULL != mAOAInstanceArray ) {
numInstances = mAOAInstanceArray->getCount();
for ( UInt32 index = 0; index < numInstances; index++ ) {
theAOA = OSDynamicCast ( AppleOnboardAudio, mAOAInstanceArray->getObject ( index ) );
if ( isTargetForMessage ( actionSelector, theAOA ) ) {
debugIOLog (3, "theAOA %p is target", theAOA);
if (theAOA->mSoftwareInterruptHandler) {
theAOA->mInterruptProduced[actionSelector]++;
theAOA->mSoftwareInterruptHandler->interruptOccurred (NULL, NULL, 0);
result = TRUE;
}
}
}
}
return result;
}
#pragma mark +IOAUDIO INIT
bool AppleOnboardAudio::initHardware (IOService * provider) {
bool result;
result = FALSE;
mSignal = IOSyncer::create (FALSE);
debugIOLog (3, "+ AppleOnboardAudio[%ld]::initHardware", mInstanceIndex);
FailIf (NULL == mInitHardwareThread, Exit);
#ifdef DONT_THREAD_INIT
if (kIOReturnSuccess == protectedInitHardware (provider)) {
result = TRUE;
}
#else
thread_call_enter1 (mInitHardwareThread, (void *)provider);
result = TRUE;
#endif
Exit:
debugIOLog (3, "- AppleOnboardAudio[%ld]::initHardware returns %d", mInstanceIndex, result);
return result;
}
void AppleOnboardAudio::initHardwareThread (AppleOnboardAudio * aoa, void * provider) {
IOCommandGate * cg;
IOReturn result;
FailIf (NULL == aoa, Exit);
FailIf (TRUE == aoa->mTerminating, Exit);
cg = aoa->getCommandGate ();
if (cg) {
result = cg->runAction (aoa->initHardwareThreadAction, provider);
}
Exit:
return;
}
IOReturn AppleOnboardAudio::initHardwareThreadAction (OSObject * owner, void * provider, void * arg2, void * arg3, void * arg4) {
AppleOnboardAudio * aoa;
IOReturn result;
result = kIOReturnError;
aoa = (AppleOnboardAudio *)owner;
FailIf (NULL == aoa, Exit);
result = aoa->protectedInitHardware ((IOService *)provider);
Exit:
return result;
}
IOReturn AppleOnboardAudio::protectedInitHardware (IOService * provider) {
OSArray * layouts;
OSArray * hardwareObjectsList;
OSArray * multipleDevicesArray;
OSDictionary * layoutEntry;
OSNumber * layoutIDNumber;
OSNumber * ampRecoveryNumber;
OSNumber * headphoneState;
OSString * platformObjectString;
OSString * transportObjectString;
OSString * comboInAssociationString;
OSString * comboOutAssociationString;
OSData * tmpData;
UInt32 * layoutID;
UInt32 layoutIDInt;
UInt32 timeWaited;
UInt32 layoutsCount;
UInt32 index;
UInt32 numPlugins;
bool done;
AudioHardwareObjectInterface * thePluginObject;
OSDictionary * AOAprop;
IOWorkLoop * workLoop;
OSBoolean * softwareInputGainBoolean;
OSNumber * inputLatencyNumber;
OSNumber * outputLatencyNumber;
OSNumber * connectionCodeNumber;
OSNumber * volumeNumber;
OSNumber * sleepPriority;
char * connectionString;
UInt32 connectionCode;
UInt32 tempLatency;
UInt32 inputLatency;
UInt32 selectorCode;
UInt32 count;
IOReturn result;
char deviceName[256];
char num[4];
result = kIOReturnError;
debugIOLog (3, "+ AppleOnboardAudio[%ld]::protectedInitHardware", mInstanceIndex);
debugIOLog (3, "provider's name is: %s", provider->getName ());
tmpData = OSDynamicCast (OSData, provider->getProperty (kLayoutID));
debugIOLog (3, "provider layoutID data = %p", tmpData);
workLoop = getWorkLoop();
FailIf (NULL == workLoop, Exit);
mSoftwareInterruptHandler = IOInterruptEventSource::interruptEventSource (this, softwareInterruptHandler);
FailIf (NULL == mSoftwareInterruptHandler, Exit);
workLoop->addEventSource (mSoftwareInterruptHandler);
mSoftwareInterruptHandler->enable ();
FailIf (NULL == tmpData, Exit);
layoutID = (UInt32 *)tmpData->getBytesNoCopy ();
debugIOLog (3, "layoutID pointer = %p", layoutID);
FailIf (NULL == layoutID, Exit)
mLayoutID = *layoutID;
mUCState.ucLayoutID = mLayoutID;
layouts = OSDynamicCast (OSArray, getProperty (kLayouts));
debugIOLog (3, "layout array = %p", layouts);
FailIf (NULL == layouts, Exit);
layoutsCount = layouts->getCount ();
layoutEntry = NULL;
index = 0;
mMatchingIndex = 0xFFFFFFFF;
layoutIDInt = 0;
debugIOLog (3, "AppleOnboardAudio[%ld] ><><>< mLayoutID 0x%lX (from provider node)", mInstanceIndex, mLayoutID);
while (layoutsCount--) {
layoutEntry = OSDynamicCast (OSDictionary, layouts->getObject (index));
FailIf (NULL == layoutEntry, Exit);
layoutIDNumber = OSDynamicCast (OSNumber, layoutEntry->getObject (kLayoutIDInfoPlist));
FailIf (NULL == layoutIDNumber, Exit);
layoutIDInt = layoutIDNumber->unsigned32BitValue ();
#ifdef REMOVE_LAYOUTS
if (layoutIDInt != mLayoutID) {
debugIOLog (3, "found layout id 0x%lX and deleted it", layoutIDInt);
layouts->removeObject (index); } else {
debugIOLog (3, "found matchine layout id 0x%lX @ index %ld", layoutIDInt, index);
mMatchingIndex = index;
index++;
}
#else
if (layoutIDInt == mLayoutID) {
debugIOLog (3, "AppleOnboardAudio[%ld] found machine layout id 0x%lX @ index %ld", mInstanceIndex, layoutIDInt, index);
mMatchingIndex = index;
break;
} else {
index++;
}
#endif
}
debugIOLog (3, "AppleOnboardAudio[%ld] ><><>< layoutIDInt 0x%lX", mInstanceIndex, layoutIDInt );
#ifdef REMOVE_LAYOUTS
layoutEntry = OSDynamicCast (OSDictionary, layouts->getObject (0));
#else
FailIf (0xFFFFFFFF == mMatchingIndex, Exit);
layoutEntry = OSDynamicCast (OSDictionary, layouts->getObject (mMatchingIndex));
#endif
debugIOLog (3, "layoutEntry = %p", layoutEntry);
FailIf (NULL == layoutEntry, Exit);
ampRecoveryNumber = OSDynamicCast ( OSNumber, layoutEntry->getObject (kAmpRecoveryTime) );
FailIf (NULL == ampRecoveryNumber, Exit);
mAmpRecoveryMuteDuration = ampRecoveryNumber->unsigned32BitValue();
debugIOLog (3, "AppleOnboardAudio[%ld]::protectedInitHardware - mAmpRecoveryMuteDuration = %ld", mInstanceIndex, mAmpRecoveryMuteDuration);
platformObjectString = OSDynamicCast ( OSString, layoutEntry->getObject ( kPlatformObject ) );
FailIf (NULL == platformObjectString, Exit);
debugIOLog (3, "AppleOnboardAudio[%ld]::protectedInitHardware - platformObjectString = %s", mInstanceIndex, platformObjectString->getCStringNoCopy());
mPlatformInterface = PlatformFactory::createPlatform (platformObjectString);
FailIf (NULL == mPlatformInterface, Exit);
debugIOLog (3, "AppleOnboardAudio[%ld]::protectedInitHardware - mPlatformInterface = %p", mInstanceIndex, mPlatformInterface);
FailIf (!mPlatformInterface->init(provider, this, AppleDBDMAAudio::kDBDMADeviceIndex), Exit);
sleepPriority = OSDynamicCast ( OSNumber, layoutEntry->getObject ( kSleepPriority ) );
if ( NULL != sleepPriority ) {
mPowerManagementPriorityID = sleepPriority->unsigned32BitValue();
debugIOLog ( 3, "This %p AOA instance with layoutID %d to register for PM tree on AOA instance with layoutID %d", this, mLayoutID, mPowerManagementPriorityID );
}
comboInAssociationString = OSDynamicCast ( OSString, layoutEntry->getObject ( kComboInObject ) );
if ( NULL != comboInAssociationString ) {
debugIOLog (3, "comboInAssociationString = %s", comboInAssociationString->getCStringNoCopy ());
if ( comboInAssociationString->isEqualTo ("LineInDetect") ) {
mPlatformInterface->setAssociateComboInTo ( kGPIO_Selector_LineInDetect );
} else if ( comboInAssociationString->isEqualTo ("ExternalMicDetect") ) {
mPlatformInterface->setAssociateComboInTo ( kGPIO_Selector_ExternalMicDetect );
}
}
comboOutAssociationString = OSDynamicCast ( OSString, layoutEntry->getObject ( kComboOutObject ) );
if ( NULL != comboOutAssociationString ) {
debugIOLog (3, "comboOutAssociationString = %s", comboOutAssociationString->getCStringNoCopy ());
if ( comboOutAssociationString->isEqualTo ("LineOutDetect") ) {
mPlatformInterface->setAssociateComboOutTo ( kGPIO_Selector_LineOutDetect );
} else if ( comboOutAssociationString->isEqualTo ("HeadphonesDetect") ) {
mPlatformInterface->setAssociateComboOutTo ( kGPIO_Selector_HeadphoneDetect );
} else if ( comboOutAssociationString->isEqualTo ("ExtSpeakersDetect") ) {
mPlatformInterface->setAssociateComboOutTo ( kGPIO_Selector_SpeakerDetect );
}
}
debugIOLog (3, "AppleOnboardAudio[%ld]::protectedInitHardware - about to mute all amps.", mInstanceIndex );
mPlatformInterface->setHeadphoneMuteState ( kGPIO_Muted );
mPlatformInterface->setLineOutMuteState ( kGPIO_Muted );
mPlatformInterface->setSpeakerMuteState ( kGPIO_Muted );
IOSleep (mAmpRecoveryMuteDuration);
transportObjectString = OSDynamicCast ( OSString, layoutEntry->getObject ( kTransportObject ) );
FailIf ( NULL == transportObjectString, Exit );
debugIOLog (3, "AppleOnboardAudio[%ld]::protectedInitHardware - transportObjectString = %s", mInstanceIndex, transportObjectString->getCStringNoCopy());
mTransportInterface = TransportFactory::createTransport ( transportObjectString );
debugIOLog (3, "AppleOnboardAudio[%ld]::protectedInitHardware - mTransportInterface = %p", mInstanceIndex, mTransportInterface);
FailIf (NULL == mTransportInterface, Exit);
FailIf (!mTransportInterface->init ( mPlatformInterface ), Exit);
hardwareObjectsList = OSDynamicCast (OSArray, layoutEntry->getObject (kHardwareObjects));
if ( NULL == hardwareObjectsList ) { debugIOLog (3, "><><>< NULL == hardwareObjectsList" ); }
FailIf (NULL == hardwareObjectsList, Exit);
numPlugins = hardwareObjectsList->getCount ();
debugIOLog (3, "AppleOnboardAudio[%ld] numPlugins to load = %ld", mInstanceIndex, numPlugins);
if (NULL == mPluginObjects) {
mPluginObjects = OSArray::withCapacity (0);
}
FailIf (NULL == mPluginObjects, Exit);
for (index = 0; index < numPlugins; index++) {
setProperty (((OSString *)hardwareObjectsList->getObject(index))->getCStringNoCopy(), "YES");
}
registerService ();
timeWaited = 0;
done = FALSE;
while (!done) {
if (NULL == mPluginObjects) {
IOSleep (10);
} else {
if (mPluginObjects->getCount () != numPlugins) {
IOSleep (10);
} else {
done = TRUE;
}
}
timeWaited++;
}
volumeNumber = OSNumber::withNumber((long long unsigned int)0, 32);
if (!super::initHardware (provider)) {
goto Exit;
}
debugIOLog (3, "A: about to set work loop");
mPlatformInterface->setWorkLoop (workLoop);
FailIf (NULL == mPluginObjects, Exit);
count = mPluginObjects->getCount ();
FailIf (0 == count, Exit);
debugIOLog (3, "AppleOnboardAudio[%ld] about to init %ld plugins", mInstanceIndex, count);
for (index = 0; index < count; index++) {
thePluginObject = getIndexedPluginObject (index);
FailIf (NULL == thePluginObject, Exit);
thePluginObject->setWorkLoop (workLoop);
thePluginObject->initPlugin (mPlatformInterface);
thePluginObject->setProperty (kPluginPListMasterVol, volumeNumber);
thePluginObject->setProperty (kPluginPListLeftVol, volumeNumber);
thePluginObject->setProperty (kPluginPListRightVol, volumeNumber);
thePluginObject->setProperty (kPluginPListLeftGain, volumeNumber);
thePluginObject->setProperty (kPluginPListRightGain, volumeNumber);
mCurrentOutputPlugin = thePluginObject;
mCurrentInputPlugin = thePluginObject;
}
volumeNumber->release ();
callPluginsInOrder (kPreDMAEngineInit, 0);
#if LOCALIZABLE
sprintf ( deviceName, "%s", "DeviceName");
if (mInstanceIndex > 1) {
sprintf (num, "%d", mInstanceIndex);
strcat (deviceName, num);
}
setDeviceName (deviceName);
sprintf ( deviceName, "%s", "DeviceShortName");
if (mInstanceIndex > 1) {
sprintf (num, "%d", mInstanceIndex);
strcat (deviceName, num);
}
setDeviceShortName (deviceName);
setManufacturerName ("ManufacturerName");
setProperty (kIOAudioDeviceLocalizedBundleKey, "AppleOnboardAudio.kext");
#else
setDeviceName ("Built-in Audio");
setDeviceShortName ("Built-in");
setManufacturerName ("Apple");
#endif
#ifdef ONLY_PUBLISH_ONE_BUILIT_DEVICE
if (mInstanceIndex > 1) {
setDeviceTransportType (kIOAudioDeviceTransportTypePCI);
} else {
setDeviceTransportType (kIOAudioDeviceTransportTypeBuiltIn);
}
#else
setDeviceTransportType (kIOAudioDeviceTransportTypeBuiltIn);
#endif
setProperty (kIOAudioEngineCoreAudioPlugInKey, "IOAudioFamily.kext/Contents/PlugIns/AOAHALPlugin.bundle");
configureDMAEngines (provider);
debugIOLog (3, "AppleOnboardAudio[%ld] finished configure DMA engine (%p) ", mInstanceIndex, mDriverDMAEngine);
FailIf (NULL == mDriverDMAEngine, Exit);
mAutoUpdatePRAM = FALSE; result = createDefaultControls ();
FailIf (kIOReturnSuccess != result, Exit);
debugIOLog (3, " AppleOnboardAudio[%ld]::initHardware - mDriverDMAEngine retain count before activateAudioEngine = %d", mInstanceIndex, mDriverDMAEngine->getRetainCount());
if (kIOReturnSuccess != activateAudioEngine (mDriverDMAEngine)) {
mDriverDMAEngine->release ();
mDriverDMAEngine = NULL;
goto Exit;
}
debugIOLog (3, " AppleOnboardAudio[%ld]::initHardware - mDriverDMAEngine retain count after activateAudioEngine = %d", mInstanceIndex, mDriverDMAEngine->getRetainCount());
idleTimer = IOTimerEventSource::timerEventSource (this, sleepHandlerTimer);
if (!idleTimer) {
goto Exit;
}
workLoop->addEventSource (idleTimer);
pollTimer = IOTimerEventSource::timerEventSource ( this, pollTimerCallback );
if ( pollTimer ) {
workLoop->addEventSource ( pollTimer );
}
ourPowerState = kIOAudioDeviceActive;
mUCState.ucPowerState = ourPowerState;
setProperty ("IOAudioPowerState", ourPowerState, 32);
idleSleepDelayTime = kNoIdleAudioPowerDown;
setIdleAudioSleepTime (idleSleepDelayTime);
mAutoUpdatePRAM = FALSE; if (NULL != mOutMasterVolumeControl) {
UInt32 volume;
volume = (mOutMasterVolumeControl->getMaxValue () - mOutMasterVolumeControl->getMinValue () + 1) * 90 / 100;
mOutMasterVolumeControl->setValue (volume);
}
if (NULL != mOutLeftVolumeControl) {
UInt32 volume;
volume = (mOutLeftVolumeControl->getMaxValue () - mOutLeftVolumeControl->getMinValue () + 1) * 65 / 100;
mOutLeftVolumeControl->setValue (volume);
}
if (NULL != mOutRightVolumeControl) {
UInt32 volume;
volume = (mOutRightVolumeControl->getMaxValue () - mOutRightVolumeControl->getMinValue () + 1) * 65 / 100;
mOutRightVolumeControl->setValue (volume);
}
callPluginsInOrder (kPostDMAEngineInit, 0);
if ( kGPIO_IsAlternate == mPlatformInterface->getInternalSpeakerID() ) {
mInternalSpeakerID = 1;
} else {
mInternalSpeakerID = 0;
}
debugIOLog (3, "Internal speaker ID is %ld\n", mInternalSpeakerID);
initializeDetectCollection();
connectionCode = parseOutputDetectCollection ();
connectionCodeNumber = OSNumber::withNumber(connectionCode, 32);
if ( mHeadphoneConnected ) {
if (mDetectCollection & kSndHWCPUHeadphone) {
headphoneState = OSNumber::withNumber (1, 32);
} else {
headphoneState = OSNumber::withNumber ((long long unsigned int)0, 32);
}
mHeadphoneConnected->hardwareValueChanged (headphoneState);
headphoneState->release ();
}
{
UInt32 comboOutJackTypeState = mPlatformInterface->getComboOutJackTypeConnected ();
if ( kGPIO_Unknown != comboOutJackTypeState ) {
GpioAttributes theAnalogState = kGPIO_Unknown;
switch ( (UInt32)mPlatformInterface->getComboOutAssociation () ) {
case kGPIO_Selector_HeadphoneDetect: theAnalogState = mPlatformInterface->getHeadphoneConnected (); break;
case kGPIO_Selector_LineOutDetect: theAnalogState = mPlatformInterface->getLineOutConnected (); break;
case kGPIO_Selector_SpeakerDetect: theAnalogState = mPlatformInterface->getSpeakerConnected (); break;
}
if ( kGPIO_Connected == theAnalogState && kGPIO_TypeIsDigital == comboOutJackTypeState ) {
callPluginsInOrder ( kSetDigitalMuteState, FALSE );
} else {
callPluginsInOrder ( kSetDigitalMuteState, TRUE );
}
} else {
callPluginsInOrder ( kSetDigitalMuteState, FALSE );
}
}
if ( NULL != mOutputSelector ) {
mOutputSelector->hardwareValueChanged (connectionCodeNumber);
}
connectionCodeNumber->release();
if ( NULL != mOutputSelector ) {
selectorCode = mOutputSelector->getIntValue ();
debugIOLog (3, "mOutputSelector->getIntValue () returns %lX", selectorCode);
if (0 != selectorCode) {
connectionString = getConnectionKeyFromCharCode (selectorCode, kIOAudioStreamDirectionOutput);
debugIOLog (3, "mOutputSelector->getIntValue () char code is %s", connectionString);
if (NULL != connectionString) {
AudioHardwareObjectInterface* theHWObject;
theHWObject = getPluginObjectForConnection (connectionString);
if (NULL != theHWObject) {
mCurrentOutputPlugin = theHWObject;
} else {
debugIOLog (1, "can't find hardware plugin for output %s", connectionString);
}
}
}
debugIOLog (3, "AppleOnboardAudio[%ld] mCurrentOutputPlugin = %p", mInstanceIndex, mCurrentOutputPlugin);
}
FailIf (NULL == mInputSelector, Exit);
selectorCode = mInputSelector->getIntValue ();
debugIOLog (3, "mInputSelector->getIntValue () returns %4s", (char *)&selectorCode);
if (0 != selectorCode) {
connectionString = getConnectionKeyFromCharCode (selectorCode, kIOAudioStreamDirectionInput);
debugIOLog (3, "mInputSelector->getIntValue () char code is %s", connectionString);
if (NULL != connectionString) {
AudioHardwareObjectInterface* theHWObject;
theHWObject = getPluginObjectForConnection (connectionString);
if (NULL != theHWObject) {
mCurrentInputPlugin = theHWObject;
} else {
debugIOLog (1, "can't find hardware plugin for input %s", connectionString);
}
}
}
debugIOLog (3, "AppleOnboardAudio[%ld] mCurrentInputPlugin = %p", mInstanceIndex, mCurrentInputPlugin);
mCurrentInputPlugin->setActiveInput (selectorCode);
AOAprop = OSDynamicCast (OSDictionary, mCurrentInputPlugin->getProperty (kPluginPListAOAAttributes));
FailIf (NULL == AOAprop, Exit);
softwareInputGainBoolean = OSDynamicCast (OSBoolean, AOAprop->getObject (kPluginPListSoftwareInputGain));
if (NULL != softwareInputGainBoolean) {
mDriverDMAEngine->setUseSoftwareInputGain (softwareInputGainBoolean->getValue ());
mCurrentPluginNeedsSoftwareInputGain = softwareInputGainBoolean->getValue ();
} else {
mDriverDMAEngine->setUseSoftwareInputGain (false);
mCurrentPluginNeedsSoftwareInputGain = false;
}
inputLatency = 0; inputLatencyNumber = OSDynamicCast (OSNumber, AOAprop->getObject (kPluginPListInputLatency));
if (NULL != inputLatencyNumber) {
inputLatency = inputLatencyNumber->unsigned32BitValue();
}
mOutputLatency = 0;
count = mPluginObjects->getCount ();
for (index = 0; index < count; index++) {
thePluginObject = getIndexedPluginObject (index);
FailIf (NULL == thePluginObject, Exit);
AOAprop = OSDynamicCast (OSDictionary, thePluginObject->getProperty (kPluginPListAOAAttributes));
FailIf (NULL == AOAprop, Exit);
outputLatencyNumber = OSDynamicCast (OSNumber, AOAprop->getObject (kPluginPListOutputLatency));
if (NULL != outputLatencyNumber) {
tempLatency = outputLatencyNumber->unsigned32BitValue();
if (tempLatency > mOutputLatency) {
mOutputLatency = tempLatency;
}
}
}
mDriverDMAEngine->setSampleLatencies (mOutputLatency, inputLatency);
mPlatformInterface->enableAmplifierMuteRelease(); mPlatformInterface->registerInterrupts ( (IOService*)mPlatformInterface );
flushAudioControls ();
if (NULL != mExternalClockSelector) { mExternalClockSelector->flushValue (); }
mSysPowerDownNotifier = registerPrioritySleepWakeInterest (&sysPowerDownHandler, this, 0);
setPollTimer ();
#ifdef FORCE_MULTIPLE_DEVICES_TO_LOAD
multipleDevicesArray = OSDynamicCast (OSArray, layoutEntry->getObject (kMultipleDevices));
debugIOLog (3, "multipleDevicesArray = %p", multipleDevicesArray);
if (1 == mInstanceIndex && (NULL != multipleDevicesArray)) {
UInt32 deviceIndex;
UInt32 devicesToLoad;
mach_timespec_t timeout;
timeout.tv_sec = 5;
timeout.tv_nsec = 0;
devicesToLoad = 0;
devicesToLoad = multipleDevicesArray->getCount();
debugIOLog (3, "devicesToLoad = %ld", devicesToLoad);
for (deviceIndex = 0; deviceIndex < devicesToLoad; deviceIndex++) {
OSDictionary * deviceDict;
OSString * i2sNodeString;
OSString * soundNodePathString;
OSString * matchPropertyString;
IOService * i2sService;
IORegistryEntry * soundRegEntry;
IOService * sound;
deviceDict = OSDynamicCast (OSDictionary, multipleDevicesArray->getObject(deviceIndex));
debugIOLog (3, "deviceDict = %p", deviceDict);
FailIf (NULL == deviceDict, Exit);
i2sNodeString = OSDynamicCast (OSString, deviceDict->getObject(kI2SNode));
debugIOLog (3, "i2sNodeString = %p", i2sNodeString);
FailIf (NULL == i2sNodeString, Exit);
soundNodePathString = OSDynamicCast (OSString, deviceDict->getObject(kSoundNodePath));
debugIOLog (3, "soundNodePathString = %p", soundNodePathString);
FailIf (NULL == soundNodePathString, Exit);
matchPropertyString = OSDynamicCast (OSString, deviceDict->getObject(kMatchProperty));
debugIOLog (3, "matchPropertyString = %p", matchPropertyString);
FailIf (NULL == matchPropertyString, Exit);
i2sService = IOService::waitForService (IOService::nameMatching(i2sNodeString->getCStringNoCopy()), &timeout);
debugIOLog (3, "i2sService = %p", deviceDict);
FailIf (NULL == i2sService, Exit);
soundRegEntry = i2sService->childFromPath (soundNodePathString->getCStringNoCopy(), gIOServicePlane);
debugIOLog (3, "soundRegEntry = %p", soundRegEntry);
FailIf (NULL == i2sService, Exit);
sound = OSDynamicCast (IOService, soundRegEntry);
FailIf (NULL == i2sService, Exit);
debugIOLog (3, "soundRegEntry = %p", soundRegEntry);
sound->setProperty (matchPropertyString->getCStringNoCopy(), "YES");
sound->registerService ();
}
} else {
debugIOLog (3, "><><>< NULL == multipleDevicesArray on instance %ld", mInstanceIndex );
}
aoaNotifier = addNotification (gIOPublishNotification, serviceMatching ("AppleOnboardAudio"), (IOServiceNotificationHandler)&aoaPublished, this);
#endif
mSignal->signal (kIOReturnSuccess, FALSE);
result = kIOReturnSuccess;
mAutoUpdatePRAM = TRUE;
Exit:
if (NULL != mInitHardwareThread) {
thread_call_free (mInitHardwareThread);
}
debugIOLog (3, "- AppleOnboardAudio[%ld]::protectedInitHardware returns 0x%x", mInstanceIndex, result);
return (result);
}
bool AppleOnboardAudio::aoaPublished (AppleOnboardAudio * aoaObject, void * refCon, IOService * newService) {
bool result = FALSE;
if ( newService != aoaObject ) {
if ( NULL == aoaObject->mAOAInstanceArray ) {
aoaObject->mAOAInstanceArray = OSArray::withObjects ( (const OSObject**)&newService, 1 );
FailIf ( NULL == aoaObject->mAOAInstanceArray, Exit );
} else {
aoaObject->mAOAInstanceArray->setObject ( newService );
}
result = TRUE;
}
Exit:
return result;
}
IOReturn AppleOnboardAudio::configureDMAEngines(IOService *provider) {
IOReturn result;
bool hasInput;
bool hasOutput;
OSArray * formatsArray;
OSArray * inputListArray;
OSArray * outputListArray;
result = kIOReturnError;
inputListArray = OSDynamicCast (OSArray, getLayoutEntry (kInputsList, this));
hasInput = (NULL != inputListArray);
outputListArray = OSDynamicCast (OSArray, getLayoutEntry (kOutputsList, this));
hasOutput = ( NULL != outputListArray );
debugIOLog (3, "+ AppleOnboardAudio[%ld]::configureDMAEngines (%p)", mInstanceIndex, provider);
mDriverDMAEngine = new AppleDBDMAAudio;
FailIf (NULL == mDriverDMAEngine, Exit);
formatsArray = OSDynamicCast (OSArray, getLayoutEntry (kFormats, this));
if (!mDriverDMAEngine->init (NULL, mPlatformInterface, (IOService *)provider->getParentEntry (gIODTPlane), hasInput, hasOutput, formatsArray)) {
mDriverDMAEngine->release ();
mDriverDMAEngine = NULL;
goto Exit;
}
result = kIOReturnSuccess;
Exit:
debugIOLog (3, "- AppleOnboardAudio[%ld]::configureDMAEngines (%p) returns %x", mInstanceIndex, provider, result);
return result;
}
UInt16 AppleOnboardAudio::getTerminalTypeForCharCode (UInt32 outputSelection) {
UInt16 terminalType;
switch (outputSelection) {
case kIOAudioSelectorControlSelectionValueInternalSpeaker:
terminalType = OUTPUT_SPEAKER;
break;
case kIOAudioSelectorControlSelectionValueHeadphones:
terminalType = OUTPUT_HEADPHONES;
break;
case kIOAudioSelectorControlSelectionValueLine:
terminalType = EXTERNAL_LINE_CONNECTOR;
break;
case kIOAudioSelectorControlSelectionValueSPDIF:
terminalType = EXTERNAL_SPDIF_INTERFACE;
break;
case kIOAudioSelectorControlSelectionValueInternalMicrophone:
terminalType = INPUT_MICROPHONE;
break;
case kIOAudioSelectorControlSelectionValueExternalMicrophone:
terminalType = INPUT_DESKTOP_MICROPHONE;
break;
default:
terminalType = OUTPUT_UNDEFINED;
}
return terminalType;
}
UInt32 AppleOnboardAudio::getCharCodeForString (OSString * string) {
UInt32 charCode;
if (string->isEqualTo (kInternalSpeakers)) {
charCode = kIOAudioOutputPortSubTypeInternalSpeaker;
} else if (string->isEqualTo (kExternalSpeakers)) {
charCode = kIOAudioOutputPortSubTypeExternalSpeaker;
} else if (string->isEqualTo (kHeadphones)) {
charCode = kIOAudioOutputPortSubTypeHeadphones;
} else if (string->isEqualTo (kLineOut)) {
charCode = kIOAudioOutputPortSubTypeLine;
} else if (string->isEqualTo (kInternalMic)) {
charCode = kIOAudioInputPortSubTypeInternalMicrophone;
} else if (string->isEqualTo (kExternalMic)) {
charCode = kIOAudioInputPortSubTypeExternalMicrophone;
} else if (string->isEqualTo (kLineIn)) {
charCode = kIOAudioInputPortSubTypeLine;
} else if (string->isEqualTo (kDigitalIn) || string->isEqualTo (kDigitalOut)) {
charCode = kIOAudioInputPortSubTypeSPDIF;
} else {
charCode = 0x3F3F3F3F; }
return charCode;
}
UInt32 AppleOnboardAudio::getCharCodeForIntCode (UInt32 inCode) {
UInt32 charCode;
if (kInternalSpeakerStatus == inCode) {
charCode = kIOAudioOutputPortSubTypeInternalSpeaker;
} else if (kExtSpeakersStatus == inCode) {
charCode = kIOAudioOutputPortSubTypeExternalSpeaker;
} else if (kHeadphoneStatus == inCode) {
charCode = kIOAudioOutputPortSubTypeHeadphones;
} else if (kLineOutStatus == inCode) {
charCode = kIOAudioOutputPortSubTypeLine;
} else if (kInputMicStatus == inCode) {
charCode = kIOAudioInputPortSubTypeInternalMicrophone;
} else if (kExternalMicInStatus == inCode) {
charCode = kIOAudioInputPortSubTypeExternalMicrophone;
} else if (kLineInStatus == inCode) {
charCode = kIOAudioInputPortSubTypeLine;
} else if ((kDigitalInInsertStatus == inCode) || (kDigitalInRemoveStatus == inCode)) {
charCode = kIOAudioInputPortSubTypeSPDIF;
} else if (kDigitalOutStatus == inCode) {
charCode = kIOAudioOutputPortSubTypeSPDIF;
} else {
charCode = 0x3F3F3F3F; }
return charCode;
}
OSString * AppleOnboardAudio::getStringForCharCode (UInt32 charCode) {
OSString * theString;
switch (charCode) {
case kIOAudioOutputPortSubTypeInternalSpeaker:
theString = OSString::withCString ("Internal Speakers");
break;
case kIOAudioOutputPortSubTypeExternalSpeaker:
theString = OSString::withCString ("External Speakers");
break;
case kIOAudioOutputPortSubTypeHeadphones:
theString = OSString::withCString ("Headphones");
break;
case kIOAudioOutputPortSubTypeLine:
theString = OSString::withCString ("Line");
break;
case kIOAudioOutputPortSubTypeSPDIF:
theString = OSString::withCString ("Digital");
break;
case kIOAudioInputPortSubTypeInternalMicrophone:
theString = OSString::withCString ("Internal Microphone");
break;
case kIOAudioInputPortSubTypeExternalMicrophone:
theString = OSString::withCString ("External Microphone");
break;
default:
theString = NULL;
break;
}
return theString;
}
char * AppleOnboardAudio::getConnectionKeyFromCharCode (const SInt32 inSelection, const UInt32 inDirection) {
char * selectedOutput;
switch (inSelection) {
case kIOAudioOutputPortSubTypeInternalSpeaker:
selectedOutput = kInternalSpeakers;
break;
case kIOAudioOutputPortSubTypeExternalSpeaker:
selectedOutput = kExternalSpeakers;
break;
case kIOAudioOutputPortSubTypeHeadphones:
selectedOutput = kHeadphones;
break;
case kIOAudioInputPortSubTypeInternalMicrophone:
selectedOutput = kInternalMic;
break;
case kIOAudioInputPortSubTypeExternalMicrophone:
selectedOutput = kExternalMic;
break;
case kIOAudioOutputPortSubTypeSPDIF:
if (kIOAudioStreamDirectionOutput == inDirection) {
selectedOutput = kDigitalOut;
} else {
selectedOutput = kDigitalIn;
}
break;
case kIOAudioOutputPortSubTypeLine:
if (kIOAudioStreamDirectionOutput == inDirection) {
selectedOutput = kLineOut;
} else {
selectedOutput = kLineIn;
}
break;
default:
selectedOutput = 0;
break;
}
return selectedOutput;
}
IOReturn AppleOnboardAudio::createInputSelectorControl (void) {
OSArray * inputsList;
OSString * inputString;
#if !LOCALIZABLE
OSString * selectionString;
#endif
IOReturn result;
UInt32 inputsCount;
UInt32 inputSelection;
UInt32 index;
result = kIOReturnError;
inputsList = OSDynamicCast (OSArray, getLayoutEntry (kInputsList, this));
FailIf (NULL == inputsList, Exit);
inputsCount = inputsList->getCount ();
inputString = OSDynamicCast (OSString, inputsList->getObject (0));
FailIf (NULL == inputString, Exit);
inputSelection = getCharCodeForString (inputString);
mInputSelector = IOAudioSelectorControl::createInputSelector (inputSelection, kIOAudioControlChannelIDAll);
if (NULL != mInputSelector) {
mDriverDMAEngine->addDefaultAudioControl (mInputSelector);
mInputSelector->setValueChangeHandler ((IOAudioControl::IntValueChangeHandler)inputControlChangeHandler, this);
for (index = 0; index < inputsCount; index++) {
inputString = OSDynamicCast (OSString, inputsList->getObject (index));
FailIf (NULL == inputString, Exit);
inputSelection = getCharCodeForString (inputString);
#if LOCALIZABLE
mInputSelector->addAvailableSelection (inputSelection, inputString);
#else
selectionString = getStringForCharCode (inputSelection);
mInputSelector->addAvailableSelection (inputSelection, selectionString);
selectionString->release ();
#endif
}
}
debugIOLog (3, "AppleOnboardAudio[%ld]::createInputSelectorControl - mInputSelector = %p", mInstanceIndex, mInputSelector);
result = kIOReturnSuccess;
Exit:
return result;
}
IOReturn AppleOnboardAudio::createOutputSelectorControl (void) {
char outputSelectionCString[5];
OSDictionary * theDictionary;
OSNumber * terminalTypeNum;
OSString * outputString;
OSString * outputSelectionString;
OSArray * outputsList;
#if !LOCALIZABLE
OSString * selectionString;
#endif
IOReturn result;
UInt32 outputsCount;
UInt32 outputSelection;
UInt32 index;
UInt16 terminalType;
UInt32 temp;
result = kIOReturnError;
outputsList = OSDynamicCast (OSArray, getLayoutEntry (kOutputsList, this));
if ( NULL != outputsList ) {
outputsCount = outputsList->getCount ();
outputString = OSDynamicCast (OSString, outputsList->getObject (0));
FailIf (NULL == outputString, Exit);
theDictionary = OSDictionary::withCapacity (outputsCount);
FailIf (NULL == theDictionary, Exit);
outputSelection = getCharCodeForString (outputString);
mOutputSelector = IOAudioSelectorControl::createOutputSelector (outputSelection, kIOAudioControlChannelIDAll);
if ( NULL == mOutputSelector ) { debugIOLog ( 3, "createOutputSelector for %4s FAILED", (char*)&outputSelection ); }
FailIf (NULL == mOutputSelector, Exit);
mDriverDMAEngine->addDefaultAudioControl (mOutputSelector);
mOutputSelector->setValueChangeHandler ((IOAudioControl::IntValueChangeHandler)outputControlChangeHandler, this);
for (index = 0; index < outputsCount; index++) {
outputString = OSDynamicCast (OSString, outputsList->getObject (index));
FailIf (NULL == outputString, Exit);
outputSelection = getCharCodeForString (outputString);
switch (outputSelection) {
case kIOAudioOutputPortSubTypeInternalSpeaker:
mInternalSpeakerOutputString = outputString;
temp = kIOAudioOutputPortSubTypeInternalSpeaker;
debugIOLog (3, "add output selection of %4s", &temp);
break;
case kIOAudioOutputPortSubTypeExternalSpeaker:
mExternalSpeakerOutputString = outputString;
temp = kIOAudioOutputPortSubTypeExternalSpeaker;
debugIOLog (3, "add output selection of %4s", &temp);
break;
case kIOAudioOutputPortSubTypeLine:
mLineOutputString = outputString;
temp = kIOAudioOutputPortSubTypeLine;
debugIOLog (3, "add output selection of %4s", &temp);
break;
case kIOAudioOutputPortSubTypeSPDIF:
mDigitalOutputString = outputString;
temp = kIOAudioOutputPortSubTypeSPDIF;
debugIOLog (3, "add output selection of %4s", &temp);
break;
case kIOAudioOutputPortSubTypeHeadphones:
mHeadphoneOutputString = outputString;
temp = kIOAudioOutputPortSubTypeHeadphones;
debugIOLog (3, "add output selection of %4s", &temp);
break;
default:
debugIOLog (2, "AppleOnboardAudio[%ld]::createOutputSelectorControl: unknown output selection", mInstanceIndex);
}
terminalType = getTerminalTypeForCharCode (outputSelection);
terminalTypeNum = OSNumber::withNumber (terminalType, 16);
FailIf (NULL == terminalTypeNum, Exit);
*(UInt32 *)outputSelectionCString = outputSelection;
outputSelectionCString[4] = 0;
outputSelectionString = OSString::withCString (outputSelectionCString);
FailIf (NULL == outputSelectionString, Exit);
theDictionary->setObject (outputSelectionString, terminalTypeNum);
terminalTypeNum->release ();
outputSelectionString->release ();
#if LOCALIZABLE
debugIOLog (3, "mOutputSelector->addAvailableSelection ( '%4s', %p )", (char*)&outputSelection, outputString );
mOutputSelector->addAvailableSelection (outputSelection, outputString);
#else
selectionString = getStringForCharCode (outputSelection);
mOutputSelector->addAvailableSelection (outputSelection, selectionString);
selectionString->release ();
#endif
}
if ( ( NULL != mInternalSpeakerOutputString ) && ( NULL != mExternalSpeakerOutputString ) ) {
if ( kGPIO_Connected == mPlatformInterface->getSpeakerConnected() ) {
mOutputSelector->removeAvailableSelection ( kIOAudioOutputPortSubTypeInternalSpeaker );
debugIOLog (6, "removed internal speaker from output selector ****");
} else {
mOutputSelector->removeAvailableSelection ( kIOAudioOutputPortSubTypeExternalSpeaker );
debugIOLog (6, "removed External Speaker from output selector");
}
}
if ( (kGPIO_Unknown != mPlatformInterface->getComboOutJackTypeConnected ()) ) {
if ( kGPIO_Connected == mPlatformInterface->getLineOutConnected () ) {
mOutputSelector->removeAvailableSelection ( kIOAudioOutputPortSubTypeSPDIF );
debugIOLog (6, "removed SPDIF from output selector");
} else if ( kGPIO_Connected == mPlatformInterface->getDigitalOutConnected () ) {
mOutputSelector->removeAvailableSelection ( kIOAudioOutputPortSubTypeLine );
debugIOLog (6, "removed Line from output selector");
} else {
mOutputSelector->removeAvailableSelection ( kIOAudioOutputPortSubTypeSPDIF );
debugIOLog (6, "removed SPDIF from output selector");
mOutputSelector->removeAvailableSelection ( kIOAudioOutputPortSubTypeLine );
debugIOLog (6, "removed Line from output selector");
}
}
mDriverDMAEngine->setProperty ("MappingDictionary", theDictionary);
}
debugIOLog (3, "AppleOnboardAudio[%ld]::createOutputSelectorControl - mOutputSelector = %p", mInstanceIndex, mOutputSelector);
result = kIOReturnSuccess;
Exit:
return result;
}
AudioHardwareObjectInterface * AppleOnboardAudio::getPluginObjectForConnection (const char * entry) {
AudioHardwareObjectInterface * thePluginObject;
OSDictionary * dictEntry;
OSString * pluginIDMatch;
debugIOLog ( 3, "+ AppleOnboardAudio[%ld]::getPluginObjectForConnection ( %s )", mInstanceIndex, entry );
thePluginObject = NULL;
pluginIDMatch = NULL;
dictEntry = NULL;
dictEntry = OSDynamicCast (OSDictionary, getLayoutEntry (entry, this));
FailIf (NULL == dictEntry, Exit);
pluginIDMatch = OSDynamicCast (OSString, dictEntry->getObject (kPluginID));
FailIf (NULL == pluginIDMatch, Exit);
thePluginObject = getPluginObjectWithName (pluginIDMatch);
debugIOLog (3, "AppleOnboardAudio[%ld]::getPluginObjectForConnection - pluginID = %s", mInstanceIndex, pluginIDMatch->getCStringNoCopy());
Exit:
return thePluginObject;
}
GpioAttributes AppleOnboardAudio::getInputDataMuxForConnection (const char * entry) {
OSDictionary * dictEntry;
OSNumber * inputDataMuxOSNumber;
GpioAttributes result;
dictEntry = NULL;
result = kGPIO_Unknown;
dictEntry = OSDynamicCast (OSDictionary, getLayoutEntry (entry, this));
FailIf (NULL == dictEntry, Exit);
inputDataMuxOSNumber = OSDynamicCast (OSNumber, dictEntry->getObject (kInputDataMux));
FailIf (NULL == inputDataMuxOSNumber, Exit);
if ( 0 == inputDataMuxOSNumber->unsigned32BitValue() ) {
result = kGPIO_MuxSelectDefault;
} else {
result = kGPIO_MuxSelectAlternate;
}
debugIOLog (3, "AppleOnboardAudio[%ld]::getInputDataMuxForConnection - GpioAttributes result = %d", mInstanceIndex, result);
Exit:
return result;
}
AudioHardwareObjectInterface * AppleOnboardAudio::getPluginObjectWithName (OSString * inName) {
AudioHardwareObjectInterface * thePluginObject;
OSDictionary * AOAprop;
OSString * thePluginID;
UInt32 index;
UInt32 count;
Boolean found;
thePluginObject = NULL;
count = mPluginObjects->getCount ();
found = FALSE;
index = 0;
while (!found && index < count) {
thePluginObject = getIndexedPluginObject (index);
FailIf (NULL == thePluginObject, Exit);
AOAprop = OSDynamicCast (OSDictionary, thePluginObject->getProperty (kPluginPListAOAAttributes));
FailIf (NULL == AOAprop, Exit);
thePluginID = OSDynamicCast (OSString, AOAprop->getObject (kPluginID));
FailIf (NULL == thePluginID, Exit);
if (thePluginID->isEqualTo (inName)) {
debugIOLog (7, "AppleOnboardAudio[%ld] found matching plugin with ID %s", mInstanceIndex, thePluginID->getCStringNoCopy());
found = TRUE;
}
index++;
}
Exit:
return thePluginObject;
}
IOReturn AppleOnboardAudio::createInputGainControls () {
AudioHardwareObjectInterface * thePluginObject;
char * selectedInput;
IOReturn result;
IOFixed mindBGain = 0;
IOFixed maxdBGain = 0;
UInt32 curSelection = 0;
SInt32 minGain = 0;
SInt32 maxGain = 0;
SInt32 defaultInputGain = 0;
debugIOLog ( 3, "+ AppleOnboardAudio[%ld]::createInputGainControls()", mInstanceIndex );
result = kIOReturnError;
curSelection = mInputSelector->getIntValue ();
selectedInput = getConnectionKeyFromCharCode (curSelection, kIOAudioStreamDirectionInput);
setUseInputGainControls (selectedInput);
if ( kNoInputGainControls != mUseInputGainControls ) {
thePluginObject = getPluginObjectForConnection (selectedInput);
FailIf (NULL == thePluginObject, Exit);
debugIOLog (3, "creating input gain controls for input %s", selectedInput);
mindBGain = thePluginObject->getMinimumdBGain ();
maxdBGain = thePluginObject->getMaximumdBGain ();
minGain = thePluginObject->getMinimumGain ();
maxGain = thePluginObject->getMaximumGain ();
defaultInputGain = thePluginObject->getDefaultInputGain ();
}
if ( kStereoInputGainControls == mUseInputGainControls ) {
debugIOLog ( 3, " mInLeftGainControl = IOAudioLevelControl::createVolumeControl( %ld, %ld, %ld, %lX, %lX, %ld, %p, 0, %lX )", defaultInputGain, minGain, maxGain, mindBGain, maxdBGain, kIOAudioControlChannelIDDefaultLeft, kIOAudioControlChannelNameLeft, 0, kIOAudioControlUsageInput);
mInLeftGainControl = IOAudioLevelControl::createVolumeControl (defaultInputGain, minGain, maxGain, mindBGain, maxdBGain, kIOAudioControlChannelIDDefaultLeft, kIOAudioControlChannelNameLeft, 0, kIOAudioControlUsageInput);
if (NULL != mInLeftGainControl) {
mDriverDMAEngine->addDefaultAudioControl (mInLeftGainControl);
mInLeftGainControl->setValueChangeHandler ((IOAudioControl::IntValueChangeHandler)inputControlChangeHandler, this);
}
debugIOLog ( 3, " mInRightGainControl = IOAudioLevelControl::createVolumeControl( %ld, %ld, %ld, %lX, %lX, %ld, %p, 0, %lX )", defaultInputGain, minGain, maxGain, mindBGain, maxdBGain, kIOAudioControlChannelIDDefaultRight, kIOAudioControlChannelNameRight, 0, kIOAudioControlUsageInput);
mInRightGainControl = IOAudioLevelControl::createVolumeControl (defaultInputGain, minGain, maxGain, mindBGain, maxdBGain, kIOAudioControlChannelIDDefaultRight, kIOAudioControlChannelNameRight, 0, kIOAudioControlUsageInput);
if (NULL != mInRightGainControl) {
mDriverDMAEngine->addDefaultAudioControl (mInRightGainControl);
mInRightGainControl->setValueChangeHandler ((IOAudioControl::IntValueChangeHandler)inputControlChangeHandler, this);
}
} else if ( kMonoInputGainControl == mUseInputGainControls ){
debugIOLog ( 3, " mInMasterGainControl = IOAudioLevelControl::createVolumeControl( %ld, %ld, %ld, %lX, %lX, %ld, %p, 0, %lX )", defaultInputGain, minGain, maxGain, mindBGain, maxdBGain, kIOAudioControlChannelIDAll, kIOAudioControlChannelNameAll, 0, kIOAudioControlUsageInput);
mInMasterGainControl = IOAudioLevelControl::createVolumeControl (defaultInputGain, minGain, maxGain, mindBGain, maxdBGain, kIOAudioControlChannelIDAll, kIOAudioControlChannelNameAll, 0, kIOAudioControlUsageInput);
if (NULL != mInMasterGainControl) {
mDriverDMAEngine->addDefaultAudioControl ( mInMasterGainControl );
mInMasterGainControl->setValueChangeHandler ( (IOAudioControl::IntValueChangeHandler)inputControlChangeHandler, this );
}
}
removePlayThruControl ();
setUsePlaythroughControl ( selectedInput );
if ( mUsePlaythroughControl ) {
createPlayThruControl ();
}
result = kIOReturnSuccess;
Exit:
debugIOLog ( 3, "- AppleOnboardAudio[%ld]::createInputGainControls() returns %lX", mInstanceIndex, result );
return result;
}
OSArray * AppleOnboardAudio::getControlsArray (const char * inSelectedOutput) {
OSArray * theArray;
OSDictionary * theOutput;
theArray = NULL;
theOutput = OSDynamicCast(OSDictionary, getLayoutEntry(inSelectedOutput, this));
FailIf (NULL == theOutput, Exit);
theArray = OSDynamicCast(OSArray, theOutput->getObject(kControls));
Exit:
return theArray;
}
UInt32 AppleOnboardAudio::getNumHardwareEQBandsForCurrentOutput () {
OSDictionary * AOApropOutput;
OSNumber * numBandsNumber;
UInt32 numBands;
numBands = 0;
AOApropOutput = OSDynamicCast (OSDictionary, mCurrentOutputPlugin->getProperty (kPluginPListAOAAttributes));
if (NULL != AOApropOutput) {
numBandsNumber = OSDynamicCast (OSNumber, AOApropOutput->getObject (kPluginPListNumHardwareEQBands));
if (NULL != numBandsNumber) {
numBands = numBandsNumber->unsigned32BitValue();
}
}
return numBands;
}
UInt32 AppleOnboardAudio::getMaxVolumeOffsetForOutput (const UInt32 inCode) {
char * connectionString;
connectionString = getConnectionKeyFromCharCode (inCode, kIOAudioStreamDirectionOutput);
return getMaxVolumeOffsetForOutput (connectionString);
}
UInt32 AppleOnboardAudio::getMaxVolumeOffsetForOutput (const char * inSelectedOutput) {
OSDictionary * theSpeakerIDDict;
OSDictionary * theSignalProcessingDict;
OSDictionary * theOutput;
OSNumber * theMaxVolumeNumber;
OSString * speakerIDString;
char speakerIDCString[32];
UInt32 maxVolumeOffset;
maxVolumeOffset = 0;
theOutput = OSDynamicCast(OSDictionary, getLayoutEntry (inSelectedOutput, this));
FailIf (NULL == theOutput, Exit);
theSignalProcessingDict = OSDynamicCast (OSDictionary, theOutput->getObject (kSignalProcessing));
if ( NULL != theSignalProcessingDict ) {
sprintf (speakerIDCString, "%s_%ld", kSpeakerID, mInternalSpeakerID);
speakerIDString = OSString::withCString (speakerIDCString);
FailIf (NULL == speakerIDString, Exit);
theSpeakerIDDict = OSDynamicCast (OSDictionary, theSignalProcessingDict->getObject (speakerIDString));
speakerIDString->release ();
FailIf (NULL == theSpeakerIDDict, Exit);
theMaxVolumeNumber = OSDynamicCast (OSNumber, theSpeakerIDDict->getObject (kMaxVolumeOffset));
if (NULL != theMaxVolumeNumber) {
debugIOLog (3, "getMaxVolumeOffsetForOutput: theMaxVolumeNumber value = %d", theMaxVolumeNumber->unsigned32BitValue ());
maxVolumeOffset = theMaxVolumeNumber->unsigned32BitValue ();
}
}
Exit:
return maxVolumeOffset;
}
void AppleOnboardAudio::setSoftwareOutputDSP (const char * inSelectedOutput) {
OSDictionary * theSpeakerIDDict;
OSDictionary * theSignalProcessingDict;
OSDictionary * theOutput;
OSDictionary * theSoftwareDSPDict;
OSString * speakerIDString;
char speakerIDCString[32];
debugIOLog (3, "+ AppleOnboardAudio[%ld]::setSoftwareOutputDSP (%s).", mInstanceIndex, inSelectedOutput);
if (mCurrentProcessingOutputString->isEqualTo (inSelectedOutput)) {
debugIOLog (3, "Enabling DSP");
mDriverDMAEngine->enableOutputProcessing ();
debugIOLog (3, "mCurrentProcessingOutputString is '%s', coefficients not updated.", mCurrentProcessingOutputString->getCStringNoCopy ());
} else {
mDriverDMAEngine->disableOutputProcessing ();
debugIOLog (3, "processing disabled.");
theOutput = OSDynamicCast(OSDictionary, getLayoutEntry (inSelectedOutput, this));
FailIf (NULL == theOutput, Exit);
theSignalProcessingDict = OSDynamicCast (OSDictionary, theOutput->getObject (kSignalProcessing));
if ( NULL != theSignalProcessingDict ) {
sprintf (speakerIDCString, "%s_%ld", kSpeakerID, mInternalSpeakerID);
debugIOLog (3, "setSoftwareOutputDSP: speakerIDString = %s", speakerIDCString);
speakerIDString = OSString::withCString (speakerIDCString);
FailIf (NULL == speakerIDString, Exit);
theSpeakerIDDict = OSDynamicCast (OSDictionary, theSignalProcessingDict->getObject (speakerIDString));
speakerIDString->release ();
FailIf (NULL == theSpeakerIDDict, Exit);
debugIOLog (3, "setSoftwareOutputDSP: theSpeakerIDDict = %p", theSpeakerIDDict);
theSoftwareDSPDict = OSDynamicCast (OSDictionary, theSpeakerIDDict->getObject (kSoftwareDSP));
if (NULL != theSoftwareDSPDict) {
debugIOLog (3, "setSoftwareOutputDSP: theSoftwareDSPDict = %p", theSoftwareDSPDict);
mDriverDMAEngine->setOutputSignalProcessing (theSoftwareDSPDict);
debugIOLog (3, "Processing set");
debugIOLog (3, "mCurrentProcessingOutputString is '%s'", mCurrentProcessingOutputString->getCStringNoCopy ());
mCurrentProcessingOutputString->initWithCString (inSelectedOutput);
debugIOLog (3, "mCurrentProcessingOutputString set to '%s', coefficients will be updated.", mCurrentProcessingOutputString->getCStringNoCopy ());
}
}
}
Exit:
debugIOLog (3, "- AppleOnboardAudio[%ld]::setSoftwareOutputDSP ('%4s' ).", mInstanceIndex, inSelectedOutput);
return;
}
void AppleOnboardAudio::setSoftwareInputDSP (const char * inSelectedInput) {
OSDictionary * theSignalProcessingDict;
OSDictionary * theMicrophoneIDDict;
OSDictionary * theSoftwareDSPDict;
OSDictionary * theInput;
OSString * microphoneIDString;
char microphoneIDCString[32];
debugIOLog (3, "set input DSP for '%s'.", inSelectedInput);
if (mCurrentProcessingInputString->isEqualTo (inSelectedInput)) {
debugIOLog (3, "Enabling input DSP");
mDriverDMAEngine->enableInputProcessing ();
debugIOLog (3, "mCurrentProcessingInputString is '%s', coefficients not updated.", mCurrentProcessingInputString->getCStringNoCopy ());
} else {
debugIOLog (3, "Disabling input DSP");
mDriverDMAEngine->disableInputProcessing ();
debugIOLog (3, "input processing disabled.");
theInput = OSDynamicCast(OSDictionary, getLayoutEntry (inSelectedInput, this));
FailIf (NULL == theInput, Exit);
theSignalProcessingDict = OSDynamicCast (OSDictionary, theInput->getObject (kSignalProcessing));
if (NULL != theSignalProcessingDict) {
sprintf (microphoneIDCString, "%s_%ld", kMicrophoneID, mInternalMicrophoneID);
debugIOLog (3, "setSoftwareInputDSP: inputDeviceIDString = %s", microphoneIDCString);
microphoneIDString = OSString::withCString (microphoneIDCString);
FailIf (NULL == microphoneIDString, Exit);
theMicrophoneIDDict = OSDynamicCast (OSDictionary, theSignalProcessingDict->getObject (microphoneIDString));
microphoneIDString->release ();
FailIf (NULL == theMicrophoneIDDict, Exit);
debugIOLog (3, "setSoftwareInputDSP: theMicrophoneIDDict = %p", theMicrophoneIDDict);
theSoftwareDSPDict = OSDynamicCast (OSDictionary, theMicrophoneIDDict->getObject (kSoftwareDSP));
FailIf (NULL == theSoftwareDSPDict, Exit);
debugIOLog (3, "setSoftwareInputDSP: theSoftwareDSPDict = %p", theSoftwareDSPDict);
mDriverDMAEngine->setInputSignalProcessing (theSoftwareDSPDict);
debugIOLog (3, "Input processing set");
debugIOLog (3, "mCurrentProcessingInputString is '%s'", mCurrentProcessingInputString->getCStringNoCopy ());
mCurrentProcessingInputString->initWithCString (inSelectedInput);
debugIOLog (3, "mCurrentProcessingInputString set to '%s', coefficients will be updated.", mCurrentProcessingInputString->getCStringNoCopy ());
}
}
Exit:
return;
}
UInt32 AppleOnboardAudio::setClipRoutineForOutput (const char * inSelectedOutput) {
OSDictionary * theOutput;
OSString * clipRoutineString;
OSArray * theArray;
IOReturn result;
UInt32 arrayCount;
UInt32 index;
debugIOLog (3, "+ AppleOnboardAudio[%ld]::setClipRoutineForOutput ( '%4s' )", mInstanceIndex, inSelectedOutput );
result = kIOReturnSuccess;
theArray = NULL;
theOutput = OSDynamicCast(OSDictionary, getLayoutEntry(inSelectedOutput, this));
FailIf (NULL == theOutput, Exit);
theArray = OSDynamicCast(OSArray, theOutput->getObject(kClipRoutines));
FailIf (NULL == theArray, Exit);
arrayCount = theArray->getCount();
mDriverDMAEngine->resetOutputClipOptions();
for (index = 0; index < arrayCount; index++) {
clipRoutineString = OSDynamicCast(OSString, theArray->getObject(index));
debugIOLog (3, "getClipRoutineForOutput: clip routine[%ld] = %s", index, clipRoutineString->getCStringNoCopy());
if (clipRoutineString->isEqualTo (kStereoToRightChanClipString)) {
mDriverDMAEngine->setRightChanMixed (true);
} else {
mDriverDMAEngine->resetOutputClipOptions();
}
}
result = kIOReturnSuccess;
Exit:
debugIOLog (3, "- AppleOnboardAudio[%ld]::setClipRoutineForOutput ( '%4s' ) returns %X", mInstanceIndex, inSelectedOutput, result );
return result;
}
UInt32 AppleOnboardAudio::setClipRoutineForInput (const char * inSelectedInput) {
OSDictionary * theInput;
OSString * clipRoutineString;
OSArray * theArray;
IOReturn result;
UInt32 arrayCount;
UInt32 index;
result = kIOReturnSuccess;
theArray = NULL;
theInput = OSDynamicCast(OSDictionary, getLayoutEntry(inSelectedInput, this));
FailIf (NULL == theInput, Exit);
theArray = OSDynamicCast(OSArray, theInput->getObject(kClipRoutines));
FailIf (NULL == theArray, Exit);
arrayCount = theArray->getCount();
mDriverDMAEngine->resetInputClipOptions();
for (index = 0; index < arrayCount; index++) {
clipRoutineString = OSDynamicCast(OSString, theArray->getObject(index));
debugIOLog (3, "getClipRoutineForInput: clip routine[%ld] = %s", index, clipRoutineString->getCStringNoCopy());
if (clipRoutineString->isEqualTo (kCopyLeftToRight)) {
mDriverDMAEngine->setDualMonoMode (e_Mode_CopyLeftToRight);
} else if (clipRoutineString->isEqualTo (kCopyRightToLeft)) {
mDriverDMAEngine->setDualMonoMode (e_Mode_CopyRightToLeft);
}
}
result = kIOReturnSuccess;
Exit:
debugIOLog (3, "getClipRoutineForInput returns %X", result);
return result;
}
void AppleOnboardAudio::cacheOutputVolumeLevels (AudioHardwareObjectInterface * thePluginObject) {
if (NULL != mOutMasterVolumeControl) {
mCurrentOutputPlugin->setProperty(kPluginPListMasterVol, mOutMasterVolumeControl->getValue ());
} else {
OSNumber * theNumber;
theNumber = OSNumber::withNumber ((unsigned long long)-1, 32);
if (NULL != mOutLeftVolumeControl) {
mCurrentOutputPlugin->setProperty(kPluginPListLeftVol, mOutLeftVolumeControl->getValue ());
mCurrentOutputPlugin->setProperty(kPluginPListMasterVol, theNumber);
}
if (NULL != mOutRightVolumeControl) {
mCurrentOutputPlugin->setProperty(kPluginPListRightVol, mOutRightVolumeControl->getValue ());
mCurrentOutputPlugin->setProperty(kPluginPListMasterVol, theNumber);
}
theNumber->release ();
}
return;
}
void AppleOnboardAudio::cacheInputGainLevels (AudioHardwareObjectInterface * thePluginObject) {
if (NULL != mInLeftGainControl) {
mCurrentInputPlugin->setProperty(kPluginPListLeftGain, mInLeftGainControl->getValue ());
}
if (NULL != mInRightGainControl) {
mCurrentInputPlugin->setProperty(kPluginPListRightGain, mInRightGainControl->getValue ());
}
if ( NULL != mInMasterGainControl ) {
mCurrentInputPlugin->setProperty ( kPluginPListMasterGain, mInMasterGainControl->getValue () );
}
return;
}
IOReturn AppleOnboardAudio::createOutputVolumeControls (void) {
AudioHardwareObjectInterface * thePluginObject;
OSArray * controlsArray;
OSString * controlString;
char * selectedOutput;
IOReturn result;
UInt32 curSelection;
UInt32 count;
UInt32 index;
debugIOLog (3, "+ AppleOnboardAudio[%ld]::createOutputVolumeControls", mInstanceIndex);
result = kIOReturnError;
if ( NULL != mOutputSelector ) {
curSelection = mOutputSelector->getIntValue ();
selectedOutput = getConnectionKeyFromCharCode(curSelection, kIOAudioStreamDirectionOutput);
thePluginObject = getPluginObjectForConnection (selectedOutput);
FailIf (NULL == thePluginObject, Exit);
AdjustOutputVolumeControls (thePluginObject, curSelection);
controlsArray = getControlsArray (selectedOutput);
FailIf (NULL == controlsArray, Exit);
count = controlsArray->getCount ();
for (index = 0; index < count; index++) {
controlString = OSDynamicCast (OSString, controlsArray->getObject (index));
if (controlString->isEqualTo (kMuteControlString)) {
mOutMuteControl = IOAudioToggleControl::createMuteControl (false, kIOAudioControlChannelIDAll, kIOAudioControlChannelNameAll, 0, kIOAudioControlUsageOutput);
if (NULL != mOutMuteControl) {
mDriverDMAEngine->addDefaultAudioControl(mOutMuteControl);
mOutMuteControl->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)outputControlChangeHandler, this);
}
break; }
}
} else {
result = kIOReturnSuccess;
}
Exit:
debugIOLog (3, "- AppleOnboardAudio[%ld]::createOutputVolumeControls", mInstanceIndex);
return result;
}
IOReturn AppleOnboardAudio::createDefaultControls () {
AudioHardwareObjectInterface * thePluginObject;
OSDictionary * AOAprop;
OSBoolean * clockSelectBoolean;
OSArray * inputListArray;
UInt32 index;
UInt32 count;
IOReturn result;
Boolean hasPlaythrough;
Boolean hasInput;
debugIOLog (3, "+ AppleOnboardAudio[%ld]::createDefaultControls", mInstanceIndex);
hasPlaythrough = FALSE;
result = kIOReturnError;
FailIf (NULL == mDriverDMAEngine, Exit);
count = mPluginObjects->getCount ();
for (index = 0; index < count; index++) {
thePluginObject = getIndexedPluginObject (index);
FailIf (NULL == thePluginObject, Exit);
AOAprop = OSDynamicCast (OSDictionary, thePluginObject->getProperty (kPluginPListAOAAttributes));
FailIf (NULL == AOAprop, Exit);
}
result = createOutputSelectorControl ();
FailIf (kIOReturnSuccess != result, Exit);
createOutputVolumeControls ();
mPRAMVolumeControl = IOAudioLevelControl::create (PRAMToVolumeValue (), 0, 7, 0x00120000, 0, kIOAudioControlChannelIDAll, "BootBeepVolume", 0, kIOAudioLevelControlSubTypePRAMVolume, kIOAudioControlUsageOutput);
if (NULL != mPRAMVolumeControl) {
mDriverDMAEngine->addDefaultAudioControl (mPRAMVolumeControl);
mPRAMVolumeControl->setValueChangeHandler ((IOAudioControl::IntValueChangeHandler)outputControlChangeHandler, this);
mPRAMVolumeControl->release ();
mPRAMVolumeControl = NULL;
}
mHeadphoneConnected = IOAudioToggleControl::create (FALSE, kIOAudioControlChannelIDAll, kIOAudioControlChannelNameAll, 0, kIOAudioControlTypeJack, kIOAudioControlUsageOutput);
if (NULL != mHeadphoneConnected) {
mDriverDMAEngine->addDefaultAudioControl (mHeadphoneConnected);
mHeadphoneConnected->setReadOnlyFlag (); }
inputListArray = OSDynamicCast (OSArray, getLayoutEntry (kInputsList, this));
hasInput = (NULL != inputListArray);
if (hasInput) {
createInputSelectorControl ();
createInputGainControls ();
}
clockSelectBoolean = OSDynamicCast ( OSBoolean, getLayoutEntry (kExternalClockSelect, this) );
if (NULL != clockSelectBoolean) {
if (TRUE == clockSelectBoolean->getValue ()) {
mExternalClockSelector = IOAudioSelectorControl::create (kClockSourceSelectionInternal, kIOAudioControlChannelIDAll, kIOAudioControlChannelNameAll, 0, kIOAudioSelectorControlSubTypeClockSource, kIOAudioControlUsageInput);
FailIf (NULL == mExternalClockSelector, Exit);
mDriverDMAEngine->addDefaultAudioControl (mExternalClockSelector);
mExternalClockSelector->setValueChangeHandler ((IOAudioControl::IntValueChangeHandler)inputControlChangeHandler, this);
mExternalClockSelector->addAvailableSelection (kClockSourceSelectionInternal, kInternalClockString);
mExternalClockSelector->addAvailableSelection (kClockSourceSelectionExternal, kExternalClockString);
}
}
result = kIOReturnSuccess;
Exit:
debugIOLog (3, "- %lX = AppleOnboardAudio[%ld]::createDefaultControls", mInstanceIndex, result);
return result;
}
AppleOnboardAudio* AppleOnboardAudio::findAOAInstanceWithLayoutID ( UInt32 layoutID ) {
AppleOnboardAudio * theAOA;
AppleOnboardAudio * result = NULL;
UInt32 numInstances;
debugIOLog ( 3, "%p AppleOnboardAudio[%ld]::findAOAInstanceWithLayoutID ( %d )", mInstanceIndex, this, layoutID );
if ( NULL != mAOAInstanceArray ) {
numInstances = mAOAInstanceArray->getCount();
for ( UInt32 index = 0; index < numInstances && ( NULL == result ); index++ ) {
theAOA = OSDynamicCast ( AppleOnboardAudio, mAOAInstanceArray->getObject ( index ) );
if ( theAOA->getLayoutID() == layoutID ) {
result = theAOA;
}
}
}
return result;
}
#pragma mark +IOAUDIO CONTROL HANDLERS
IOReturn AppleOnboardAudio::AdjustOutputVolumeControls (AudioHardwareObjectInterface * thePluginObject, UInt32 selectionCode) {
IOFixed mindBVol;
IOFixed maxdBVol;
SInt32 minVolume;
SInt32 maxVolume;
Boolean hasMaster;
Boolean hasLeft;
Boolean hasRight;
Boolean stereoOutputConnected;
FailIf (NULL == mDriverDMAEngine, Exit);
mindBVol = thePluginObject->getMinimumdBVolume ();
maxdBVol = thePluginObject->getMaximumdBVolume ();
minVolume = thePluginObject->getMinimumVolume ();
maxVolume = thePluginObject->getMaximumVolume ();
maxVolume += getMaxVolumeOffsetForOutput (selectionCode);
debugIOLog (3, "+ AppleOnboardAudio[%ld]::AdjustOutputVolumeControls( %p, '%4s' ) - mindBVol %lX, maxdBVol %lX, minVolume %ld, maxVolume %ld",
mInstanceIndex, thePluginObject, (char*)&selectionCode, mindBVol, maxdBVol, minVolume, maxVolume);
mDriverDMAEngine->pauseAudioEngine ();
mDriverDMAEngine->beginConfigurationChange ();
if ( ((kIOAudioOutputPortSubTypeSPDIF == selectionCode) && (kGPIO_Unknown == mPlatformInterface->getComboOutJackTypeConnected())) || (kIOAudioOutputPortSubTypeSPDIF != selectionCode) ) {
debugIOLog ( 3, " output is not exclusive digital output!" );
hasMaster = hasMasterVolumeControl (selectionCode);
hasLeft = hasLeftVolumeControl (selectionCode);
hasRight = hasRightVolumeControl (selectionCode);
if ((hasMaster || hasLeft || hasRight) && (FALSE == thePluginObject->hasHardwareVolume ())) {
debugIOLog (3, "have volume controls and need software implementation.");
mCurrentPluginNeedsSoftwareOutputVolume = TRUE;
mDriverDMAEngine->setUseSoftwareOutputVolume (TRUE, minVolume, maxVolume, mindBVol, maxdBVol);
} else {
debugIOLog (3, "no volume controls or don't need software implementation.");
mCurrentPluginNeedsSoftwareOutputVolume = FALSE;
mDriverDMAEngine->setUseSoftwareOutputVolume (FALSE);
}
if ((kGPIO_Connected == mPlatformInterface->getHeadphoneConnected ()) ||
(kGPIO_Connected == mPlatformInterface->getSpeakerConnected ()) ||
(kGPIO_Connected == mPlatformInterface->getLineOutConnected ()) ||
(kGPIO_Connected == mPlatformInterface->getDigitalOutConnected ())) {
stereoOutputConnected = true;
} else {
stereoOutputConnected = false;
}
if ((TRUE == hasMaster && NULL == mOutMasterVolumeControl) || (FALSE == hasMaster && NULL != mOutMasterVolumeControl) ||
(NULL != mOutMasterVolumeControl && mOutMasterVolumeControl->getMinValue () != minVolume) ||
(NULL != mOutMasterVolumeControl && mOutMasterVolumeControl->getMaxValue () != maxVolume)) {
if (TRUE == hasMaster) {
if (NULL != mOutMasterVolumeControl) {
mOutMasterVolumeControl->setMinValue (minVolume);
mOutMasterVolumeControl->setMinDB (mindBVol);
mOutMasterVolumeControl->setMaxValue (maxVolume);
mOutMasterVolumeControl->setMaxDB (maxdBVol);
if (mOutMasterVolumeControl->getIntValue () > maxVolume) {
mOutMasterVolumeControl->setValue (maxVolume);
}
mOutMasterVolumeControl->flushValue ();
} else {
createMasterVolumeControl (mindBVol, maxdBVol, minVolume, maxVolume);
}
} else {
removeMasterVolumeControl();
}
}
if ((TRUE == hasLeft && NULL == mOutLeftVolumeControl) || (FALSE == hasLeft && NULL != mOutLeftVolumeControl) ||
(NULL != mOutLeftVolumeControl && mOutLeftVolumeControl->getMinValue () != minVolume) ||
(NULL != mOutLeftVolumeControl && mOutLeftVolumeControl->getMaxValue () != maxVolume)) {
if (TRUE == hasLeft) {
if (NULL != mOutLeftVolumeControl) {
mOutLeftVolumeControl->setMinValue (minVolume);
mOutLeftVolumeControl->setMinDB (mindBVol);
mOutLeftVolumeControl->setMaxValue (maxVolume);
mOutLeftVolumeControl->setMaxDB (maxdBVol);
if (mOutLeftVolumeControl->getIntValue () > maxVolume) {
mOutLeftVolumeControl->setValue (maxVolume);
}
mOutLeftVolumeControl->flushValue ();
} else {
createLeftVolumeControl(mindBVol, maxdBVol, minVolume, maxVolume);
}
} else {
if (!stereoOutputConnected) {
removeLeftVolumeControl();
}
}
}
if ((TRUE == hasRight && NULL == mOutRightVolumeControl) || (FALSE == hasRight && NULL != mOutRightVolumeControl) ||
(NULL != mOutRightVolumeControl && mOutRightVolumeControl->getMinValue () != minVolume) ||
(NULL != mOutRightVolumeControl && mOutRightVolumeControl->getMaxValue () != maxVolume)) {
if (TRUE == hasRight) {
if (NULL != mOutRightVolumeControl) {
mOutRightVolumeControl->setMinValue (minVolume);
mOutRightVolumeControl->setMinDB (mindBVol);
mOutRightVolumeControl->setMaxValue (maxVolume);
mOutRightVolumeControl->setMaxDB (maxdBVol);
if (mOutRightVolumeControl->getIntValue () > maxVolume) {
mOutRightVolumeControl->setValue (maxVolume);
}
mOutRightVolumeControl->flushValue ();
} else {
createRightVolumeControl(mindBVol, maxdBVol, minVolume, maxVolume);
}
} else {
if (!stereoOutputConnected) {
removeRightVolumeControl ();
}
}
}
} else {
debugIOLog ( 3, " output is exclusive digital output- removing all level controls!" );
mCurrentPluginNeedsSoftwareOutputVolume = FALSE;
mDriverDMAEngine->setUseSoftwareOutputVolume (FALSE);
removeMasterVolumeControl();
removeLeftVolumeControl();
removeRightVolumeControl ();
}
mDriverDMAEngine->completeConfigurationChange ();
mDriverDMAEngine->resumeAudioEngine ();
Exit:
debugIOLog (3, "- AppleOnboardAudio[%ld]::AdjustOutputVolumeControls( %p, '%4s' )", mInstanceIndex, thePluginObject, (char*)&selectionCode );
return kIOReturnSuccess;
}
IOReturn AppleOnboardAudio::AdjustInputGainControls (AudioHardwareObjectInterface * thePluginObject) {
IOFixed mindBGain;
IOFixed maxdBGain;
SInt32 minGain;
SInt32 maxGain;
FailIf (NULL == mDriverDMAEngine, Exit);
mindBGain = thePluginObject->getMinimumdBGain ();
maxdBGain = thePluginObject->getMaximumdBGain ();
minGain = thePluginObject->getMinimumGain ();
maxGain = thePluginObject->getMaximumGain ();
debugIOLog (3, "AppleOnboardAudio[%ld]::AdjustInputGainControls - mindBGain %lX, maxdBGain %lX, minGain %ld, maxGain %ld", mInstanceIndex, mindBGain, maxdBGain, minGain, maxGain);
mDriverDMAEngine->pauseAudioEngine ();
mDriverDMAEngine->beginConfigurationChange ();
removePlayThruControl ();
if ( mUsePlaythroughControl ) {
createPlayThruControl ();
}
if ( kStereoInputGainControls == mUseInputGainControls ) {
debugIOLog (3, "AdjustInputGainControls - creating input gain controls.");
if (NULL != mInLeftGainControl) {
mInLeftGainControl->setMinValue (minGain);
mInLeftGainControl->setMinDB (mindBGain);
mInLeftGainControl->setMaxValue (maxGain);
mInLeftGainControl->setMaxDB (maxdBGain);
if (mInLeftGainControl->getIntValue () > maxGain) {
mInLeftGainControl->setValue (maxGain);
}
mInLeftGainControl->flushValue ();
} else {
createLeftGainControl(mindBGain, maxdBGain, minGain, maxGain);
}
if (NULL != mInRightGainControl) {
mInRightGainControl->setMinValue (minGain);
mInRightGainControl->setMinDB (mindBGain);
mInRightGainControl->setMaxValue (maxGain);
mInRightGainControl->setMaxDB (maxdBGain);
if (mInRightGainControl->getIntValue () > maxGain) {
mInRightGainControl->setValue (maxGain);
}
mInRightGainControl->flushValue ();
} else {
createRightGainControl(mindBGain, maxdBGain, minGain, maxGain);
}
removeMasterGainControl();
} else if ( kMonoInputGainControl == mUseInputGainControls ) {
if (NULL != mInMasterGainControl) {
mInMasterGainControl->setMinValue (minGain);
mInMasterGainControl->setMinDB (mindBGain);
mInMasterGainControl->setMaxValue (maxGain);
mInMasterGainControl->setMaxDB (maxdBGain);
if (mInMasterGainControl->getIntValue () > maxGain) {
mInMasterGainControl->setValue (maxGain);
}
mInMasterGainControl->flushValue ();
} else {
createMasterGainControl(mindBGain, maxdBGain, minGain, maxGain);
}
removeLeftGainControl();
removeRightGainControl();
} else {
debugIOLog (3, "AdjustInputGainControls - removing input gain controls.");
removeLeftGainControl();
removeRightGainControl();
removeMasterGainControl();
}
mDriverDMAEngine->completeConfigurationChange ();
mDriverDMAEngine->resumeAudioEngine ();
Exit:
return kIOReturnSuccess;
}
IORegistryEntry * AppleOnboardAudio::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;
}
}
}
Exit:
if (NULL != iterator) {
iterator->release ();
}
return theEntry;
}
void AppleOnboardAudio::createLeftVolumeControl (IOFixed mindBVol, IOFixed maxdBVol, SInt32 minVolume, SInt32 maxVolume) {
OSNumber * theNumber;
SInt32 leftVol;
leftVol = 0;
theNumber = OSDynamicCast(OSNumber, mCurrentOutputPlugin->getProperty(kPluginPListLeftVol));
if (NULL != theNumber) {
leftVol = theNumber->unsigned32BitValue();
}
if (NULL == theNumber || leftVol == 0) {
theNumber = OSDynamicCast(OSNumber, mCurrentOutputPlugin->getProperty(kPluginPListMasterVol));
if (NULL != theNumber) {
leftVol = theNumber->unsigned32BitValue();
if (leftVol == -1) {
leftVol = maxVolume / 2;
}
}
}
debugIOLog (3, "createLeftVolumeControl - leftVol = %ld", leftVol);
mOutLeftVolumeControl = IOAudioLevelControl::createVolumeControl (leftVol, minVolume, maxVolume, mindBVol, maxdBVol,
kIOAudioControlChannelIDDefaultLeft,
kIOAudioControlChannelNameLeft,
0,
kIOAudioControlUsageOutput);
if (NULL != mOutLeftVolumeControl) {
mDriverDMAEngine->addDefaultAudioControl (mOutLeftVolumeControl);
mOutLeftVolumeControl->setValueChangeHandler ((IOAudioControl::IntValueChangeHandler)outputControlChangeHandler, this);
mOutLeftVolumeControl->flushValue ();
}
}
void AppleOnboardAudio::createRightVolumeControl (IOFixed mindBVol, IOFixed maxdBVol, SInt32 minVolume, SInt32 maxVolume) {
OSNumber * theNumber;
SInt32 rightVol;
rightVol = 0;
theNumber = OSDynamicCast(OSNumber, mCurrentOutputPlugin->getProperty(kPluginPListRightVol));
if (NULL != theNumber) {
rightVol = theNumber->unsigned32BitValue();
}
if (NULL == theNumber || rightVol == 0) {
theNumber = OSDynamicCast(OSNumber, mCurrentOutputPlugin->getProperty(kPluginPListMasterVol));
if (NULL != theNumber) {
rightVol = theNumber->unsigned32BitValue();
if (rightVol == -1) {
rightVol = maxVolume / 2;
}
}
}
debugIOLog (3, "createRightVolumeControl - rightVol = %ld", rightVol);
mOutRightVolumeControl = IOAudioLevelControl::createVolumeControl (rightVol, minVolume, maxVolume, mindBVol, maxdBVol,
kIOAudioControlChannelIDDefaultRight,
kIOAudioControlChannelNameRight,
0,
kIOAudioControlUsageOutput);
if (NULL != mOutRightVolumeControl) {
mDriverDMAEngine->addDefaultAudioControl (mOutRightVolumeControl);
mOutRightVolumeControl->setValueChangeHandler ((IOAudioControl::IntValueChangeHandler)outputControlChangeHandler, this);
mOutRightVolumeControl->flushValue ();
}
}
void AppleOnboardAudio::createMasterVolumeControl (IOFixed mindBVol, IOFixed maxdBVol, SInt32 minVolume, SInt32 maxVolume) {
OSNumber * theNumber;
SInt32 masterVol;
masterVol = 0;
theNumber = OSDynamicCast(OSNumber, mCurrentOutputPlugin->getProperty(kPluginPListMasterVol));
if (NULL != theNumber) {
masterVol = theNumber->unsigned32BitValue();
}
if (-1 == masterVol || NULL == theNumber) {
theNumber = OSDynamicCast(OSNumber, mCurrentOutputPlugin->getProperty(kPluginPListRightVol));
if (NULL == theNumber) {
masterVol = maxVolume;
} else {
masterVol = theNumber->unsigned32BitValue();
}
theNumber = OSDynamicCast(OSNumber, mCurrentOutputPlugin->getProperty(kPluginPListLeftVol));
if (NULL != theNumber) {
masterVol += theNumber->unsigned32BitValue();
}
masterVol >>= 1;
}
debugIOLog (3, "createMasterVolumeControl - masterVol = %ld", masterVol);
mOutMasterVolumeControl = IOAudioLevelControl::createVolumeControl (masterVol, minVolume, maxVolume, mindBVol, maxdBVol,
kIOAudioControlChannelIDAll,
kIOAudioControlChannelNameAll,
0,
kIOAudioControlUsageOutput);
if (NULL != mOutMasterVolumeControl) {
mDriverDMAEngine->addDefaultAudioControl(mOutMasterVolumeControl);
mOutMasterVolumeControl->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)outputControlChangeHandler, this);
mOutMasterVolumeControl->flushValue ();
}
}
void AppleOnboardAudio::createLeftGainControl (IOFixed mindBGain, IOFixed maxdBGain, SInt32 minGain, SInt32 maxGain) {
OSNumber * theNumber;
SInt32 leftGain;
theNumber = OSDynamicCast(OSNumber, mCurrentInputPlugin->getProperty("left-gain"));
if (NULL == theNumber) {
leftGain = 0;
} else {
leftGain = theNumber->unsigned32BitValue();
}
debugIOLog (3, "createLeftGainControl - leftVol = %ld", leftGain);
mInLeftGainControl = IOAudioLevelControl::createVolumeControl (leftGain, minGain, maxGain, mindBGain, maxdBGain,
kIOAudioControlChannelIDDefaultLeft,
kIOAudioControlChannelNameLeft,
0,
kIOAudioControlUsageInput);
if (NULL != mInLeftGainControl) {
mDriverDMAEngine->addDefaultAudioControl (mInLeftGainControl);
mInLeftGainControl->setValueChangeHandler ((IOAudioControl::IntValueChangeHandler)inputControlChangeHandler, this);
mInLeftGainControl->flushValue ();
}
}
void AppleOnboardAudio::createRightGainControl (IOFixed mindBGain, IOFixed maxdBGain, SInt32 minGain, SInt32 maxGain) {
OSNumber * theNumber;
SInt32 rightGain;
theNumber = OSDynamicCast(OSNumber, mCurrentInputPlugin->getProperty("right-gain"));
if (NULL == theNumber) {
rightGain = 0;
} else {
rightGain = theNumber->unsigned32BitValue();
}
debugIOLog (3, "createRightGainControl - rightVol = %ld", rightGain);
mInRightGainControl = IOAudioLevelControl::createVolumeControl (rightGain, minGain, maxGain, mindBGain, maxdBGain,
kIOAudioControlChannelIDDefaultRight,
kIOAudioControlChannelNameRight,
0,
kIOAudioControlUsageInput);
if (NULL != mInRightGainControl) {
mDriverDMAEngine->addDefaultAudioControl (mInRightGainControl);
mInRightGainControl->setValueChangeHandler ((IOAudioControl::IntValueChangeHandler)inputControlChangeHandler, this);
mInRightGainControl->flushValue ();
}
}
void AppleOnboardAudio::createMasterGainControl (IOFixed mindBGain, IOFixed maxdBGain, SInt32 minGain, SInt32 maxGain) {
OSNumber * theNumber;
SInt32 masterGain;
theNumber = OSDynamicCast(OSNumber, mCurrentInputPlugin->getProperty("master-gain"));
if (NULL == theNumber) {
masterGain = 0;
} else {
masterGain = theNumber->unsigned32BitValue();
}
debugIOLog (3, "createMasterGainControl - masterVol = %ld", masterGain);
mInMasterGainControl = IOAudioLevelControl::createVolumeControl (masterGain, minGain, maxGain, mindBGain, maxdBGain,
kIOAudioControlChannelIDAll,
kIOAudioControlChannelNameAll,
0,
kIOAudioControlUsageInput);
if (NULL != mInMasterGainControl) {
mDriverDMAEngine->addDefaultAudioControl (mInMasterGainControl);
mInMasterGainControl->setValueChangeHandler ((IOAudioControl::IntValueChangeHandler)inputControlChangeHandler, this);
mInMasterGainControl->flushValue ();
}
}
void AppleOnboardAudio::removeLeftVolumeControl() {
if (NULL != mOutLeftVolumeControl) {
mDriverDMAEngine->removeDefaultAudioControl (mOutLeftVolumeControl);
mOutLeftVolumeControl = NULL;
}
}
void AppleOnboardAudio::removeRightVolumeControl() {
if (NULL != mOutRightVolumeControl) {
mDriverDMAEngine->removeDefaultAudioControl (mOutRightVolumeControl);
mOutRightVolumeControl = NULL;
}
}
void AppleOnboardAudio::removeMasterVolumeControl() {
if (NULL != mOutMasterVolumeControl) {
mDriverDMAEngine->removeDefaultAudioControl (mOutMasterVolumeControl);
mOutMasterVolumeControl = NULL;
}
}
void AppleOnboardAudio::removeLeftGainControl() {
if (NULL != mInLeftGainControl) {
mDriverDMAEngine->removeDefaultAudioControl (mInLeftGainControl);
mInLeftGainControl = NULL;
}
}
void AppleOnboardAudio::removeRightGainControl() {
if (NULL != mInRightGainControl) {
mDriverDMAEngine->removeDefaultAudioControl (mInRightGainControl);
mInRightGainControl = NULL;
}
}
void AppleOnboardAudio::removeMasterGainControl() {
if ( NULL != mInMasterGainControl ) {
mDriverDMAEngine->removeDefaultAudioControl ( mInMasterGainControl );
mInMasterGainControl = NULL;
}
}
IOReturn AppleOnboardAudio::outputControlChangeHandler (IOService *target, IOAudioControl *control, SInt32 oldValue, SInt32 newValue) {
IOReturn result;
AppleOnboardAudio * audioDevice;
IOAudioLevelControl * levelControl;
IODTPlatformExpert * platform;
UInt32 leftVol;
UInt32 rightVol;
Boolean wasPoweredDown;
UInt32 subType;
result = kIOReturnError;
audioDevice = OSDynamicCast (AppleOnboardAudio, target);
wasPoweredDown = FALSE;
FailIf (NULL == audioDevice, Exit);
debugIOLog (3, "+ AppleOnboardAudio[%ld]::outputControlChangeHandler (%p, %p, %lX, %lX)", audioDevice->mInstanceIndex, target, control, oldValue, newValue);
if (kIOAudioDeviceSleep == audioDevice->ourPowerState) {
IOAudioDevicePowerState newState;
newState = kIOAudioDeviceActive;
if ( NULL != audioDevice->mTransportInterface ) {
result = audioDevice->mTransportInterface->performTransportWake ();
}
result = audioDevice->callPluginsInOrder (kPowerStateChange, kIOAudioDeviceActive);
if ( kIOAudioDeviceActive != audioDevice->ourPowerState ) { debugIOLog ( 5, "AppleOnboardAudio::outputControlChangeHandler setting 'ourPowerState' to kIOAudioDeviceActive" ); }
audioDevice->ourPowerState = kIOAudioDeviceActive;
audioDevice->mUCState.ucPowerState = audioDevice->ourPowerState;
if (NULL != audioDevice->mExternalClockSelector) {
audioDevice->mExternalClockSelector->flushValue ();
}
if (NULL != audioDevice->mOutMuteControl) {
audioDevice->mOutMuteControl->flushValue (); }
wasPoweredDown = TRUE;
}
switch (control->getType ()) {
case kIOAudioControlTypeLevel:
debugIOLog ( 5, " control->getType () is a kIOAudioControlTypeLevel" );
switch (control->getSubType ()) {
case kIOAudioLevelControlSubTypeVolume:
debugIOLog ( 5, " control->getSubType () is a kIOAudioLevelControlSubTypeVolume" );
levelControl = OSDynamicCast (IOAudioLevelControl, control);
switch (control->getChannelID ()) {
case kIOAudioControlChannelIDAll:
result = audioDevice->volumeMasterChange (newValue);
if (newValue == levelControl->getMinValue ()) {
OSNumber * muteState;
muteState = OSNumber::withNumber ((long long unsigned int)1, 32);
if (NULL != audioDevice->mOutMuteControl) {
audioDevice->mOutMuteControl->hardwareValueChanged (muteState);
debugIOLog (3, "volume control change calling audioDevice->callPluginsInOrder ( kSetAnalogMuteState, TRUE )");
result = audioDevice->callPluginsInOrder ( kSetAnalogMuteState, TRUE );
}
} else if (oldValue == levelControl->getMinValue () && FALSE == audioDevice->mIsMute) {
OSNumber * muteState;
muteState = OSNumber::withNumber ((long long unsigned int)0, 32);
if (NULL != audioDevice->mOutMuteControl) {
audioDevice->mOutMuteControl->hardwareValueChanged (muteState);
debugIOLog (3, "volume control change calling audioDevice->callPluginsInOrder ( kSetAnalogMuteState, FALSE )");
result = audioDevice->callPluginsInOrder ( kSetAnalogMuteState, FALSE );
}
}
break;
case kIOAudioControlChannelIDDefaultLeft:
result = audioDevice->volumeLeftChange (newValue);
break;
case kIOAudioControlChannelIDDefaultRight:
result = audioDevice->volumeRightChange (newValue);
break;
}
break;
case kIOAudioLevelControlSubTypePRAMVolume:
debugIOLog ( 5, " control->getSubType () is a kIOAudioLevelControlSubTypePRAMVolume" );
platform = OSDynamicCast (IODTPlatformExpert, getPlatform());
if (platform) {
UInt8 curPRAMVol;
result = platform->readXPRAM ((IOByteCount)kPRamVolumeAddr, &curPRAMVol, (IOByteCount)1);
curPRAMVol = (curPRAMVol & 0xF8) | newValue;
result = platform->writeXPRAM ((IOByteCount)kPRamVolumeAddr, &curPRAMVol, (IOByteCount) 1);
audioDevice->mUCState.ucPramData = (UInt32)curPRAMVol;
audioDevice->mUCState.ucPramVolume = audioDevice->mUCState.ucPramData & 0x00000007;
}
break;
default:
result = kIOReturnBadArgument;
}
break;
case kIOAudioControlTypeToggle:
debugIOLog ( 5, " control->getType () is a kIOAudioControlTypeToggle" );
subType = control->getSubType ();
switch (control->getSubType ()) {
case kIOAudioToggleControlSubTypeMute:
result = audioDevice->outputMuteChange ( newValue ); if ( kIOReturnSuccess == result ) {
audioDevice->mIsMute = newValue;
}
break;
default:
result = kIOReturnBadArgument;
break;
}
break;
case kIOAudioControlTypeSelector:
result = audioDevice->outputSelectorChanged (newValue);
break;
default:
break;
}
if (control->getSubType () == kIOAudioLevelControlSubTypeVolume) {
levelControl = OSDynamicCast (IOAudioLevelControl, control);
if (audioDevice->mOutRightVolumeControl && audioDevice->mOutLeftVolumeControl) {
if (audioDevice->mOutRightVolumeControl->getMinValue () == audioDevice->mVolRight &&
audioDevice->mOutLeftVolumeControl->getMinValue () == audioDevice->mVolLeft) {
OSNumber * muteState;
muteState = OSNumber::withNumber ((long long unsigned int)1, 32);
if (NULL != audioDevice->mOutMuteControl) {
audioDevice->mOutMuteControl->hardwareValueChanged (muteState);
}
muteState->release ();
} else if (newValue != levelControl->getMinValue () && oldValue == levelControl->getMinValue () && FALSE == audioDevice->mIsMute) {
OSNumber * muteState;
muteState = OSNumber::withNumber ((long long unsigned int)0, 32);
if (NULL != audioDevice->mOutMuteControl) {
audioDevice->mOutMuteControl->hardwareValueChanged (muteState);
}
muteState->release ();
}
}
}
if (audioDevice->mIsMute) {
leftVol = 0;
rightVol = 0;
} else {
leftVol = audioDevice->mVolLeft;
rightVol = audioDevice->mVolRight;
}
if (TRUE == audioDevice->mAutoUpdatePRAM) { audioDevice->WritePRAMVol (leftVol, rightVol);
}
Exit:
if (TRUE == wasPoweredDown) {
audioDevice->setTimerForSleep ();
}
debugIOLog (3, "- AppleOnboardAudio[%ld]::outputControlChangeHandler (%p, %p, %lX, %lX) returns %X", audioDevice->mInstanceIndex, target, control, oldValue, newValue, result);
return result;
}
void AppleOnboardAudio::createPlayThruControl (void) {
OSDictionary * AOAprop;
AOAprop = OSDynamicCast (OSDictionary, mCurrentInputPlugin->getProperty (kPluginPListAOAAttributes));
FailIf (NULL == AOAprop, Exit);
if (kOSBooleanTrue == OSDynamicCast (OSBoolean, AOAprop->getObject ("Playthrough"))) {
mPlaythruToggleControl = IOAudioToggleControl::createMuteControl (TRUE, kIOAudioControlChannelIDAll, kIOAudioControlChannelNameAll, 0, kIOAudioControlUsagePassThru);
if (NULL != mPlaythruToggleControl) {
mDriverDMAEngine->addDefaultAudioControl (mPlaythruToggleControl);
mPlaythruToggleControl->setValueChangeHandler ((IOAudioControl::IntValueChangeHandler)inputControlChangeHandler, this);
}
}
Exit:
return;
}
void AppleOnboardAudio::removePlayThruControl (void) {
if (NULL != mPlaythruToggleControl) {
mDriverDMAEngine->removeDefaultAudioControl (mPlaythruToggleControl);
mPlaythruToggleControl->release ();
mPlaythruToggleControl = NULL;
}
}
IOReturn AppleOnboardAudio::outputSelectorChanged (SInt32 newValue) {
AudioHardwareObjectInterface * thePluginObject;
IOAudioStream * outputStream;
const IOAudioStreamFormat * theFormat;
char * connectionString;
IOReturn result;
UInt32 inputLatency;
debugIOLog (3, "+ AppleOnboardAudio[%ld]::outputSelectorChanged( '%4s' )", mInstanceIndex, (char *)&newValue);
result = kIOReturnSuccess;
inputLatency = 0;
if (kIOAudioOutputPortSubTypeLine == newValue) {
if ( !(mDetectCollection & kSndHWLineOutput) ) {
result = kIOReturnError;
}
} else if (kIOAudioOutputPortSubTypeHeadphones == newValue) {
if ( !(mDetectCollection & kSndHWCPUHeadphone) ) {
result = kIOReturnError;
}
} else if ((kIOAudioOutputPortSubTypeSPDIF == newValue) && (kGPIO_Unknown != mPlatformInterface->getComboOutJackTypeConnected ())) {
if ( !(mDetectCollection & kSndHWDigitalOutput) ) {
result = kIOReturnError;
}
}
if ( (kIOAudioOutputPortSubTypeInternalSpeaker == newValue) || (kIOAudioOutputPortSubTypeExternalSpeaker == newValue) ) { if ( (mDetectCollection & kSndHWLineOutput) || (mDetectCollection & kSndHWCPUHeadphone) ) {
result = kIOReturnError;
}
}
if ( kIOReturnSuccess == result ) {
connectionString = getConnectionKeyFromCharCode (newValue, kIOAudioStreamDirectionOutput);
FailIf (0 == connectionString, Exit);
thePluginObject = getPluginObjectForConnection (connectionString);
FailIf (NULL == thePluginObject, Exit);
outputStream = mDriverDMAEngine->getAudioStream (kIOAudioStreamDirectionOutput, 1);
FailIf (NULL == outputStream, Exit);
theFormat = outputStream->getFormat ();
FailWithAction (kIOAudioStreamSampleFormat1937AC3 == theFormat->fSampleFormat, result = kIOReturnNotPermitted, Exit);
outputStream->setTerminalType (getTerminalTypeForCharCode (newValue));
cacheOutputVolumeLevels (mCurrentOutputPlugin);
setClipRoutineForOutput (connectionString);
if (mCurrentOutputPlugin != thePluginObject) {
mCurrentOutputPlugin = thePluginObject;
}
setSoftwareOutputDSP (connectionString);
AdjustOutputVolumeControls(mCurrentOutputPlugin, newValue);
selectOutput(newValue, mIsMute, FALSE); } else {
debugIOLog ( 3, " AppleOnboardAudio[%ld]::outputSelectorChanged disallowing selection of '%4s'", mInstanceIndex, (char *)&newValue );
}
Exit:
debugIOLog (3, "- AppleOnboardAudio[%ld]::outputSelectorChanged( '%4s' ) returns %X", mInstanceIndex, (char *)&newValue, result);
return result;
}
IOReturn AppleOnboardAudio::volumeMasterChange (SInt32 newValue) {
IOReturn result = kIOReturnSuccess;
debugIOLog (3, "+ AppleOnboardAudio[%ld]::volumeMasterChange (%ld)", mInstanceIndex, newValue);
result = kIOReturnError;
result = volumeLeftChange (newValue);
result = volumeRightChange (newValue);
result = kIOReturnSuccess;
debugIOLog (3, "- AppleOnboardAudio[%ld]::volumeMasterChange, 0x%x", mInstanceIndex, result);
return result;
}
IOReturn AppleOnboardAudio::volumeLeftChange (SInt32 newValue) {
IOReturn result;
UInt32 count;
UInt32 index;
AudioHardwareObjectInterface* thePluginObject;
debugIOLog (3, "+ AppleOnboardAudio[%ld]::volumeLeftChange (%ld)", mInstanceIndex, newValue);
if ( mIsMute ) { if (NULL != mPluginObjects) {
count = mPluginObjects->getCount ();
for (index = 0; index < count; index++) {
thePluginObject = getIndexedPluginObject (index);
if((NULL != thePluginObject)) {
thePluginObject->setMute (mIsMute);
}
}
}
} else {
if (TRUE == mCurrentPluginNeedsSoftwareOutputVolume) { mDriverDMAEngine->setOutputVolumeLeft (newValue);
if (NULL != mPluginObjects) {
count = mPluginObjects->getCount ();
for (index = 0; index < count; index++) {
thePluginObject = getIndexedPluginObject (index);
if((NULL != thePluginObject)) {
thePluginObject->setVolume (thePluginObject->getMaximumVolume (), thePluginObject->getMaximumVolume ());
}
}
}
} else {
if (NULL != mPluginObjects) {
count = mPluginObjects->getCount ();
for (index = 0; index < count; index++) {
thePluginObject = getIndexedPluginObject (index);
if((NULL != thePluginObject)) {
thePluginObject->setVolume (newValue, mVolRight);
}
}
}
}
}
mVolLeft = newValue;
result = kIOReturnSuccess;
debugIOLog (3, "- AppleOnboardAudio[%ld]::volumeLeftChange, 0x%x", mInstanceIndex, result);
return result;
}
IOReturn AppleOnboardAudio::volumeRightChange (SInt32 newValue) {
IOReturn result;
UInt32 count;
UInt32 index;
AudioHardwareObjectInterface* thePluginObject;
debugIOLog (3, "+ AppleOnboardAudio[%ld]::volumeRightChange (%ld)", mInstanceIndex, newValue);
if ( mIsMute ) { if (NULL != mPluginObjects) {
count = mPluginObjects->getCount ();
for (index = 0; index < count; index++) {
thePluginObject = getIndexedPluginObject (index);
if((NULL != thePluginObject)) {
thePluginObject->setMute (mIsMute);
}
}
}
} else {
if (TRUE == mCurrentPluginNeedsSoftwareOutputVolume) { mDriverDMAEngine->setOutputVolumeRight (newValue);
if (NULL != mPluginObjects) {
count = mPluginObjects->getCount ();
for (index = 0; index < count; index++) {
thePluginObject = getIndexedPluginObject (index);
if((NULL != thePluginObject)) {
thePluginObject->setVolume (thePluginObject->getMaximumVolume (), thePluginObject->getMaximumVolume ());
}
}
}
} else {
if (NULL != mPluginObjects) {
count = mPluginObjects->getCount ();
for (index = 0; index < count; index++) {
thePluginObject = getIndexedPluginObject (index);
if((NULL != thePluginObject)) {
thePluginObject->setVolume (mVolLeft, newValue);
}
}
}
}
}
mVolRight = newValue;
result = kIOReturnSuccess;
debugIOLog (3, "- AppleOnboardAudio[%ld]::volumeRightChange, result = 0x%x", mInstanceIndex, result);
return result;
}
IOReturn AppleOnboardAudio::outputMuteChange (SInt32 newValue) {
UInt32 comboOutJackTypeState;
IOReturn result = kIOReturnError;
debugIOLog (3, "+ AppleOnboardAudio[%ld]::outputMuteChange (%ld)", mInstanceIndex, newValue);
FailIf ( NULL == mPlatformInterface, Exit );
comboOutJackTypeState = mPlatformInterface->getComboOutJackTypeConnected ();
if ( kGPIO_Unknown == comboOutJackTypeState ) {
if ( !mEncodedOutputFormat ) {
debugIOLog (3, " outputMuteChange calling callPluginsInOrder ( kSetMuteState, %ld ) non-exclusive dig", newValue);
result = callPluginsInOrder ( kSetMuteState, newValue );
} else {
debugIOLog (3, " outputMuteChange calling callPluginsInOrder ( kSetAnalogMuteState, %ld ) exclusive dig", TRUE);
result = callPluginsInOrder ( kSetAnalogMuteState, TRUE );
if ( kIOReturnSuccess == result ) {
debugIOLog (3, " outputMuteChange calling callPluginsInOrder ( kSetDigitalMuteState, %ld ) exclusive dig", newValue);
result = callPluginsInOrder ( kSetDigitalMuteState, newValue );
}
}
} else {
if ( !mEncodedOutputFormat ) {
GpioAttributes theAnalogState = kGPIO_Unknown;
debugIOLog (3, "(UInt32)mPlatformInterface->getComboOutAssociation () returns 0x%lx", (UInt32)mPlatformInterface->getComboOutAssociation ());
switch ( (UInt32)mPlatformInterface->getComboOutAssociation () ) {
case kGPIO_Selector_HeadphoneDetect: theAnalogState = mPlatformInterface->getHeadphoneConnected (); break;
case kGPIO_Selector_LineOutDetect: theAnalogState = mPlatformInterface->getLineOutConnected (); break;
case kGPIO_Selector_SpeakerDetect: theAnalogState = mPlatformInterface->getSpeakerConnected (); break;
}
debugIOLog (3, "theAnalogState = 0x%lx, comboOutJackTypeState = 0x%lx", theAnalogState, comboOutJackTypeState);
if ( kGPIO_Connected == theAnalogState && kGPIO_TypeIsDigital == comboOutJackTypeState ) {
debugIOLog (3, " outputMuteChange calling callPluginsInOrder ( kSetAnalogMuteState, %ld ) exclusive dig", TRUE);
result = callPluginsInOrder ( kSetAnalogMuteState, TRUE );
if ( kIOReturnSuccess == result ) {
debugIOLog (3, " outputMuteChange calling callPluginsInOrder ( kSetDigitalMuteState, %ld ) exclusive dig", newValue);
result = callPluginsInOrder ( kSetDigitalMuteState, newValue );
}
} else {
debugIOLog (3, " outputMuteChange calling callPluginsInOrder ( kSetAnalogMuteState, %ld ) exclusive dig", newValue);
result = callPluginsInOrder ( kSetAnalogMuteState, newValue );
if ( kIOReturnSuccess == result ) {
debugIOLog (3, " outputMuteChange calling callPluginsInOrder ( kSetDigitalMuteState, %ld ) exclusive dig", TRUE);
result = callPluginsInOrder ( kSetDigitalMuteState, TRUE );
}
}
} else {
GpioAttributes theAnalogState = kGPIO_Unknown;
switch ( (UInt32)mPlatformInterface->getComboOutAssociation () ) {
case kGPIO_Selector_HeadphoneDetect: theAnalogState = mPlatformInterface->getHeadphoneConnected (); break;
case kGPIO_Selector_LineOutDetect: theAnalogState = mPlatformInterface->getLineOutConnected (); break;
case kGPIO_Selector_SpeakerDetect: theAnalogState = mPlatformInterface->getSpeakerConnected (); break;
}
if ( kGPIO_Connected == theAnalogState && kGPIO_TypeIsDigital == comboOutJackTypeState ) {
debugIOLog (3, " outputMuteChange calling callPluginsInOrder ( kSetAnalogMuteState, %ld ) exclusive dig", TRUE);
result = callPluginsInOrder ( kSetAnalogMuteState, TRUE );
if ( kIOReturnSuccess == result ) {
debugIOLog (3, " outputMuteChange calling callPluginsInOrder ( kSetDigitalMuteState, %ld ) exclusive dig", newValue);
result = callPluginsInOrder ( kSetDigitalMuteState, newValue );
}
} else {
debugIOLog (3, " outputMuteChange calling callPluginsInOrder ( kSetAnalogMuteState, %ld ) exclusive dig", TRUE);
result = callPluginsInOrder ( kSetAnalogMuteState, newValue );
if ( kIOReturnSuccess == result ) {
debugIOLog (3, " outputMuteChange calling callPluginsInOrder ( kSetDigitalMuteState, %ld ) exclusive dig", TRUE);
result = callPluginsInOrder ( kSetDigitalMuteState, TRUE );
}
}
}
}
Exit:
debugIOLog (3, "- AppleOnboardAudio[%ld]::outputMuteChange", mInstanceIndex);
return result;
}
IOReturn AppleOnboardAudio::inputControlChangeHandler (IOService *target, IOAudioControl *control, SInt32 oldValue, SInt32 newValue) {
IOReturn result = kIOReturnError;
AppleOnboardAudio * audioDevice;
IOAudioLevelControl * levelControl;
Boolean wasPoweredDown;
audioDevice = OSDynamicCast (AppleOnboardAudio, target);
wasPoweredDown = FALSE;
FailIf (NULL == audioDevice, Exit);
debugIOLog (3, "+ AppleOnboardAudio[%ld]::inputControlChangeHandler (%p, %p, %lX, %lX)", audioDevice->mInstanceIndex, target, control, oldValue, newValue);
if (kIOAudioDeviceSleep == audioDevice->ourPowerState) {
IOAudioDevicePowerState newState;
newState = kIOAudioDeviceActive;
if ( NULL != audioDevice->mTransportInterface ) {
result = audioDevice->mTransportInterface->performTransportWake ();
}
result = audioDevice->callPluginsInOrder (kPowerStateChange, kIOAudioDeviceActive);
if ( kIOAudioDeviceActive != audioDevice->ourPowerState ) { debugIOLog ( 5, "AppleOnboardAudio::inputControlChangeHandler setting 'ourPowerState' to kIOAudioDeviceActive" ); }
audioDevice->ourPowerState = kIOAudioDeviceActive;
audioDevice->mUCState.ucPowerState = audioDevice->ourPowerState;
if (NULL != audioDevice->mExternalClockSelector) {
audioDevice->mExternalClockSelector->flushValue ();
}
if (NULL != audioDevice->mOutMuteControl) {
audioDevice->mOutMuteControl->flushValue (); }
wasPoweredDown = TRUE;
}
switch (control->getType ()) {
case kIOAudioControlTypeLevel:
debugIOLog ( 3, " control type = kIOAudioControlTypeLevel" );
levelControl = OSDynamicCast (IOAudioLevelControl, control);
switch (control->getChannelID ()) {
case kIOAudioControlChannelIDDefaultLeft:
debugIOLog ( 3, " channel ID = kIOAudioControlChannelIDDefaultLeft" );
result = audioDevice->gainLeftChanged (newValue);
break;
case kIOAudioControlChannelIDDefaultRight:
debugIOLog ( 3, " channel ID = kIOAudioControlChannelIDDefaultRight" );
result = audioDevice->gainRightChanged (newValue);
break;
case kIOAudioControlChannelIDAll:
debugIOLog ( 3, " channel ID = kIOAudioControlChannelIDAll" );
result = audioDevice->gainRightChanged (newValue);
break;
}
break;
case kIOAudioControlTypeToggle:
debugIOLog ( 3, " control type = kIOAudioControlTypeToggle" );
result = audioDevice->passThruChanged (newValue);
break;
case kIOAudioControlTypeSelector:
debugIOLog ( 3, " control type = kIOAudioControlTypeSelector" );
debugIOLog (3, "input selector change handler");
switch (control->getSubType ()) {
case kIOAudioSelectorControlSubTypeInput:
result = audioDevice->inputSelectorChanged (newValue);
break;
case kIOAudioSelectorControlSubTypeClockSource:
result = audioDevice->clockSelectorChanged (newValue);
break;
default:
debugIOLog (3, "unknown control type in input selector change handler");
break;
}
default:
break;
}
Exit:
if (TRUE == wasPoweredDown) {
audioDevice->setTimerForSleep ();
}
debugIOLog (3, "- AppleOnboardAudio::inputControlChangeHandler (%p, %p, oldValue %lX, newValue %lX) returns %lX", target, control, oldValue, newValue, result);
return result;
}
IOReturn AppleOnboardAudio::gainLeftChanged (SInt32 newValue) {
IOReturn result;
debugIOLog (3, "+ AppleOnboardAudio[%ld]::gainLeftChanged", mInstanceIndex);
if (mCurrentPluginNeedsSoftwareInputGain) {
mDriverDMAEngine->setInputGainL (newValue);
} else {
mCurrentInputPlugin->setInputGain (newValue, mGainRight);
}
mGainLeft = newValue;
result = kIOReturnSuccess;
debugIOLog (3, "- AppleOnboardAudio[%ld]::gainLeftChanged, %d", mInstanceIndex, (result == kIOReturnSuccess));
return result;
}
IOReturn AppleOnboardAudio::gainRightChanged (SInt32 newValue) {
IOReturn result;
debugIOLog (3, "+ AppleOnboardAudio[%ld]::gainRightChanged", mInstanceIndex);
if (mCurrentPluginNeedsSoftwareInputGain) {
mDriverDMAEngine->setInputGainR (newValue);
} else {
mCurrentInputPlugin->setInputGain (newValue, mGainRight);
}
mGainRight = newValue;
result = kIOReturnSuccess;
debugIOLog (3, "- AppleOnboardAudio[%ld]::gainRightChanged, %d", mInstanceIndex, (result == kIOReturnSuccess));
return result;
}
IOReturn AppleOnboardAudio::gainMasterChanged (SInt32 newValue) {
IOReturn result;
debugIOLog (3, "+ AppleOnboardAudio[%ld]::gainMasterChanged", mInstanceIndex);
if (mCurrentPluginNeedsSoftwareInputGain) {
mDriverDMAEngine->setInputGainR (newValue);
mDriverDMAEngine->setInputGainL (newValue);
} else {
mCurrentInputPlugin->setInputGain (newValue, newValue);
}
result = kIOReturnSuccess;
debugIOLog (3, "- AppleOnboardAudio[%ld]::gainMasterChanged, %d", mInstanceIndex, (result == kIOReturnSuccess));
return result;
}
IOReturn AppleOnboardAudio::passThruChanged (SInt32 newValue) {
IOReturn result;
debugIOLog (3, "+ AppleOnboardAudio[%ld]::passThruChanged", mInstanceIndex);
result = kIOReturnError;
mCurrentInputPlugin->setPlayThrough (!newValue);
result = kIOReturnSuccess;
debugIOLog (3, "- AppleOnboardAudio[%ld]::passThruChanged", mInstanceIndex);
return result;
}
IOReturn AppleOnboardAudio::inputSelectorChanged (SInt32 newValue) {
AudioHardwareObjectInterface * thePluginObject;
IOAudioStream * inputStream;
OSDictionary * AOApropInput;
OSBoolean * softwareInputGainBoolean;
OSNumber * inputLatencyNumber;
char * connectionString;
IOReturn result;
UInt32 inputLatency;
debugIOLog (3, "+ AppleOnboardAudio[%ld]::inputSelectorChanged (%4s)", mInstanceIndex, (char *)&newValue);
result = kIOReturnError;
inputLatency = 0;
connectionString = getConnectionKeyFromCharCode (newValue, kIOAudioStreamDirectionInput);
FailIf (0 == connectionString, Exit);
thePluginObject = getPluginObjectForConnection (connectionString);
FailIf (NULL == thePluginObject, Exit);
inputStream = mDriverDMAEngine->getAudioStream (kIOAudioStreamDirectionInput, 1);
FailIf (NULL == inputStream, Exit);
inputStream->setTerminalType (getTerminalTypeForCharCode (newValue));
setUseInputGainControls (connectionString);
setUsePlaythroughControl (connectionString);
setClipRoutineForInput (connectionString);
setSoftwareInputDSP (connectionString);
mCurrentInputPlugin->setInputMute (TRUE);
if (mCurrentInputPlugin != thePluginObject) {
thePluginObject->setInputMute (TRUE);
cacheInputGainLevels (mCurrentInputPlugin);
ConfigChangeHelper theConfigeChangeHelper(mDriverDMAEngine);
setInputDataMuxForConnection ( connectionString );
AOApropInput = OSDynamicCast (OSDictionary, thePluginObject->getProperty (kPluginPListAOAAttributes));
if (NULL != AOApropInput) {
softwareInputGainBoolean = OSDynamicCast (OSBoolean, AOApropInput->getObject (kPluginPListSoftwareInputGain));
if (NULL != softwareInputGainBoolean) {
mDriverDMAEngine->setUseSoftwareInputGain (softwareInputGainBoolean->getValue ());
mCurrentPluginNeedsSoftwareInputGain = softwareInputGainBoolean->getValue ();
} else {
mDriverDMAEngine->setUseSoftwareInputGain (false);
mCurrentPluginNeedsSoftwareInputGain = false;
}
}
if (NULL != AOApropInput) {
inputLatencyNumber = OSDynamicCast (OSNumber, AOApropInput->getObject (kPluginPListInputLatency));
if (NULL != inputLatencyNumber) {
inputLatency = inputLatencyNumber->unsigned32BitValue();
}
}
mDriverDMAEngine->setSampleLatencies (mOutputLatency, inputLatency);
mCurrentInputPlugin = thePluginObject;
debugIOLog (3, "+ AppleOnboardAudio[%ld]::inputSelectorChanged - mCurrentInputPlugin updated to %p", mInstanceIndex, mCurrentInputPlugin);
}
mCurrentInputPlugin->setActiveInput (newValue);
AdjustInputGainControls (mCurrentInputPlugin);
if ((mDetectCollection & kSndHWLineInput) && (kIOAudioInputPortSubTypeLine == newValue)) {
mCurrentInputPlugin->setInputMute (FALSE);
} else if (!(mDetectCollection & kSndHWLineInput) && (kIOAudioInputPortSubTypeLine == newValue)) {
mCurrentInputPlugin->setInputMute (TRUE);
}
result = kIOReturnSuccess;
Exit:
debugIOLog (3, "- AppleOnboardAudio[%ld]::inputSelectorChanged", mInstanceIndex);
return result;
}
IOReturn AppleOnboardAudio::clockSelectorChanged (SInt32 newValue) {
IOReturn result;
debugIOLog (7, "+ AppleOnboardAudio[%ld]::clockSelectorChanged (%4s)", mInstanceIndex, (char *)&newValue);
result = kIOReturnError;
mClockSelectInProcessSemaphore = true;
FailIf ( NULL == mDriverDMAEngine, Exit );
FailIf ( NULL == mTransportInterface, Exit );
if ( mCurrentClockSelector != newValue ) {
callPluginsInOrder ( kSetMuteState, TRUE );
if ( kClockSourceSelectionInternal == newValue ) {
ConfigChangeHelper theConfigeChangeHelper(mDriverDMAEngine, 10);
mTransportInterface->transportBreakClockSelect ( kTRANSPORT_MASTER_CLOCK );
callPluginsInOrder ( kBreakClockSelect, kTRANSPORT_MASTER_CLOCK );
mTransportInterface->transportMakeClockSelect ( kTRANSPORT_MASTER_CLOCK );
callPluginsInOrder ( kMakeClockSelect, kTRANSPORT_MASTER_CLOCK );
if ( NULL != mOutputSelector ) {
selectOutput ( mOutputSelector->getIntValue (), mIsMute);
}
} else if ( kClockSourceSelectionExternal == newValue ) {
ConfigChangeHelper theConfigeChangeHelper(mDriverDMAEngine, 10);
mTransportInterface->transportBreakClockSelect ( kTRANSPORT_SLAVE_CLOCK );
callPluginsInOrder ( kBreakClockSelect, kTRANSPORT_SLAVE_CLOCK );
mTransportInterface->transportMakeClockSelect ( kTRANSPORT_SLAVE_CLOCK );
callPluginsInOrder ( kMakeClockSelect, kTRANSPORT_SLAVE_CLOCK );
if ( NULL != mOutputSelector ) {
selectOutput ( mOutputSelector->getIntValue (), mIsMute);
}
} else {
debugIOLog (3, "Unknown clock source selection." );
FailIf (TRUE, Exit);
}
mCurrentClockSelector = newValue;
}
result = kIOReturnSuccess;
Exit:
mClockSelectInProcessSemaphore = false; debugIOLog (7, "- AppleOnboardAudio[%ld]::inputSelectorChanged", mInstanceIndex);
return result;
}
UInt32 AppleOnboardAudio::getCurrentSampleFrame (void) {
return mPlatformInterface->getFrameCount ();
}
void AppleOnboardAudio::setCurrentSampleFrame (UInt32 inValue) {
mPlatformInterface->setFrameCount (inValue);
return;
}
void AppleOnboardAudio::setInputDataMuxForConnection ( char * connectionString ) {
GpioAttributes theMuxSelect;
theMuxSelect = getInputDataMuxForConnection ( connectionString );
if ( kGPIO_Unknown != theMuxSelect ) {
debugIOLog (3, "AppleOnboardAudio[%ld]::setInputDataMuxForConnection setting input data mux to %d", mInstanceIndex, (unsigned int)theMuxSelect );
mPlatformInterface->setInputDataMux ( theMuxSelect );
}
}
#pragma mark +POWER MANAGEMENT
void AppleOnboardAudio::setTimerForSleep () {
AbsoluteTime fireTime;
UInt64 nanos;
if (idleTimer && idleSleepDelayTime != kNoIdleAudioPowerDown) {
clock_get_uptime (&fireTime);
absolutetime_to_nanoseconds (fireTime, &nanos);
nanos += idleSleepDelayTime;
nanoseconds_to_absolutetime (nanos, &fireTime);
idleTimer->wakeAtTime (fireTime); }
}
void AppleOnboardAudio::sleepHandlerTimer (OSObject *owner, IOTimerEventSource *sender) {
AppleOnboardAudio * audioDevice;
UInt32 time = 0;
audioDevice = OSDynamicCast (AppleOnboardAudio, owner);
FailIf (NULL == audioDevice, Exit);
if (audioDevice->getPowerState () != kIOAudioDeviceActive) {
audioDevice->performPowerStateChange (audioDevice->getPowerState (), kIOAudioDeviceIdle, &time);
}
Exit:
return;
}
IOReturn AppleOnboardAudio::setAggressiveness (unsigned long type, unsigned long newLevel) {
UInt32 time = 0;
if (type == kPMPowerSource) {
debugIOLog (3, "setting power aggressivness state to ");
switch (newLevel) {
case kIOPMInternalPower: debugIOLog (3, "battery power");
idleSleepDelayTime = kBatteryPowerDownDelayTime;
setIdleAudioSleepTime (idleSleepDelayTime);
if (getPowerState () != kIOAudioDeviceActive) {
performPowerStateChange (getPowerState (), kIOAudioDeviceIdle, &time);
}
break;
case kIOPMExternalPower: debugIOLog (3, "wall power");
idleSleepDelayTime = kNoIdleAudioPowerDown;
setIdleAudioSleepTime (idleSleepDelayTime); if (getPowerState () != kIOAudioDeviceActive) {
performPowerStateChange (getPowerState (), kIOAudioDeviceActive, &time);
}
break;
default:
break;
}
}
return super::setAggressiveness (type, newLevel);
}
IOReturn AppleOnboardAudio::performPowerStateChange (IOAudioDevicePowerState oldPowerState, IOAudioDevicePowerState newPowerState, UInt32 *microsecondsUntilComplete)
{
AppleOnboardAudio * higherPriorityPowerMgmtAOAInstance;
IOReturn result;
debugIOLog (3, "+ AppleOnboardAudio[%ld]::performPowerStateChange (%d, %d) -- ourPowerState = %d", mInstanceIndex, oldPowerState, newPowerState, ourPowerState);
*microsecondsUntilComplete = 2000000;
result = super::performPowerStateChange (oldPowerState, newPowerState, microsecondsUntilComplete);
if ( !mPowerOrderHasBeenSet && ( 0 != mPowerManagementPriorityID ) ) {
higherPriorityPowerMgmtAOAInstance = findAOAInstanceWithLayoutID ( mPowerManagementPriorityID );
if ( NULL != higherPriorityPowerMgmtAOAInstance ) {
debugIOLog ( 3, "This %p AOA instance with layoutID %d is joining PM tree on %p AOA instance with layoutID %d", this, mLayoutID, higherPriorityPowerMgmtAOAInstance, mPowerManagementPriorityID );
higherPriorityPowerMgmtAOAInstance->joinPMtree ( this );
mPowerOrderHasBeenSet = true;
}
}
if ( kIOAudioDeviceIdle == ourPowerState && kIOAudioDeviceActive == newPowerState ) {
result = performPowerStateChangeThreadAction ( this, (void*)newPowerState, 0, 0, 0 );
} else {
if (mPowerThread) {
thread_call_enter1(mPowerThread, (thread_call_param_t)newPowerState);
}
}
debugIOLog (3, "- AppleOnboardAudio[%ld]::performPowerStateChange -- ourPowerState = %d", mInstanceIndex, ourPowerState);
return result;
}
void AppleOnboardAudio::performPowerStateChangeThread (AppleOnboardAudio * aoa, void * newPowerState) {
IOCommandGate * cg;
IOReturn result;
FailIf (NULL == aoa, Exit);
debugIOLog (3, "+ AppleOnboardAudio[%ld]::performPowerStateChangeThread (%p, %ld)", aoa->mInstanceIndex, aoa, (UInt32)newPowerState);
aoa->mSignal->wait (FALSE);
FailWithAction (TRUE == aoa->mTerminating, aoa->completePowerStateChange (), Exit);
cg = aoa->getCommandGate ();
if (cg) {
result = cg->runAction (aoa->performPowerStateChangeThreadAction, newPowerState, (void *)aoa);
}
Exit:
return;
}
IOReturn AppleOnboardAudio::performPowerStateChangeThreadAction (OSObject * owner, void * newPowerState, void * us, void * arg3, void * arg4) {
AppleOnboardAudio * aoa;
IOReturn result;
result = kIOReturnError;
aoa = OSDynamicCast (AppleOnboardAudio, (OSObject *)us);
FailIf (NULL == aoa, Exit);
debugIOLog (3, "+ AppleOnboardAudio[%ld]::performPowerStateChangeThreadAction (%p, %ld) -- ourPowerState = %d", aoa->mInstanceIndex, owner, (UInt32)newPowerState, aoa->ourPowerState);
FailIf (NULL == aoa->mTransportInterface, Exit);
FailIf (NULL == aoa->mPlatformInterface, Exit);
switch ((UInt32)newPowerState) {
case kIOAudioDeviceSleep:
if (kIOAudioDeviceActive == aoa->ourPowerState) {
debugIOLog (3, "active to sleep power change calling outputMuteChange(TRUE)");
aoa->outputMuteChange (TRUE); aoa->mPlatformInterface->setHeadphoneMuteState ( kGPIO_Muted ); aoa->mPlatformInterface->setSpeakerMuteState ( kGPIO_Muted ); aoa->mPlatformInterface->setLineOutMuteState ( kGPIO_Muted ); result = aoa->callPluginsInReverseOrder (kPowerStateChange, kIOAudioDeviceSleep);
if ( NULL != aoa->mTransportInterface ) {
result = aoa->mTransportInterface->performTransportSleep ();
}
if ( NULL != aoa->mPlatformInterface ) {
aoa->mPlatformInterface->performPlatformSleep ();
}
aoa->ourPowerState = kIOAudioDeviceSleep;
}
break;
case kIOAudioDeviceIdle:
if (kIOAudioDeviceActive == aoa->ourPowerState) {
debugIOLog (3, "active to idle power change calling outputMuteChange(TRUE)");
aoa->outputMuteChange (TRUE); result = aoa->callPluginsInReverseOrder (kPowerStateChange, kIOAudioDeviceSleep);
if ( NULL != aoa->mTransportInterface ) {
result = aoa->mTransportInterface->performTransportSleep ();
}
aoa->ourPowerState = kIOAudioDeviceSleep;
} else if (kIOAudioDeviceSleep == aoa->ourPowerState && kNoIdleAudioPowerDown == aoa->idleSleepDelayTime) {
if ( NULL != aoa->mTransportInterface ) {
result = aoa->mTransportInterface->performTransportWake ();
}
result = aoa->callPluginsInOrder (kPowerStateChange, kIOAudioDeviceActive);
if (NULL != aoa->mExternalClockSelector) {
aoa->mExternalClockSelector->flushValue ();
}
if ( kIOAudioDeviceActive != aoa->ourPowerState ) { debugIOLog ( 5, "AppleOnboardAudio::performPowerStateChangeThreadAction 1 setting 'ourPowerState' to kIOAudioDeviceActive" ); }
aoa->ourPowerState = kIOAudioDeviceActive;
if ( NULL != aoa->mPlatformInterface ) {
aoa->mPlatformInterface->performPlatformWake ( aoa );
}
if ( NULL != aoa->mOutputSelector ) {
aoa->selectOutput (aoa->mOutputSelector->getIntValue (), aoa->mIsMute); }
if (NULL != aoa->mOutMuteControl) {
aoa->mOutMuteControl->flushValue (); }
}
break;
case kIOAudioDeviceActive:
if (kIOAudioDeviceActive != aoa->ourPowerState) {
if ( NULL != aoa->mTransportInterface ) {
result = aoa->mTransportInterface->performTransportWake ();
}
result = aoa->callPluginsInOrder (kPowerStateChange, kIOAudioDeviceActive);
aoa->selectOutput ( aoa->mCurrentOutputSelection, aoa->mIsMute ); if ( kIOAudioDeviceActive != aoa->ourPowerState ) { debugIOLog ( 5, "AppleOnboardAudio::performPowerStateChangeThreadAction 2 setting 'ourPowerState' to kIOAudioDeviceActive" ); }
if ( NULL != aoa->mPlatformInterface && ( kIOAudioDeviceSleep == aoa->ourPowerState ) ) {
aoa->mPlatformInterface->performPlatformWake ( aoa ); } else {
debugIOLog ( 5, "Did not perform platform wake, aoa->mPlatformInterface = %d, aoa->ourPowerState = %d, kIOAudioDeviceSleep = %d", aoa->mPlatformInterface, aoa->ourPowerState, kIOAudioDeviceSleep );
}
aoa->ourPowerState = kIOAudioDeviceActive;
if (NULL != aoa->mExternalClockSelector) {
aoa->mExternalClockSelector->flushValue ();
}
if ( NULL != aoa->mOutputSelector ) {
aoa->selectOutput (aoa->mOutputSelector->getIntValue (), aoa->mIsMute); }
if (NULL != aoa->mOutMuteControl) {
aoa->mOutMuteControl->flushValue (); }
} else {
debugIOLog (3, "trying to wake, but we're already awake");
}
break;
default:
break;
}
aoa->setProperty ("IOAudioPowerState", aoa->ourPowerState, 32);
aoa->mUCState.ucPowerState = aoa->ourPowerState;
Exit:
if (NULL != aoa) {
aoa->protectedCompletePowerStateChange ();
}
debugIOLog (3, "- AppleOnboardAudio[%ld]::performPowerStateChangeThreadAction (%p, %ld) -- ourPowerState = %d", aoa->mInstanceIndex, owner, (UInt32)newPowerState, aoa->ourPowerState);
return result;
}
IOReturn AppleOnboardAudio::sysPowerDownHandler (void * target, void * refCon, UInt32 messageType, IOService * provider, void * messageArgument, vm_size_t argSize) {
AppleOnboardAudio * appleOnboardAudio;
IOReturn result;
result = kIOReturnUnsupported;
appleOnboardAudio = OSDynamicCast (AppleOnboardAudio, (OSObject *)target);
FailIf (NULL == appleOnboardAudio, Exit);
switch (messageType) {
case kIOMessageSystemWillPowerOff:
case kIOMessageSystemWillRestart:
appleOnboardAudio->performPowerStateChangeThread ( appleOnboardAudio, (void*)kIOAudioDeviceSleep );
result = kIOReturnSuccess;
break;
default:
break;
}
Exit:
return result;
}
#pragma mark +PRAM VOLUME
UInt8 AppleOnboardAudio::VolumeToPRAMValue (UInt32 inLeftVol, UInt32 inRightVol) {
UInt32 pramVolume; UInt32 averageVolume; UInt32 volumeRange;
UInt32 volumeSteps;
UInt32 leftVol;
UInt32 rightVol;
debugIOLog (3, "+ AppleOnboardAudio[%ld]::VolumeToPRAMValue ( 0x%X, 0x%X )", mInstanceIndex, (unsigned int)inLeftVol, (unsigned int)inRightVol );
pramVolume = 0; if ( ( 0 != inLeftVol ) || ( 0 != inRightVol ) ) { leftVol = inLeftVol;
rightVol = inRightVol;
if (NULL != mOutLeftVolumeControl) {
leftVol -= mOutLeftVolumeControl->getMinValue ();
}
if (NULL != mOutRightVolumeControl) {
rightVol -= mOutRightVolumeControl->getMinValue ();
}
debugIOLog (3, "... leftVol = 0x%X, rightVol = 0x%X", (unsigned int)leftVol, (unsigned int)rightVol );
if (NULL != mOutMasterVolumeControl) {
volumeRange = (mOutMasterVolumeControl->getMaxValue () - mOutMasterVolumeControl->getMinValue () + 1);
debugIOLog (3, "... mOutMasterVolumeControl volumeRange = 0x%X", (unsigned int)volumeRange );
} else if (NULL != mOutLeftVolumeControl) {
volumeRange = (mOutLeftVolumeControl->getMaxValue () - mOutLeftVolumeControl->getMinValue () + 1);
debugIOLog (3, "... mOutLeftVolumeControl volumeRange = 0x%X", (unsigned int)volumeRange );
} else if (NULL != mOutRightVolumeControl) {
volumeRange = (mOutRightVolumeControl->getMaxValue () - mOutRightVolumeControl->getMinValue () + 1);
debugIOLog (3, "... mOutRightVolumeControl volumeRange = 0x%X", (unsigned int)volumeRange );
} else {
volumeRange = kMaximumPRAMVolume;
debugIOLog (3, "... volumeRange = 0x%X **** NO AUDIO LEVEL CONTROLS!", (unsigned int)volumeRange );
}
averageVolume = (leftVol + rightVol) >> 1; debugIOLog (3, "... averageVolume = 0x%X", (unsigned int)volumeRange );
debugIOLog (3, "... volumeRange %X, kMaximumPRAMVolume %X", (unsigned int)volumeRange, (unsigned int)kMaximumPRAMVolume );
volumeSteps = volumeRange / kMaximumPRAMVolume; pramVolume = averageVolume / volumeSteps;
if ((pramVolume == 0) && (leftVol != 0 || rightVol !=0 )) {
pramVolume = 1;
}
}
debugIOLog (3, "- AppleOnboardAudio[%ld]::VolumeToPRAMValue returns 0x%X", mInstanceIndex, (unsigned int)pramVolume );
return (pramVolume & 0x07);
}
UInt32 AppleOnboardAudio::PRAMToVolumeValue (void) {
UInt32 volumeRange;
UInt32 volumeSteps;
if (NULL != mOutMasterVolumeControl) {
volumeRange = (mOutMasterVolumeControl->getMaxValue () - mOutMasterVolumeControl->getMinValue () + 1);
} else if (NULL != mOutLeftVolumeControl) {
volumeRange = (mOutLeftVolumeControl->getMaxValue () - mOutLeftVolumeControl->getMinValue () + 1);
} else if (NULL != mOutRightVolumeControl) {
volumeRange = (mOutRightVolumeControl->getMaxValue () - mOutRightVolumeControl->getMinValue () + 1);
} else {
volumeRange = kMaximumPRAMVolume;
}
volumeSteps = volumeRange / KNumPramVolumeSteps;
return (volumeSteps * ReadPRAMVol ());
}
void AppleOnboardAudio::WritePRAMVol (UInt32 leftVol, UInt32 rightVol) {
UInt8 pramVolume;
UInt8 curPRAMVol;
IODTPlatformExpert * platform;
IOReturn err;
platform = OSDynamicCast(IODTPlatformExpert,getPlatform());
debugIOLog (3, "+ AppleOnboardAudio[%ld]::WritePRAMVol leftVol=%lu, rightVol=%lu", mInstanceIndex, leftVol, rightVol);
if (platform) {
debugIOLog (3, "... platform 0x%X", (unsigned int)platform );
pramVolume = VolumeToPRAMValue (leftVol, rightVol);
err = platform->readXPRAM((IOByteCount)kPRamVolumeAddr, &curPRAMVol, (IOByteCount)1);
if ( kIOReturnSuccess == err ) {
debugIOLog (3, "... curPRAMVol = 0x%X before write", (curPRAMVol & 0x07) );
if (pramVolume != (curPRAMVol & 0x07)) {
curPRAMVol = (curPRAMVol & 0xF8) | pramVolume;
debugIOLog (3, "... curPRAMVol = 0x%x",curPRAMVol);
err = platform->writeXPRAM((IOByteCount)kPRamVolumeAddr, &curPRAMVol,(IOByteCount) 1);
if ( kIOReturnSuccess != err ) {
debugIOLog (3, "0x%X = platform->writeXPRAM( 0x%X, & 0x%X, 1 ), value = 0x%X", err, (unsigned int)kPRamVolumeAddr, (unsigned int)&curPRAMVol, (unsigned int)curPRAMVol );
} else {
mUCState.ucPramData = (UInt32)curPRAMVol;
mUCState.ucPramVolume = mUCState.ucPramData & 0x00000007;
}
} else {
debugIOLog (3, "PRAM write request is to current value: no I/O" );
}
} else {
debugIOLog (3, "Could not readXPRAM prior to write! Error 0x%X", err );
}
} else {
debugIOLog (3, "... no platform" );
}
debugIOLog (3, "- AppleOnboardAudio[%ld]::WritePRAMVol", mInstanceIndex);
}
UInt8 AppleOnboardAudio::ReadPRAMVol (void) {
UInt8 curPRAMVol;
IODTPlatformExpert * platform;
curPRAMVol = 0;
platform = OSDynamicCast(IODTPlatformExpert,getPlatform());
if (platform) {
platform->readXPRAM((IOByteCount)kPRamVolumeAddr, &curPRAMVol, (IOByteCount)1);
curPRAMVol &= 0x07;
}
return curPRAMVol;
}
#pragma mark +USER CLIENT
IOReturn AppleOnboardAudio::newUserClient( task_t inOwningTask,
void * inSecurityID,
UInt32 inType,
IOUserClient ** outHandler )
{
#pragma unused( inType )
IOUserClient * userClientPtr;
IOReturn err;
bool result;
err = kIOReturnError;
result = false;
userClientPtr = AppleOnboardAudioUserClient::Create( this, inOwningTask );
FailIf (NULL == userClientPtr, Exit);
err = kIOReturnError;
result = userClientPtr->attach( this );
FailIf (!result, Exit);
result = userClientPtr->start( this );
FailIf (!result, Exit);
*outHandler = userClientPtr;
err = kIOReturnSuccess;
Exit:
if( err != kIOReturnSuccess )
{
if( userClientPtr )
{
userClientPtr->detach( this );
userClientPtr->release();
}
}
return( err );
}
IOReturn AppleOnboardAudio::getPlatformState ( UInt32 arg2, void * outState ) {
#pragma unused ( arg2 )
IOReturn result = kIOReturnError;
FailIf ( NULL == outState, Exit );
FailIf ( NULL == mPlatformInterface, Exit );
result = mPlatformInterface->getPlatformState ( (PlatformStateStructPtr)outState );
Exit:
return result;
}
IOReturn AppleOnboardAudio::getPluginState ( HardwarePluginType thePluginType, void * outState ) {
AudioHardwareObjectInterface * thePluginObject;
IOReturn result = kIOReturnError;
debugIOLog (7, "AppleOnboardAudio[%ld]::getPluginState for type %d", mInstanceIndex, thePluginType );
FailIf ( NULL == outState, Exit );
thePluginObject = findPluginForType ( thePluginType );
if ( NULL != thePluginObject ) {
result = thePluginObject->getPluginState ( (HardwarePluginDescriptorPtr)outState );
}
Exit:
return result;
}
IOReturn AppleOnboardAudio::getDMAStateAndFormat ( UInt32 arg2, void * outState ) {
IOReturn result;
switch ( (DMA_STATE_SELECTOR)arg2 ) {
case kGetDMAStateAndFormat: result = mDriverDMAEngine->copyDMAStateAndFormat ( (DBDMAUserClientStructPtr)outState ); break;
case kGetDMAInputChannelCommands: result = mDriverDMAEngine->copyInputChannelCommands ( outState ); break;
case kGetDMAOutputChannelCommands: result = mDriverDMAEngine->copyOutputChannelCommands ( outState ); break;
case kGetInputChannelRegisters: result = mDriverDMAEngine->copyInputChannelRegisters ( outState ); break;
case kGetOutputChannelRegisters: result = mDriverDMAEngine->copyOutputChannelRegisters ( outState ); break;
default: result = kIOReturnBadArgument; break;
}
return result;
}
IOReturn AppleOnboardAudio::getSoftwareProcessingState ( UInt32 arg2, void * outState ) {
#pragma unused ( arg2 )
return kIOReturnError;
}
IOReturn AppleOnboardAudio::getAOAState ( UInt32 arg2, void * outState ) {
#pragma unused ( arg2 )
IOReturn result;
result = kIOReturnError;
FailIf ( 0 != arg2, Exit );
FailIf (NULL == outState, Exit );
debugIOLog (3, "AppleOnboardAudio[%ld]::getAOAState for type %ld", mInstanceIndex, arg2 );
((AOAStateUserClientStructPtr)outState)->ucPramData = mUCState.ucPramData;
((AOAStateUserClientStructPtr)outState)->ucPramVolume = mUCState.ucPramVolume;
((AOAStateUserClientStructPtr)outState)->ucPowerState = mUCState.ucPowerState;
((AOAStateUserClientStructPtr)outState)->ucLayoutID = mLayoutID;
result = kIOReturnSuccess;
Exit:
return result;
}
IOReturn AppleOnboardAudio::getTransportInterfaceState ( UInt32 arg2, void * outState ) {
#pragma unused ( arg2 )
IOReturn result = kIOReturnError;
if ( NULL != mTransportInterface ) {
result = mTransportInterface->getTransportInterfaceState ( (TransportStateStructPtr)outState );
}
return result;
}
IOReturn AppleOnboardAudio::setPlatformState ( UInt32 arg2, void * inState ) {
#pragma unused ( arg2 )
IOReturn result = kIOReturnError;
FailIf ( NULL == inState, Exit );
FailIf ( NULL == mPlatformInterface, Exit );
result = mPlatformInterface->setPlatformState ( (PlatformStateStructPtr)inState );
Exit:
return result;
}
IOReturn AppleOnboardAudio::setPluginState ( HardwarePluginType thePluginType, void * inState ) {
AudioHardwareObjectInterface * thePluginObject;
IOReturn result = kIOReturnError;
FailIf ( NULL == inState, Exit );
thePluginObject = findPluginForType ( thePluginType );
FailIf ( NULL == thePluginObject, Exit );
result = thePluginObject->setPluginState ( (HardwarePluginDescriptorPtr)inState );
Exit:
return result;
}
IOReturn AppleOnboardAudio::setDMAState ( UInt32 arg2, void * inState ) {
#pragma unused ( arg2 )
return kIOReturnError;
}
IOReturn AppleOnboardAudio::setSoftwareProcessingState ( UInt32 arg2, void * inState ) {
#pragma unused ( arg2 )
return kIOReturnError;
}
IOReturn AppleOnboardAudio::setAOAState ( UInt32 arg2, void * inState ) {
#pragma unused ( arg2 )
return kIOReturnError;
}
IOReturn AppleOnboardAudio::setTransportInterfaceState ( UInt32 arg2, void * inState ) {
#pragma unused ( arg2 )
IOReturn result = kIOReturnError;
if ( NULL != mTransportInterface ) {
result = mTransportInterface->setTransportInterfaceState ( (TransportStateStructPtr)inState );
}
return result;
}
ConfigChangeHelper::ConfigChangeHelper (IOAudioEngine * inEngine, UInt32 inSleep) {
mDriverDMAEngine = inEngine;
if (NULL != mDriverDMAEngine) {
debugIOLog (4, "ConfigChangeHelper (%p, %ld): calling pauseAudioEngine and beginConfigurationChange", inEngine, inSleep);
mDriverDMAEngine->pauseAudioEngine ();
if (0 != inSleep) {
debugIOLog (4, "waiting %d ms between pause and begin", inSleep);
IOSleep ( 10 );
}
mDriverDMAEngine->beginConfigurationChange ();
}
}
ConfigChangeHelper::~ConfigChangeHelper () {
if (NULL != mDriverDMAEngine) {
debugIOLog (4, "~ConfigChangeHelper: calling completeConfigurationChange and resumeAudioEngine");
mDriverDMAEngine->completeConfigurationChange ();
mDriverDMAEngine->resumeAudioEngine ();
}
}