AppleOnboardAudio.cpp [plain text]
#include <IOKit/IOCommandGate.h>
#include <IOKit/IOMessage.h>
#include <IOKit/pwr_mgt/RootDomain.h>
#include <IOKit/IOTimerEventSource.h>
#include "AppleOnboardAudio.h"
OSDefineMetaClassAndAbstractStructors(AppleOnboardAudio, IOAudioDevice)
#define super IOAudioDevice
#pragma mark +UNIX LIKE FUNCTIONS
bool AppleOnboardAudio::init(OSDictionary *properties)
{
OSDictionary *AOAprop;
DEBUG_IOLOG("+ AppleOnboardAudio::init\n");
if (!super::init(properties)) return false;
currentDevices = 0xFFFF;
mHasHardwareInputGain = true; ourPowerState = kIOAudioDeviceActive;
mInternalMicDualMonoMode = e_Mode_Disabled;
if (AOAprop = OSDynamicCast(OSDictionary, properties->getObject("AOAAttributes"))) {
gHasModemSound = (kOSBooleanTrue == OSDynamicCast(OSBoolean, AOAprop->getObject("analogModem")));
}
CLOG("- AppleOnboardAudio::init\n");
return true;
}
void AppleOnboardAudio::free()
{
DEBUG_IOLOG("+ AppleOnboardAudio::free\n");
if (driverDMAEngine) {
driverDMAEngine->release();
driverDMAEngine = NULL;
}
CLEAN_RELEASE(outMute);
CLEAN_RELEASE(headphoneConnection);
CLEAN_RELEASE(outVolLeft);
CLEAN_RELEASE(outVolRight);
CLEAN_RELEASE(outVolMaster);
CLEAN_RELEASE(inGainLeft);
CLEAN_RELEASE(inGainRight);
CLEAN_RELEASE(inputSelector);
CLEAN_RELEASE(theAudioPowerObject);
CLEAN_RELEASE(AudioDetects);
CLEAN_RELEASE(AudioOutputs);
CLEAN_RELEASE(AudioInputs);
CLEAN_RELEASE(theAudioDeviceTreeParser);
publishResource ("setModemSound", NULL);
super::free();
DEBUG_IOLOG("- AppleOnboardAudio::free, (void)\n");
}
IOService* AppleOnboardAudio::probe(IOService* provider, SInt32* score)
{
DEBUG_IOLOG("+ AppleOnboardAudio::probe\n");
super::probe(provider, score);
DEBUG_IOLOG("- AppleOnboardAudio::probe\n");
return (0);
}
OSArray *AppleOnboardAudio::getDetectArray(){
return(AudioDetects);
}
bool AppleOnboardAudio::getMuteState(){
return(gIsMute);
}
void AppleOnboardAudio::setMuteState(bool newMuteState){
outMute->setValue(newMuteState);
}
#pragma mark +PORT HANDLER FUNCTIONS
IOReturn AppleOnboardAudio::configureAudioOutputs(IOService *provider) {
IOReturn result = kIOReturnSuccess;
AudioHardwareOutput *theOutput;
UInt16 idx;
DEBUG_IOLOG("+ AppleOnboardAudio::configureAudioOutputs\n");
if(!theAudioDeviceTreeParser)
goto BAIL;
AudioOutputs = theAudioDeviceTreeParser->createOutputsArray();
if(!AudioOutputs)
goto BAIL;
for(idx = 0; idx < AudioOutputs->getCount(); idx++) {
theOutput = OSDynamicCast(AudioHardwareOutput, AudioOutputs->getObject(idx));
if( theOutput) theOutput->attachAudioPluginRef((AppleOnboardAudio *) this);
}
EXIT:
DEBUG2_IOLOG("- AppleOnboardAudio::configureAudioOutputs, %d\n", (result == kIOReturnSuccess));
return(result);
BAIL:
result = kIOReturnError;
goto EXIT;
}
IOReturn AppleOnboardAudio::configureAudioDetects(IOService *provider) {
IOReturn result = kIOReturnSuccess;
DEBUG_IOLOG("+ AppleOnboardAudio::configureAudioDetects\n");
if(!theAudioDeviceTreeParser)
goto BAIL;
AudioDetects = theAudioDeviceTreeParser->createDetectsArray();
EXIT:
DEBUG2_IOLOG("- AppleOnboardAudio::configureAudioDetects, %d \n", (result == kIOReturnSuccess));
return(result);
BAIL:
result = kIOReturnError;
goto EXIT;
}
IOReturn AppleOnboardAudio::configureAudioInputs(IOService *provider) {
IOReturn result = kIOReturnSuccess;
UInt16 idx;
AudioHardwareInput *theInput;
AudioHardwareMux *theMux;
DEBUG_IOLOG("+ AppleOnboardAudio::configureAudioDetects\n");
FailIf (NULL == theAudioDeviceTreeParser, BAIL);
AudioInputs = theAudioDeviceTreeParser->createInputsArrayWithMuxes();
FailIf (NULL == AudioInputs, BAIL);
for(idx = 0; idx < AudioInputs->getCount(); idx++) {
theInput = OSDynamicCast(AudioHardwareInput, AudioInputs->getObject(idx));
if (NULL != theInput) {
theInput->attachAudioPluginRef((AppleOnboardAudio *) this);
} else {
theMux = OSDynamicCast(AudioHardwareMux, AudioInputs->getObject(idx));
if (NULL != theMux) {
theMux->attachAudioPluginRef((AppleOnboardAudio *) this);
} else {
DEBUG_IOLOG ("!!!It's not an input and it's not a mux!!!\n");
}
}
}
EXIT:
DEBUG2_IOLOG("- %d = AppleOnboardAudio::configureAudioDetects\n", result);
return (result);
BAIL:
result = kIOReturnError;
goto EXIT;
}
IOReturn AppleOnboardAudio::parseAndActivateInit(IOService *provider){
IOReturn result = kIOReturnSuccess;
SInt16 initType = 0;
DEBUG_IOLOG("+ AppleOnboardAudio::parseAndActivateInit\n");
if(!theAudioDeviceTreeParser)
goto BAIL;
initType = theAudioDeviceTreeParser->getInitOperationType();
if(2 == initType)
sndHWSetProgOutput(kSndHWProgOutput0);
EXIT:
DEBUG2_IOLOG("- AppleOnboardAudio::parseAndActivateInit, %d\n", (result == kIOReturnSuccess));
return(result);
BAIL:
result = kIOReturnError;
goto EXIT;
}
UInt32 AppleOnboardAudio::getCurrentDevices(){
return(currentDevices);
}
void AppleOnboardAudio::setCurrentDevices(UInt32 devices){
UInt32 odevice;
if(devices != currentDevices) {
odevice = currentDevices;
currentDevices = devices;
changedDeviceHandler(odevice);
}
debug2IOLog ("currentDevices = %ld\n", currentDevices);
debug2IOLog ("fCPUNeedsPhaseInversion = %d\n", fCPUNeedsPhaseInversion);
if (fCPUNeedsPhaseInversion) {
bool state;
if (currentDevices == 0 || currentDevices & kSndHWInternalSpeaker) { state = true;
} else {
state = false;
}
driverDMAEngine->setPhaseInversion(state);
}
if (devices & kSndHWInputDevices || odevice & kSndHWInputDevices) {
if (NULL != inputConnection) {
OSNumber * inputState;
UInt32 active;
active = devices & kSndHWInputDevices ? 1 : 0; inputState = OSNumber::withNumber ((long long unsigned int)active, 32);
(void)inputConnection->hardwareValueChanged (inputState);
}
}
}
void AppleOnboardAudio::changedDeviceHandler(UInt32 olddevices){
UInt16 i;
AudioHardwareOutput *theOutput;
if(AudioOutputs) {
for(i = 0; i< AudioOutputs->getCount(); i++) {
theOutput = OSDynamicCast(AudioHardwareOutput, AudioOutputs->getObject(i));
if( theOutput) theOutput->deviceIntService(currentDevices);
}
}
}
#pragma mark +IOAUDIO INIT
bool AppleOnboardAudio::initHardware (IOService *provider){
IOWorkLoop * workLoop;
IOAudioStream * inputStream;
IOAudioStream * outputStream;
bool result;
DEBUG_IOLOG("+ AppleOnboardAudio::initHardware\n");
result = FALSE;
if (!super::initHardware (provider)) {
goto EXIT;
}
sndHWInitialize (provider);
theAudioDeviceTreeParser = AudioDeviceTreeParser::createWithEntryProvider (provider);
setManufacturerName ("Apple");
setDeviceName ("Built-in audio controller");
setDeviceTransportType (kIOAudioDeviceTransportTypeBuiltIn);
parseAndActivateInit (provider);
configureAudioDetects (provider);
configureAudioOutputs (provider);
configureAudioInputs (provider);
configurePowerObject (provider);
configureDMAEngines (provider);
createDefaultsPorts ();
if (kIOReturnSuccess != activateAudioEngine (driverDMAEngine)){
driverDMAEngine->release ();
driverDMAEngine = NULL;
goto EXIT;
}
workLoop = getWorkLoop ();
FailIf (NULL == workLoop, EXIT);
outputStream = driverDMAEngine->getAudioStream (kIOAudioStreamDirectionOutput, 1);
if (outputStream) {
outputStream->setTerminalType (OUTPUT_SPEAKER);
} else {
debugIOLog ("didn't get the output stream\n");
}
inputStream = driverDMAEngine->getAudioStream (kIOAudioStreamDirectionInput, 1);
if (inputStream) {
inputStream->setTerminalType (INPUT_MICROPHONE);
} else {
debugIOLog ("didn't get the input stream\n");
}
setIdleAudioSleepTime (kNoIdleAudioPowerDown);
sndHWPostDMAEngineInit (provider);
gExpertMode = TRUE; if (NULL != outVolLeft) {
outVolLeft->setValue (PRAMToVolumeValue ());
}
if (NULL != outVolRight) {
outVolRight->setValue (PRAMToVolumeValue ());
}
flushAudioControls ();
gExpertMode = FALSE;
publishResource ("setModemSound", this);
registerPrioritySleepWakeInterest (&sysPowerDownHandler, this, 0);
registerService ();
mHasHardwareInputGain = theAudioDeviceTreeParser->getHasHWInputGain();
if (mHasHardwareInputGain) {
driverDMAEngine->setUseSoftwareInputGain(false);
} else {
driverDMAEngine->setUseSoftwareInputGain(true);
}
#ifdef _AML_LOG_INPUT_GAIN
if (mHasHardwareInputGain)
IOLog("AppleOnboardAudio::configureDMAEngines - has hardware input gain = TRUE.\n");
else
IOLog("AppleOnboardAudio::configureDMAEngines - has hardware input gain = FALSE.\n");
#endif
result = TRUE;
EXIT:
DEBUG_IOLOG ("- AppleOnboardAudio::initHardware\n");
return (result);
}
IOReturn AppleOnboardAudio::configureDMAEngines(IOService *provider){
IOReturn result;
bool hasInput;
result = kIOReturnError;
FailIf (NULL == theAudioDeviceTreeParser, EXIT);
if (theAudioDeviceTreeParser->getNumberOfInputs () > 0)
hasInput = true;
else
hasInput = false;
driverDMAEngine = new AppleDBDMAAudioDMAEngine;
FailIf (NULL == driverDMAEngine, EXIT);
fCPUNeedsPhaseInversion = theAudioDeviceTreeParser->getPhaseInversion ();
driverDMAEngine->setPhaseInversion (false);
if (!driverDMAEngine->init (NULL, provider, hasInput)) {
driverDMAEngine->release ();
driverDMAEngine = NULL;
goto EXIT;
}
result = kIOReturnSuccess;
EXIT:
return result;
}
IOReturn AppleOnboardAudio::createDefaultsPorts () {
IOAudioPort * outputPort = NULL;
IOAudioPort * inputPort = NULL;
OSDictionary * AOAprop = NULL;
OSDictionary * theRange = NULL;
OSNumber * theNumber;
OSData * theData;
AudioHardwareInput * theInput;
UInt32 inputType;
SInt32 OutminLin;
SInt32 OutmaxLin;
SInt32 InminLin;
SInt32 InmaxLin;
IOFixed OutminDB;
IOFixed OutmaxDB;
IOFixed InminDB;
IOFixed InmaxDB;
UInt32 idx;
IOReturn result;
Boolean done;
Boolean hasPlaythrough;
DEBUG_IOLOG("+ AppleOnboardAudio::createDefaultsPorts\n");
hasPlaythrough = FALSE;
result = kIOReturnSuccess;
FailIf (NULL == driverDMAEngine, BAIL);
FailIf (NULL == (AOAprop = OSDynamicCast(OSDictionary, this->getProperty("AOAAttributes"))), BAIL);
outputSelector = IOAudioSelectorControl::createOutputSelector ('ispk', kIOAudioControlChannelIDAll);
if (NULL != outputSelector) {
driverDMAEngine->addDefaultAudioControl(outputSelector);
outputSelector->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)outputControlChangeHandler, this);
outputSelector->addAvailableSelection(kIOAudioOutputPortSubTypeInternalSpeaker, "Internal speaker");
outputSelector->addAvailableSelection(kIOAudioOutputPortSubTypeHeadphones, "Headphones");
}
if (NULL != (theRange = OSDynamicCast(OSDictionary, AOAprop->getObject("RangeOut")))) {
outputPort = IOAudioPort::withAttributes(kIOAudioPortTypeOutput, "Main Output port");
if (NULL != outputPort) {
theNumber = OSDynamicCast(OSNumber, theRange->getObject("minLin"));
OutminLin = (SInt32) theNumber->unsigned32BitValue();
theNumber = OSDynamicCast(OSNumber, theRange->getObject("maxLin"));
OutmaxLin = (SInt32) theNumber->unsigned32BitValue();
theData = OSDynamicCast(OSData, theRange->getObject("minLog"));
OutminDB = *((IOFixed*) theData->getBytesNoCopy());
theData = OSDynamicCast(OSData, theRange->getObject("maxLog"));
OutmaxDB = *((IOFixed*) theData->getBytesNoCopy());
fMaxVolume = OutmaxLin;
fMinVolume = OutminLin;
outVolMaster = NULL;
pramVol = IOAudioLevelControl::create(PRAMToVolumeValue (), 0, 7, OutminDB, OutmaxDB,
kIOAudioControlChannelIDAll,
"Boot beep volume",
kPRAMVol,
kIOAudioLevelControlSubTypePRAMVolume,
kIOAudioControlUsageOutput);
if (NULL != pramVol) {
driverDMAEngine->addDefaultAudioControl(pramVol);
pramVol->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)outputControlChangeHandler, this);
pramVol->release ();
pramVol = NULL;
}
outVolLeft = IOAudioLevelControl::createVolumeControl(OutmaxLin, OutminLin, OutmaxLin, OutminDB, OutmaxDB,
kIOAudioControlChannelIDDefaultLeft,
kIOAudioControlChannelNameLeft,
kOutVolLeft,
kIOAudioControlUsageOutput);
if (NULL != outVolLeft) {
driverDMAEngine->addDefaultAudioControl(outVolLeft);
outVolLeft->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)outputControlChangeHandler, this);
}
outVolRight = IOAudioLevelControl::createVolumeControl(OutmaxLin, OutminLin, OutmaxLin, OutminDB, OutmaxDB,
kIOAudioControlChannelIDDefaultRight,
kIOAudioControlChannelNameRight,
kOutVolRight,
kIOAudioControlUsageOutput);
if (NULL != outVolRight) {
driverDMAEngine->addDefaultAudioControl(outVolRight);
outVolRight->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)outputControlChangeHandler, this);
}
outMute = IOAudioToggleControl::createMuteControl(false,
kIOAudioControlChannelIDAll,
kIOAudioControlChannelNameAll,
kOutMute,
kIOAudioControlUsageOutput);
if (NULL != outMute) {
driverDMAEngine->addDefaultAudioControl(outMute);
outMute->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)outputControlChangeHandler, this);
}
headphoneConnection = IOAudioToggleControl::create (FALSE,
kIOAudioControlChannelIDAll,
kIOAudioControlChannelNameAll,
kHeadphoneInsert,
kIOAudioControlTypeJack,
kIOAudioControlUsageOutput);
if (NULL != headphoneConnection) {
driverDMAEngine->addDefaultAudioControl (headphoneConnection);
}
attachAudioPort(outputPort, driverDMAEngine, 0);
}
}
if ((theAudioDeviceTreeParser->getNumberOfInputs() > 0)) {
if (NULL != (theRange = OSDynamicCast(OSDictionary, AOAprop->getObject("RangeIn")))) {
inputPort = IOAudioPort::withAttributes(kIOAudioPortTypeInput, "Main Input Port");
if (NULL != inputPort) {
theNumber = OSDynamicCast(OSNumber, theRange->getObject("minLin"));
InminLin = (SInt32) theNumber->unsigned32BitValue();
theNumber = OSDynamicCast(OSNumber, theRange->getObject("maxLin"));
InmaxLin = (SInt32) theNumber->unsigned32BitValue();
theData = OSDynamicCast(OSData, theRange->getObject("minLog"));
InminDB = *((IOFixed*) theData->getBytesNoCopy());
theData = OSDynamicCast(OSData, theRange->getObject("maxLog"));
InmaxDB = *((IOFixed*) theData->getBytesNoCopy());
hasPlaythrough = (kOSBooleanTrue == OSDynamicCast(OSBoolean, AOAprop->getObject("Playthrough")));
mDefaultInMinDB = InminDB;
mDefaultInMaxDB = InmaxDB;
inGainLeft = IOAudioLevelControl::createVolumeControl((InmaxLin-InminLin)/2, InminLin, InmaxLin, InminDB, InmaxDB,
kIOAudioControlChannelIDDefaultLeft,
kIOAudioControlChannelNameLeft,
kInGainLeft,
kIOAudioControlUsageInput);
if (NULL != inGainLeft) {
driverDMAEngine->addDefaultAudioControl(inGainLeft);
inGainLeft->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)inputControlChangeHandler, this);
}
inGainRight = IOAudioLevelControl::createVolumeControl((InmaxLin-InminLin)/2, InminLin, InmaxLin, InminDB, InmaxDB,
kIOAudioControlChannelIDDefaultRight,
kIOAudioControlChannelNameRight,
kInGainRight,
kIOAudioControlUsageInput);
if (NULL != inGainRight) {
driverDMAEngine->addDefaultAudioControl(inGainRight);
inGainRight->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)inputControlChangeHandler, this);
}
attachAudioPort(inputPort, 0, driverDMAEngine);
inputPort->release();
inputPort = NULL;
}
}
if(AudioInputs) {
inputSelector = NULL;
for (idx = 0; idx < AudioInputs->getCount(); idx++) {
theInput = OSDynamicCast(AudioHardwareInput, AudioInputs->getObject(idx));
if (theInput) {
inputType = theInput->getInputPortType();
DEBUG2_IOLOG ("Creating input selector of type %4s\n", (char*)&inputType);
if (NULL == inputSelector && 'none' != inputType) {
inputSelector = IOAudioSelectorControl::createInputSelector(inputType,
kIOAudioControlChannelIDAll,
kIOAudioControlChannelNameAll,
kInputSelector);
if (NULL != inputSelector) {
driverDMAEngine->addDefaultAudioControl(inputSelector);
inputSelector->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)inputControlChangeHandler, this);
}
}
if (NULL != inputSelector) {
DEBUG2_IOLOG ("Calling addAvailableSelection with type %4s\n", (char*)&inputType);
switch(inputType) {
case 'imic' :
inputSelector->addAvailableSelection('imic', "Internal microphone");
break;
case 'emic' :
inputSelector->addAvailableSelection('emic', "External microphone/Line In");
break;
case 'sinj' :
inputSelector->addAvailableSelection('sinj', "Sound Input");
break;
case 'line' :
inputSelector->addAvailableSelection('line', "Line In");
break;
case 'zvpc' :
inputSelector->addAvailableSelection('zvpc', "Zoomed Video");
break;
default:
break;
}
}
}
}
}
done = FALSE;
for (idx = 0; idx < AudioInputs->getCount () && !done; idx++) {
theInput = OSDynamicCast (AudioHardwareInput, AudioInputs->getObject(idx));
if (theInput) {
inputType = theInput->getInputPortType ();
switch (inputType) {
case 'emic':
case 'sinj':
case 'line':
inputConnection = IOAudioToggleControl::create (FALSE,
kIOAudioControlChannelIDAll,
kIOAudioControlChannelNameAll,
kInputInsert,
kIOAudioControlTypeJack,
kIOAudioControlUsageInput);
if (NULL != inputConnection) {
driverDMAEngine->addDefaultAudioControl (inputConnection);
}
done = TRUE;
break;
default:
break;
}
}
}
if (NULL != outputPort && TRUE == hasPlaythrough) {
playthruToggle = IOAudioToggleControl::createMuteControl (TRUE,
kIOAudioControlChannelIDAll,
kIOAudioControlChannelNameAll,
kPassThruToggle,
kIOAudioControlUsagePassThru);
if (NULL != playthruToggle) {
driverDMAEngine->addDefaultAudioControl (playthruToggle);
playthruToggle->setValueChangeHandler ((IOAudioControl::IntValueChangeHandler)inputControlChangeHandler, this);
playthruToggle->release ();
playthruToggle = NULL;
}
outputPort->release();
outputPort = NULL;
}
}
EXIT:
DEBUG2_IOLOG("- %d = AppleOnboardAudio::createDefaultsPorts\n", result);
return result;
BAIL:
result = kIOReturnError;
goto EXIT;
}
#pragma mark +IOAUDIO CONTROL HANDLERS
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;
FAIL_IF (NULL == start, Exit);
iterator = start->getChildIterator (gIOServicePlane);
FAIL_IF (NULL == iterator, Exit);
while (NULL == theEntry && (tmpReg = OSDynamicCast (IORegistryEntry, iterator->getNextObject ())) != NULL) {
if (strcmp (tmpReg->getName (), name) == 0) {
tmpNumber = OSDynamicCast (OSNumber, tmpReg->getProperty (key));
if (NULL != tmpNumber && tmpNumber->unsigned32BitValue () == value) {
theEntry = tmpReg;
theEntry->retain();
}
}
}
Exit:
if (NULL != iterator) {
iterator->release ();
}
return theEntry;
}
IOReturn AppleOnboardAudio::outputControlChangeHandler (IOService *target, IOAudioControl *control, SInt32 oldValue, SInt32 newValue) {
IOReturn result = kIOReturnError;
AppleOnboardAudio * audioDevice;
IOAudioLevelControl * levelControl;
IODTPlatformExpert * platform;
UInt32 leftVol;
UInt32 rightVol;
Boolean wasPoweredDown;
debug5IOLog ("+ AppleOnboardAudio::outputControlChangeHandler (%p, %p, %ld, %ld)\n", target, control, oldValue, newValue);
audioDevice = OSDynamicCast (AppleOnboardAudio, target);
FailIf (NULL == audioDevice, Exit);
if (kIOAudioDeviceSleep == audioDevice->ourPowerState && NULL != audioDevice->theAudioPowerObject) {
audioDevice->ourPowerState = kIOAudioDeviceActive;
audioDevice->theAudioPowerObject->setHardwarePowerOn ();
if (NULL != audioDevice->outMute) {
audioDevice->outMute->flushValue (); }
wasPoweredDown = TRUE;
} else {
wasPoweredDown = FALSE;
}
switch (control->getSubType ()) {
case 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->outMute) {
audioDevice->outMute->hardwareValueChanged (muteState);
}
} else if (oldValue == levelControl->getMinValue () && FALSE == audioDevice->gIsMute) {
OSNumber * muteState;
muteState = OSNumber::withNumber ((long long unsigned int)0, 32);
if (NULL != audioDevice->outMute) {
audioDevice->outMute->hardwareValueChanged (muteState);
}
}
break;
case kIOAudioControlChannelIDDefaultLeft:
result = audioDevice->volumeLeftChange (newValue);
break;
case kIOAudioControlChannelIDDefaultRight:
result = audioDevice->volumeRightChange (newValue);
break;
}
break;
case kIOAudioToggleControlSubTypeMute:
result = audioDevice->outputMuteChange (newValue);
break;
case kIOAudioSelectorControlSubTypeOutput:
result = kIOReturnUnsupported;
break;
case 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);
}
break;
default:
result = kIOReturnBadArgument;
}
if (control->getSubType () == kIOAudioLevelControlSubTypeVolume) {
levelControl = OSDynamicCast (IOAudioLevelControl, control);
if (audioDevice->outVolRight && audioDevice->outVolLeft) {
if (audioDevice->outVolRight->getMinValue () == audioDevice->gVolRight &&
audioDevice->outVolLeft->getMinValue () == audioDevice->gVolLeft) {
OSNumber * muteState;
muteState = OSNumber::withNumber ((long long unsigned int)1, 32);
if (NULL != audioDevice->outMute) {
audioDevice->outMute->hardwareValueChanged (muteState);
}
} else if (newValue != levelControl->getMinValue () && oldValue == levelControl->getMinValue () && FALSE == audioDevice->gIsMute) {
OSNumber * muteState;
muteState = OSNumber::withNumber ((long long unsigned int)0, 32);
if (NULL != audioDevice->outMute) {
audioDevice->outMute->hardwareValueChanged (muteState);
}
}
}
}
if (audioDevice->gIsMute) {
leftVol = 0;
rightVol = 0;
} else {
leftVol = audioDevice->gVolLeft;
rightVol = audioDevice->gVolRight;
}
if (FALSE == audioDevice->gExpertMode) { audioDevice->WritePRAMVol (leftVol, rightVol);
}
Exit:
if (TRUE == wasPoweredDown) {
audioDevice->scheduleIdleAudioSleep ();
}
debug6IOLog ("- AppleOnboardAudio::outputControlChangeHandler (%p, %p, %ld, %ld) returns %X\n", target, control, oldValue, newValue, result);
return result;
}
#if 0
IOReturn AppleOnboardAudio::setiSubVolume (UInt32 iSubVolumeControl, SInt32 iSubVolumeLevel) {
IOReturn result;
IOAudioLevelControl * iSubVolume;
IORegistryEntry * start;
result = kIOReturnSuccess;
if (NULL != driverDMAEngine->iSubBufferMemory) {
start = childFromPath ("AppleDBDMAAudioDMAEngine", gIOServicePlane);
FAIL_IF (NULL == start, Exit);
iSubVolume = (IOAudioLevelControl *)FindEntryByNameAndProperty (start, "AppleUSBAudioLevelControl", kIOAudioControlSubTypeKey, iSubVolumeControl);
start->release ();
if (NULL != iSubVolume) {
iSubVolume->setValue (iSubVolumeLevel);
iSubVolume->release();
}
}
Exit:
return result;
}
IOReturn AppleOnboardAudio::setiSubMute (UInt32 setMute) {
IOReturn result;
IOAudioToggleControl * iSubMute;
IORegistryEntry * start;
result = kIOReturnSuccess;
start = childFromPath ("AppleDBDMAAudioDMAEngine", gIOServicePlane);
FailIf (NULL == start, Exit);
iSubMute = (IOAudioToggleControl *)FindEntryByNameAndProperty (start, "AppleUSBAudioMuteControl", kIOAudioControlSubTypeKey, kIOAudioToggleControlSubTypeLFEMute);
start->release ();
if ( NULL != iSubMute ) {
iSubMute->setValue (setMute);
iSubMute->release ();
}
Exit:
return result;
}
#endif
IOReturn AppleOnboardAudio::volumeMasterChange(SInt32 newValue){
IOReturn result = kIOReturnSuccess;
DEBUG_IOLOG("+ AppleOnboardAudio::volumeMasterChange\n");
result = kIOReturnError;
result = volumeLeftChange(newValue);
result = volumeRightChange(newValue);
result = kIOReturnSuccess;
DEBUG2_IOLOG("- AppleOnboardAudio::volumeMasterChange, 0x%x\n", result);
return result;
}
IOReturn AppleOnboardAudio::volumeLeftChange(SInt32 newValue){
IOReturn result;
AudioHardwareOutput * theOutput;
UInt32 idx;
DEBUG2_IOLOG("+ AppleOnboardAudio::volumeLeftChange (%ld)\n", newValue);
result = kIOReturnError;
FailIf (NULL == AudioOutputs, Exit);
debug3IOLog("... gIsMute %d, AudioOutputs->getCount() = %d\n", gIsMute, AudioOutputs->getCount());
if (!gIsMute) {
for (idx = 0; idx < AudioOutputs->getCount(); idx++) {
theOutput = OSDynamicCast (AudioHardwareOutput, AudioOutputs->getObject (idx));
if (theOutput) {
debug4IOLog ( "... %X theOutput->setVolume ( %X, %X )\n", (unsigned int)theOutput, (unsigned int)newValue, (unsigned int)gVolRight );
theOutput->setVolume (newValue, gVolRight);
} else {
debugIOLog("... ### NO AudioHardwareOutput*\n");
}
}
}
gVolLeft = newValue;
result = kIOReturnSuccess;
Exit:
DEBUG2_IOLOG("- AppleOnboardAudio::volumeLeftChange, 0x%x\n", result);
return result;
}
IOReturn AppleOnboardAudio::volumeRightChange(SInt32 newValue){
IOReturn result;
AudioHardwareOutput * theOutput;
UInt32 idx;
DEBUG2_IOLOG("+ AppleOnboardAudio::volumeRightChange (%ld)\n", newValue);
result = kIOReturnError;
FailIf (NULL == AudioOutputs, Exit);
debug3IOLog("... gIsMute %d, AudioOutputs->getCount() = %d\n", gIsMute, AudioOutputs->getCount());
if (!gIsMute) {
for (idx = 0; idx < AudioOutputs->getCount(); idx++) {
theOutput = OSDynamicCast (AudioHardwareOutput, AudioOutputs->getObject (idx));
if (theOutput) {
debug4IOLog ( "... %X theOutput->setVolume ( %X, %X )\n", (unsigned int)theOutput, (unsigned int)newValue, (unsigned int)gVolRight );
theOutput->setVolume (gVolLeft, newValue);
} else {
debugIOLog("... ### NO AudioHardwareOutput*\n");
}
}
}
gVolRight = newValue;
result = kIOReturnSuccess;
Exit:
DEBUG2_IOLOG("- AppleOnboardAudio::volumeRightChange, result = 0x%x\n", result);
return result;
}
IOReturn AppleOnboardAudio::outputMuteChange(SInt32 newValue){
IOReturn result;
UInt32 idx;
AudioHardwareOutput * theOutput;
DEBUG2_IOLOG("+ AppleOnboardAudio::outputMuteChange (%ld)\n", newValue);
result = kIOReturnError;
FailIf (NULL == AudioOutputs, Exit);
for (idx = 0; idx < AudioOutputs->getCount(); idx++) {
theOutput = OSDynamicCast (AudioHardwareOutput, AudioOutputs->getObject (idx));
if (theOutput) {
theOutput->setMute (newValue);
}
}
gIsMute = newValue;
result = kIOReturnSuccess;
Exit:
DEBUG2_IOLOG("- AppleOnboardAudio::outputMuteChange, 0x%x\n", result);
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);
FailIf (NULL == audioDevice, Exit);
if (kIOAudioDeviceSleep == audioDevice->ourPowerState && NULL != audioDevice->theAudioPowerObject) {
audioDevice->ourPowerState = kIOAudioDeviceActive;
audioDevice->theAudioPowerObject->setHardwarePowerOn ();
if (NULL != audioDevice->outMute) {
audioDevice->outMute->flushValue (); }
wasPoweredDown = TRUE;
} else {
wasPoweredDown = FALSE;
}
switch (control->getType ()) {
case kIOAudioControlTypeLevel:
switch (control->getSubType ()) {
case kIOAudioLevelControlSubTypeVolume:
levelControl = OSDynamicCast (IOAudioLevelControl, control);
switch (control->getChannelID ()) {
case kIOAudioControlChannelIDDefaultLeft:
result = audioDevice->gainLeftChanged (newValue);
break;
case kIOAudioControlChannelIDDefaultRight:
result = audioDevice->gainRightChanged (newValue);
break;
}
break;
}
break;
case kIOAudioControlTypeToggle:
switch (control->getSubType ()) {
case kIOAudioToggleControlSubTypeMute:
result = audioDevice->passThruChanged (newValue);
break;
}
break;
case kIOAudioControlTypeSelector:
result = audioDevice->inputSelectorChanged (newValue);
break;
default:
;
}
Exit:
if (TRUE == wasPoweredDown) {
audioDevice->scheduleIdleAudioSleep ();
}
return result;
}
#if 0
IOReturn AppleOnboardAudio::gainLeftChangeHandler(IOService *target, IOAudioControl *gainControl, SInt32 oldValue, SInt32 newValue){
IOReturn result = kIOReturnSuccess;
AppleOnboardAudio *audioDevice;
DEBUG_IOLOG("_ AppleOnboardAudio::gainLeftChangeHandler\n");
audioDevice = (AppleOnboardAudio *)target;
if(!audioDevice)
goto BAIL;
result = audioDevice->gainLeftChanged(gainControl, oldValue, newValue);
EXIT:
DEBUG2_IOLOG("- AppleOnboardAudio::gainLeftChangeHandler, 0x%x\n", result);
return result;
BAIL:
result = kIOReturnError;
goto EXIT;
}
#endif
IOReturn AppleOnboardAudio::gainLeftChanged(SInt32 newValue){
IOReturn result = kIOReturnSuccess;
UInt32 idx;
AudioHardwareInput *theInput;
DEBUG_IOLOG("+ AppleOnboardAudio::gainLeftChanged\n");
if(!AudioInputs)
goto BAIL;
gGainLeft = newValue;
if (!mHasHardwareInputGain) {
#ifdef _AML_LOG_INPUT_GAIN
IOLog("AppleOnboardAudio::gainLeftChanged - using software gain (0x%X).\n", gGainLeft);
#endif
driverDMAEngine->setInputGainL(gGainLeft);
} else {
for(idx = 0; idx< AudioInputs->getCount(); idx++) {
theInput = OSDynamicCast(AudioHardwareInput, AudioInputs->getObject(idx));
if(theInput)
theInput->setInputGain(newValue, gGainRight);
}
}
EXIT:
DEBUG2_IOLOG("- AppleOnboardAudio::gainLeftChanged, %d\n", (result == kIOReturnSuccess));
return result;
BAIL:
result = kIOReturnError;
goto EXIT;
}
#if 0
IOReturn AppleOnboardAudio::gainRightChangeHandler(IOService *target, IOAudioControl *gainControl, SInt32 oldValue, SInt32 newValue){
IOReturn result = kIOReturnSuccess;
AppleOnboardAudio *audioDevice;
DEBUG_IOLOG("+ AppleOnboardAudio::gainRightChangeHandler\n");
audioDevice = (AppleOnboardAudio *)target;
if(!audioDevice)
goto BAIL;
result = audioDevice->gainRightChanged(gainControl, oldValue, newValue);
EXIT:
DEBUG_IOLOG("- AppleOnboardAudio::gainRightChangeHandler\n");
return result;
BAIL:
result = kIOReturnError;
goto EXIT;
}
#endif
IOReturn AppleOnboardAudio::gainRightChanged(SInt32 newValue){
IOReturn result = kIOReturnSuccess;
UInt32 idx;
AudioHardwareInput *theInput;
DEBUG_IOLOG("+ AppleOnboardAudio::gainRightChanged\n");
if(!AudioInputs)
goto BAIL;
gGainRight = newValue;
if (!mHasHardwareInputGain) {
#ifdef _AML_LOG_INPUT_GAIN
IOLog("AppleOnboardAudio::gainRightChanged - using software gain (0x%X).\n", gGainRight);
#endif
driverDMAEngine->setInputGainR(gGainRight);
} else {
for(idx = 0; idx< AudioInputs->getCount(); idx++) {
theInput = OSDynamicCast(AudioHardwareInput, AudioInputs->getObject(idx));
if( theInput) theInput->setInputGain(gGainLeft, newValue);
}
}
EXIT:
DEBUG2_IOLOG("- AppleOnboardAudio::gainRightChanged, %d\n", (result == kIOReturnSuccess));
return result;
BAIL:
result = kIOReturnError;
goto EXIT;
}
#if 0
IOReturn AppleOnboardAudio::passThruChangeHandler(IOService *target, IOAudioControl *passThruControl, SInt32 oldValue, SInt32 newValue){
IOReturn result = kIOReturnSuccess;
AppleOnboardAudio *audioDevice;
DEBUG_IOLOG("+ AppleOnboardAudio::passThruChangeHandler\n");
audioDevice = (AppleOnboardAudio *)target;
if(!audioDevice) goto BAIL;
result = audioDevice->passThruChanged(passThruControl, oldValue, newValue);
EXIT:
DEBUG_IOLOG("- AppleOnboardAudio::passThruChangeHandler\n");
return result;
BAIL:
result = kIOReturnError;
goto EXIT;
}
#endif
IOReturn AppleOnboardAudio::passThruChanged(SInt32 newValue){
IOReturn result = kIOReturnSuccess;
DEBUG_IOLOG("+ AppleOnboardAudio::passThruChanged\n");
gIsPlayThroughActive = newValue;
sndHWSetPlayThrough(!newValue);
DEBUG_IOLOG("- AppleOnboardAudio::passThruChanged\n");
return result;
}
#if 0
IOReturn AppleOnboardAudio::inputSelectorChangeHandler(IOService *target, IOAudioControl *inputSelector, SInt32 oldValue, SInt32 newValue){
IOReturn result = kIOReturnSuccess;
AppleOnboardAudio *audioDevice;
DEBUG_IOLOG("+ AppleOnboardAudio::inputSelectorChangeHandler\n");
audioDevice = (AppleOnboardAudio *)target;
if(!audioDevice) goto BAIL;
result = audioDevice->inputSelectorChanged(inputSelector, oldValue, newValue);
EXIT:
DEBUG_IOLOG("- AppleOnboardAudio::inputSelectorChangeHandler\n");
return result;
BAIL:
result = kIOReturnError;
goto EXIT;
}
#endif
IOReturn AppleOnboardAudio::inputSelectorChanged(SInt32 newValue){
AudioHardwareInput *theInput;
UInt32 idx;
IOAudioEngine* audioEngine;
IOFixed mindBVol;
IOFixed maxdBVol;
IOFixed dBOffset;
IOReturn result = kIOReturnSuccess;
DEBUG_IOLOG("+ AppleOnboardAudio::inputSelectorChanged\n");
if(AudioInputs) {
for(idx = 0; idx< AudioInputs->getCount(); idx++) {
theInput = OSDynamicCast(AudioHardwareInput, AudioInputs->getObject(idx));
if( theInput) theInput->forceActivation(newValue);
}
if (newValue == kIntMicSource) {
dBOffset = theAudioDeviceTreeParser->getInternalMicGainOffset();
if (dBOffset != 0x0) {
if (dBOffset > mDefaultInMaxDB) {
dBOffset = mDefaultInMaxDB;
}
mindBVol = mDefaultInMinDB - dBOffset;
maxdBVol = mDefaultInMaxDB - dBOffset;
audioEngine = OSDynamicCast (IOAudioEngine, audioEngines->getObject(0));
audioEngine->pauseAudioEngine ();
audioEngine->beginConfigurationChange ();
if (NULL != inGainLeft) {
inGainLeft->setMinDB (mindBVol);
inGainLeft->setMaxDB (maxdBVol);
mRangeInChanged = true;
}
if (NULL != inGainRight) {
inGainRight->setMinDB (mindBVol);
inGainRight->setMaxDB (maxdBVol);
mRangeInChanged = true;
}
audioEngine->completeConfigurationChange ();
audioEngine->resumeAudioEngine ();
}
if (mInternalMicDualMonoMode != e_Mode_Disabled) {
driverDMAEngine->setDualMonoMode(mInternalMicDualMonoMode);
}
} else {
if (mRangeInChanged) {
mRangeInChanged = false;
audioEngine = OSDynamicCast (IOAudioEngine, audioEngines->getObject(0));
audioEngine->pauseAudioEngine ();
audioEngine->beginConfigurationChange ();
if (NULL != inGainLeft) {
inGainLeft->setMinDB (mDefaultInMinDB);
inGainLeft->setMaxDB (mDefaultInMaxDB);
}
if (NULL != inGainRight) {
inGainRight->setMinDB (mDefaultInMinDB);
inGainRight->setMaxDB (mDefaultInMaxDB);
}
audioEngine->completeConfigurationChange ();
audioEngine->resumeAudioEngine ();
}
if (mInternalMicDualMonoMode != e_Mode_Disabled) {
driverDMAEngine->setDualMonoMode(e_Mode_Disabled);
}
}
}
DEBUG_IOLOG("- AppleOnboardAudio::inputSelectorChanged\n");
return result;
}
#pragma mark +POWER MANAGEMENT
IOReturn AppleOnboardAudio::configurePowerObject(IOService *provider){
IOReturn result = kIOReturnSuccess;
DEBUG_IOLOG("+ AppleOnboardAudio::configurePowerObject\n");
switch (theAudioDeviceTreeParser->getPowerObjectType()) {
case kProj6PowerObject:
theAudioPowerObject = AudioProj6PowerObject::createAudioProj6PowerObject(this);
if(!theAudioPowerObject) goto BAIL;
break;
case kProj7PowerObject:
theAudioPowerObject = AudioProj7PowerObject::createAudioProj7PowerObject(this);
if(!theAudioPowerObject) goto BAIL;
break;
case kProj8PowerObject:
theAudioPowerObject = AudioProj8PowerObject::createAudioProj8PowerObject(this);
if(!theAudioPowerObject) goto BAIL;
break;
case kProj10PowerObject:
theAudioPowerObject = AudioProj10PowerObject::createAudioProj10PowerObject(this);
if(!theAudioPowerObject) goto BAIL;
break;
case kProj14PowerObject:
theAudioPowerObject = AudioProj14PowerObject::createAudioProj14PowerObject(this);
if(!theAudioPowerObject) goto BAIL;
break;
case kProj16PowerObject:
theAudioPowerObject = AudioProj16PowerObject::createAudioProj16PowerObject(this);
if(!theAudioPowerObject) goto BAIL;
break;
case kBasePowerObject:
default: theAudioPowerObject = AudioPowerObject::createAudioPowerObject(this);
if(!theAudioPowerObject) goto BAIL;
break;
}
EXIT:
DEBUG2_IOLOG("- AppleOnboardAudio::configurePowerObject result = %d\n", (result == kIOReturnSuccess));
return(result);
BAIL:
result = kIOReturnError;
goto EXIT;
}
IOReturn AppleOnboardAudio::setAggressiveness(unsigned long type, unsigned long newLevel)
{
if (type == kPMPowerSource) {
switch (newLevel) {
case kIOPMInternalPower: setIdleAudioSleepTime (kBatteryPowerDownDelayTime);
break;
case kIOPMExternalPower: setIdleAudioSleepTime (kNoIdleAudioPowerDown); break;
default:
break;
}
}
return super::setAggressiveness(type, newLevel);
}
IOReturn AppleOnboardAudio::performPowerStateChange(IOAudioDevicePowerState oldPowerState,
IOAudioDevicePowerState newPowerState,
UInt32 *microsecondsUntilComplete)
{
IOReturn result;
debug4IOLog ("+ AppleOnboardAudio::performPowerStateChange (%d, %d) -- ourPowerState = %d\n", oldPowerState, newPowerState, ourPowerState);
if (NULL != theAudioPowerObject) {
*microsecondsUntilComplete = theAudioPowerObject->GetTimeToChangePowerState (ourPowerState, newPowerState);
}
result = super::performPowerStateChange (oldPowerState, newPowerState, microsecondsUntilComplete);
if (NULL != theAudioPowerObject) {
switch (newPowerState) {
case kIOAudioDeviceSleep:
if (ourPowerState == kIOAudioDeviceActive) {
outputMuteChange (TRUE); theAudioPowerObject->setHardwarePowerOff ();
ourPowerState = newPowerState;
}
break;
case kIOAudioDeviceIdle:
if (ourPowerState == kIOAudioDeviceActive) {
outputMuteChange (TRUE); theAudioPowerObject->setHardwarePowerOff ();
ourPowerState = kIOAudioDeviceSleep;
}
break;
case kIOAudioDeviceActive:
theAudioPowerObject->setHardwarePowerOn ();
if (NULL != outMute) {
outMute->flushValue (); }
ourPowerState = newPowerState;
break;
default:
;
}
}
debug2IOLog ("- AppleOnboardAudio::performPowerStateChange -- ourPowerState = %d\n", 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:
if (NULL != appleOnboardAudio->theAudioPowerObject) {
appleOnboardAudio->theAudioPowerObject->setIdlePowerState ();
}
result = kIOReturnSuccess;
break;
default:
break;
}
Exit:
return result;
}
#pragma mark +MODEM SOUND
IOReturn AppleOnboardAudio::setModemSound (bool state){
AudioHardwareInput * theInput;
UInt32 idx;
Boolean wasPoweredDown;
debugIOLog ("+ AppleOnboardAudio::setModemSound\n");
if (kIOAudioDeviceSleep == ourPowerState && NULL != theAudioPowerObject) {
ourPowerState = kIOAudioDeviceActive;
theAudioPowerObject->setHardwarePowerOn ();
if (NULL != outMute) {
outMute->flushValue (); }
wasPoweredDown = TRUE;
} else {
wasPoweredDown = FALSE;
}
theInput = NULL;
if (gIsModemSoundActive == state)
goto EXIT;
if (FALSE != state) { if (NULL != AudioInputs) {
for (idx = 0; idx < AudioInputs->getCount (); idx++) {
theInput = OSDynamicCast (AudioHardwareInput, AudioInputs->getObject (idx));
if (NULL != theInput) {
theInput->forceActivation ('modm');
theInput->setInputGain (0,0);
}
}
}
sndHWSetPlayThrough (true);
} else {
sndHWSetPlayThrough (!gIsPlayThroughActive);
if (NULL != AudioInputs) {
for (idx = 0; idx < AudioInputs->getCount (); idx++) {
theInput = OSDynamicCast (AudioHardwareInput, AudioInputs->getObject (idx));
if (NULL != theInput){
theInput->forceActivation (inputSelector->getIntValue ());
theInput->setInputGain (gGainLeft, gGainRight);
}
}
}
}
gIsModemSoundActive = state;
EXIT:
if (TRUE == wasPoweredDown) {
scheduleIdleAudioSleep ();
}
debugIOLog ("- AppleOnboardAudio::setModemSound\n");
return kIOReturnSuccess;
}
IOReturn AppleOnboardAudio::callPlatformFunction( const OSSymbol * functionName, bool waitForFunction,void *param1, void *param2, void *param3, void *param4 ) {
debugIOLog ("+ AppleOnboardAudio::callPlatformFunction\n");
if (functionName->isEqualTo ("setModemSound")) {
return (setModemSound ((bool)param1));
}
debugIOLog ("- AppleOnboardAudio::callPlatformFunction\n");
return (super::callPlatformFunction (functionName, waitForFunction,param1, param2, param3, param4));
}
#pragma mark +PRAM VOLUME
UInt8 AppleOnboardAudio::VolumeToPRAMValue (UInt32 inLeftVol, UInt32 inRightVol) {
UInt32 pramVolume; UInt32 averageVolume; UInt32 volumeRange;
UInt32 volumeSteps;
UInt32 leftVol;
UInt32 rightVol;
debug3IOLog ( "+ AppleOnboardAudio::VolumeToPRAMValue ( 0x%X, 0x%X )\n", (unsigned int)inLeftVol, (unsigned int)inRightVol );
pramVolume = 0; if ( ( 0 != inLeftVol ) || ( 0 != inRightVol ) ) { leftVol = inLeftVol;
rightVol = inRightVol;
if (NULL != outVolLeft) {
leftVol -= outVolLeft->getMinValue ();
}
if (NULL != outVolRight) {
rightVol -= outVolRight->getMinValue ();
}
debug3IOLog ( "... leftVol = 0x%X, rightVol = 0x%X\n", (unsigned int)leftVol, (unsigned int)rightVol );
if (NULL != outVolMaster) {
volumeRange = (outVolMaster->getMaxValue () - outVolMaster->getMinValue () + 1);
debug2IOLog ( "... outVolMaster volumeRange = 0x%X\n", (unsigned int)volumeRange );
} else if (NULL != outVolLeft) {
volumeRange = (outVolLeft->getMaxValue () - outVolLeft->getMinValue () + 1);
debug2IOLog ( "... outVolLeft volumeRange = 0x%X\n", (unsigned int)volumeRange );
} else if (NULL != outVolRight) {
volumeRange = (outVolRight->getMaxValue () - outVolRight->getMinValue () + 1);
debug2IOLog ( "... outVolRight volumeRange = 0x%X\n", (unsigned int)volumeRange );
} else {
volumeRange = kMaximumPRAMVolume;
debug2IOLog ( "... volumeRange = 0x%X **** NO AUDIO LEVEL CONTROLS!\n", (unsigned int)volumeRange );
}
averageVolume = (leftVol + rightVol) >> 1; debug2IOLog ( "... averageVolume = 0x%X\n", (unsigned int)volumeRange );
debug3IOLog ( "... volumeRange %X, kMaximumPRAMVolume %X\n", (unsigned int)volumeRange, (unsigned int)kMaximumPRAMVolume );
volumeSteps = volumeRange / kMaximumPRAMVolume; pramVolume = averageVolume / volumeSteps;
if ((pramVolume == 0) && (leftVol != 0 || rightVol !=0 )) {
pramVolume = 1;
}
}
debug2IOLog ( "- AppleOnboardAudio::VolumeToPRAMValue returns 0x%X\n", (unsigned int)pramVolume );
return (pramVolume & 0x07);
}
UInt32 AppleOnboardAudio::PRAMToVolumeValue (void) {
UInt32 volumeRange;
UInt32 volumeSteps;
if (NULL != outVolLeft) {
volumeRange = (outVolLeft->getMaxValue () - outVolLeft->getMinValue () + 1);
} else if (NULL != outVolRight) {
volumeRange = (outVolRight->getMaxValue () - outVolRight->getMinValue () + 1);
} else {
volumeRange = kMaximumPRAMVolume;
}
volumeSteps = volumeRange / kMaximumPRAMVolume;
return (volumeSteps * ReadPRAMVol ());
}
void AppleOnboardAudio::WritePRAMVol (UInt32 leftVol, UInt32 rightVol) {
UInt8 pramVolume;
UInt8 curPRAMVol;
IODTPlatformExpert * platform;
IOReturn err;
platform = OSDynamicCast(IODTPlatformExpert,getPlatform());
debug3IOLog("+ AppleOnboardAudio::WritePRAMVol leftVol=%lu, rightVol=%lu\n",leftVol, rightVol);
if (platform) {
debug2IOLog ( "... platform 0x%X\n", (unsigned int)platform );
pramVolume = VolumeToPRAMValue (leftVol, rightVol);
#if 0
curPRAMVol = pramVolume ^ 0xFF;
debug3IOLog ( "... target pramVolume = 0x%X, curPRAMVol = 0x%X\n", pramVolume, curPRAMVol );
#endif
err = platform->readXPRAM((IOByteCount)kPRamVolumeAddr, &curPRAMVol, (IOByteCount)1);
if ( kIOReturnSuccess == err ) {
debug2IOLog ( "... curPRAMVol = 0x%X before write\n", (curPRAMVol & 0x07) );
if (pramVolume != (curPRAMVol & 0x07)) {
curPRAMVol = (curPRAMVol & 0xF8) | pramVolume;
debug2IOLog("... curPRAMVol = 0x%x\n",curPRAMVol);
err = platform->writeXPRAM((IOByteCount)kPRamVolumeAddr, &curPRAMVol,(IOByteCount) 1);
if ( kIOReturnSuccess != err ) {
debug5IOLog ( "0x%X = platform->writeXPRAM( 0x%X, & 0x%X, 1 ), value = 0x%X\n", err, (unsigned int)kPRamVolumeAddr, (unsigned int)&curPRAMVol, (unsigned int)curPRAMVol );
} else {
#if 0
err = platform->readXPRAM((IOByteCount)kPRamVolumeAddr, &curPRAMVol, (IOByteCount)1);
if ( kIOReturnSuccess == err ) {
if ( ( 0x07 & curPRAMVol ) != pramVolume ) {
debug3IOLog ( "PRAM Read after Write did not compare: Write = 0x%X, Read = 0x%X\n", (unsigned int)pramVolume, (unsigned int)curPRAMVol );
} else {
debugIOLog ( "PRAM verified after write!\n" );
}
} else {
debugIOLog ( "Could not readXPRAM to verify write!\n" );
}
#endif
}
} else {
debugIOLog ( "PRAM write request is to current value: no I/O\n" );
}
} else {
debug2IOLog ( "Could not readXPRAM prior to write! Error 0x%X\n", err );
}
} else {
debugIOLog ( "... no platform\n" );
}
debugIOLog("- AppleOnboardAudio::WritePRAMVol\n");
}
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;
}
IOReturn AppleOnboardAudio::newUserClient( task_t inOwningTask,
void * inSecurityID,
UInt32 inType,
IOUserClient ** outHandler )
{
#pragma unused( inType )
IOReturn err;
IOUserClient * userClientPtr;
bool result;
IOLog( "[AppleOnboardAudio] creating user client for task 0x%08lX\n", ( UInt32 ) inOwningTask );
err = kIOReturnNoMemory;
userClientPtr = AppleOnboardAudioUserClient::Create( this, inOwningTask );
if( !userClientPtr ) goto exit;
err = kIOReturnError;
result = userClientPtr->attach( this );
if( !result ) goto exit;
result = userClientPtr->start( this );
if( !result ) goto exit;
*outHandler = userClientPtr;
err = kIOReturnSuccess;
exit:
IOLog( "[AppleOnboardAudio] newUserClient done (err=%d)\n", err );
if( err != kIOReturnSuccess )
{
if( userClientPtr )
{
userClientPtr->detach( this );
userClientPtr->release();
}
}
return( err );
}
#if 0
#pragma mark -
#endif
const IOExternalMethod AppleOnboardAudioUserClient::sMethods[] =
{
{
NULL, ( IOMethod ) &AppleOnboardAudioUserClient::gpioRead, kIOUCScalarIScalarO, 1, 1 },
{
NULL, ( IOMethod ) &AppleOnboardAudioUserClient::gpioWrite, kIOUCScalarIScalarO, 2, 0 },
{
NULL, ( IOMethod ) &AppleOnboardAudioUserClient::gpioGetActiveState, kIOUCScalarIScalarO, 1, 1 },
{
NULL, ( IOMethod ) &AppleOnboardAudioUserClient::gpioSetActiveState, kIOUCScalarIScalarO, 2, 0 },
{
NULL, ( IOMethod ) &AppleOnboardAudioUserClient::gpioCheckAvailable, kIOUCScalarIScalarO, 1, 1 },
{
NULL, ( IOMethod ) &AppleOnboardAudioUserClient::hwRegisterRead32, kIOUCScalarIScalarO, 1, 1 },
{
NULL, ( IOMethod ) &AppleOnboardAudioUserClient::hwRegisterWrite32, kIOUCScalarIScalarO, 2, 0 },
{
NULL, ( IOMethod ) &AppleOnboardAudioUserClient::codecReadRegister, kIOUCScalarIStructO, 1, kMaxCodecStructureSize },
{
NULL, ( IOMethod ) &AppleOnboardAudioUserClient::codecWriteRegister, kIOUCScalarIStructI, 1, kMaxCodecRegisterWidth },
{
NULL, ( IOMethod ) &AppleOnboardAudioUserClient::readSpeakerID, kIOUCScalarIScalarO, 1, 1 },
{
NULL, ( IOMethod ) &AppleOnboardAudioUserClient::codecRegisterSize, kIOUCScalarIScalarO, 1, 1 },
{
NULL, ( IOMethod ) &AppleOnboardAudioUserClient::readPRAMVolume, kIOUCScalarIScalarO, 1, 1 },
{
NULL, ( IOMethod ) &AppleOnboardAudioUserClient::readDMAState, kIOUCScalarIScalarO, 1, 1 },
{
NULL, ( IOMethod ) &AppleOnboardAudioUserClient::readStreamFormat, kIOUCScalarIStructO, 1, sizeof ( IOAudioStreamFormat ) },
{
NULL, ( IOMethod ) &AppleOnboardAudioUserClient::readPowerState, kIOUCScalarIScalarO, 1, 1 },
{
NULL, ( IOMethod ) &AppleOnboardAudioUserClient::setPowerState, kIOUCScalarIScalarO, 2, 0 },
{
NULL, ( IOMethod ) &AppleOnboardAudioUserClient::setBiquadCoefficients, kIOUCScalarIStructI, 1, kMaxBiquadWidth },
{
NULL, ( IOMethod ) &AppleOnboardAudioUserClient::getBiquadInfo, kIOUCScalarIStructO, 1, kMaxBiquadInfoSize },
{
NULL, ( IOMethod ) &AppleOnboardAudioUserClient::getProcessingParams, kIOUCScalarIStructO, 1, kMaxProcessingParamSize },
{
NULL, ( IOMethod ) &AppleOnboardAudioUserClient::setProcessingParams, kIOUCScalarIStructI, 1, kMaxProcessingParamSize },
{
NULL, ( IOMethod ) &AppleOnboardAudioUserClient::invokeInternalFunction, kIOUCScalarIStructI, 1, 16 },
};
const IOItemCount AppleOnboardAudioUserClient::sMethodCount = sizeof( AppleOnboardAudioUserClient::sMethods ) /
sizeof( AppleOnboardAudioUserClient::sMethods[ 0 ] );
OSDefineMetaClassAndStructors( AppleOnboardAudioUserClient, IOUserClient )
AppleOnboardAudioUserClient * AppleOnboardAudioUserClient::Create( AppleOnboardAudio *inDriver, task_t inTask )
{
AppleOnboardAudioUserClient * userClient;
userClient = new AppleOnboardAudioUserClient;
if( !userClient )
{
IOLog( "[AppleOnboardAudio] create user client object failed\n" );
goto exit;
}
if( !userClient->initWithDriver( inDriver, inTask ) )
{
IOLog( "[AppleOnboardAudio] initWithDriver failed\n" );
userClient->release();
userClient = NULL;
goto exit;
}
IOLog( "[AppleOnboardAudio] User client created for task 0x%08lX\n", ( UInt32 ) inTask );
exit:
return( userClient );
}
bool AppleOnboardAudioUserClient::initWithDriver( AppleOnboardAudio *inDriver, task_t inTask )
{
bool result;
IOLog( "[AppleOnboardAudio] initWithDriver\n" );
result = false;
if( !initWithTask( inTask, NULL, 0 ) )
{
IOLog( "[AppleOnboardAudio] initWithTask failed\n" );
goto exit;
}
if( !inDriver )
{
IOLog( "[AppleOnboardAudio] initWithDriver failed (null input driver)\n" );
goto exit;
}
mDriver = inDriver;
mClientTask = inTask;
result = true;
exit:
return( result );
}
void AppleOnboardAudioUserClient::free( void )
{
IOLog( "[AppleOnboardAudio] free\n" );
IOUserClient::free();
}
IOReturn AppleOnboardAudioUserClient::clientClose( void )
{
IOLog( "[AppleOnboardAudio] clientClose\n" );
if( !isInactive() )
{
mDriver = NULL;
}
return( kIOReturnSuccess );
}
IOReturn AppleOnboardAudioUserClient::clientDied( void )
{
IOLog( "[AppleOnboardAudio] clientDied\n" );
return( clientClose() );
}
IOExternalMethod * AppleOnboardAudioUserClient::getTargetAndMethodForIndex( IOService **outTarget, UInt32 inIndex )
{
IOExternalMethod * methodPtr;
methodPtr = NULL;
if( inIndex <= sMethodCount ) {
*outTarget = this;
methodPtr = ( IOExternalMethod * ) &sMethods[ inIndex ];
} else {
IOLog( "[AppleOnboardAudio] getTargetAndMethodForIndex - bad index (index=%lu)\n", inIndex );
}
return( methodPtr );
}
IOReturn AppleOnboardAudioUserClient::gpioRead (UInt32 selector, UInt8 * gpioState) {
IOReturn err = kIOReturnNotReadable;
if ( NULL != mDriver && NULL != gpioState ) {
*gpioState = mDriver->readGPIO ( selector );
err = kIOReturnSuccess;
}
return (err);
}
IOReturn AppleOnboardAudioUserClient::gpioWrite (UInt32 selector, UInt8 data) {
IOReturn err = kIOReturnNotReadable;
if ( NULL != mDriver ) {
mDriver->writeGPIO ( selector, data );
err = kIOReturnSuccess;
}
return (err);
}
IOReturn AppleOnboardAudioUserClient::gpioGetActiveState (UInt32 selector, UInt8 * gpioActiveState) {
IOReturn err = kIOReturnNotReadable;
if ( NULL != mDriver && NULL != gpioActiveState ) {
*gpioActiveState = mDriver->getGPIOActiveState ( selector );
err = kIOReturnSuccess;
}
return (err);
}
IOReturn AppleOnboardAudioUserClient::gpioSetActiveState (UInt32 selector, UInt8 gpioActiveState) {
IOReturn err = kIOReturnNotReadable;
if ( NULL != mDriver ) {
mDriver->setGPIOActiveState ( selector, gpioActiveState );
err = kIOReturnSuccess;
}
return (err);
}
IOReturn AppleOnboardAudioUserClient::gpioCheckAvailable ( UInt32 selector, UInt8 * gpioExists ) {
IOReturn err = kIOReturnNotReadable;
if ( NULL != mDriver || NULL != gpioExists ) {
*gpioExists = mDriver->checkGpioAvailable ( selector );
err = kIOReturnSuccess;
}
return (err);
}
IOReturn AppleOnboardAudioUserClient::hwRegisterRead32 ( UInt32 selector, UInt32 * data ) {
IOReturn err = kIOReturnNotReadable;
if ( NULL != mDriver && NULL != data ) {
err = mDriver->readHWReg32 ( selector, data );
}
return (err);
}
IOReturn AppleOnboardAudioUserClient::hwRegisterWrite32 ( UInt32 selector, UInt32 data ) {
IOReturn err = kIOReturnNotReadable;
if ( NULL != mDriver ) {
err = mDriver->writeHWReg32 ( selector, data );
}
return (err);
}
IOReturn AppleOnboardAudioUserClient::codecReadRegister ( UInt32 scalarArg1, void * outStructPtr, IOByteCount * outStructSizePtr ) {
kern_return_t err = kIOReturnNotReadable;
if ( NULL != mDriver && NULL != outStructPtr && NULL != outStructSizePtr ) {
err = mDriver->readCodecReg ( scalarArg1, outStructPtr, outStructSizePtr );
}
return ( err );
}
IOReturn AppleOnboardAudioUserClient::codecWriteRegister ( UInt32 selector, void * data, UInt32 inStructSize ) {
IOReturn err = kIOReturnNotReadable;
if ( NULL != mDriver && NULL != data ) {
err = mDriver->writeCodecReg ( selector, data );
}
return (err);
}
IOReturn AppleOnboardAudioUserClient::readSpeakerID ( UInt32 selector, UInt32 * data ) {
IOReturn err = kIOReturnNotReadable;
if ( NULL != mDriver && NULL != data ) {
err = mDriver->readSpkrID ( selector, data );
}
return (err);
}
IOReturn AppleOnboardAudioUserClient::codecRegisterSize ( UInt32 selector, UInt32 * codecRegSizePtr ) {
IOReturn err = kIOReturnNotReadable;
if ( NULL != mDriver && NULL != codecRegSizePtr ) {
err = mDriver->getCodecRegSize ( selector, codecRegSizePtr );
}
return (err);
}
IOReturn AppleOnboardAudioUserClient::readPRAMVolume ( UInt32 selector, UInt32 * pramDataPtr ) {
IOReturn err = kIOReturnNotReadable;
if ( NULL != mDriver && NULL != pramDataPtr ) {
err = (UInt32)mDriver->getVolumePRAM ( pramDataPtr );
}
return (err);
}
IOReturn AppleOnboardAudioUserClient::readDMAState ( UInt32 selector, UInt32 * dmaStatePtr ) {
IOReturn err = kIOReturnNotReadable;
if ( NULL != mDriver && NULL != dmaStatePtr ) {
err = (UInt32)mDriver->getDmaState ( dmaStatePtr );
}
return err;
}
IOReturn AppleOnboardAudioUserClient::readStreamFormat ( UInt32 selector, IOAudioStreamFormat * outStructPtr, IOByteCount * outStructSizePtr ) {
#pragma unused ( selector )
IOReturn err = kIOReturnNotReadable;
if ( NULL != mDriver && NULL != outStructPtr && NULL != outStructSizePtr ) {
if ( sizeof ( IOAudioStreamFormat ) <= *outStructSizePtr ) {
err = (UInt32)mDriver->getStreamFormat ( outStructPtr );
if ( kIOReturnSuccess == err ) {
*outStructSizePtr = sizeof ( IOAudioStreamFormat );
}
}
}
return err;
}
IOReturn AppleOnboardAudioUserClient::readPowerState ( UInt32 selector, IOAudioDevicePowerState * powerState ) {
IOReturn err = kIOReturnNotReadable;
if ( NULL != mDriver && NULL != powerState ) {
err = mDriver->readPowerState ( selector, powerState );
}
return (err);
}
IOReturn AppleOnboardAudioUserClient::setPowerState ( UInt32 selector, IOAudioDevicePowerState powerState ) {
IOReturn err = kIOReturnNotReadable;
if ( NULL != mDriver ) {
err = mDriver->setPowerState ( selector, powerState );
}
return (err);
}
IOReturn AppleOnboardAudioUserClient::setBiquadCoefficients ( UInt32 selector, void * biquadCoefficients, UInt32 coefficientSize ) {
IOReturn err = kIOReturnNotReadable;
if ( NULL != mDriver && NULL != biquadCoefficients && kMaxBiquadWidth >= coefficientSize ) {
err = mDriver->setBiquadCoefficients ( selector, biquadCoefficients, coefficientSize );
}
return (err);
}
IOReturn AppleOnboardAudioUserClient::getBiquadInfo ( UInt32 scalarArg1, void * outStructPtr, IOByteCount * outStructSizePtr ) {
IOReturn err = kIOReturnNotReadable;
if ( NULL != mDriver && NULL != outStructPtr && NULL != outStructSizePtr ) {
err = mDriver->getBiquadInformation ( scalarArg1, outStructPtr, outStructSizePtr );
}
return (err);
}
IOReturn AppleOnboardAudioUserClient::getProcessingParams ( UInt32 scalarArg1, void * outStructPtr, IOByteCount * outStructSizePtr ) {
IOReturn err = kIOReturnNotReadable;
if ( NULL != mDriver && NULL != outStructPtr && NULL != outStructSizePtr ) {
if ( kMaxProcessingParamSize >= *outStructSizePtr ) {
err = mDriver->getProcessingParameters ( scalarArg1, outStructPtr, outStructSizePtr );
}
}
return (err);
}
IOReturn AppleOnboardAudioUserClient::setProcessingParams ( UInt32 scalarArg1, void * inStructPtr, UInt32 inStructSize ) {
IOReturn err = kIOReturnNotReadable;
if ( NULL != mDriver && NULL != inStructPtr && kMaxProcessingParamSize >= inStructSize ) {
err = mDriver->setProcessingParameters ( scalarArg1, inStructPtr, inStructSize );
}
return (err);
}
IOReturn AppleOnboardAudioUserClient::invokeInternalFunction ( UInt32 functionSelector, void * inData, UInt32 inDataSize ) {
IOReturn err = kIOReturnNotReadable;
if ( NULL != mDriver ) {
err = mDriver->invokeInternalFunction ( functionSelector, inData );
}
return (err);
}
#if 0
enum
{
kgpioReadIndex = 0,
kgpioWriteIndex = 1
};
static IOReturn SetupUserClient( void );
static void TearDownUserClient( void );
static mach_port_t gMasterPort = 0;
static io_object_t gDriverObject = 0;
static io_connect_t gDataPort = 0;
static IOReturn SetupUserClient( void )
{
IOReturn err;
CFDictionaryRef matchingDictionary;
io_iterator_t serviceIter;
err = kIOReturnSuccess;
matchingDictionary = NULL;
serviceIter = NULL;
if( gDataPort )
{
goto exit;
}
err = IOMasterPort( NULL, &gMasterPort );
if( err != kIOReturnSuccess ) goto exit;
err = kIOReturnNotFound;
matchingDictionary = IOServiceNameMatching( "AppleTexasAudio" );
if( !matchingDictionary ) goto exit;
err = IOServiceGetMatchingServices( gMasterPort, matchingDictionary, &serviceIter );
if( err != kIOReturnSuccess ) goto exit;
matchingDictionary = NULL;
err = kIOReturnNotFound;
gDriverObject = IOIteratorNext( serviceIter );
if( !gDriverObject ) goto exit;
err = IOServiceOpen( gDriverObject, mach_task_self(), 0, &gDataPort );
if( err != kIOReturnSuccess ) goto exit;
exit:
if( serviceIter )
{
IOObjectRelease( serviceIter );
}
if( matchingDictionary )
{
CFRelease( matchingDictionary );
}
if( err != kIOReturnSuccess )
{
TearDownUserClient();
}
return( err );
}
static void TearDownUserClient( void )
{
if( gDataPort )
{
IOServiceClose( gDataPort );
gDataPort = 0;
}
if( gDriverObject )
{
IOObjectRelease( gDriverObject );
gDriverObject = NULL;
}
if( gMasterPort )
{
mach_port_deallocate( mach_task_self(), gMasterPort );
gMasterPort = 0;
}
}
#if 0
#pragma mark -
#endif
OSStatus gpioRead( UInt32 selector, UInt8 * gpioState )
{
OSStatus err;
err = SetupUserClient();
if( err != noErr ) goto exit;
err = IOConnectMethodScalarIScalarO( gDataPort, kgpioReadIndex, 1, 1, selector, gpioState );
if( err != noErr ) goto exit;
exit:
return( err );
}
OSStatus gpioWrite( UInt32 selector, UInt8 value )
{
OSStatus err;
err = SetupUserClient();
if( err != noErr ) goto exit;
err = IOConnectMethodScalarIScalarO( gDataPort, kgpioWriteIndex, 2, 0, selector, gpioState );
if( err != noErr ) goto exit;
exit:
return( err );
}
OSStatus gpioGetAddress( UInt32 selector, UInt8 ** gpioAddress )
{
OSStatus err;
err = SetupUserClient();
if( err != noErr ) goto exit;
err = IOConnectMethodScalarIScalarO( gDataPort, kgpiogetAddressIndex, 2, selector, gpioAddress );
if( err != noErr ) goto exit;
exit:
return( err );
}
#endif