AppleDACAAudio.cpp [plain text]
#include "AudioHardwareCommon.h"
#include "AudioHardwareConstants.h"
#include "AudioHardwareUtilities.h"
#include "AudioI2SHardwareConstants.h"
#include "AppleDACAAudio.h"
#include "daca_hw.h"
#include "AppleDBDMAAudioDMAEngine.h"
#include "AudioI2SControl.h"
#define super AppleOnboardAudio
OSDefineMetaClassAndStructors(AppleDACAAudio, AppleOnboardAudio)
#pragma mark +UNIX LIKE FUNCTIONS
bool AppleDACAAudio::init(
OSDictionary *properties)
{
DEBUG_IOLOG("+ AppleDACAAudio::init\n");
if (!super::init(properties))
return false;
DEBUG_IOLOG("- AppleDACAAudio::init\n");
return true;
}
void AppleDACAAudio::free()
{
DEBUG_IOLOG("+ AppleDACAAudio::free\n");
CLEAN_RELEASE(ioBaseAddressMemory); CLEAN_RELEASE(myAudioI2SControl) ;
publishResource (fAppleAudioVideoJackStateKey, NULL);
super::free();
DEBUG_IOLOG("- AppleDACAAudio::free\n");
}
IOService* AppleDACAAudio::probe(IOService *provider, SInt32 *score)
{
DEBUG_IOLOG("+ AppleDACAAudio::probe\n");
super::probe(provider, score);
*score = kIODefaultProbeScore;
sound = provider->childFromPath("sound", gIODTPlane);
if(sound)
{
OSData *tmpData = OSDynamicCast(OSData, sound->getProperty(kModelPropName));
if(tmpData)
{
if(tmpData->isEqualTo(kDacaModelName, sizeof(kDacaModelName) -1) )
{
*score = *score+1;
DEBUG_IOLOG("- AppleDACAAudio::probe\n");
return(this);
}
}
}
DEBUG_IOLOG("- AppleDACAAudio::probe\n");
return (0);
}
bool AppleDACAAudio::initHardware(IOService *provider)
{
bool myreturn = true;
DEBUG_IOLOG("+ AppleDACAAudio::initHardware\n");
super::initHardware(provider);
DEBUG_IOLOG("- AppleDACAAudio::initHardware\n");
return myreturn;
}
void AppleDACAAudio::timerCallback(OSObject *target, IOAudioDevice *device)
{
AppleDACAAudio *daca;
daca = OSDynamicCast(AppleDACAAudio, target);
if (daca) {
daca->checkStatus(false);
}
return;
}
void AppleDACAAudio::checkStatus(bool force)
{
static UInt32 lastStatus = 0L;
UInt32 extdevices;
AudioHardwareDetect *theDetect;
OSArray *AudioDetects;
UInt8 currentStatusRegister = 0;
UInt32 i ;
bool cachedHeadphonesInserted ;
currentStatusRegister = ioConfigurationBaseAddress[kEXTINT_GPIO12];
cachedHeadphonesInserted = fHeadphonesInserted ;
if(mCanPollStatus == false)
{
return;
}
if (lastStatus != currentStatusRegister || force)
{
lastStatus = currentStatusRegister;
AudioDetects = super::getDetectArray();
extdevices = 0;
if(AudioDetects)
{
for(i = 0 ; i < AudioDetects->getCount() ; i++ )
{
theDetect = OSDynamicCast(AudioHardwareDetect, AudioDetects->getObject(i));
if (theDetect)
extdevices |= theDetect->refreshDevices(currentStatusRegister);
else
DEBUG_IOLOG("The detect was null. That's bad.\n") ;
}
if(i==0) DEBUG_IOLOG("AudioDetects->getCount() returned zero\n") ;
super::setCurrentDevices(extdevices);
AdjustControls ();
}
else
{
DEBUG_IOLOG("AppleDACAAudio::checkStatus couldn't get detect array\n");
}
if(fAppleAudioVideoJackStateKey != 0 && cachedHeadphonesInserted != fHeadphonesInserted)
{
publishResource (fAppleAudioVideoJackStateKey, fHeadphonesInserted ? kOSBooleanTrue : kOSBooleanFalse);
}
}
}
#pragma mark +HARDWARE REGISTER MANIPULATION
void AppleDACAAudio::sndHWInitialize(IOService *provider)
{
DEBUG_IOLOG("+ AppleDACAAudio::sndHWInitialize\n");
IOMemoryMap *map;
OSObject *t = 0;
IORegistryEntry *theEntry;
IORegistryEntry *tmpReg;
IORegistryIterator *theIterator;
map = provider->mapDeviceMemoryWithIndex ( AppleDBDMAAudioDMAEngine::kDBDMADeviceIndex );
if ( map ) {
soundConfigSpace = (UInt8*)map->getPhysicalAddress();
if ((((UInt32)soundConfigSpace ^ kI2S0BaseOffset) & 0x0001FFFF) == 0)
{
ioBaseAddress = (void *)((UInt32)soundConfigSpace - kI2S0BaseOffset);
}
else if ((((UInt32)soundConfigSpace ^ kI2S1BaseOffset) & 0x0001FFFF) == 0)
{
ioBaseAddress = (void *)((UInt32)soundConfigSpace - kI2S1BaseOffset);
}
if ( ioBaseAddress ) {
ioBaseAddressMemory = IODeviceMemory::withRange ((IOPhysicalAddress)((UInt8 *)ioBaseAddress), 256);
ioConfigurationBaseAddress = (UInt8*)ioBaseAddressMemory->map()->getVirtualAddress();
}
}
minVolume = kDACA_MINIMUM_HW_VOLUME; maxVolume = kDACA_MAXIMUM_HW_VOLUME;
theEntry = 0;
theIterator = IORegistryIterator::iterateOver(gIODTPlane, kIORegistryIterateRecursively);
if(theIterator)
{
while (!theEntry && (tmpReg = OSDynamicCast (IORegistryEntry, theIterator->getNextObject ())) != 0)
{
if( tmpReg->compareName(OSString::withCString("extint-gpio12")) )
theEntry = tmpReg;
}
theIterator->release();
}
if ( theEntry ) {
t = theEntry->getProperty("video");
if(t)
fAppleAudioVideoJackStateKey = OSSymbol::withCStringNoCopy ("AppleAudioVideoJackState");
else
fAppleAudioVideoJackStateKey = 0;
}
map = provider->mapDeviceMemoryWithIndex(AppleDBDMAAudioDMAEngine::kDBDMADeviceIndex);
if(!map)
{
DEBUG_IOLOG("AppleDACAAudio::sndHWInitialize ERROR: unable to mapDeviceMemoryWithIndex\n");
goto error_exit ;
}
AudioI2SInfo tempInfo;
tempInfo.map = map;
tempInfo.i2sSerialFormat = kSerialFormatSony;
myAudioI2SControl = AudioI2SControl::create(&tempInfo) ;
if(myAudioI2SControl == NULL)
{
DEBUG_IOLOG("AppleDACAAudio::sndHWInitialize ERROR: unable to i2s control object\n");
goto error_exit ;
}
myAudioI2SControl->retain();
dataFormat = ( ( 0 << kNumChannelsInShift ) | kDataIn16 | ( 2 << kNumChannelsOutShift ) | kDataOut16 );
myAudioI2SControl->setSampleParameters(kDACA_FRAME_RATE, 0, &clockSource, &mclkDivisor, &sclkDivisor, kSndIOFormatI2S32x);
myAudioI2SControl->setSerialFormatRegister(clockSource, mclkDivisor, sclkDivisor, kSndIOFormatI2S32x, dataFormat);
setDACASampleRate(kDACA_FRAME_RATE);
if (!findAndAttachI2C(provider))
{
DEBUG_IOLOG("AppleDACAAudio::sndHWInitialize ERROR: unable to find and attach i2c\n");
goto error_exit ;
}
sampleRateReg = (UInt8)kLeftLRSelSR_REG | k1BitDelaySPSelSR_REG | kSRC_48SR_REG ;
analogVolumeReg = kPowerOnDefaultAVOL ;
configurationReg = (UInt8)kInvertRightAmpGCFG | kDACOnGCFG | kSelect5VoltGCFG ;
debug4IOLog("AppleDACAAudio::sndHWInitialize - writing registers: 0x%x, 0x%x, 0x%x\n", sampleRateReg, analogVolumeReg, configurationReg);
if (openI2C())
{
interface->writeI2CBus((UInt8)i2cBusAddrDAC3550A, i2cBusSubAddrSR_REG, &sampleRateReg, sizeof(sampleRateReg));
interface->writeI2CBus((UInt8)i2cBusAddrDAC3550A, i2cBusSubAddrAVOL, (UInt8 *)&analogVolumeReg, sizeof(analogVolumeReg));
interface->writeI2CBus((UInt8)i2cBusAddrDAC3550A, i2cBusSubaddrGCFG, &configurationReg, sizeof(configurationReg));
closeI2C();
}
error_exit:
DEBUG_IOLOG("- AppleDACAAudio::sndHWInitialize\n");
return ;
}
void AppleDACAAudio::sndHWPostDMAEngineInit (IOService *provider) {
AbsoluteTime timerInterval;
mCanPollStatus = true;
checkStatus(true);
nanoseconds_to_absolutetime(NSEC_PER_SEC, &timerInterval);
addTimerEvent(this, &AppleDACAAudio::timerCallback, timerInterval);
if (NULL == outVolRight && NULL != outVolLeft) {
lastRightVol = kDACA_OUT_OF_BOUNDS_HW_VOLUME;
lastLeftVol = outVolLeft->getIntValue ();
}
}
UInt32 AppleDACAAudio::sndHWGetInSenseBits(void)
{
DEBUG_IOLOG("+ AppleDACAAudio::sndHWGetInSenseBits\n");
DEBUG_IOLOG("- AppleDACAAudio::sndHWGetInSenseBits\n");
return 0;
}
UInt32 AppleDACAAudio::sndHWGetRegister(UInt32 regNum)
{
DEBUG_IOLOG("+ AppleDACAAudio::sndHWGetRegister\n");
UInt32 returnValue = 0;
switch (regNum)
{
case i2cBusSubAddrSR_REG:
returnValue = sampleRateReg ;
break;
case i2cBusSubAddrAVOL:
returnValue = analogVolumeReg ;
break;
case i2cBusSubaddrGCFG:
returnValue = configurationReg ;
break;
default:
DEBUG2_IOLOG("AppleDACAAudio::sndHWGetRegister 0x%x unknown subaddress\n", (UInt16)regNum);
break;
}
return returnValue;
}
IOReturn AppleDACAAudio::sndHWSetRegister(UInt32 regNum, UInt32 val)
{
UInt8 value8 ;
UInt16 value16 ;
bool success ;
UInt8 subAddress ;
IOReturn myReturn ;
DEBUG_IOLOG("+ AppleDACAAudio::sndHWSetRegister\n");
value8 = (val & 0x000000FF) ; value16 = (val & 0x0000FFFF) ; success = false ; subAddress = (regNum & 0x000000FF) ; myReturn = kIOReturnSuccess ;
if (openI2C())
{
switch (subAddress)
{
case i2cBusSubAddrSR_REG:
success = interface->writeI2CBus((UInt8)i2cBusAddrDAC3550A, i2cBusSubAddrSR_REG, &value8, sizeof(value8));
DEBUG2_IOLOG("writing status register %02x\n", (UInt16)value8);
if (success)
sampleRateReg = value8;
break;
case i2cBusSubAddrAVOL:
success = interface->writeI2CBus((UInt8)i2cBusAddrDAC3550A, i2cBusSubAddrAVOL, (UInt8*)&value16, sizeof(value16));
DEBUG2_IOLOG("writing analog vol register %04x\n", value16);
if (success)
analogVolumeReg = value16;
break;
case i2cBusSubaddrGCFG:
success = interface->writeI2CBus((UInt8)i2cBusAddrDAC3550A, i2cBusSubaddrGCFG, &value8, sizeof(value8));
debug3IOLog("writing config reg %02x, success = %d\n", (UInt16)value8, success);
if (success)
configurationReg = value8;
break;
default:
DEBUG2_IOLOG("AppleDACAAudio::sndHWSetRegister 0x%x unknown register\n", (UInt16)subAddress);
success = true ;
myReturn = kIOReturnBadArgument ;
break;
}
closeI2C();
}
if(success != true)
{
myReturn = kIOReturnError ;
DEBUG_IOLOG("sndHWSetRegister: something went wrong\n") ;
}
DEBUG_IOLOG("- AppleDACAAudio::sndHWSetRegister\n");
return(myReturn);
}
#pragma mark +HARDWARE IO ACTIVATION
UInt32 AppleDACAAudio::sndHWGetActiveOutputExclusive(void)
{
UInt32 returnVal = 0l;
DEBUG_IOLOG("+ AppleDACAAudio::sndHWGetActiveOutputExclusive\n");
if( fHeadphonesInserted == false )
returnVal = kSndHWOutput1 ;
else
returnVal = kSndHWOutput2 ;
DEBUG_IOLOG("- AppleDACAAudio::sndHWGetActiveOutputExclusive\n");
return 0;
}
IOReturn AppleDACAAudio::sndHWSetActiveOutputExclusive(UInt32 outputPort )
{
IOReturn myReturn;
UInt8 tmpConfigReg;
DEBUG_IOLOG("+ AppleDACAAudio::sndHWSetActiveOutputExclusive\n");
myReturn = kIOReturnBadArgument;
switch( outputPort )
{
case kSndHWOutput1: fHeadphonesInserted = false ;
tmpConfigReg = setBitsGCFGShadowReg(kInvertRightAmpGCFG, kInvertRightAmpGCFG) ;
myReturn = sndHWSetRegister(i2cBusSubaddrGCFG, tmpConfigReg);
if (NULL != driverDMAEngine) {
driverDMAEngine->setRightChanMixed (TRUE);
useMasterVolumeControl = TRUE;
}
break;
case kSndHWOutput2: fHeadphonesInserted = true ;
tmpConfigReg = setBitsGCFGShadowReg(!kInvertRightAmpGCFG, kInvertRightAmpGCFG) ;
myReturn = sndHWSetRegister(i2cBusSubaddrGCFG, tmpConfigReg);
if (NULL != driverDMAEngine) {
driverDMAEngine->setRightChanMixed (FALSE);
useMasterVolumeControl = FALSE;
}
break;
default:
DEBUG_IOLOG("Invalid set output active request\n");
break;
}
DEBUG_IOLOG("- AppleDACAAudio::sndHWSetActiveOutputExclusive\n");
return(myReturn);
}
UInt32 AppleDACAAudio::sndHWGetActiveInputExclusive(void)
{
DEBUG_IOLOG("+ AppleDACAAudio::sndHWGetActiveInputExclusive\n");
DEBUG_IOLOG("- AppleDACAAudio::sndHWGetActiveInputExclusive\n");
return fActiveInput;
}
IOReturn AppleDACAAudio::sndHWSetActiveInputExclusive(UInt32 input )
{
IOReturn myReturn = kIOReturnBadArgument;
UInt8 tmpConfigReg = 0;
DEBUG_IOLOG("+ AppleDACAAudio::sndHWSetActiveInputExclusive\n");
switch (input)
{
case kSndHWInputNone:
tmpConfigReg = setBitsGCFGShadowReg(kNoChangeMask, kAuxOneGCFG | kAuxTwoGCFG) ;
myReturn = sndHWSetRegister(i2cBusSubaddrGCFG, tmpConfigReg);
break;
case kSndHWInput1: tmpConfigReg = setBitsGCFGShadowReg(kAuxOneGCFG, kAuxTwoGCFG) ;
myReturn = sndHWSetRegister(i2cBusSubaddrGCFG, tmpConfigReg);
break;
case kSndHWInput2: tmpConfigReg = setBitsGCFGShadowReg(kAuxTwoGCFG, kAuxOneGCFG) ;
myReturn = sndHWSetRegister(i2cBusSubaddrGCFG, tmpConfigReg);
break;
default:
debugIOLog("Invalid set output active request\n");
break;
}
fActiveInput = input;
DEBUG_IOLOG("- AppleDACAAudio::sndHWSetActiveInputExclusive\n");
return(myReturn);
}
IOReturn AppleDACAAudio::AdjustControls (void) {
IOFixed mindBVol;
IOFixed maxdBVol;
Boolean mustUpdate;
debugIOLog ("+ AdjustControls()\n");
FailIf (NULL == driverDMAEngine, Exit);
mustUpdate = FALSE;
mindBVol = kDACA_MIN_VOLUME;
maxdBVol = kDACA_MAX_VOLUME;
if ((NULL == outVolMaster && TRUE == useMasterVolumeControl) ||
(NULL != outVolMaster && FALSE == useMasterVolumeControl) ||
(NULL != outVolLeft && outVolLeft->getMinValue () != minVolume) ||
(NULL != outVolLeft && outVolLeft->getMaxValue () != maxVolume) ||
(NULL != outVolRight && outVolRight->getMinValue () != minVolume) ||
(NULL != outVolRight && outVolRight->getMaxValue () != maxVolume)) {
mustUpdate = TRUE;
}
if (TRUE == mustUpdate) {
debug5IOLog ("AdjustControls: mindBVol = %d.0x%x, maxdBVol = %d.0x%x\n",
0 != mindBVol & 0x80000000 ? (unsigned int)(( mindBVol >> 16 ) | 0xFFFF0000) : (unsigned int)(mindBVol >> 16), (unsigned int)(mindBVol << 16),
0 != maxdBVol & 0x80000000 ? (unsigned int)(( maxdBVol >> 16 ) | 0xFFFF0000) : (unsigned int)(maxdBVol >> 16), (unsigned int)(maxdBVol << 16) );
driverDMAEngine->pauseAudioEngine ();
driverDMAEngine->beginConfigurationChange ();
if (TRUE == useMasterVolumeControl) {
if (NULL == outVolMaster) {
debugIOLog ("AdjustControls: deleteing descrete channel controls and creating master control\n");
if (NULL != outVolLeft) {
lastLeftVol = outVolLeft->getIntValue ();
driverDMAEngine->removeDefaultAudioControl (outVolLeft);
outVolLeft = NULL;
}
if (NULL != outVolRight) {
lastRightVol = outVolRight->getIntValue ();
driverDMAEngine->removeDefaultAudioControl (outVolRight);
outVolRight = NULL;
}
outVolMaster = IOAudioLevelControl::createVolumeControl((lastLeftVol + lastRightVol) / 2, minVolume, maxVolume, mindBVol, maxdBVol,
kIOAudioControlChannelIDAll,
kIOAudioControlChannelNameAll,
kOutVolMaster,
kIOAudioControlUsageOutput);
if (NULL != outVolMaster) {
driverDMAEngine->addDefaultAudioControl(outVolMaster);
outVolMaster->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)outputControlChangeHandler, this);
outVolMaster->flushValue ();
}
}
} else {
if (NULL == outVolLeft) {
debugIOLog ("AdjustControls: deleteing master control and creating descrete channel controls\n");
if (lastLeftVol > kDACA_MAXIMUM_HW_VOLUME && NULL != outVolMaster) {
lastLeftVol = outVolMaster->getIntValue ();
}
outVolLeft = IOAudioLevelControl::createVolumeControl (lastLeftVol, kDACA_MINIMUM_HW_VOLUME, kDACA_MAXIMUM_HW_VOLUME, mindBVol, maxdBVol,
kIOAudioControlChannelIDDefaultLeft,
kIOAudioControlChannelNameLeft,
kOutVolLeft,
kIOAudioControlUsageOutput);
if (NULL != outVolLeft) {
driverDMAEngine->addDefaultAudioControl (outVolLeft);
outVolLeft->setValueChangeHandler ((IOAudioControl::IntValueChangeHandler)outputControlChangeHandler, this);
}
}
if (NULL == outVolRight) {
if (lastRightVol > kDACA_MAXIMUM_HW_VOLUME && NULL != outVolMaster) {
lastRightVol = outVolMaster->getIntValue ();
}
outVolRight = IOAudioLevelControl::createVolumeControl (lastRightVol, kDACA_MINIMUM_HW_VOLUME, kDACA_MAXIMUM_HW_VOLUME, mindBVol, maxdBVol,
kIOAudioControlChannelIDDefaultRight,
kIOAudioControlChannelNameRight,
kOutVolRight,
kIOAudioControlUsageOutput);
if (NULL != outVolRight) {
driverDMAEngine->addDefaultAudioControl (outVolRight);
outVolRight->setValueChangeHandler ((IOAudioControl::IntValueChangeHandler)outputControlChangeHandler, this);
}
}
if (NULL != outVolMaster) {
driverDMAEngine->removeDefaultAudioControl (outVolMaster);
outVolMaster = NULL;
}
}
if (NULL != outVolMaster) {
outVolMaster->setMinValue (minVolume);
outVolMaster->setMinDB (mindBVol);
outVolMaster->setMaxValue (maxVolume);
outVolMaster->setMaxDB (maxdBVol);
if (outVolMaster->getIntValue () > maxVolume) {
outVolMaster->setValue (maxVolume);
}
outVolMaster->flushValue ();
}
if (NULL != outVolLeft) {
outVolLeft->setMinValue (minVolume);
outVolLeft->setMinDB (mindBVol);
outVolLeft->setMaxValue (maxVolume);
outVolLeft->setMaxDB (maxdBVol);
if (outVolLeft->getIntValue () > maxVolume) {
outVolLeft->setValue (maxVolume);
}
outVolLeft->flushValue ();
}
if (NULL != outVolRight) {
outVolRight->setMinValue (minVolume);
outVolRight->setMinDB (mindBVol);
outVolRight->setMaxValue (maxVolume);
outVolRight->setMaxDB (maxdBVol);
if (outVolRight->getIntValue () > maxVolume) {
outVolRight->setValue (maxVolume);
}
outVolRight->flushValue ();
}
driverDMAEngine->completeConfigurationChange ();
driverDMAEngine->resumeAudioEngine ();
}
Exit:
debugIOLog ("- AdjustControls()\n");
return kIOReturnSuccess;
}
#pragma mark +CONTROL FUNCTIONS
bool AppleDACAAudio::sndHWGetSystemMute(void)
{
DEBUG_IOLOG("+ AppleDACAAudio::sndHWGetSystemMute\n");
DEBUG_IOLOG("- AppleDACAAudio::sndHWGetSystemMute\n");
return gIsMute;
}
IOReturn AppleDACAAudio::sndHWSetSystemMute(bool mutestate)
{
IOReturn retval = kIOReturnSuccess;
UInt16 tmpAnalogVolumeReg;
DEBUG_IOLOG("+ AppleDACAAudio::sndHWSetSystemMute\n");
if (true == mutestate) {
tmpAnalogVolumeReg = setBitsAVOLShadowReg(0x00, kLeftAVOLMask | kRightAVOLMask) ;
retval = sndHWSetRegister(i2cBusSubAddrAVOL, tmpAnalogVolumeReg);
} else {
tmpAnalogVolumeReg = setBitsAVOLShadowReg(((gVolLeft << kLeftAVOLShift) | (gVolRight << kRightAVOLShift)), (kLeftAVOLMask | kRightAVOLMask));
retval = sndHWSetRegister(i2cBusSubAddrAVOL, tmpAnalogVolumeReg);
}
DEBUG_IOLOG("- AppleDACAAudio::sndHWSetSystemMute\n");
return(retval);
}
bool AppleDACAAudio::sndHWSetSystemVolume(UInt32 leftVolume, UInt32 rightVolume)
{
bool retval = false ;
UInt16 tmpAnalogVolumeReg ;
DEBUG3_IOLOG("+ AppleDACAAudio::sndHWSetSystemVolume (left: %ld, right %ld)\n", leftVolume, rightVolume);
tmpAnalogVolumeReg = setBitsAVOLShadowReg(
((leftVolume << kLeftAVOLShift) | (rightVolume << kRightAVOLShift)),
(kLeftAVOLMask | kRightAVOLMask) ) ;
retval = sndHWSetRegister(i2cBusSubAddrAVOL, tmpAnalogVolumeReg);
DEBUG_IOLOG("- AppleDACAAudio::sndHWSetSystemVolume\n");
return (retval==kIOReturnSuccess);
}
IOReturn AppleDACAAudio::sndHWSetSystemVolume(UInt32 value)
{
DEBUG2_IOLOG("+ AppleDACAAudio::sndHWSetSystemVolume (vol: %ld)\n", value);
IOReturn myReturn = kIOReturnError ;
if( true == sndHWSetSystemVolume( value, value ))
{
myReturn = kIOReturnSuccess;
}
DEBUG_IOLOG("- AppleDACAAudio::sndHWSetSystemVolume\n");
return(myReturn);
}
IOReturn AppleDACAAudio::sndHWSetPlayThrough(bool playthroughState)
{
IOReturn myReturn;
UInt8 tmpConfigReg = 0;
DEBUG_IOLOG("+ AppleDACAAudio::sndHWSetPlayThrough\n");
if (playthroughState) { switch (fActiveInput) {
case kSndHWInputNone:
myReturn = kIOReturnSuccess;
break;
case kSndHWInput1: tmpConfigReg = setBitsGCFGShadowReg(kAuxOneGCFG, kNoChangeMask) ;
myReturn = sndHWSetRegister(i2cBusSubaddrGCFG, tmpConfigReg);
break;
case kSndHWInput2: tmpConfigReg = setBitsGCFGShadowReg(kAuxTwoGCFG, kNoChangeMask) ;
myReturn = sndHWSetRegister(i2cBusSubaddrGCFG, tmpConfigReg);
break;
default:
myReturn = kIOReturnError;
break;
}
} else { tmpConfigReg = setBitsGCFGShadowReg(kNoChangeMask, kAuxOneGCFG | kAuxTwoGCFG) ;
myReturn = sndHWSetRegister(i2cBusSubaddrGCFG, tmpConfigReg);
}
gIsPlayThroughActive = playthroughState;
DEBUG_IOLOG("- AppleDACAAudio::sndHWSetPlayThrough\n");
return(myReturn);
}
IOReturn AppleDACAAudio::sndHWSetSystemInputGain(UInt32 leftGain, UInt32 rightGain)
{
DEBUG_IOLOG("+ AppleDACAAudio::sndHWSetSystemInputGain\n");
IOReturn myReturn = kIOReturnSuccess;
DEBUG_IOLOG("- AppleDACAAudio::sndHWSetSystemInputGain\n");
return(myReturn);
}
#pragma mark +INDENTIFICATION
UInt32 AppleDACAAudio::sndHWGetType( void )
{
DEBUG_IOLOG("+ AppleDACAAudio::sndHWGetType\n");
UInt32 returnValue = kSndHWTypeDaca ;
DEBUG_IOLOG("- AppleDACAAudio::sndHWGetType\n");
return returnValue ;
}
UInt32 AppleDACAAudio::sndHWGetManufacturer( void )
{
DEBUG_IOLOG("+ AppleDACAAudio::sndHWGetManufacturer\n");
UInt32 returnValue = kSndHWManfMicronas ;
DEBUG_IOLOG("- AppleDACAAudio::sndHWGetManufacturer\n");
return returnValue ;
}
#pragma mark +DETECT ACTIVATION & DEACTIVATION
void AppleDACAAudio::setDeviceDetectionActive(void)
{
DEBUG_IOLOG("+ AppleDACAAudio::setDeviceDetectionActive\n");
mCanPollStatus = true ;
DEBUG_IOLOG("- AppleDACAAudio::setDeviceDetectionActive\n");
return ;
}
void AppleDACAAudio::setDeviceDetectionInActive(void)
{
DEBUG_IOLOG("+ AppleDACAAudio::setDeviceDetectionInActive\n");
mCanPollStatus = false ;
DEBUG_IOLOG("- AppleDACAAudio::setDeviceDetectionInActive\n");
return ;
}
#pragma mark +POWER MANAGEMENT
IOReturn AppleDACAAudio::sndHWSetPowerState(IOAudioDevicePowerState theState)
{
IOReturn myReturn;
UInt16 tmpAnalogVolReg;
UInt8 tmpConfigReg;
IOService *keyLargo;
UInt32 temp;
DEBUG_IOLOG("+ AppleDACAAudio::sndHWSetPowerState\n");
myReturn = kIOReturnSuccess;
keyLargo = NULL;
keyLargo = IOService::waitForService ( IOService::serviceMatching ( "KeyLargo" ) );
switch(theState)
{
case kIOAudioDeviceSleep : case kIOAudioDeviceIdle : temp = myAudioI2SControl->GetSerialFormatReg();
temp = myAudioI2SControl->GetDataWordSizesReg();
tmpAnalogVolReg = 0x00 ;
tmpConfigReg = 0x0 ;
if (openI2C())
{
interface->writeI2CBus((UInt8)i2cBusAddrDAC3550A, i2cBusSubAddrAVOL, (UInt8 *)&tmpAnalogVolReg, sizeof(tmpAnalogVolReg));
interface->writeI2CBus((UInt8)i2cBusAddrDAC3550A, i2cBusSubaddrGCFG, &tmpConfigReg, sizeof(tmpConfigReg));
closeI2C();
}
if ( NULL != keyLargo ) {
IODelay ( 100 );
keyLargo->callPlatformFunction ( OSSymbol::withCString ( "keyLargo_powerI2S" ), false, (void*)false, (void*)0, 0, 0 );
}
temp = myAudioI2SControl->GetSerialFormatReg();
temp = myAudioI2SControl->GetDataWordSizesReg();
break ;
case kIOAudioDeviceActive : temp = myAudioI2SControl->GetSerialFormatReg();
temp = myAudioI2SControl->GetDataWordSizesReg();
if ( NULL != keyLargo ) {
keyLargo->callPlatformFunction ( OSSymbol::withCString ( "keyLargo_powerI2S" ), false, (void*)true, (void*)0, 0, 0 );
IODelay ( 100 );
}
myAudioI2SControl->setSampleParameters(kDACA_FRAME_RATE, 0, &clockSource, &mclkDivisor, &sclkDivisor, kSndIOFormatI2S32x);
myAudioI2SControl->setSerialFormatRegister(clockSource, mclkDivisor, sclkDivisor, kSndIOFormatI2S32x, dataFormat);
setDACASampleRate(kDACA_FRAME_RATE);
if (openI2C())
{
interface->writeI2CBus((UInt8)i2cBusAddrDAC3550A, i2cBusSubaddrGCFG, &configurationReg, sizeof(configurationReg));
interface->writeI2CBus((UInt8)i2cBusAddrDAC3550A, i2cBusSubAddrSR_REG, &sampleRateReg, sizeof(sampleRateReg));
interface->writeI2CBus((UInt8)i2cBusAddrDAC3550A, i2cBusSubAddrAVOL, (UInt8 *)&analogVolumeReg, sizeof(analogVolumeReg));
closeI2C();
}
temp = myAudioI2SControl->GetSerialFormatReg();
temp = myAudioI2SControl->GetDataWordSizesReg();
break ;
default:
DEBUG_IOLOG("AppleDACAAudio::sndHWSetPowerState unknown power state\n");
myReturn = kIOReturnBadArgument ;
break ;
}
DEBUG_IOLOG("- AppleDACAAudio::sndHWSetPowerState\n");
return(myReturn);
}
UInt32 AppleDACAAudio::sndHWGetConnectedDevices(void)
{
DEBUG_IOLOG("+ AppleDACAAudio::sndHWGetConnectedDevices\n");
UInt32 returnValue = currentDevices;
DEBUG_IOLOG("- AppleDACAAudio::sndHWGetConnectedDevices\n");
return returnValue ;
}
UInt32 AppleDACAAudio::sndHWGetProgOutput(void)
{
DEBUG_IOLOG("+ AppleDACAAudio::sndHWGetProgOutput\n");
DEBUG_IOLOG("- AppleDACAAudio::sndHWGetProgOutput\n");
return 0;
}
IOReturn AppleDACAAudio::sndHWSetProgOutput(UInt32 outputBits)
{
DEBUG_IOLOG("+ AppleDACAAudio::sndHWSetProgOutput\n");
IOReturn myReturn = kIOReturnSuccess;
DEBUG_IOLOG("- AppleDACAAudio::sndHWSetProgOutput\n");
return(myReturn);
}
#pragma mark +PRIVATE ROUTINES FOR ACCESSING I2C
bool AppleDACAAudio::findAndAttachI2C(IOService *provider)
{
DEBUG_IOLOG("+ AppleDACAAudio::findAndAttachI2C\n");
const OSSymbol *i2cDriverName;
IOService *i2cCandidate;
i2cDriverName = OSSymbol::withCStringNoCopy("PPCI2CInterface.i2c-mac-io");
i2cCandidate = waitForService(resourceMatching(i2cDriverName));
interface = (PPCI2CInterface*)i2cCandidate->getProperty(i2cDriverName);
if (interface == NULL) {
DEBUG_IOLOG("- AppleDACAAudio::findAndAttachI2C ERROR: can't find the i2c in the registry\n");
return false;
}
interface->retain();
DEBUG_IOLOG("- AppleDACAAudio::findAndAttachI2C\n");
return true;
}
bool AppleDACAAudio::detachFromI2C(IOService* )
{
DEBUG_IOLOG("+ AppleDACAAudio::detachFromI2C\n");
if (interface)
{
interface->release();
interface = 0;
}
DEBUG_IOLOG("- AppleDACAAudio::detachFromI2C\n");
return (true);
}
UInt32 AppleDACAAudio::getI2CPort(void)
{
UInt32 myPort = 0L;
DEBUG_IOLOG("+ AppleDACAAudio::getI2CPort\n");
if(sound) {
OSData *t ;
t = OSDynamicCast(OSData, sound->getProperty("AAPL,i2c-port-select")) ;
if (t != NULL)
{
myPort = *((UInt32*)t->getBytesNoCopy());
}
else
{
DEBUG_IOLOG( "AppleDACAAudio::getI2CPort ERROR missing property port\n");
myPort = 0L ;
}
}
DEBUG_IOLOG( "- AppleDACAAudio::getI2CPort\n");
return myPort;
}
bool AppleDACAAudio::openI2C(void)
{
DEBUG_IOLOG( "+ AppleDACAAudio::openI2C\n");
bool canOpenI2C = false ;
if (interface != NULL)
{
if(interface->openI2CBus(getI2CPort()) == true)
{
interface->setStandardSubMode();
interface->setPollingMode(false);
canOpenI2C = true ;
}
}
DEBUG_IOLOG( "- AppleDACAAudio::openI2C\n");
return canOpenI2C ;
}
void AppleDACAAudio::closeI2C(void)
{
DEBUG_IOLOG( "+ AppleDACAAudio::closeI2C\n");
interface->closeI2CBus();
DEBUG_IOLOG( "- AppleDACAAudio::closeI2C\n");
}
#pragma mark + GENERAL PURPOSE UTILITY ROUTINES
#define kCommonFrameRate 44100
UInt32 AppleDACAAudio::frameRate(UInt32 index)
{
return (UInt32)kCommonFrameRate;
}
bool AppleDACAAudio::setDACASampleRate(UInt rate)
{
UInt32 dacRate;
dacRate = 44100 == rate ? kSRC_48SR_REG : 0;
return ( sndHWSetRegister ( i2cBusSubAddrSR_REG, setBitsSR_REGShadowReg(dacRate, kSampleRateControlMask ) ) );
}
IORegistryEntry * AppleDACAAudio::FindEntryByProperty (const IORegistryEntry * start, const char * key, const char * value) {
OSIterator *iterator;
IORegistryEntry *theEntry;
IORegistryEntry *tmpReg;
OSData *tmpData;
theEntry = NULL;
iterator = start->getChildIterator (gIODTPlane);
FailIf (NULL == iterator, Exit);
while (NULL == theEntry && (tmpReg = OSDynamicCast (IORegistryEntry, iterator->getNextObject ())) != NULL) {
tmpData = OSDynamicCast (OSData, tmpReg->getProperty (key));
if (NULL != tmpData && tmpData->isEqualTo (value, strlen (value))) {
theEntry = tmpReg;
}
}
Exit:
if (NULL != iterator) {
iterator->release ();
}
return theEntry;
}