/* * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. * * Hardware independent (relatively) code for the Burgundy Controller * * HISTORY * * */ #include "AudioHardwareCommon.h" #include "AudioHardwareConstants.h" #include "AudioHardwareUtilities.h" #include "AudioHardwareDetect.h" #include "AudioHardwareOutput.h" #include "AudioHardwareInput.h" #include "AudioHardwareMux.h" #include "AudioHardwarePower.h" #include "AppleBurgundyAudio.h" #include "burgundy_hw.h" #include "Apple02DBDMAAudioDMAEngine.h" /* * Prototyes for the "very private methods" at the end of this * file. They provide access to the burgundy registers: */ static void Burgundy_writeSoundControlReg( volatile UInt8*, int); static int Burgundy_readCodecSenseLines( volatile UInt8*); static int Burgundy_readCodecReg( volatile UInt8*, int); static void Burgundy_writeCodecReg( volatile UInt8*, int, int); /* ============================================================= * VERY Private Methods used to access to the burgundy registers * ============================================================= */ static void Burgundy_writeCodecReg( volatile UInt8 *ioBaseBurgundy, int regInfo, int value ) { u_int32_t regBits; u_int32_t regValue; u_int32_t i; volatile u_int32_t CodecControlReg; struct _reg { UInt8 unused0; UInt8 size; UInt8 addr; UInt8 offset; } *reg = (struct _reg *)®Info; regBits = (kCodecCtlReg_Write | kCodecCtlReg_Reset) | ((u_int32_t) reg->addr * kCodecCtlReg_Addr_Bit) | ((u_int32_t)(reg->size + reg->offset - 1) * kCodecCtlReg_LastByte_Bit); for ( i=0; i < reg->size; i++ ) { regValue = regBits | ((u_int32_t)(reg->offset + i) * kCodecCtlReg_CurrentByte_Bit) | (value & 0xFF); OSWriteLittleInt32(ioBaseBurgundy, kCodecCtlReg, regValue ); eieio(); debugIOLog (3, "PPCSound(burgundy): CodecWrite = %08x", regValue ); value >>= 8; regBits &= ~kCodecCtlReg_Reset; do { CodecControlReg = OSReadLittleInt32( ioBaseBurgundy, kCodecCtlReg ); eieio(); } while ( CodecControlReg & kCodecCtlReg_Busy ); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // This function is used to read any Burgundy CODEC register. The routine also // updates member variables to indicate the current state of the configuration // pins. To update the configuration pin status, issue this function with any // target register and then access the configuration pin status. Burgundy pipelining // is NOT functional so it is necessary to operate two parallel state machines // to handle the codec control and status transactions when reading a Burgundy // codec register. NOTE: The transaction level mechanism used under MacOS 9 // to retry the register access if the current register access is preempted by // another register access from interrupt level has not been ported to this // member function. Any register access that is preempted by another register // access will result in erroneous data. A blocking mechanism should be implemented // here to prevent this situation. Then this note should be removed... static int Burgundy_readCodecReg( volatile UInt8 *ioBaseBurgundy, int regInfo ) { u_int32_t regBits; u_int32_t regValue = 0; u_int32_t i,j; int value; u_int32_t byteCounter; u_int32_t currentCounter; volatile u_int32_t CodecControlReg; volatile u_int32_t CodecStatusReg; struct _reg { UInt8 unused0; UInt8 size; UInt8 addr; UInt8 offset; } *reg = (struct _reg *)®Info; value = 0; regBits = (kCodecCtlReg_Reset) | ((u_int32_t) reg->addr * kCodecCtlReg_Addr_Bit) | ((u_int32_t)(reg->size + reg->offset - 1) * kCodecCtlReg_LastByte_Bit); CodecStatusReg = OSReadLittleInt32( ioBaseBurgundy, kCodecStatusReg ); eieio(); byteCounter = ((CodecStatusReg & kCodecStatusReg_ByteCounter_Mask) / kCodecStatusReg_ByteCounter_Bit + 1) & 0x03; for ( i=0; i < reg->size; i++ ) { regValue = regBits | ((u_int32_t)(reg->offset + i) * kCodecCtlReg_CurrentByte_Bit); OSWriteLittleInt32(ioBaseBurgundy, kCodecCtlReg, regValue ); eieio(); regBits &= ~kCodecCtlReg_Reset; do { CodecControlReg = OSReadLittleInt32( ioBaseBurgundy, kCodecCtlReg ); eieio(); } while ( CodecControlReg & kCodecCtlReg_Busy ); j=0; do { CodecStatusReg = OSReadLittleInt32( ioBaseBurgundy, kCodecStatusReg ); eieio(); currentCounter = ((CodecStatusReg & kCodecStatusReg_ByteCounter_Mask) / kCodecStatusReg_ByteCounter_Bit) & 0x03; } while ( (byteCounter != currentCounter) && (j++ < 1000)); byteCounter++; IODelay(10); CodecStatusReg = OSReadLittleInt32( ioBaseBurgundy, kCodecStatusReg ); value |= ((CodecStatusReg & kCodecStatusReg_Data_Mask) / kCodecStatusReg_Data_Bit) << 8*i; } // debugIOLog (3, "PPCSound(burgundy): CodecRead = %08x %08x", regValue, value ); return value; } static int Burgundy_readCodecSenseLines( volatile UInt8 *ioBaseBurgundy ) { return ((OSReadLittleInt32( ioBaseBurgundy, kCodecStatusReg ) / kCodecStatusReg_Sense_Bit) & kCodecStatusReg_Sense_Mask); } static void Burgundy_writeSoundControlReg( volatile UInt8 *ioBaseBurgundy, int value ) { debugIOLog (3, "PPCSound(burgundy): SoundControlReg = %08x", value); OSWriteLittleInt32( ioBaseBurgundy, kSoundCtlReg, value ); eieio(); } #define super Apple02Audio OSDefineMetaClassAndStructors( AppleBurgundyAudio, Apple02Audio ) /* ============== * Public Methods * ============== */ bool AppleBurgundyAudio::init(OSDictionary * properties) { debugIOLog (3, "+ AppleBurgundyAudio::init"); if (!super::init(properties)) return false; mVolLeft = 0; mVolRight = 0; mIsMute = false; mLogicalInput = 0; mVolumeMuteIsActive = false; mMuxMix = 0; debugIOLog (3, "- AppleBurgundyAudio::init"); return true; } void AppleBurgundyAudio::free() { debugIOLog (3, "+ AppleBurgundyAudio::free"); super::free(); debugIOLog (3, "- AppleBurgundyAudio::free"); } IOService* AppleBurgundyAudio::probe(IOService* provider, SInt32* score) { IORegistryEntry *sound = 0; IORegistryEntry *perch = 0; IOService *result = 0; // We CAN fail the type check: super::probe(provider, score); *score = kIODefaultProbeScore; // we may be on a Beige G3 perch = IORegistryEntry::fromPath("/perch", gIODTPlane); if(perch) { // there is a perch we are on a beige G3 OSData *s = NULL; s = OSDynamicCast(OSData, perch->getProperty("compatible")); if (s) { if(s->isEqualTo("burgundy", sizeof("burgundy")-1) || (s->isEqualTo("DVD-Video and Audio/Video", sizeof("DVD-Video and Audio/Video")-1)) || (s->isEqualTo("bordeaux", sizeof("bordeaux")-1))) { *score = *score+2; result = this; goto BAIL; } } } // we are on a new world : the registry is assumed to be fixed sound = provider->childFromPath("sound", gIODTPlane); if(sound) { OSData *tmpData; tmpData = OSDynamicCast(OSData, sound->getProperty(kModelPropName)); if(tmpData) { if(tmpData->isEqualTo(kBurgundyModelName, sizeof(kBurgundyModelName) -1) ) { *score = *score+1; result = this; goto BAIL; } } } BAIL: debugIOLog (3, "- AppleBurgundyAudio::probe"); return (result); } bool AppleBurgundyAudio::initHardware(IOService* provider) { bool myreturn = true; debugIOLog (3, "+ AppleBurgundyAudio::initHardware"); super::initHardware(provider); // this code moved to sndHWPostThreadedInit () for [3284411] /* gCanPollSatus = true; checkStatus(true); // flushAudioControls(); nanoseconds_to_absolutetime(NSEC_PER_SEC, &timerInterval); addTimerEvent(this, &AppleBurgundyAudio::timerCallback, timerInterval); // aml 6.17.02, burgundy internal mic is mono mInternalMicDualMonoMode = e_Mode_CopyRightToLeft; duringInitialization = false; */ debugIOLog (3, "- AppleBurgundyAudio::initHardware"); return myreturn; } void AppleBurgundyAudio::setDeviceDetectionActive(){ gCanPollSatus = true; } void AppleBurgundyAudio::setDeviceDetectionInActive(){ gCanPollSatus = false; } void AppleBurgundyAudio::timerCallback(OSObject *target, IOAudioDevice *device) { AppleBurgundyAudio *burgundy; burgundy = OSDynamicCast(AppleBurgundyAudio, target); if (burgundy) burgundy->checkStatus(false); } // -------------------------------------------------------------------------- // Method: checkStatusRegister // // Purpose: // if the argument is true mutes the internal speaker, otherwise // it "unmutes" it. void AppleBurgundyAudio::checkStatus(bool force) { UInt32 tempInSense, i; AudioHardwareDetect * theDetect; UInt32 mextdev; UInt32 numDetects; if(false == gCanPollSatus) return; mextdev = 0; tempInSense = sndHWGetInSenseBits(); if( (curInsense != tempInSense) || force) { curInsense = tempInSense; AudioDetects = super::getDetectArray(); if(AudioDetects) { numDetects = AudioDetects->getCount(); for(i = 0; i < numDetects; i++) { theDetect = OSDynamicCast(AudioHardwareDetect, AudioDetects->getObject(i)); if ( theDetect ) { mextdev |= theDetect->refreshDevices(curInsense); } } super::setCurrentDevices(mextdev); // Opportunity to omit Balance controls if on the internal mono speaker... [3042660] begin { useMasterVolumeControl = FALSE; if (NULL != driverDMAEngine) { if ( layoutYosemite == mLayoutID ) { // The master control should be used when headphones are NOT present. if ( kSndHWCPUHeadphone != ( mextdev & kSndHWCPUHeadphone ) ) { useMasterVolumeControl = TRUE; } } } debugIOLog (3, "... useMasterVolumeControl %d", useMasterVolumeControl ); AdjustControls (); // rbm 30 Sept 2002 [3042660] } end } } } #pragma mark -- sndHW METHODS -- // sndHWXXXXX functions void AppleBurgundyAudio::sndHWInitialize(IOService *provider){ IOMemoryMap *map; UInt32 idx, tmpReg; debugIOLog (3, "+ AppleBurgundyAudio::sndHWInitialize"); ourProvider = provider; map = provider->mapDeviceMemoryWithIndex(Apple02DBDMAAudioDMAEngine::kDBDMADeviceIndex); ioBaseBurgundy = (UInt8 *)map->getVirtualAddress(); if(!ioBaseBurgundy) debugIOLog (3, "We have no mermory map !!!"); curInsense = 0xFFFF; mLayoutID = GetDeviceID (); minVolume = kBURGUNDY_MINIMUM_HW_VOLUME; maxVolume = kBURGUNDY_MAXIMUM_HW_VOLUME; // update local variables for the settling time for( idx = kBurgundyPhysOutputPort13-kBurgundyPhysOutputPort13; idx <= kBurgundyPhysOutputPort17-kBurgundyPhysOutputPort13; idx++ ){ localSettlingTime[idx] = 0; //this is an array of 5 stuff } // set the IO part sub frame 0 soundControlRegister = ( kSoundCtlReg_InSubFrame0 | \ kSoundCtlReg_OutSubFrame0 | \ kSoundCtlReg_Rate_44100 ); Burgundy_writeSoundControlReg(ioBaseBurgundy, soundControlRegister); //Verify we are on a Burgundy hardware by getting the type // Enable the programmable output // tmpReg = kOutputCtl0Reg_OutCtl0_High | kOutputCtl0Reg_OutCtl1_High; tmpReg = kOutputCtl0Reg_OutCtl1_High; Burgundy_writeCodecReg( ioBaseBurgundy, kOutputCtl0Reg,tmpReg); // tmpReg = kOutputCtl2Reg_OutCtl2_High | kOutputCtl2Reg_OutCtl3_High| kOutputCtl2Reg_OutCtl4_High; // Burgundy_writeCodecReg( ioBaseBurgundy, kOutputCtl2Reg,tmpReg); // Muxes configuration : Mux 0 has port 1, Mux 1 has port 3, Mux 2 has port 5 tmpReg =kBurgundyAMux_0SelPort_1; Burgundy_writeCodecReg( ioBaseBurgundy, kMux01Reg , tmpReg); // select input 6 for test on Yosemite tmpReg = kBurgundyAMux_2SelPort_5; Burgundy_writeCodecReg( ioBaseBurgundy, kMux2Reg , kMux2Reg_Mux2L_SelectPort6L|kMux2Reg_Mux2R_SelectPort6R); // configure the mixers : mixer0 has nothing, // mixer 1 has the input builtin signal, // mixer2 connect digital stream A Burgundy_writeCodecReg( ioBaseBurgundy, kMX0Reg, 0); mMuxMix = kBurgundyW_2_n; Burgundy_writeCodecReg( ioBaseBurgundy, kMX1Reg,kBurgundyW_2_n); // this for input selection Burgundy_writeCodecReg( ioBaseBurgundy, kMX2Reg, kBurgundyW_A_n); Burgundy_writeCodecReg( ioBaseBurgundy, kMX3Reg, 0); // apply the default gain 0xDF to mixer normalization Burgundy_writeCodecReg( ioBaseBurgundy, kMXEQ0LReg, kMXEQ_Default_Gain ); Burgundy_writeCodecReg( ioBaseBurgundy, kMXEQ0RReg, kMXEQ_Default_Gain ); Burgundy_writeCodecReg( ioBaseBurgundy, kMXEQ1LReg, kMXEQ_Default_Gain ); Burgundy_writeCodecReg( ioBaseBurgundy, kMXEQ1RReg, kMXEQ_Default_Gain ); Burgundy_writeCodecReg( ioBaseBurgundy, kMXEQ2LReg, kMXEQ_Default_Gain ); Burgundy_writeCodecReg( ioBaseBurgundy, kMXEQ2RReg, kMXEQ_Default_Gain ); Burgundy_writeCodecReg( ioBaseBurgundy, kMXEQ3LReg, kMXEQ_Default_Gain ); Burgundy_writeCodecReg( ioBaseBurgundy, kMXEQ3RReg, kMXEQ_Default_Gain ); // configure the ouput stream selection // OS_O listens to mixer 2, OS_1 listens to Mixer 2 ==> this goes to output // OS_E listen to mixer 1 this is the input Burgundy_writeCodecReg( ioBaseBurgundy, kOSReg, kBurgundyOS_0_MXO_2| kBurgundyOS_1_MXO_2 | kBurgundyOS_E_MXO_1); // set the amplification OS/AP Burgundy_writeCodecReg( ioBaseBurgundy, kGAP0LReg , 0xFF); Burgundy_writeCodecReg( ioBaseBurgundy, kGAP0RReg , 0xFF); Burgundy_writeCodecReg( ioBaseBurgundy, kGAP1RReg , 0xFF); Burgundy_writeCodecReg( ioBaseBurgundy, kGAP1LReg , 0xFF); Burgundy_writeCodecReg( ioBaseBurgundy, kGAP2LReg , 0xFF); Burgundy_writeCodecReg( ioBaseBurgundy, kGAP2RReg , 0xFF); Burgundy_writeCodecReg( ioBaseBurgundy, kGAP3LReg , 0xFF); Burgundy_writeCodecReg( ioBaseBurgundy, kGAP3RReg , 0xFF); // Mute everything Burgundy_writeCodecReg(ioBaseBurgundy, kOutputMuteReg, 0x00); // prepare the output amplification Burgundy_writeCodecReg( ioBaseBurgundy, kOutputLvlPort14Reg, 0); Burgundy_writeCodecReg( ioBaseBurgundy, kOutputLvlPort15Reg, 0); Burgundy_writeCodecReg( ioBaseBurgundy, kOutputLvlPort16Reg, 0); Burgundy_writeCodecReg( ioBaseBurgundy, kOutputLvlPort17Reg, 0); // set up the gains : // Unity to gain and Pain 0 Burgundy_writeCodecReg( ioBaseBurgundy, kGAS0LReg,0xDF); Burgundy_writeCodecReg( ioBaseBurgundy, kPAS0LReg,0); Burgundy_writeCodecReg( ioBaseBurgundy, kGAS0RReg,0xDF); Burgundy_writeCodecReg( ioBaseBurgundy, kPAS0RReg,0); Burgundy_writeCodecReg( ioBaseBurgundy, kGAS1LReg,0xDF); Burgundy_writeCodecReg( ioBaseBurgundy, kPAS1LReg,0); Burgundy_writeCodecReg( ioBaseBurgundy, kGAS1RReg,0xDF); Burgundy_writeCodecReg( ioBaseBurgundy, kPAS1RReg,0); Burgundy_writeCodecReg( ioBaseBurgundy, kGAS2LReg,0xDF); Burgundy_writeCodecReg( ioBaseBurgundy, kPAS2LReg,0); Burgundy_writeCodecReg( ioBaseBurgundy, kGAS2RReg,0xDF); Burgundy_writeCodecReg( ioBaseBurgundy, kPAS2RReg,0); // Set up modem to unity Burgundy_writeCodecReg( ioBaseBurgundy, kGAS3LReg,0xDF); Burgundy_writeCodecReg( ioBaseBurgundy, kGAS3RReg,0xDF); // Set up PCMCIA to unity Burgundy_writeCodecReg( ioBaseBurgundy, kGAS4LReg,0xDF); Burgundy_writeCodecReg( ioBaseBurgundy, kGAS4RReg,0xDF); // Default gain for all digital input Burgundy_writeCodecReg( ioBaseBurgundy, kGASALReg, kGAS_Default_Gain ); Burgundy_writeCodecReg( ioBaseBurgundy, kGASARReg, kGAS_Default_Gain ); Burgundy_writeCodecReg( ioBaseBurgundy, kGASBLReg, kGAS_Default_Gain ); Burgundy_writeCodecReg( ioBaseBurgundy, kGASBRReg, kGAS_Default_Gain ); Burgundy_writeCodecReg( ioBaseBurgundy, kGASCLReg, kGAS_Default_Gain ); Burgundy_writeCodecReg( ioBaseBurgundy, kGASCRReg, kGAS_Default_Gain ); Burgundy_writeCodecReg( ioBaseBurgundy, kGASDLReg, kGAS_Default_Gain ); Burgundy_writeCodecReg( ioBaseBurgundy, kGASDRReg, kGAS_Default_Gain ); Burgundy_writeCodecReg( ioBaseBurgundy, kGASELReg, kGAS_Default_Gain ); Burgundy_writeCodecReg( ioBaseBurgundy, kGASERReg, kGAS_Default_Gain ); Burgundy_writeCodecReg( ioBaseBurgundy, kGASFLReg, kGAS_Default_Gain ); Burgundy_writeCodecReg( ioBaseBurgundy, kGASFRReg, kGAS_Default_Gain ); Burgundy_writeCodecReg( ioBaseBurgundy, kGASGLReg, kGAS_Default_Gain ); Burgundy_writeCodecReg( ioBaseBurgundy, kGASGRReg, kGAS_Default_Gain ); Burgundy_writeCodecReg( ioBaseBurgundy, kGASHLReg, kGAS_Default_Gain ); Burgundy_writeCodecReg( ioBaseBurgundy, kGASHRReg, kGAS_Default_Gain ); // set analog gain on input to 0 Burgundy_writeCodecReg( ioBaseBurgundy, kVGA0Reg, 0); Burgundy_writeCodecReg( ioBaseBurgundy, kVGA1Reg, 0); Burgundy_writeCodecReg( ioBaseBurgundy, kVGA2Reg, 0); Burgundy_writeCodecReg( ioBaseBurgundy, kVGA3Reg, 0); // enable digital output driver OS_E on subframe 0 Burgundy_writeCodecReg( ioBaseBurgundy, kSDInReg, 0 ); Burgundy_writeCodecReg( ioBaseBurgundy, kSDInReg2, kBurgundyOS_EOutputEnable ); debugIOLog (3, "- AppleBurgundyAudio::sndHWInitialize"); } void AppleBurgundyAudio::sndHWPostDMAEngineInit (IOService *provider) { if (NULL != driverDMAEngine) driverDMAEngine->setSampleLatencies (kBurgundySampleLatency, kBurgundySampleLatency); } // This method handles everything after the initHW thread is done, keeping the // same sequence of code as before the thread was introduced. [3284411] void AppleBurgundyAudio::sndHWPostThreadedInit (IOService *provider) { AbsoluteTime timerInterval; gCanPollSatus = true; checkStatus(true); nanoseconds_to_absolutetime(NSEC_PER_SEC, &timerInterval); addTimerEvent(this, &AppleBurgundyAudio::timerCallback, timerInterval); mInternalMicDualMonoMode = e_Mode_CopyRightToLeft; duringInitialization = false; } UInt32 AppleBurgundyAudio::sndHWGetCurrentSampleFrame (void) { return OSReadLittleInt32 (ioBaseBurgundy, 0x50); } void AppleBurgundyAudio::sndHWSetCurrentSampleFrame (UInt32 value) { OSWriteLittleInt32 (ioBaseBurgundy, 0x50, value); } UInt32 AppleBurgundyAudio::sndHWGetInSenseBits(){ UInt32 status, inSense; inSense = 0; // we need to add the parrallel input part status = Burgundy_readCodecSenseLines(ioBaseBurgundy) & kBurgundyInSenseMask; if(status & kBurgundyInSense0) inSense |= kBurgundyInSense3; if(status & kBurgundyInSense1) inSense |= kBurgundyInSense2; if(status & kBurgundyInSense2) inSense |= kBurgundyInSense1; if(status & kBurgundyInSense3) inSense |= kBurgundyInSense0; return(inSense); } UInt32 AppleBurgundyAudio::sndHWGetRegister(UInt32 regNum){ return(CodecControlRegister[regNum]); } IOReturn AppleBurgundyAudio::sndHWSetRegister(UInt32 regNum, UInt32 value){ UInt32 result = 0; return(result); } UInt32 AppleBurgundyAudio::sndHWGetConnectedDevices(void){ return(super::getCurrentDevices()); } /************************** Manipulation of input and outputs ***********************/ /********(These functions are enough to implement the simple UI policy)**************/ UInt32 AppleBurgundyAudio::sndHWGetActiveOutputExclusive(void){ UInt32 result = 0; return(result); } IOReturn AppleBurgundyAudio::sndHWSetActiveOutputExclusive (UInt32 outputPort) { IOReturn result= kIOReturnSuccess; UInt32 physicalPort; // UInt32 tempOutputReg; UInt32 logicalOutputPort; logicalOutputPort = outputPort; if (logicalOutputPort > kSndHWOutput5) return (kIOReturnError); physicalPort = GetPhysicalOutputPort (logicalOutputPort); // Changes here are to fix 3461225 // tempOutputReg = kBurgundyMuteAll; mModemActive = FALSE; mInternalSpeakerActive = FALSE; mExternalSpeakerActive = FALSE; mHeadphonesActive = FALSE; mMonoSpeakerActive = FALSE; debugIOLog (3, "sndHWSetActiveOutputExclusive switching to port %d", outputPort); switch (physicalPort) { case kBurgundyPhysOutputPortNone: debugIOLog (3, " ++ Writing Port None"); break; case kBurgundyPhysOutputPort13: debugIOLog (3, " ++ Writing Port 13"); mModemActive = TRUE; // tempOutputReg |= ( kBurgundyMuteOffState << kBurgundyPort13MonoMute); break; case kBurgundyPhysOutputPort14: debugIOLog (3, " ++ Writing Port 14"); mInternalSpeakerActive = TRUE; // tempOutputReg |= (( kBurgundyMuteOffState << kBurgundyPort14LMute) | ( kBurgundyMuteOffState << kBurgundyPort14RMute)); break; case kBurgundyPhysOutputPort15: debugIOLog (3, " ++ Writing Port 15"); mExternalSpeakerActive = TRUE; // tempOutputReg |= (( kBurgundyMuteOffState << kBurgundyPort15LMute) | ( kBurgundyMuteOffState << kBurgundyPort15RMute)); break; case kBurgundyPhysOutputPort16: debugIOLog (3, " ++ Writing Port 16"); mHeadphonesActive = TRUE; // tempOutputReg |= (( kBurgundyMuteOffState << kBurgundyPort16LMute) | ( kBurgundyMuteOffState << kBurgundyPort16RMute)); break; case kBurgundyPhysOutputPort17: debugIOLog (3, " ++ Writing Port 17"); mMonoSpeakerActive = TRUE; // tempOutputReg |= ( kBurgundyMuteOffState << kBurgundyPort17MonoMute); break; } // Burgundy_writeCodecReg (ioBaseBurgundy, kOutputMuteReg, tempOutputReg); sndHWSetSystemMute (mIsMute | mVolumeMuteIsActive); // end 3461225 changes return (result); } UInt32 AppleBurgundyAudio::sndHWGetActiveInputExclusive(void){ UInt32 result = mLogicalInput; return(result); } IOReturn AppleBurgundyAudio::sndHWSetActiveInputExclusive(UInt32 input ){ UInt32 physicalInput , curPhysicalInput, tmpReg; UInt8 muxToBe, curMux; debugIOLog (3, " + AppleBurgundyAudio::sndHWSetActiveInputExclusive : %lu", input); IOReturn result= kIOReturnSuccess; tmpReg = 0; if(mLogicalInput != input) { physicalInput = GetPhysicalInputPort(input ); curPhysicalInput = GetPhysicalInputPort( mLogicalInput ); curMux = GetInputMux(curPhysicalInput); muxToBe = GetInputMux(physicalInput); // first we disconnect the first input from the mixer 1; // - get the mux of the input // - putting the input analog gain to 0 // - putting the digital gain to 0dB // - disconnecting the input from the mixer one if( 0!= curPhysicalInput) { switch( curMux ) { case kBurgundyMux0: Burgundy_writeCodecReg( ioBaseBurgundy, kGAS0LReg,0); Burgundy_writeCodecReg( ioBaseBurgundy, kPAS0LReg,0); Burgundy_writeCodecReg( ioBaseBurgundy, kGAS0RReg,0); Burgundy_writeCodecReg( ioBaseBurgundy, kPAS0RReg,0); Burgundy_writeCodecReg( ioBaseBurgundy, kVGA0Reg, 0); Burgundy_writeCodecReg( ioBaseBurgundy, kMX1Reg, 0); break; case kBurgundyMux1: Burgundy_writeCodecReg( ioBaseBurgundy, kGAS1LReg,0); Burgundy_writeCodecReg( ioBaseBurgundy, kPAS1LReg,0); Burgundy_writeCodecReg( ioBaseBurgundy, kGAS1RReg,0); Burgundy_writeCodecReg( ioBaseBurgundy, kPAS1RReg,0); Burgundy_writeCodecReg( ioBaseBurgundy, kVGA1Reg, 0); Burgundy_writeCodecReg( ioBaseBurgundy, kMX1Reg,0); break; // fall through case kBurgundyMux2: Burgundy_writeCodecReg( ioBaseBurgundy, kGAS2LReg,0); Burgundy_writeCodecReg( ioBaseBurgundy, kPAS2LReg,0); Burgundy_writeCodecReg( ioBaseBurgundy, kGAS2RReg,0); Burgundy_writeCodecReg( ioBaseBurgundy, kPAS2RReg,0); Burgundy_writeCodecReg( ioBaseBurgundy, kVGA2Reg, 0); Burgundy_writeCodecReg( ioBaseBurgundy, kMX1Reg, 0); break; // fall through default: break; } } // select the mux // reactivate the digital gain : // put the input to mixer 1 if( physicalInput != kBurgundyPhysInputPortNone ) { switch( muxToBe ) { case kBurgundyMux0: Burgundy_writeCodecReg( ioBaseBurgundy, kGAS0LReg,0xDF); Burgundy_writeCodecReg( ioBaseBurgundy, kPAS0LReg,0); Burgundy_writeCodecReg( ioBaseBurgundy, kGAS0RReg,0xDF); Burgundy_writeCodecReg( ioBaseBurgundy, kPAS0RReg,0); // select the mux switch(physicalInput) { case kBurgundyPhysInputPort1: tmpReg =kBurgundyAMux_0SelPort_1; break; case kBurgundyPhysInputPort2: tmpReg =kBurgundyAMux_0SelPort_2; break; case kBurgundyPhysInputPort3: tmpReg =kBurgundyAMux_0SelPort_3; break; } Burgundy_writeCodecReg( ioBaseBurgundy, kMux01Reg , tmpReg); // connect the mux tp the mixer mMuxMix = kBurgundyW_0_n; Burgundy_writeCodecReg( ioBaseBurgundy, kMX1Reg,mMuxMix); break; case kBurgundyMux1: Burgundy_writeCodecReg( ioBaseBurgundy, kGAS1LReg,0xDF); Burgundy_writeCodecReg( ioBaseBurgundy, kPAS1LReg,0); Burgundy_writeCodecReg( ioBaseBurgundy, kGAS1RReg,0xDF); Burgundy_writeCodecReg( ioBaseBurgundy, kPAS1RReg,0); switch(physicalInput) { case kBurgundyPhysInputPort4: tmpReg = kBurgundyAMux_1SelPort_4; break; case kBurgundyPhysInputPort5: tmpReg = kBurgundyAMux_1SelPort_5; break; } Burgundy_writeCodecReg( ioBaseBurgundy, kMux01Reg , tmpReg); mMuxMix = kBurgundyW_1_n; Burgundy_writeCodecReg( ioBaseBurgundy, kMX1Reg,mMuxMix); break; case kBurgundyMux2: Burgundy_writeCodecReg( ioBaseBurgundy, kGAS2LReg,0xDF); Burgundy_writeCodecReg( ioBaseBurgundy, kPAS2LReg,0); Burgundy_writeCodecReg( ioBaseBurgundy, kGAS2RReg,0xDF); Burgundy_writeCodecReg( ioBaseBurgundy, kPAS2RReg,0); switch(physicalInput) { case kBurgundyPhysInputPort6: tmpReg = kBurgundyAMux_2SelPort_6; break; case kBurgundyPhysInputPort7: tmpReg = kBurgundyAMux_2SelPort_7; break; } Burgundy_writeCodecReg( ioBaseBurgundy, kMux2Reg , tmpReg); mMuxMix = kBurgundyW_2_n; Burgundy_writeCodecReg( ioBaseBurgundy, kMX1Reg,mMuxMix); break; default: break; } } mLogicalInput = input; // keep track of our new current active input for this system } debugIOLog (3, " - AppleBurgundyAudio::sndHWSetActiveInputExclusive"); return(result); } // -------------------------------------------------------------------------- // You either have only a master volume control, or you have both volume controls. IOReturn AppleBurgundyAudio::AdjustControls (void) { IOFixed mindBVol; IOFixed maxdBVol; Boolean mustUpdate; debugIOLog (3, "+ AdjustControls()"); FailIf (NULL == driverDMAEngine, Exit); mustUpdate = FALSE; mindBVol = kBURGUNDY_MIN_VOLUME; maxdBVol = kBURGUNDY_MAX_VOLUME; // Must update if any of the following conditions exist: // 1. No master volume control exists AND the master volume is the target // 2. The master volume control exists AND the master volume is not the target // 3. the minimum or maximum dB volume setting for the left volume control changes // 4. the minimum or maximum dB volume setting for the right volume control changes 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) { debugIOLog (3, "AdjustControls: mindBVol = %d.0x%x, maxdBVol = %d.0x%x", (unsigned int)( 0 != mindBVol & 0x80000000 ? ( mindBVol >> 16 ) | 0xFFFF0000 : mindBVol >> 16 ), (unsigned int)( mindBVol << 16 ), (unsigned int)( 0 != maxdBVol & 0x80000000 ? ( maxdBVol >> 16 ) | 0xFFFF0000 : maxdBVol >> 16 ), (unsigned int)( maxdBVol << 16 ) ); driverDMAEngine->pauseAudioEngine (); driverDMAEngine->beginConfigurationChange (); if (TRUE == useMasterVolumeControl) { // We have only the master volume control (possibly not created yet) and have to remove the other volume controls (possibly don't exist) if (NULL == outVolMaster) { debugIOLog (3, "AdjustControls: deleteing descrete channel controls and creating master control"); // remove the existing left and right volume controls if (NULL != outVolLeft) { lastLeftVol = outVolLeft->getIntValue (); driverDMAEngine->removeDefaultAudioControl (outVolLeft); outVolLeft = NULL; } if (NULL != outVolRight) { lastRightVol = outVolRight->getIntValue (); driverDMAEngine->removeDefaultAudioControl (outVolRight); outVolRight = NULL; } // Create the master control 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 { // or we have both controls (possibly not created yet) and we have to remove the master volume control (possibly doesn't exist) if (NULL == outVolLeft) { debugIOLog (3, "AdjustControls: deleteing master control and creating descrete channel controls"); // Have to create the control again... if (lastLeftVol > kBURGUNDY_MAXIMUM_HW_VOLUME && NULL != outVolMaster) { lastLeftVol = outVolMaster->getIntValue (); } outVolLeft = IOAudioLevelControl::createVolumeControl (lastLeftVol, kBURGUNDY_MINIMUM_HW_VOLUME, kBURGUNDY_MAXIMUM_HW_VOLUME, mindBVol, maxdBVol, kIOAudioControlChannelIDDefaultLeft, kIOAudioControlChannelNameLeft, kOutVolLeft, kIOAudioControlUsageOutput); if (NULL != outVolLeft) { driverDMAEngine->addDefaultAudioControl (outVolLeft); outVolLeft->setValueChangeHandler ((IOAudioControl::IntValueChangeHandler)outputControlChangeHandler, this); } } if (NULL == outVolRight) { // Have to create the control again... if (lastRightVol > kBURGUNDY_MAXIMUM_HW_VOLUME && NULL != outVolMaster) { lastRightVol = outVolMaster->getIntValue (); } outVolRight = IOAudioLevelControl::createVolumeControl (lastRightVol, kBURGUNDY_MINIMUM_HW_VOLUME, kBURGUNDY_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 (3, "- AdjustControls()"); return kIOReturnSuccess; } UInt32 AppleBurgundyAudio::sndHWGetProgOutput(){ UInt32 result = 0, outputConfigPins; outputConfigPins = 0; // just to quiet the warning in the compiler // outputConfigPins = Burgundy_readCodecReg( ioBaseBurgundy, kOutputCtl0Reg); result |= ( outputConfigPins & kBurgundyOut_Ctrl_0State ) ? kSndHWProgOutput0 : 0; result |= ( outputConfigPins & kBurgundyOut_Ctrl_1State ) ? kSndHWProgOutput1 : 0; // outputConfigPins = Burgundy_readCodecReg( ioBaseBurgundy, kOutputCtl2Reg); result |= ( outputConfigPins & kBurgundyOut_Ctrl_2State ) ? kSndHWProgOutput2 : 0; result |= ( outputConfigPins & kBurgundyOut_Ctrl_3State ) ? kSndHWProgOutput3 : 0; result |= ( outputConfigPins & kBurgundyOut_Ctrl_4State ) ? kSndHWProgOutput4 : 0; return(result); } IOReturn AppleBurgundyAudio::sndHWSetProgOutput(UInt32 outputBits){ IOReturn result= kIOReturnSuccess; UInt32 outputConfigPins; outputConfigPins = 0; if( outputBits & ( kSndHWProgOutput0 ) ) outputConfigPins |= kBurgundyOut_Ctrl_0State; if( outputBits & ( kSndHWProgOutput1 ) ) outputConfigPins |= kBurgundyOut_Ctrl_1State; // Burgundy_writeCodecReg( ioBaseBurgundy, kOutputCtl0Reg, outputConfigPins); outputConfigPins = 0; if( outputBits & ( kSndHWProgOutput2 ) ) outputConfigPins |= kBurgundyOut_Ctrl_2State; if( outputBits & ( kSndHWProgOutput3 ) ) outputConfigPins |= kBurgundyOut_Ctrl_3State; if( outputBits & ( kSndHWProgOutput4 ) ) outputConfigPins |= kBurgundyOut_Ctrl_4State; // Burgundy_writeCodecReg( ioBaseBurgundy, kOutputCtl2Reg,outputConfigPins); return(result); } // control function bool AppleBurgundyAudio::sndHWGetSystemMute(void){ return (mIsMute); } IOReturn AppleBurgundyAudio::sndHWSetSystemMute (bool mutestate){ IOReturn result = kIOReturnSuccess; UInt32 mutes; mutes = 0; // mute everything and keep the compiler happy // if (mutestate != mIsMute) { // 3461225 mIsMute = mutestate; if (mutestate | mVolumeMuteIsActive) { // 3461225 // we are muting. We do it by disconnecting the output from the mixer // we let only the OS_E stream for the sound input. Ther may be other // possibilities // Burgundy_writeCodecReg( ioBaseBurgundy, kOSReg, kBurgundyOS_E_MXO_1); // Mute all the amps mutestate = kBurgundyMuteAll; } else { // we reconnect everything // Burgundy_writeCodecReg( ioBaseBurgundy, kOSReg, kBurgundyOS_0_MXO_2| kBurgundyOS_1_MXO_2 | kBurgundyOS_E_MXO_1); // Set the volume to the correct volume as it might have been changed while we were muted sndHWSetSystemVolume (gVolLeft, gVolRight); // Unmute the amp currently in use if (TRUE == mModemActive) { mutes = kBurgundyMuteOffState << kBurgundyPort13MonoMute; } else if (TRUE == mInternalSpeakerActive) { mutes = kBurgundyMuteOffState << kBurgundyPort14LMute | kBurgundyMuteOffState << kBurgundyPort14RMute; } else if (TRUE == mExternalSpeakerActive) { mutes = kBurgundyMuteOffState << kBurgundyPort15LMute | kBurgundyMuteOffState << kBurgundyPort15RMute; } else if (TRUE == mHeadphonesActive) { mutes = kBurgundyMuteOffState << kBurgundyPort16LMute | kBurgundyMuteOffState << kBurgundyPort16RMute; } else if (TRUE == mMonoSpeakerActive) { mutes = kBurgundyMuteOffState << kBurgundyPort17MonoMute; } } Burgundy_writeCodecReg (ioBaseBurgundy, kOutputMuteReg, mutes); // } return (result); } bool AppleBurgundyAudio::sndHWSetSystemVolume (UInt32 leftVolume, UInt32 rightVolume) { UInt8 leftAttn, rightAttn; UInt8 comAttn; UInt32 tLeftVolume, tRightVolume; debugIOLog (3, "sndHWSetSystemVolume (%ld, %ld)", leftVolume, rightVolume); // mVolLeft and leftVolume between 0 and 16 if (leftVolume != mVolLeft) mVolLeft = leftVolume; tLeftVolume = mVolLeft; if (0 == tLeftVolume) tLeftVolume = 1; // leftVolume between 1 and 16 tLeftVolume -= 1; // leftVolume between 0 and 15 leftAttn = 15 - (UInt8) tLeftVolume; // leftAttn between 15 and 0 if (rightVolume != mVolRight) mVolRight = rightVolume; tRightVolume = mVolRight; if (0 == tRightVolume) tRightVolume = 1; tRightVolume -= 1; rightAttn = 15 - (UInt8) tRightVolume; // rightAttn between 15 and 0 UInt32 muteStates; muteStates = Burgundy_readCodecReg (ioBaseBurgundy, kOutputMuteReg); if (mVolLeft == 0) { // Mute headphone and speaker because volume is 0 // Changes here are to fix 3461225 // muteStates = kBurgundyMuteAll; muteStates &= ~(kOutputMuteReg_Port13M | kOutputMuteReg_Port14L | kOutputMuteReg_Port15L | kOutputMuteReg_Port16L | kOutputMuteReg_Port17M); debugIOLog (3, "muting left speaker/headphone"); } else { // Unmute either the headphone or the speaker, depending on which we're not using if (TRUE == mModemActive) { muteStates |= kBurgundyMuteOffState << kBurgundyPort13MonoMute; } else if (TRUE == mInternalSpeakerActive) { muteStates |= kBurgundyMuteOffState << kBurgundyPort14LMute; } else if (TRUE == mExternalSpeakerActive) { muteStates |= kBurgundyMuteOffState << kBurgundyPort15LMute; } else if (TRUE == mHeadphonesActive) { muteStates |= kBurgundyMuteOffState << kBurgundyPort16LMute; } else if (TRUE == mMonoSpeakerActive) { muteStates |= kBurgundyMuteOffState << kBurgundyPort17MonoMute; } // end 3461225 changes } if (mVolRight == 0) { // Mute headphone and speaker because volume is 0 // Changes here are to fix 3461225 // muteStates = kBurgundyMuteAll; muteStates &= ~(kOutputMuteReg_Port13M | kOutputMuteReg_Port14R | kOutputMuteReg_Port15R | kOutputMuteReg_Port16R | kOutputMuteReg_Port17M); debugIOLog (3, "muting right speaker/headphone"); } else { // Unmute either the headphone or the speaker, depending on which we're not using if (TRUE == mModemActive) { muteStates |= kBurgundyMuteOffState << kBurgundyPort13MonoMute; } else if (TRUE == mInternalSpeakerActive) { muteStates |= kBurgundyMuteOffState << kBurgundyPort14RMute; } else if (TRUE == mExternalSpeakerActive) { muteStates |= kBurgundyMuteOffState << kBurgundyPort15RMute; } else if (TRUE == mHeadphonesActive) { muteStates |= kBurgundyMuteOffState << kBurgundyPort16RMute; } else if (TRUE == mMonoSpeakerActive) { muteStates |= kBurgundyMuteOffState << kBurgundyPort17MonoMute; } // End 3461225 changes } Burgundy_writeCodecReg (ioBaseBurgundy, kOutputMuteReg, muteStates); if ((mVolLeft == 0) && (mVolRight == 0)) { mVolumeMuteIsActive = TRUE; } else { mVolumeMuteIsActive = FALSE; } #if 0 if ((mVolLeft == 0) && (mVolRight == 0)) { mVolumeMuteIsActive = true; Burgundy_writeCodecReg (ioBaseBurgundy, kGAP0LReg , 0x00); Burgundy_writeCodecReg (ioBaseBurgundy, kGAP0RReg , 0x00); Burgundy_writeCodecReg (ioBaseBurgundy, kGAP1RReg , 0x00); Burgundy_writeCodecReg (ioBaseBurgundy, kGAP1LReg , 0x00); } else { // we should do it better to mute one channel only to have a good balance if (mVolumeMuteIsActive) { // we do it only if we come back from noting mVolumeMuteIsActive = false; Burgundy_writeCodecReg (ioBaseBurgundy, kGAP0LReg , 0xFF); Burgundy_writeCodecReg (ioBaseBurgundy, kGAP0RReg , 0xFF); Burgundy_writeCodecReg (ioBaseBurgundy, kGAP1RReg , 0xFF); Burgundy_writeCodecReg (ioBaseBurgundy, kGAP1LReg , 0xFF); } } #endif comAttn = rightAttn << 4 | leftAttn; Burgundy_writeCodecReg (ioBaseBurgundy, kOutputLvlPort13Reg, comAttn & 0x0F); Burgundy_writeCodecReg (ioBaseBurgundy, kOutputLvlPort14Reg, comAttn); Burgundy_writeCodecReg (ioBaseBurgundy, kOutputLvlPort15Reg, comAttn); Burgundy_writeCodecReg (ioBaseBurgundy, kOutputLvlPort16Reg, comAttn); Burgundy_writeCodecReg (ioBaseBurgundy, kOutputLvlPort17Reg, comAttn & 0x0F); bool result = true; return(result); } IOReturn AppleBurgundyAudio::sndHWSetSystemVolume (UInt32 value) { IOReturn result= kIOReturnSuccess; sndHWSetSystemVolume(value, value); return(result); } IOReturn AppleBurgundyAudio::sndHWSetSystemInputGain (UInt32 leftGain, UInt32 rightGain) { IOReturn myReturn = kIOReturnSuccess; UInt32 totGain; UInt8 galeft, garight; debugIOLog (3, "+ AppleBurgundyAudio::sndHWSetSystemInputGain (%ld, %ld)", leftGain, rightGain); totGain = 0; galeft = (UInt8) leftGain; garight = (UInt8) rightGain; totGain |= galeft; totGain |= (garight <<4); Burgundy_writeCodecReg( ioBaseBurgundy, kVGA0Reg, totGain ); Burgundy_writeCodecReg( ioBaseBurgundy, kVGA1Reg, totGain ); Burgundy_writeCodecReg( ioBaseBurgundy, kVGA2Reg, totGain ); Burgundy_writeCodecReg( ioBaseBurgundy, kVGA3Reg, leftGain ); debugIOLog (3, "- AppleBurgundyAudio::sndHWSetSystemInputGain"); return(myReturn); } IOReturn AppleBurgundyAudio::sndHWSetPlayThrough(bool playthroughstate){ IOReturn result= kIOReturnSuccess; debugIOLog (3, "+ AppleBurgundyAudio::sndHWSetPlayThrough"); if(playthroughstate) Burgundy_writeCodecReg( ioBaseBurgundy, kMX2Reg, mMuxMix | kBurgundyW_A_n); else Burgundy_writeCodecReg( ioBaseBurgundy, kMX2Reg, kBurgundyW_A_n); debugIOLog (3, "- AppleBurgundyAudio::sndHWSetPlayThrough"); return(result); } // Power Management IOReturn AppleBurgundyAudio::sndHWSetPowerState ( IOAudioDevicePowerState theState ) { IOReturn myReturn; debugIOLog (3, "+ AppleBurgundyAudio::sndHWSetPowerState"); myReturn = kIOReturnSuccess; switch ( theState ) { case kIOAudioDeviceSleep: myReturn = performDeviceIdleSleep(); break; // When sleeping case kIOAudioDeviceIdle: myReturn = performDeviceSleep(); break; // When no audio engines running case kIOAudioDeviceActive: myReturn = performDeviceWake(); break; // audio engines running default: debugIOLog (3, "AppleDACAAudio::sndHWSetPowerState unknown power state"); myReturn = kIOReturnBadArgument ; break ; } debugIOLog (3, "- AppleBurgundyAudio::sndHWSetPowerState"); return ( myReturn ); } // -------------------------------------------------------------------------- IOReturn AppleBurgundyAudio::performDeviceWake () { debugIOLog (3, "+ AppleBurgundyAudio::performDeviceWake"); debugIOLog (3, "- AppleBurgundyAudio::performDeviceWake"); return ( kIOReturnSuccess ); } // -------------------------------------------------------------------------- IOReturn AppleBurgundyAudio::performDeviceSleep () { debugIOLog (3, "+ AppleBurgundyAudio::performDeviceSleep"); debugIOLog (3, "- AppleBurgundyAudio::performDeviceSleep"); return ( kIOReturnSuccess ); } // -------------------------------------------------------------------------- IOReturn AppleBurgundyAudio::performDeviceIdleSleep () { debugIOLog (3, "+ AppleBurgundyAudio::performDeviceIdleSleep"); debugIOLog (3, "- AppleBurgundyAudio::performDeviceIdleSleep"); return ( kIOReturnSuccess ); } // Identification UInt32 AppleBurgundyAudio::sndHWGetType( void ){ UInt32 result; debugIOLog (3, "+ AppleBurgundyAudio::sndHWGetType"); result = 0; debugIOLog (3, "- AppleBurgundyAudio::sndHWGetType"); return(result); } UInt32 AppleBurgundyAudio::sndHWGetManufacturer( void ){ UInt32 result, info; debugIOLog (3, "+ AppleBurgundyAudio::sndHWGetManufacturer"); info = sndHWGetRegister(kBurgundyIDReg); switch (info & kBurgundySiliconVendor){ case kBurgundyManfCrystal: result = kSndHWManfCrystal; break; case kBurgundyManfTI: result = kSndHWManfTI; break; default: result = kSndHWManfUnknown; break; } debugIOLog (3, "- AppleBurgundyAudio::sndHWGetManufacturer"); return(result); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ UInt32 AppleBurgundyAudio::GetDeviceID (void) { IORegistryEntry *sound; OSData *tmpData; UInt32 *deviceID; UInt32 theDeviceID; debugIOLog (3, "+ AppleBurgundyAudio::GetDeviceID" ); theDeviceID = 0; FailIf ( NULL == ourProvider, Exit ); sound = ourProvider->childFromPath (kSoundEntry, gIODTPlane); FailIf (!sound, Exit); tmpData = OSDynamicCast (OSData, sound->getProperty (kDeviceID)); FailIf (!tmpData, Exit); deviceID = (UInt32*)tmpData->getBytesNoCopy (); if (NULL != deviceID) { theDeviceID = *deviceID; } Exit: debugIOLog (3, "- AppleBurgundyAudio::GetDeviceID returns %d", (unsigned int)theDeviceID ); return theDeviceID; } #pragma mark -- BURGUNDY SPECIFIC -- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // This routine will disconnect an input sample stream (i.e. MUX) from // ALL mixers. Argument "mixer" is a bit mapped enable of the mixer // sources to be disconnected from an input stream as follows: // // kBurgundyW_0_n mux_0 ports 1, 2 & 3 built-in // kBurgundyW_1_n mux_1 ports 4 & 5 built-in // kBurgundyW_2_n mux_2 ports 6 & 7 built-in // kBurgundyW_3_n mux_3 port 8 telephony modem record // kBurgundyW_4_n mux_4 port 9 pcmcia // kBurgundyW_A_n subframe 0 built-in digital play // kBurgundyW_B_n subframe 1 telephony digital play void AppleBurgundyAudio::DisconnectMixer(UInt32 mixer) { UInt32 temp; temp = Burgundy_readCodecReg( ioBaseBurgundy, kMX0Reg); temp &= ~mixer; temp |= kBurgundyW_A_n; Burgundy_writeCodecReg( ioBaseBurgundy, kMX0Reg, temp); // playthrough path always gets digital stream Burgundy_writeCodecReg( ioBaseBurgundy, kMX2Reg, temp); // ext. speaker/line out is a mirror image of play path temp = Burgundy_readCodecReg( ioBaseBurgundy, kMX1Reg); // disconnect input from recording input stream temp &= ~mixer; Burgundy_writeCodecReg( ioBaseBurgundy, kMX1Reg, temp); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ UInt32 AppleBurgundyAudio::GetPhysicalInputPort( UInt32 logicalPort ) { UInt32 physicalPort; physicalPort = kBurgundyPhysInputPortIllegal; switch( logicalPort ){ case kSndHWInputNone: physicalPort = kBurgundyPhysInputPortNone; break; case kSndHWInput1: physicalPort = kBurgundyPhysInputPort1; break; case kSndHWInput2: physicalPort = kBurgundyPhysInputPort2; break; case kSndHWInput3: physicalPort = kBurgundyPhysInputPort3; break; case kSndHWInput4: physicalPort = kBurgundyPhysInputPort4; break; case kSndHWInput5: physicalPort = kBurgundyPhysInputPort5; break; case kSndHWInput6: physicalPort = kBurgundyPhysInputPort6; break; case kSndHWInput7: physicalPort = kBurgundyPhysInputPort7; break; case kSndHWInput8: physicalPort = kBurgundyPhysInputPort8; break; case kSndHWInput9: physicalPort = kBurgundyPhysInputPort9; break; } return physicalPort; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ UInt32 AppleBurgundyAudio::GetPhysicalOutputPort(UInt32 logicalPort ) { UInt32 physicalPort; physicalPort = kBurgundyPhysOutputPortIllegal; switch( logicalPort ) { case kSndHWOutputNone: physicalPort = kBurgundyPhysOutputPortNone; break; case kSndHWOutput1: physicalPort = kBurgundyPhysOutputPort14; break; case kSndHWOutput2: physicalPort = kBurgundyPhysOutputPort15; break; case kSndHWOutput3: physicalPort = kBurgundyPhysOutputPort16; break; case kSndHWOutput4: physicalPort = kBurgundyPhysOutputPort17; break; case kSndHWOutput5: physicalPort = kBurgundyPhysOutputPort13; break; } return physicalPort; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Returns the port configuration so that maximum gain can be determined. // // DIGITAL ONLY: 9 // ANALOG & DIGITAL: 1 2 3 4 8 // PREAMP, ANALOG & DIGITAL: 5 6 7 UInt32 AppleBurgundyAudio::GetInputPortType(UInt32 inputPhysicalPort){ UInt32 result; switch( inputPhysicalPort ) { case kBurgundyPhysInputPort1: // fallthrough case kBurgundyPhysInputPort2: // fallthrough case kBurgundyPhysInputPort3: // fallthrough case kBurgundyPhysInputPort4: // fallthrough case kBurgundyPhysInputPort8: result = kBurgundyPortType_AD; break; case kBurgundyPhysInputPort5: // fallthrough case kBurgundyPhysInputPort6: // fallthrough case kBurgundyPhysInputPort7: result = kBurgundyPortType_AAD; break; case kBurgundyPhysInputPort9: result = kBurgundyPortType_D; break; case kBurgundyPhysInputPortNone: // fallthrough default: result = kBurgundyPortType_NONE; break; } return result; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Several of the analog inputs are available as in input selection to // more than one mux. This routine determines which mux is the primary // destination for a specific input source. For inputs that have more // than one possible destination, the primary source is the lower orderd // destination multiplexer. UInt8 AppleBurgundyAudio::GetInputMux(UInt32 physicalInput){ UInt8 theMux; if( physicalInput > kSndHWInput9) { theMux = kBurgundyMuxNone; goto Exit; } switch( physicalInput ){ case kBurgundyPhysInputPort1: // fall through (port 1, 2 & 3 share the same mux) case kBurgundyPhysInputPort2: // fall through (port 1, 2 & 3 share the same mux) case kBurgundyPhysInputPort3: theMux = kBurgundyMux0; break; case kBurgundyPhysInputPort4: // fall through (port 4 & 5 share the same mux) case kBurgundyPhysInputPort5: theMux = kBurgundyMux1; break; case kBurgundyPhysInputPort6: // fall through (port 6 & 7 share the same mux) case kBurgundyPhysInputPort7: theMux = kBurgundyMux2; break; case kBurgundyPhysInputPort8: theMux = kBurgundyMux3; break; case kBurgundyPhysInputPort9: theMux = kBurgundyMux4; break; case kBurgundyPhysInputPortNone: theMux = kBurgundyMuxNone; break; } Exit: return theMux; } void AppleBurgundyAudio::ReleaseMux(UInt8 mux){ // __SndHWSetPan( system, kMinSoftwareGain, kMinSoftwareGain ); UInt32 temp; temp = 0; switch( mux ){ case kBurgundyMux0: temp = kBurgundyW_0_n; break; // prepare to disconnect the mux 0 from mixer 'n' connection case kBurgundyMux1: temp = kBurgundyW_1_n; break; // prepare to disconnect the mux 1 from mixer 'n' connection case kBurgundyMux2: temp = kBurgundyW_2_n; break; // prepare to disconnect the mux 2 from mixer 'n' connection case kBurgundyMux4: temp = kBurgundyW_4_n; break; // prepare to disconnect the mux 4 from mixer 'n' connection } // disconnect the mux to mixer connection DisconnectMixer( temp ); // // gGlobals->muxReservation[mux] = kSndHWInputNone; } void AppleBurgundyAudio::ReserveMux(UInt8 mux, UInt32 physicalInput){ } IOReturn AppleBurgundyAudio::setModemSound(bool state) { IOReturn myReturn = kIOReturnSuccess; debugIOLog (3, "+ AppleBurgundyAudio::setModemSound(%d)", state); // make sure that the imic is not enabled when playthrough is turned on -- there will be no FEEDBACK!!! if(TRUE == state) { gIsModemSoundActive = true; Burgundy_writeCodecReg( ioBaseBurgundy, kMX2Reg, kBurgundyW_3_n | kBurgundyW_A_n ); } else { Burgundy_writeCodecReg( ioBaseBurgundy, kMX2Reg, kBurgundyW_A_n); super::setModemSound(state); } debugIOLog (3, "- AppleBurgundyAudio::setModemSound(%d)", state); return(myReturn); }