/* * KeyLargoPlatform.h * * * Created by Aram Lindahl on Mon Mar 10 2003. * Copyright (c) 2003 AppleComputer. All rights reserved. * */ #include "PlatformInterface.h" #include #include #include #include #include #include #include #include "AppleOnboardAudioUserClient.h" #define kKL_AUDIO_MAC_IO_BASE_ADDRESS 0x80000000 #define kKL_AUDIO_MAC_IO_SIZE 256 class KeyLargoPlatform : public PlatformInterface { OSDeclareDefaultStructors(KeyLargoPlatform); typedef bool GpioActiveState; typedef UInt8* GpioPtr; public: static void testInterruptHandler(); virtual bool init (IOService* device, AppleOnboardAudio* provider, UInt32 inDBDMADeviceIndex); virtual void setWorkLoop(IOWorkLoop* inWorkLoop) {mWorkLoop = inWorkLoop; return;} virtual void free(); virtual IOReturn performPlatformSleep ( void ); virtual IOReturn performPlatformWake ( IOService * device ); // // Codec Methods // virtual bool readCodecRegister(UInt8 address, UInt8 subAddress, UInt8 *data, UInt16 len, BusMode mode); virtual bool writeCodecRegister(UInt8 address, UInt8 subAddress, UInt8 *data, UInt16 len, BusMode mode); virtual IOReturn setCodecReset ( CODEC_RESET target, GpioAttributes reset ); virtual GpioAttributes getCodecReset ( CODEC_RESET target ); // // I2S Methods: FCR3 // virtual IOReturn requestI2SClockSource(I2SClockFrequency inFrequency); virtual IOReturn releaseI2SClockSource(I2SClockFrequency inFrequency); // // I2S Methods: FCR1 // virtual IOReturn setI2SEnable(bool enable); virtual bool getI2SEnable(); virtual IOReturn setI2SClockEnable(bool enable); virtual bool getI2SClockEnable(); virtual IOReturn setI2SCellEnable(bool enable); virtual bool getI2SCellEnable(); // virtual IOReturn setI2SSWReset(bool enable); // virtual bool getI2SSWReset(); // // I2S Methods: IOM Control (non-FCR1) // virtual IOReturn setSerialFormatRegister(UInt32 serialFormat); virtual UInt32 getSerialFormatRegister(); virtual IOReturn setDataWordSizes(UInt32 dataWordSizes); virtual UInt32 getDataWordSizes(); virtual IOReturn setFrameCount(UInt32 value); virtual UInt32 getFrameCount(); virtual IOReturn setI2SIOMIntControl(UInt32 intCntrl); virtual UInt32 getI2SIOMIntControl(); virtual IOReturn setI2SIOM_CodecMsgOut(UInt32 value); virtual UInt32 getI2SIOM_CodecMsgOut(); virtual IOReturn setI2SIOM_CodecMsgIn(UInt32 value); virtual UInt32 getI2SIOM_CodecMsgIn(); virtual IOReturn setI2SIOM_FrameMatch(UInt32 value); virtual UInt32 getI2SIOM_FrameMatch(); virtual IOReturn setI2SIOM_PeakLevelSel(UInt32 value); virtual UInt32 getI2SIOM_PeakLevelSel(); virtual IOReturn setI2SIOM_PeakLevelIn0(UInt32 value); virtual UInt32 getI2SIOM_PeakLevelIn0(); virtual IOReturn setI2SIOM_PeakLevelIn1(UInt32 value); virtual UInt32 getI2SIOM_PeakLevelIn1(); virtual IOReturn setPeakLevel ( UInt32 channelTarget, UInt32 levelMeterValue ); virtual UInt32 getPeakLevel ( UInt32 channelTarget ); // // GPIO Methods // virtual void initAudioGpioPtr ( const IORegistryEntry * start, const char * gpioName, GpioPtr* gpioH, GpioActiveState* gpioActiveStatePtr, IOService ** intProvider ); virtual IOReturn getGpioPtrAndActiveState ( GPIOSelector theGpio, GpioPtr * gpioPtrPtr, GpioActiveState * activeStatePtr ) ; virtual GpioAttributes getGpioAttributes ( GPIOSelector theGpio ); virtual IOReturn setGpioAttributes ( GPIOSelector theGpio, GpioAttributes attributes ); virtual IOReturn setClockMux(GpioAttributes muxState); virtual GpioAttributes getClockMux(); virtual GpioAttributes getCodecErrorInterrupt(); virtual GpioAttributes getCodecInterrupt(); virtual GpioAttributes getComboInJackTypeConnected(); virtual GpioAttributes getComboOutJackTypeConnected(); virtual GpioAttributes getDigitalInConnected(); virtual GpioAttributes getDigitalOutConnected(); virtual GpioAttributes getHeadphoneConnected(); virtual IOReturn setHeadphoneMuteState(GpioAttributes muteState); virtual GpioAttributes getHeadphoneMuteState(); virtual IOReturn setInputDataMux(GpioAttributes muxState) ; virtual GpioAttributes getInputDataMux(); virtual GpioAttributes getInternalSpeakerID(); virtual GpioAttributes getLineInConnected(); virtual GpioAttributes getLineOutConnected(); virtual IOReturn setLineOutMuteState(GpioAttributes muteState); virtual GpioAttributes getLineOutMuteState(); virtual GpioAttributes getSpeakerConnected(); virtual IOReturn setSpeakerMuteState(GpioAttributes muteState); virtual GpioAttributes getSpeakerMuteState(); // // Non-inherited public User Client support // UInt8 userClientReadGPIO (UInt32 selector); void userClientWriteGPIO (UInt32 selector, UInt8 data); bool getGPIOActiveState (UInt32 gpioSelector); void setGPIOActiveState (UInt32 selector, UInt8 gpioActiveState); UInt8 * getGPIOAddress (UInt32 gpioSelector); bool checkGpioAvailable (UInt32 selector); virtual void logFCR1(); virtual void logFCR3(); // // Set Interrupt Handler Methods // virtual IOReturn registerInterruptHandler (IOService * theDevice, void * interruptHandler, PlatformInterruptSource source ); virtual IOReturn unregisterInterruptHandler (IOService * theDevice, void * interruptHandler, PlatformInterruptSource source ); // // DBDMA Memory Address Acquisition Methods // virtual IODBDMAChannelRegisters * GetInputChannelRegistersVirtualAddress ( IOService * dbdmaProvider ); virtual IODBDMAChannelRegisters * GetOutputChannelRegistersVirtualAddress ( IOService * dbdmaProvider ); // // User Client Support // virtual IOReturn getPlatformState ( PlatformStateStructPtr outState ); virtual IOReturn setPlatformState ( PlatformStateStructPtr inState ); virtual PlatformInterfaceObjectType getPlatformInterfaceType () { return kPlatformInterfaceType_KeyLargo; } private: IOWorkLoop* mWorkLoop; IOService* mKeyLargoService; IODBDMAChannelRegisters * mIOBaseDMAOutput; const OSSymbol * mKLI2SPowerSymbolName; // [3324205] // // GPIO // IOReturn gpioWrite( UInt8* gpioAddress, UInt8 data ); GpioPtr mAmplifierMuteGpio; GpioPtr mAnalogResetGpio; GpioPtr mClockMuxGpio; GpioPtr mComboInJackTypeGpio; GpioPtr mComboOutJackTypeGpio; GpioPtr mCodecErrorInterruptGpio; GpioPtr mCodecInterruptGpio; GpioPtr mDigitalInDetectGpio; GpioPtr mDigitalOutDetectGpio; GpioPtr mDigitalResetGpio; GpioPtr mHeadphoneDetectGpio; GpioPtr mHeadphoneMuteGpio; GpioPtr mInputDataMuxGpio; GpioPtr mInternalSpeakerIDGpio; GpioPtr mLineInDetectGpio; GpioPtr mLineOutDetectGpio; GpioPtr mLineOutMuteGpio; GpioPtr mSpeakerDetectGpio; GpioActiveState mAmplifierMuteActiveState; GpioActiveState mAnalogResetActiveState; GpioActiveState mClockMuxActiveState; GpioActiveState mCodecErrorInterruptActiveState; GpioActiveState mCodecInterruptActiveState; GpioActiveState mDigitalInDetectActiveState; GpioActiveState mComboInJackTypeActiveState; GpioActiveState mDigitalOutDetectActiveState; GpioActiveState mComboOutJackTypeActiveState; GpioActiveState mDigitalResetActiveState; GpioActiveState mHeadphoneDetectActiveState; GpioActiveState mHeadphoneMuteActiveState; GpioActiveState mInputDataMuxActiveState; GpioActiveState mInternalSpeakerIDActiveState; GpioActiveState mLineInDetectActiveState; GpioActiveState mLineOutDetectActiveState; GpioActiveState mLineOutMuteActiveState; GpioActiveState mSpeakerDetectActiveState; volatile UInt8 * mHwPtr; // remove after burning real rom on real hardware IOService * mCodecIntProvider; IOService * mCodecErrorIntProvider; IOService * mComboInDetectIntProvider; IOService * mComboOutDetectIntProvider; IOService * mDigitalInDetectIntProvider; IOService * mDigitalOutDetectIntProvider; IOService * mHeadphoneDetectIntProvider; IOService * mLineInDetectIntProvider; IOService * mLineOutDetectIntProvider; IOService * mSpeakerDetectIntProvider; IOInterruptEventSource *mHeadphoneDetectIntEventSource; IOInterruptEventSource *mSpeakerDetectIntEventSource; IOInterruptEventSource *mLineOutDetectIntEventSource; IOInterruptEventSource *mLineInDetectIntEventSource; IOInterruptEventSource *mDigitalOutDetectIntEventSource; IOInterruptEventSource *mDigitalInDetectIntEventSource; IOInterruptEventSource *mCodecInterruptEventSource; IOInterruptEventSource *mCodecErrorInterruptEventSource; IOInterruptEventSource *mComboInDetectInterruptEventSource; IOInterruptEventSource *mComboOutDetectInterruptEventSource; enum extInt_gpio { intEdgeSEL = 7, // bit address: R/W Enable Dual Edge positiveEdge = 0, // 0 = positive edge detect for ExtInt interrupt sources (default) dualEdge = 1 // 1 = enable both edges }; enum gpio { gpioOS = 4, // bit address: output select gpioBit0isOutput = 0, // use gpio bit 0 as output (default) gpioMediaBayIsOutput = 1, // use media bay power gpioReservedOutputSel = 2, // reserved gpioMPICopenCollector = 3, // MPIC CPUInt2_1 (open collector) gpioAltOE = 3, // bit address: alternate output enable gpioOE_DDR = 0, // use DDR for output enable gpioOE_Use_OS = 1, // use gpioOS for output enable gpioDDR = 2, // bit address: r/w data direction gpioDDR_INPUT = 0, // use for input (default) gpioDDR_OUTPUT = 1, // use for output gpioPIN_RO = 1, // bit address: read only level on pin gpioDATA = 0, // bit address: the gpio itself gpioBIT_MASK = 1 // value shifted by bit position to be used to determine a GPIO bit state }; // // I2S // typedef enum i2sReference { kUseI2SCell0 = 0, kUseI2SCell1 = 1, kNoI2SCell = 0xFFFFFFFF } I2SCell; I2SCell mI2SInterfaceNumber; bool findAndAttachI2C(); bool detachFromI2C(); bool openI2C(); void closeI2C(); IOReturn initI2S(IOMemoryMap* map); UInt32 mI2CPort; bool mI2C_lastTransactionResult; PPCI2CInterface* mI2CInterface; // Sound Formats: typedef enum SoundFormat { kSndIOFormatI2SSony, kSndIOFormatI2S64x, kSndIOFormatI2S32x, // This says "we never decided for a sound format before" kSndIOFormatUnknown } SoundFormat; // Characteristic constants: typedef enum TicksPerFrame { k64TicksPerFrame = 64, // 64 ticks per frame k32TicksPerFrame = 32 // 32 ticks per frame } TicksPerFrame; typedef enum ClockSourceValue { kClock49MHz = 49152000, // 49 MHz clock source kClock45MHz = 45158400, // 45 MHz clock source kClock18MHz = 18432000 // 18 MHz clock source } ClockSourceValue; void * mSoundConfigSpace; // address of sound config space void * mIOBaseAddress; // base address of our I/O controller void * mIOConfigurationBaseAddress; // base address for the configuration registers void * mI2SBaseAddress; // base address of I2S I/O Module IODeviceMemory * mIOBaseAddressMemory; // Have to free this in free() IODeviceMemory * mIOI2SBaseAddressMemory; static const UInt32 kFCR0Offset; static const UInt32 kFCR1Offset; static const UInt32 kFCR2Offset; static const UInt32 kFCR3Offset; static const UInt32 kFCR4Offset; enum FCR1_Bit_Addresses { // bit addresses kI2S1Enable = 20, // 1 = normal, 0 = tristate kI2S1ClkEnBit = 19, // 1 = normal, 0 = stopped low kI2S1SwReset = 18, // 1 = reset, 0 = run kI2S1CellEn = 17, // 1 = clock running, 0 = clock stopped kI2S0Enable = 13, // 1 = normal, 0 = tristate kI2S0ClkEnBit = 12, // 1 = normal, 0 = stopped low kI2S0SwReset = 11, // 1 = reset, 0 = run kI2S0CellEn = 10, // 1 = clock running, 0 = clock stopped kChooseI2S0 = 9, // 1 = I2S0 drives clock out, 0 = SccB or IrDA drives clock out kChooseAudio = 7, // 1 = DAV audio, 0 = I2S0 kAUDIOCellEN = 6, // 1 = DAV clock running, 0 = DAV clocks stopped kAudioClkOut_EN_h = 5, // 1 = DAV AudioClkOut active, 0 = DAV AudioClkOut tristate kAudioSW_Reset_h = 4, // 1 = DAV reset, 0 = run kAudioClkEnBit_h = 3, // 1 = normal, 0 = stopped low kAudioClkDiv2_h = 2, // 1 = divided by 4, 0 = divided by 2 kAudio_Sel22MClk = 1, kAudioClkOut1X_h = 0 }; enum FCR1_Field_Width { kI2S1Enable_bitWidth = 1, // kI2S1ClkEnBit_bitWidth = 1, // kI2S1SwReset_bitWidth = 1, // kI2S1CellEn_bitWidth = 1, // kI2S0Enable_bitWidth = 1, // kI2S0ClkEnBit_bitWidth = 1, // kI2S0SwReset_bitWidth = 1, // kI2S0CellEn_bitWidth = 1, // kChooseI2S0_bitWidth = 1, // kChooseAudio_bitWidth = 1, // kAUDIOCellEN_bitWidth = 1 // }; enum FCR3_Bit_Addresses { kClk18_EN_h = 14, // 1 = enable 18.4320 MHz clock to the 12S0 cell kI2S1_Clk18_EN_h = 13, // 1 = enable 18.4320 MHz clock to the 12S1 cell kClk45_EN_h = 10, // 1 = enable 45.1584 MHz clock to Audio, I2S0, I2S1 and SCC kClk49_EN_h = 9, // 1 = enable 49.1520 MHz clock to Audio, I2S0 kShutdown_PLLKW4 = 2, // 1 = shutdown the 45.1584 MHz PLL kShutdown_PLLKW6 = 1, // 1 = shutdown the 49.1520 MHz PLL kShutdown_PLL_Total = 0 // 1 = shutdown all five PLL modules }; enum FCR3_FieldWidth { kClk18_EN_h_bitWidth = 1, // kI2S1_Clk18_EN_h_bitWidth = 1, // kClk45_EN_h_bitWidth = 1, // kClk49_EN_h_bitWidth = 1, // kShutdown_PLLKW4_bitWidth = 1, // kShutdown_PLLKW6_bitWidth = 1, // kShutdown_PLL_Total_bitWidth = 1 // }; static const char* kAmpMuteEntry; static const char* kAnalogHWResetEntry; static const char* kCodecErrorIrqTypeEntry; static const char* kCodecIrqTypeEntry; static const char* kComboInJackTypeEntry; static const char* kComboOutJackTypeEntry; static const char* kDigitalHWResetEntry; static const char* kDigitalInDetectEntry; static const char* kDigitalOutDetectEntry; static const char* kHeadphoneDetectInt; static const char* kHeadphoneMuteEntry; static const char* kInternalSpeakerIDEntry; static const char* kLineInDetectInt; static const char* kLineOutDetectInt; static const char* kLineOutMuteEntry; static const char* kSpeakerDetectEntry; static const char* kNumInputs; static const char* kDeviceID; static const char* kSpeakerID; static const char* kCompatible; static const char* kI2CAddress; static const char* kAudioGPIO; static const char* kAudioGPIOActiveState; static const char* kIOInterruptControllers; static const UInt16 kAPPLE_IO_CONFIGURATION_SIZE; static const UInt16 kI2S_IO_CONFIGURATION_SIZE; static const UInt32 kI2S0BaseOffset; /* mapped by AudioI2SControl */ static const UInt32 kI2S1BaseOffset; /* mapped by AudioI2SControl */ static const UInt32 kI2SIntCtlOffset; static const UInt32 kI2SSerialFormatOffset; static const UInt32 kI2SCodecMsgOutOffset; static const UInt32 kI2SCodecMsgInOffset; static const UInt32 kI2SFrameCountOffset; static const UInt32 kI2SFrameMatchOffset; static const UInt32 kI2SDataWordSizesOffset; static const UInt32 kI2SPeakLevelSelOffset; static const UInt32 kI2SPeakLevelIn0Offset; static const UInt32 kI2SPeakLevelIn1Offset; static const UInt32 kI2SClockOffset; /* FCR1 offset (not mapped by AudioI2SControl) */ static const UInt32 kI2S0ClockEnable; static const UInt32 kI2S1ClockEnable; static const UInt32 kI2S0CellEnable; static const UInt32 kI2S1CellEnable; static const UInt32 kI2S0InterfaceEnable; static const UInt32 kI2S1InterfaceEnable; // // Utilties // virtual IOReturn setHeadphoneDetectInterruptHandler(IOService* theDevice, void* interruptHandler); virtual IOReturn setSpeakerDetectInterruptHandler (IOService* theDevice, void* interruptHandler); virtual IOReturn setLineOutDetectInterruptHandler(IOService* theDevice, void* interruptHandler); virtual IOReturn setLineInDetectInterruptHandler(IOService* theDevice, void* interruptHandler); virtual IOReturn setDigitalOutDetectInterruptHandler(IOService* theDevice, void* interruptHandler); virtual IOReturn setDigitalInDetectInterruptHandler(IOService* theDevice, void* interruptHandler); virtual IOReturn setCodecInterruptHandler(IOService* theDevice, void* interruptHandler); virtual IOReturn setCodecErrorInterruptHandler(IOService* theDevice, void* interruptHandler); virtual IOReturn setComboInDetectInterruptHandler(IOService* theDevice, void* interruptHandler); virtual IOReturn setComboOutDetectInterruptHandler(IOService* theDevice, void* interruptHandler); inline void setKeyLargoRegister(void *klRegister, UInt32 value); inline UInt32 getKeyLargoRegister(void *klRegister); inline UInt32 getFCR1(); inline void setFCR1(UInt32 value); inline UInt32 getFCR3(); inline void setFCR3(UInt32 value); inline UInt8 assertGPIO(GpioActiveState inState) {return ((0 == inState) ? 0 : 1);} inline UInt8 negateGPIO(GpioActiveState inState) {return ((0 == inState) ? 1 : 0);} IORegistryEntry* FindEntryByProperty (const IORegistryEntry * start, const char * key, const char * value); };