Annotation of XNU/iokit/Drivers/audio/drvPPCDACA/PPCDACA.cpp, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  * Copyright (c) 1998 Apple Computer, Inc.  All rights reserved. 
                     24:  *
                     25:  * Interface implementation for the DAC 3550A audio Controller
                     26:  *
                     27:  * HISTORY
                     28:  *
                     29:  *
                     30:  */
                     31: 
                     32: #include <IOKit/assert.h>
                     33: #include <IOKit/system.h>
                     34: 
                     35: #include <IOKit/IOLib.h>
                     36: #include <IOKit/IODeviceTreeSupport.h>
                     37: #include <IOKit/IOPlatformExpert.h>
                     38: #include <IOKit/ppc/IODBDMA.h>
                     39: 
                     40: // Driver headers
                     41: #include "daca_hw.h"
                     42: #include "PPCDACA_inlined.h"
                     43: #include "PPCDACA.h"
                     44: 
                     45: #define super IOAudioBus
                     46: OSDefineMetaClassAndStructors( PPCDACA, IOAudioBus )
                     47: 
                     48: /* ==============
                     49:  * Public Methods
                     50:  * ============== */
                     51: bool
                     52: PPCDACA::init(OSDictionary * properties)
                     53: {
                     54:     if (!super::init(properties))
                     55:             return false;
                     56:  
                     57:     // Nulls the pointers for the arrays we allocate:
                     58:     fOutputComponents = NULL;
                     59:     numOutputComponents = NULL;
                     60: 
                     61:     // Initialize  the defualt registers to non zero values (so they will be revitten)
                     62:     sampleRateReg = 0xFF;
                     63:     analogVolumeReg = kPowerOnDefaultAVOL;
                     64:     configurationReg = 0xFF;
                     65: 
                     66:     // Mirror the analogVolumeReg for the speaker and for the headphones.
                     67:     internalSpeakerVolume = analogVolumeReg;
                     68:     internalHeadphonesVolume = analogVolumeReg;
                     69: 
                     70:     // Last value of the status is 0
                     71:     lastStatus = 0;
                     72:  
                     73:     // Clears the interface
                     74:     interface = NULL;
                     75:     
                     76:     // Forget the provider:
                     77:     sound = NULL;
                     78: 
                     79:     // Initialize the sound format:
                     80:     dacaSerialFormat = kSndIOFormatUnknown;
                     81: 
                     82:     return true;
                     83: }
                     84: 
                     85: void
                     86: PPCDACA::free()
                     87: {
                     88:     // Releases the sound:
                     89:     if(sound != NULL)
                     90:         sound->release();
                     91:     sound = NULL;
                     92: 
                     93:     super::free();
                     94: }
                     95: 
                     96: IOService*
                     97: PPCDACA::probe(IOService* provider, SInt32* score)
                     98: {
                     99:     // Finds the possible candidate for sound, to be used in
                    100:     // reading the caracteristics of this hardware:
                    101:     IORegistryEntry *soundCandidate = provider->childFromPath("sound", gIODTPlane);
                    102: 
                    103:     if (super::probe(provider, score) && implementsDACA(soundCandidate)) {
                    104: #ifdef DEBUGMODE
                    105:         IOLog("PPCDACA::probe we are on a PPCDACA device !!\n");
                    106: #endif // DEBUGMODE
                    107: 
                    108:         // we did not fail:
                    109:         *score = kIODefaultProbeScore;
                    110:         sound = soundCandidate;
                    111:         return this;
                    112:     }
                    113: 
                    114:     return (NULL);
                    115: }
                    116: 
                    117: #define kNumDMAStreams 1
                    118: bool
                    119: PPCDACA::start(IOService* provider)
                    120: {
                    121:     // Gets the base for the DAC-3550 registers:
                    122:     IOMemoryMap *map;
                    123:     int i;
                    124: 
                    125: #ifdef DEBUGMODE
                    126:     // Delay for 30 seconds so we have the time to attach the debugger and look at
                    127:     // what is going on here (only if DEBUGMODE of course).
                    128:     IOLog("Starting DAC-3550 with provider %s ...", provider->getName());
                    129:     IOSleep(30 * 1000);
                    130:     IOLog("...\n");
                    131: #endif // DEBUGMODE
                    132: 
                    133:     if(!super::start(provider)) {
                    134: #ifdef DEBUGMODE
                    135:         IOLog("PPCDACA::start if(!super::start(provider)) fails !!\n");
                    136: #endif // DEBUGMODE
                    137:         return (false);
                    138:     }
                    139: 
                    140:     if (!findAndAttachI2C(provider))  {
                    141: #ifdef DEBUGMODE
                    142:         IOLog("PPCDACA::start if (!findAndAttachI2C(IOService *provider)) fails !!\n");
                    143: #endif // DEBUGMODE
                    144:         return (false);
                    145:     }
                    146: 
                    147:     map = provider->mapDeviceMemoryWithIndex(kAudioDMAdeviceInt);
                    148:     if(!map)  {
                    149: #ifdef DEBUGMODE
                    150:         IOLog("PPCDACA::start if(!map) %d fails !!\n",kAudioDMAdeviceInt);
                    151: #endif // DEBUGMODE
                    152:         return (false);
                    153:     }
                    154:     soundConfigSpace = (UInt8 *)map->getPhysicalAddress();
                    155: 
                    156:     if (!AllocateStreams(kNumDMAStreams)) {
                    157: #ifdef DEBUGMODE
                    158:         IOLog("PPCDACA::start if (!AllocateStreams(kNumDMAStreams)) fails !!\n");
                    159: #endif // DEBUGMODE
                    160:         return (false);
                    161:     }
                    162: 
                    163:     map = provider->mapDeviceMemoryWithIndex(kAudioDMAtxInt);
                    164:     if(!map)  {
                    165: #ifdef DEBUGMODE
                    166:         IOLog("PPCDACA::start if(!map) %d fails !!\n",kAudioDMAtxInt);
                    167: #endif // DEBUGMODE
                    168:         return (false);
                    169:     }
                    170:     DefineStream(kAudioDMAOutputStream, kOutput, frameRate(0), (IODBDMAChannelRegisters*)map->getVirtualAddress());
                    171: 
                    172:     // Creates the array of output components
                    173:     numOutputComponents = numberOfInputComponents();
                    174: 
                    175:     fOutputComponents = (IOAudioComponentImplPtr*)IOMalloc(sizeof(IOAudioComponentImplPtr) * numOutputComponents);
                    176:     if (fOutputComponents == NULL) {
                    177: #ifdef DEBUGMODE
                    178:         IOLog("PPCDACA::start if (fOutputComponents == NULL) fails !!\n");
                    179: #endif // DEBUGMODE
                    180: 
                    181:         // Free the DMA and exit:
                    182:         FreeStreams();
                    183:         return false;
                    184:     }
                    185: 
                    186:     // Initalizes all the components:
                    187:     for (i = 0; i < numOutputComponents; i++)
                    188:         fOutputComponents[i] = NULL;
                    189: 
                    190:     // sets the clock base address figuring out which I2S cell we're on
                    191:     if ((((UInt32)soundConfigSpace ^ kI2S0BaseOffset) & 0x0001FFFF) == 0) {
                    192:         ioBaseAddress = (void *)((UInt32)soundConfigSpace - kI2S0BaseOffset);
                    193:         i2SInterfaceNumber = 0;
                    194:     }
                    195:     else if ((((UInt32)soundConfigSpace ^ kI2S1BaseOffset) & 0x0001FFFF) == 0) {
                    196:         ioBaseAddress = (void *)((UInt32)soundConfigSpace - kI2S1BaseOffset);
                    197:         i2SInterfaceNumber = 1;
                    198:     }
                    199:     else {
                    200:         IOLog("PPCDACA::start failed to setup ioBaseAddress and ioClockBaseAddress\n");
                    201:     }
                    202: 
                    203:     // This is the keylargo FC1 (Feature configuration 1)
                    204:     ioClockBaseAddress = (void *)((UInt32)ioBaseAddress + kI2SClockOffset);
                    205: 
                    206:     // Finds the position of the status register:
                    207:     ioStatusRegister_GPIO12 = (void *)((UInt32)ioBaseAddress + kGPio12);
                    208: 
                    209:     // Enables the I2S Interface:
                    210:     KLSetRegister(ioClockBaseAddress, KLGetRegister(ioClockBaseAddress) | kI2S0InterfaceEnable);
                    211:  
                    212:     // Starts the workloop and exit since there is nothing we can be interested about anymore
                    213:     startWorkLoop();
                    214: 
                    215:     return true;
                    216: }
                    217: 
                    218: void
                    219: PPCDACA::stop(IOService *provider)
                    220: {
                    221:     // Releases all DMA streams:
                    222:     FreeStreams();
                    223: 
                    224:     // Releases the output components
                    225:     if (fOutputComponents != NULL) {
                    226:         IOFree(fOutputComponents, sizeof(IOAudioComponentImplPtr) * numOutputComponents);
                    227:         fOutputComponents = NULL;
                    228:         numOutputComponents = 0;
                    229:     }
                    230: 
                    231:     // Call the parent stop:
                    232:     super::stop(provider);
                    233: }
                    234: 
                    235: void
                    236: PPCDACA::CreateAudioTopology(IOCommandQueue *queue)
                    237: {
                    238:     IOAudioComponentImpl *mixerOut;
                    239:     IOAudioComponentImpl *modem;
                    240:     IOAudioComponentImpl *headphones;
                    241:     IOAudioComponentImpl *cd;
                    242:     IOAudioComponentImpl *speaker;
                    243:     IOAudioComponentImpl *passthru;
                    244: 
                    245:     AudioStreamIndex outputStream;
                    246:     
                    247:     if (!fStreams)
                    248:         return;
                    249: 
                    250:     outputStream = firstStreamAfter(kOutput, 0);
                    251: 
                    252:     if (outputStream == kInvalidStreamIndex) {
                    253:         IOLog("PPCDACA::CreateAudioTopology called without available DMA streams\n");
                    254:         return;
                    255:     }
                    256:     else
                    257:         IOLog("PPCDACA::CreateAudioTopology output stream is %d\n", outputStream);
                    258: 
                    259:     mixerOut = buildComponentAndAttach(GetStream(outputStream), NULL, componentDictionaryMixerOut(), queue);
                    260:     headphones = buildComponentAndAttach(mixerOut, NULL, componentDictionaryHeadphones(), queue);
                    261:     speaker = buildComponentAndAttach(mixerOut, NULL, componentDictionarySpeaker(), queue);
                    262: 
                    263:     cd = buildComponentAndAttach(NULL, NULL,  componentDictionaryCD(), queue);
                    264:     modem = buildComponentAndAttach(NULL, NULL, componentDictionaryModem(), queue);
                    265: 
                    266:     passthru = buildComponentAndAttach(NULL, mixerOut, componentDictionaryPassThru(), queue);
                    267: 
                    268:     // FIXME: the component connection could be done better than so
                    269:     if (fOutputComponents != NULL) {
                    270:         fOutputComponents[kSpeaker] = speaker;
                    271: 
                    272:         if (numOutputComponents > 1)
                    273:             fOutputComponents[kHeadphones] = headphones;
                    274:     }
                    275: 
                    276:     // Sets ups the DAC-3550 as required by this machine wiring
                    277:     // configuration:
                    278:     if (!dependentSetup())
                    279:         IOLog("PPCDACA::CreateAudioTopology DAC-3550 setup failed\n");
                    280: }
                    281: 
                    282: void
                    283: PPCDACA::DoClockTick(IOTimerEventSource *t)
                    284: {
                    285:     checkStatusRegister();
                    286:     super::DoClockTick(t);
                    287: }
                    288: 
                    289: void
                    290: PPCDACA::calculateTickInterval(AbsoluteTime *tickInterval)
                    291: {
                    292:     AbsoluteTime maxInterval;
                    293: 
                    294:     // We want to check the status at least one a second
                    295:     nanoseconds_to_absolutetime(NSEC_PER_SEC, &maxInterval);
                    296:     if(CMP_ABSOLUTETIME(&maxInterval, tickInterval) < 0) {
                    297:         *tickInterval = maxInterval;
                    298:     }
                    299:     super::calculateTickInterval(tickInterval);
                    300: }
                    301: 
                    302: IOReturn
                    303: PPCDACA::SetControl(UInt16 id, int val)
                    304: {
                    305:     IOReturn res = kIOReturnSuccess;
                    306:     
                    307:     switch(id) {
                    308:         case kSpeakerMute:
                    309:             muteInternalSpeaker(val != 0);
                    310:             muteHeadphones(val == 0);
                    311:             break;
                    312: 
                    313:         case kHeadphonesMute:
                    314:             muteHeadphones(val != 0);
                    315:             muteInternalSpeaker(val == 0);
                    316:             break;
                    317: 
                    318:         case kModemMute:
                    319:             setModemInput(val == 0);
                    320:             break;
                    321: 
                    322:         case kSpeakerVolLeft:
                    323:             volumeInternalSpeakerLeft(val);
                    324:             break;
                    325: 
                    326:         case kSpeakerVolRight:
                    327:             volumeInternalSpeakerRight(val);
                    328:             break;
                    329: 
                    330:         case kHeadphonesVolLeft:
                    331:             volumeHeadphonesLeft(val);
                    332:             break;
                    333: 
                    334:         case kHeadphonesVolRight:
                    335:             volumeHeadphonesRight(val);
                    336:             break;
                    337: 
                    338:         case kCDMute:
                    339:             muteCDLine(val != 0);
                    340:             break;
                    341: 
                    342:         case kPassThruVolLeft:
                    343:             break;
                    344: 
                    345:         case kPassThruVolRight:
                    346:             break;
                    347: 
                    348:         case kPassThruMute:
                    349:             break;
                    350: 
                    351:         default:
                    352:             res = kIOReturnUnsupported;
                    353:     }
                    354:     return res;
                    355: }
                    356: 
                    357: /* ===============
                    358:  * Private Methods
                    359:  * =============== */
                    360: 
                    361: // --------------------------------------------------------------------------
                    362: // Method: findAndAttachI2C
                    363: //
                    364: // Purpose:
                    365: //   Attaches to the i2c interface:
                    366: bool
                    367: PPCDACA::findAndAttachI2C(IOService *provider)
                    368: {
                    369:     OSData *t;
                    370:     UInt32 baseAddress;
                    371:     UInt32 addressSteps;
                    372:     UInt32 rate;
                    373:     IORegistryEntry *i2cCandidate;
                    374: 
                    375:     // Searches the i2c:
                    376:     for (i2cCandidate = NULL;
                    377:          (provider != NULL) && (i2cCandidate == NULL);
                    378:          provider = provider->getProvider()) {
                    379:         i2cCandidate = provider->childFromPath("i2c", gIODTPlane);
                    380: #ifdef DEBUGMODE
                    381:         IOLog("Looking for i2c in %s -> 0x%08lx\n", provider->getName(), (UInt32)i2cCandidate);
                    382: #endif // DEBUGMODE
                    383:     }
                    384: 
                    385:     if (i2cCandidate == NULL) {
                    386: #ifdef DEBUGMODE
                    387:         IOLog("PPCDACA::findAndAttachI2C can't find the i2c in the registry\n");
                    388: #endif // DEBUGMODE
                    389:         return false;
                    390:     }
                    391: 
                    392:     // creates the interface for real:
                    393:     interface = new PPCI2CInterface;
                    394:     if (interface == NULL) {
                    395: #ifdef DEBUGMODE
                    396:         IOLog("PPCDACA::findAndAttachI2C can't allocate memory for the PPCI2CInterface\n");
                    397: #endif // DEBUGMODE
                    398:         return false;
                    399:     }
                    400: 
                    401:     // sets up the interface:
                    402:     t = OSDynamicCast(OSData, i2cCandidate->getProperty("AAPL,address"));
                    403:     if (t != NULL)
                    404:         baseAddress = *((UInt32*)t->getBytesNoCopy());
                    405:     else {
                    406: #ifdef DEBUGMODE
                    407:         IOLog( "PPCDACA::findAndAttachI2C missing property AAPL,address in i2c registry\n");
                    408: #endif
                    409:         return false;
                    410:     }
                    411: 
                    412:     t = OSDynamicCast(OSData, i2cCandidate->getProperty("AAPL,address-step"));
                    413:     if (t != NULL)
                    414:         addressSteps = *((UInt32*)t->getBytesNoCopy());
                    415:     else {
                    416: #ifdef DEBUGMODE
                    417:         IOLog( "PPCDACA::findAndAttachI2C missing property AAPL,address-step in i2c registry\n");
                    418: #endif
                    419:         return false;
                    420:     }
                    421: 
                    422:     t = OSDynamicCast(OSData, i2cCandidate->getProperty("AAPL,i2c-rate"));
                    423:     if (t != NULL)
                    424:         rate = *((UInt32*)t->getBytesNoCopy());
                    425:     else {
                    426: #ifdef DEBUGMODE
                    427:         IOLog( "PPCDACA::findAndAttachI2C missing property AAPL,i2c-rate in i2c registry\n");
                    428: #endif
                    429:         return false;
                    430:     }
                    431: 
                    432:     if (!interface->initI2CBus((UInt8*)baseAddress, (UInt8)addressSteps))
                    433:         return false;
                    434: 
                    435:     if (!interface->setKhzSpeed((UInt)rate))
                    436:         return false;
                    437: 
                    438:     // Also sets the default mode
                    439:     interface->setStandardSubMode();
                    440:   
                    441:     // Finds the port to use:
                    442:     return(interface->openI2CBus(getI2CPort()));
                    443: }
                    444: 
                    445: // --------------------------------------------------------------------------
                    446: // Method: detachFromI2C
                    447: //
                    448: // Purpose:
                    449: //   detaches from the I2C
                    450: bool
                    451: PPCDACA::detachFromI2C(IOService* /*provider*/)
                    452: {
                    453:     if (interface)
                    454:         delete interface;
                    455: 
                    456:     return (true);
                    457: }
                    458: 
                    459: // --------------------------------------------------------------------------
                    460: // Method: implementsDACA
                    461: //
                    462: // Purpose:
                    463: //   Attempts to discover if the device implements DAC-3550:
                    464: bool
                    465: PPCDACA::implementsDACA(IORegistryEntry *device)
                    466: {
                    467:     if (device != NULL) {
                    468:         OSData *s = NULL;
                    469: 
                    470: #ifdef DEBUGMODE
                    471:         IOLog("Matching DAC-3550 compatibility with %s\n", device->getName());
                    472: #endif // DEBUGMODE
                    473:         s = OSDynamicCast(OSData, device->getProperty("compatible"));
                    474: 
                    475:         if (s != NULL) {
                    476:             if(s->isEqualTo("daca", sizeof("daca")-1)) {
                    477:                 return true;
                    478:             }
                    479:             else {
                    480: #ifdef DEBUGMODE
                    481:                 IOLog("PPCDAC-3550::probe sound is compatible with %s.\n", (char*)s->getBytesNoCopy(0, sizeof("daca")-1));
                    482: #endif // DEBUGMODE
                    483:             }
                    484:         }
                    485:         else {
                    486: #ifdef DEBUGMODE
                    487:             IOLog("PPCDAC-3550::probe sound does not have a compatible property.\n");
                    488: #endif // DEBUGMODE
                    489:         }
                    490:     }
                    491:     else{
                    492: #ifdef DEBUGMODE
                    493:         IOLog("PPCDAC-3550::probe this hardware does not have a sound chip\n");
                    494: #endif // DEBUGMODE
                    495:     }
                    496:     return false;
                    497: }
                    498: 
                    499: // --------------------------------------------------------------------------
                    500: // Method: numberOfInputComponents
                    501: //
                    502: // Purpose:
                    503: //        returns the number of components for the input lines
                    504: //        the name registry describes the CHIP (which has 3 inputs
                    505: //       however, the iBook has no inputs, so I have to force 0
                    506: //        as output).
                    507: #define kCommonNumberOfInputComponents 0
                    508: 
                    509: int
                    510: PPCDACA::numberOfInputComponents()
                    511: {
                    512:     return kCommonNumberOfInputComponents;
                    513: }
                    514: 
                    515: // --------------------------------------------------------------------------
                    516: // Method: numberOfOutputComponents
                    517: //
                    518: // Purpose:
                    519: //        returns the number of components for the output lines
                    520: //        usually are 2 one is the internal speacker and the other
                    521: //        is the headphone line.
                    522: #define kCommonNumberOfOutputComponents 2
                    523: 
                    524: int
                    525: PPCDACA::numberOfOutputComponents()
                    526: {
                    527:     if(sound) {
                    528:         OSData *t;
                    529:         
                    530:         t = OSDynamicCast(OSData, sound->getProperty("#-outputs"));
                    531:         if (t != NULL) {
                    532:             return *(UInt32*)(t->getBytesNoCopy());
                    533:         }
                    534:     }
                    535:     return kCommonNumberOfOutputComponents;
                    536: }
                    537: 
                    538: 
                    539: // --------------------------------------------------------------------------
                    540: // Method: frameRate
                    541: //
                    542: // Purpose:
                    543: //        returns the frame rate as in the registry, if it is
                    544: //        not found in the registry, it returns the default value.
                    545: #define kCommonFrameRate 44100
                    546: 
                    547: UInt32
                    548: PPCDACA::frameRate(UInt32 index)
                    549: {
                    550:     if(sound) {
                    551:         OSData *t;
                    552: 
                    553:         t = OSDynamicCast(OSData, sound->getProperty("sample-rates"));
                    554:         if (t != NULL) {
                    555:             UInt32 *fArray = (UInt32*)(t->getBytesNoCopy());
                    556: 
                    557:             if ((fArray != NULL) && (index < fArray[0])){
                    558:                 // I could do >> 16, but in this way the code is portable and
                    559:                 // however any decent compiler will recognize this as a shift
                    560:                 // and do the right thing.
                    561:                 UInt32 fR = fArray[index + 1] / (UInt32)65536;
                    562: 
                    563: #ifdef DEBUGMODE
                    564:                 IOLog( "PPCDACA::frameRate (%ld)\n",  fR);
                    565: #endif
                    566:                 return fR;
                    567:             }
                    568:         }
                    569:     }
                    570: 
                    571:     return (UInt32)kCommonFrameRate;
                    572: }
                    573: 
                    574: // --------------------------------------------------------------------------
                    575: // Method: getI2CPort
                    576: //
                    577: // Purpose:
                    578: //        returns the i2c port to use for the audio chip.
                    579: UInt32
                    580: PPCDACA::getI2CPort()
                    581: {
                    582:     if(sound) {
                    583:         OSData *t;
                    584: 
                    585:         t = OSDynamicCast(OSData, sound->getProperty("AAPL,i2c-port-select"));
                    586:         if (t != NULL) {
                    587:             UInt32 myPort = *((UInt32*)t->getBytesNoCopy());
                    588:             return myPort;
                    589:         }
                    590: #ifdef DEBUGMODE
                    591:         else
                    592:             IOLog( "PPCDACA::getI2CPort missing property port\n");
                    593: #endif
                    594:     }
                    595:     
                    596:     return 0;
                    597: }
                    598: 
                    599: // --------------------------------------------------------------------------
                    600: // Method(s): componentDictionaryXXXXXX
                    601: //
                    602: // Purpose:
                    603: //        the next N methods return the strings for the component dictionaries
                    604: //        for each kind of component. As stated in the AWACS driver, these should
                    605: //        end in the driver resources.
                    606: 
                    607: // NOTE: (This is important !!!) the soundControls enum in the header file is
                    608: //       bounded to the following stings in this way:
                    609: //       for each component the control Id in the string must have the same value
                    610: //       of the corrispondent soundControls enum item. For example the sound control
                    611: //       enum item kHeadphonesVolLeft has value 4, so in sHeadphones the ID of the
                    612: //       volume left control must be 4.
                    613: 
                    614: char*
                    615: PPCDACA::componentDictionarySpeaker()
                    616: {
                    617:     static const char *sSpeaker =
                    618:     "{
                    619:     'Type' = 'Speaker';
                    620:     'Channels' = 2:8;
                    621:     'Master' = 1:8;
                    622:     'Controls' = {
                    623:         'MuteAll' = {
                    624:             'Type' = 'Mute';
                    625:             'Id' = 0:16;
                    626:             'Val' = 0:8;
                    627:             'Min' = 0:8;
                    628:             'Max' = 1:8;
                    629:             'Chan' = 0:8;
                    630:         };
                    631:         'VolumeLeft' = {
                    632:             'Type' = 'Volume';
                    633:             'Id' = 1:16;
                    634:             'Val' = 65535:16;
                    635:             'Min' = 0:16;
                    636:             'Max' = 65535:16;
                    637:             'Chan' = 1:8;
                    638:         };
                    639:         'VolumeRight' = {
                    640:             'Type' = 'Volume';
                    641:             'Id' = 2:16;
                    642:             'Val' = 65535:16;
                    643:             'Min' = 0:16;
                    644:             'Max' = 65535:16;
                    645:             'Chan' = 2:8;
                    646:         };
                    647:     };
                    648:     }";
                    649:     return (char*)sSpeaker;
                    650: }
                    651: 
                    652: char*
                    653: PPCDACA::componentDictionaryHeadphones()
                    654: {
                    655:     static const char *sHeadphones =
                    656:     "{
                    657:     'Type' = 'Headphones';
                    658:     'Channels' = 2:8;
                    659:     'Master' = 1:8;
                    660:     'Controls' = {
                    661:         'MuteAll' = {
                    662:             'Type' = 'Mute';
                    663:             'Id' = 3:16;
                    664:             'Val' = 0:8;
                    665:             'Min' = 0:8;
                    666:             'Max' = 1:8;
                    667:             'Chan' = 0:8;
                    668:         };
                    669:         'VolumeLeft' = {
                    670:             'Type' = 'Volume';
                    671:             'Id' = 4:16;
                    672:             'Val' = 65535:16;
                    673:             'Min' = 0:16;
                    674:             'Max' = 65535:16;
                    675:             'Chan' = 1:8;
                    676:         };
                    677:         'VolumeRight' = {
                    678:             'Type' = 'Volume';
                    679:             'Id' = 5:16;
                    680:             'Val' = 65535:16;
                    681:             'Min' = 0:16;
                    682:             'Max' = 65535:16;
                    683:             'Chan' = 2:8;
                    684:         };
                    685:     };
                    686:     'Inputs' = {
                    687:         'Jack' = {
                    688:             'Val' = 0:8;
                    689:             'Min' = 0:8;
                    690:             'Max' = 1:8;
                    691:         };
                    692:     };
                    693:     }";
                    694:     return (char*)sHeadphones;
                    695: }
                    696: 
                    697: char*
                    698: PPCDACA::componentDictionaryModem()
                    699: {
                    700:     static const char *sModem =
                    701:     "{
                    702:     'Type' = 'Modem';
                    703:     'Channels' = 2:8;
                    704:     'Controls' = {
                    705:         'MuteAll' = {
                    706:             'Type' = 'Mute';
                    707:             'Id' = 6:16;
                    708:             'Val' = 0:8;
                    709:             'Min' = 0:8;
                    710:             'Max' = 1:8;
                    711:             'Chan' = 0:8;
                    712:         };
                    713:     };
                    714:     'Inputs' = {
                    715:         'Jack' = {
                    716:             'Val' = 0:8;
                    717:             'Min' = 0:8;
                    718:             'Max' = 1:8;
                    719:         };
                    720:     };
                    721:     }";
                    722:     return (char*)sModem;
                    723: }
                    724: 
                    725: char*
                    726: PPCDACA::componentDictionaryCD()
                    727: {
                    728:     static const char *sCD =
                    729:     "{
                    730:     'Type' = 'CD';
                    731:     'Channels' = 2:8;
                    732:     'Controls' = {
                    733:         'MuteAll' = {
                    734:             'Type' = 'Mute';
                    735:             'Id' = 7:16;
                    736:             'Val' = 0:8;
                    737:             'Min' = 0:8;
                    738:             'Max' = 1:8;
                    739:             'Chan' = 0:8;
                    740:         };
                    741:     };
                    742:     }";
                    743:     return (char*)sCD;
                    744: }
                    745: 
                    746: char*
                    747: PPCDACA::componentDictionaryMixerOut()
                    748: {
                    749:     static const char *sMixerOut =
                    750:     "{
                    751:     'Type' = 'Mixer';
                    752:     'Channels' = 2:8;
                    753:     }";
                    754:     return (char*)sMixerOut;
                    755: }
                    756: 
                    757: char*
                    758: PPCDACA::componentDictionaryPassThru()
                    759: {
                    760:     static const char *sPassThru =
                    761:     "{
                    762:     'Type' = 'Feature';
                    763:     'Channels' = 2:8;
                    764:     'Controls' = {
                    765:         'MuteAll' = {
                    766:             'Type' = 'Mute';
                    767:             'Id' = 12:16;
                    768:             'Val' = 1:8;
                    769:             'Min' = 0:8;
                    770:             'Max' = 1:8;
                    771:             'Chan' = 0:8;
                    772:         };
                    773:         'VolumeLeft' = {
                    774:             'Type' = 'Volume';
                    775:             'Id' = 10:16;
                    776:             'Val' = 65535:16;
                    777:             'Min' = 0:16;
                    778:             'Max' = 65535:16;
                    779:             'Chan' = 1:8;
                    780:         };
                    781:         'VolumeRight' = {
                    782:             'Type' = 'Volume';
                    783:             'Id' = 11:16;
                    784:             'Val' = 65535:16;
                    785:             'Min' = 0:16;
                    786:             'Max' = 65535:16;
                    787:             'Chan' = 2:8;
                    788:         };
                    789:     };
                    790:     }";
                    791:     return (char*)sPassThru;
                    792: }
                    793: 
                    794: // --------------------------------------------------------------------------
                    795: // Method: dependentSetup
                    796: //
                    797: // Purpose:
                    798: //        this handles the setup of the DAC-3550 chip for each kind of
                    799: //        hosting hardware.
                    800: bool
                    801: PPCDACA::dependentSetup()
                    802: {
                    803:     // Sets the frame rate:
                    804:     UInt32 myFrameRate = frameRate(0);
                    805: 
                    806:     dacaSerialFormat = kSndIOFormatI2SSony;                    // start out in Sony format
                    807: 
                    808:     // Reads the initial status of the DAC3550A registers:
                    809:     // The following functions return "false" on the first generation of iBooks. However I wish to
                    810:     // keep them, since:
                    811:     // 1] it is bad to make assumptions on what the hardware can do and can not do here (eventually these
                    812:     //    assumptions should be made in the i2c driver).
                    813:     // 2] the next generation of iBook may supprot reading the DACA registers, and we will have more precise
                    814:     //    values in the "mirror" registers.
                    815:     if (interface != NULL) {
                    816:         interface->readI2CBus((UInt8)i2cBusAddrDAC3550A, i2cBusSubAddrSR_REG, & sampleRateReg, sizeof(sampleRateReg));
                    817:         interface->readI2CBus((UInt8)i2cBusAddrDAC3550A, i2cBusSubAddrAVOL, (UInt8*)& analogVolumeReg, sizeof(analogVolumeReg));
                    818:         interface->readI2CBus((UInt8)i2cBusAddrDAC3550A, i2cBusSubaddrGCFG, & configurationReg, sizeof(configurationReg));
                    819:     }
                    820: 
                    821:     // If nobody set a format before choose one:
                    822:     if (dacaSerialFormat ==  kSndIOFormatUnknown)
                    823:         dacaSerialFormat = kSndIOFormatI2SSony;
                    824: 
                    825:     // This call will set the next of the drame parametes
                    826:     // (dacaClockSource, dacaMclkDivisor,  dacaSclkDivisor)
                    827:     if (!setSampleParameters(myFrameRate, 0)) {
                    828:         IOLog("PPCDACA::dependentSetup can not set i2s sample rate\n");
                    829:         return false;
                    830:     }
                    831:     else if (!setDACASampleRate(myFrameRate)) {
                    832:         IOLog("PPCDACA::dependentSetup can not set DACA sample rate\n");
                    833:         return false;
                    834:     }
                    835:     else 
                    836:         setSerialFormatRegister(dacaClockSource, dacaMclkDivisor, dacaSclkDivisor, dacaSerialFormat);
                    837: 
                    838:     // Sets the molumes to max as in the audio registry:
                    839:     volumeInternalSpeakerLeft(65535);
                    840:     volumeInternalSpeakerRight(65535);
                    841:     volumeHeadphonesLeft(65535);
                    842:     volumeHeadphonesRight(65535);
                    843:     volumeCDLineLeft(65535);
                    844:     volumeCDLineRight(65535);
                    845: 
                    846:     return true;
                    847: }
                    848: 
                    849: // --------------------------------------------------------------------------
                    850: // Method: checkStatusRegister
                    851: //
                    852: // Purpose:
                    853: //        if the argument is true mutes the internal speaker, otherwise
                    854: //        it "unmutes" it.
                    855: void
                    856: PPCDACA::checkStatusRegister()
                    857: {
                    858:     if (statusChanged())  {
                    859:         int i;
                    860: 
                    861:         OSNumber * num = OSNumber::withNumber(lastStatus, 8);
                    862:         setProperty("Status", num);
                    863:         num->release();
                    864: 
                    865: #ifdef DEBUGMODE
                    866:         IOLog("New Status = 0x%02x\n", lastStatus);
                    867: #endif
                    868: 
                    869:         for (i = 0; i < numOutputComponents; i++)
                    870:             if (fOutputComponents[i] != NULL)
                    871:                 fOutputComponents[i]->Set(gInputsSym, gJackSym, outputComponentStatus(i));
                    872:     }
                    873: }
                    874: 
                    875: // --------------------------------------------------------------------------
                    876: // Method: outputComponentStatus
                    877: //
                    878: // Purpose:
                    879: //        checks the status of the jack line of the ith output component:
                    880: bool
                    881: PPCDACA::outputComponentStatus(int index)
                    882: {
                    883:     switch(index)
                    884:     {
                    885:         case kSpeaker:
                    886:             return false;      // the internal speaker does not have a jack
                    887: 
                    888:         case kHeadphones:      // check the headphones:
                    889:             return headphonesInserted();
                    890:     }
                    891: 
                    892:     return false;      // by deafult there is no jack
                    893: }
                    894: 
                    895: // --------------------------------------------------------------------------
                    896: // Method: muteInternalSpeaker
                    897: //
                    898: // Purpose:
                    899: //        if the argument is true mutes the internal speaker, otherwise
                    900: //        it "unmutes" it.
                    901: void
                    902: PPCDACA::muteInternalSpeaker(bool mute)
                    903: {
                    904:     if (mute){
                    905:         if (!headphonesInserted())
                    906:             writeRegisterBits(i2cBusSubAddrAVOL, 0, kRightAVOLMask | kLeftAVOLMask);
                    907:         internalSpeakerMuted = mute;
                    908:     }
                    909:     else {
                    910:         internalSpeakerMuted = mute;
                    911: 
                    912:         if (!headphonesInserted())
                    913:             writeRegisterBits(i2cBusSubAddrAVOL, internalSpeakerVolume, kRightAVOLMask | kLeftAVOLMask);
                    914:     }
                    915: }
                    916: 
                    917: // --------------------------------------------------------------------------
                    918: // Method: muteHeadphones
                    919: //
                    920: // Purpose:
                    921: //        if the argument is true mutes the rear panel mini jack, otherwise
                    922: //        it "unmutes" it.
                    923: void
                    924: PPCDACA::muteHeadphones(bool mute)
                    925: {
                    926:     if (mute){
                    927:         if (headphonesInserted())
                    928:             writeRegisterBits(i2cBusSubAddrAVOL, 0, kRightAVOLMask | kLeftAVOLMask);
                    929:         internalHeadphonesMuted = mute;       
                    930:     }
                    931:     else {
                    932:         internalHeadphonesMuted = mute;        
                    933: 
                    934:         if (headphonesInserted())
                    935:             writeRegisterBits(i2cBusSubAddrAVOL, internalHeadphonesVolume, kRightAVOLMask | kLeftAVOLMask);
                    936:     }
                    937: }
                    938: 
                    939: // --------------------------------------------------------------------------
                    940: // Method: muteCDLine
                    941: //
                    942: // Purpose:
                    943: //        if the argument is true mutes the line of the cd player
                    944: void
                    945: PPCDACA::muteCDLine(bool mute)
                    946: {
                    947:     // FIXME: Figure out how this is wired up:
                    948: }
                    949: 
                    950: // --------------------------------------------------------------------------
                    951: // Method: setModemInput
                    952: //
                    953: // Purpose:
                    954: //        selects the modem as input source (if bool = true)
                    955: void
                    956: PPCDACA::setModemInput(bool mod)
                    957: {
                    958: #ifdef DEBUGMODE
                    959:     IOLog( "PPCDACA::setModemInput: %s\n", (mod ? "True" : "False"));
                    960: #endif
                    961: }
                    962: 
                    963: 
                    964: // --------------------------------------------------------------------------
                    965: // Method: statusChanged()
                    966: //
                    967: // Purpose:
                    968: //        returns true if something changed in the status register:.
                    969: bool
                    970: PPCDACA::statusChanged()
                    971: {
                    972:     UInt8 currentStatusRegister = *(UInt8*)ioStatusRegister_GPIO12;
                    973: 
                    974:     if (lastStatus == currentStatusRegister)
                    975:         return (false);
                    976: 
                    977:     // Otherwise refresh the value of the last status register read and
                    978:     // returns that the value changed:
                    979:     lastStatus = currentStatusRegister;
                    980:     return (true);
                    981: }
                    982: 
                    983: // --------------------------------------------------------------------------
                    984: // Method: headphonesInserted
                    985: //
                    986: // Purpose:
                    987: //        returns true if the headphones are inserted.
                    988: bool
                    989: PPCDACA::headphonesInserted()
                    990: {
                    991:     return((lastStatus & kHeadphoneBit) == 0);
                    992: }
                    993: 
                    994: // --------------------------------------------------------------------------
                    995: // Method: volumeHeadphonesLeft & volumeHeadphonesRight
                    996: //
                    997: // Purpose:
                    998: //        sets the volume for the left and right channel of the internal
                    999: //        headphones.
                   1000: void
                   1001: PPCDACA::volumeHeadphonesLeft(int vol)
                   1002: {
                   1003:     analogVolumeReg = internalHeadphonesVolume;
                   1004:     setDACAVolume(vol, true);
                   1005:     internalHeadphonesVolume = analogVolumeReg;
                   1006: }
                   1007: 
                   1008: void
                   1009: PPCDACA::volumeHeadphonesRight(int vol)
                   1010: {
                   1011:     analogVolumeReg = internalHeadphonesVolume;
                   1012:     setDACAVolume(vol, false);
                   1013:     internalHeadphonesVolume = analogVolumeReg;
                   1014: }
                   1015: 
                   1016: // --------------------------------------------------------------------------
                   1017: // Method: volumeInternalSpeakerLeft & volumeInternalSpeakerRight
                   1018: //
                   1019: // Purpose:
                   1020: //        sets the volume for the left and right channel of the internal
                   1021: //        speaker.
                   1022: void
                   1023: PPCDACA::volumeInternalSpeakerLeft(int vol)
                   1024: {
                   1025:     analogVolumeReg = internalSpeakerVolume;
                   1026:     setDACAVolume(vol, true);
                   1027:     internalSpeakerVolume = analogVolumeReg;
                   1028: }
                   1029: 
                   1030: void
                   1031: PPCDACA::volumeInternalSpeakerRight(int vol)
                   1032: {
                   1033:     analogVolumeReg = internalSpeakerVolume;
                   1034:     setDACAVolume(vol, false);
                   1035:     internalSpeakerVolume = analogVolumeReg;
                   1036: }
                   1037: 
                   1038: // --------------------------------------------------------------------------
                   1039: // Method: volumeCDLineLeft & volumeCDLineRight
                   1040: //
                   1041: // Purpose:
                   1042: //        sets the volume for the left and right channel of the CD
                   1043: //        line.
                   1044: void
                   1045: PPCDACA::volumeCDLineLeft(int vol)
                   1046: {
                   1047: }
                   1048: 
                   1049: void
                   1050: PPCDACA::volumeCDLineRight(int vol)
                   1051: {
                   1052: }
                   1053: 
                   1054: /* =============================================================
                   1055:  * VERY Private Methods used to access to the DAC-3550 registers
                   1056:  * ============================================================= */
                   1057: 
                   1058: // --------------------------------------------------------------------------
                   1059: // Method: enableInterrupts
                   1060: //
                   1061: // Purpose:
                   1062: //         enable the interrupts for the I2S interface:
                   1063: bool
                   1064: PPCDACA::enableInterrupts()
                   1065: {
                   1066:     I2SSetIntCtlReg(kFrameCountEnable | kClocksStoppedEnable);
                   1067:     return true;
                   1068: }
                   1069: 
                   1070: // Method: disableInterrupts
                   1071: //
                   1072: // Purpose:
                   1073: //         disable the interrupts for the I2S interface:
                   1074: bool
                   1075: PPCDACA::disableInterrupts()
                   1076: {
                   1077:     I2SSetIntCtlReg(I2SGetIntCtlReg() & (~(kFrameCountEnable | kClocksStoppedEnable)));
                   1078:     return true;
                   1079: }
                   1080: 
                   1081: // --------------------------------------------------------------------------
                   1082: // Method: clockRun
                   1083: //
                   1084: // Purpose:
                   1085: //         starts and stops the clock count:
                   1086: bool
                   1087: PPCDACA::clockRun(bool start)
                   1088: {
                   1089:     bool success = true;
                   1090:     UInt32 *baseInterrupt = (UInt32*)soundConfigSpace + kI2SIntCtlOffset;
                   1091: 
                   1092: #ifdef DEBUGMODE
                   1093:     IOLog("PPCDACA::clockRun(%s) 1] 0x%08lx -> 0x%08lx\n", (start ? "true" : "false"), (UInt32)baseInterrupt, *baseInterrupt);
                   1094: #endif
                   1095: 
                   1096:     if (start) {
                   1097:         KLSetRegister(ioClockBaseAddress, KLGetRegister(ioClockBaseAddress) | kI2S0ClockEnable);
                   1098:     }
                   1099:     else {
                   1100:         UInt16 loop = 50;
                   1101:         KLSetRegister(ioClockBaseAddress, KLGetRegister(ioClockBaseAddress) & (~kI2S0ClockEnable));
                   1102:         
                   1103:         while (((I2SGetIntCtlReg() & kClocksStoppedPending) == 0) && (loop--)) {
                   1104:             // it does not do anything, jut waites for the clock
                   1105:             // to stop
                   1106:             IOSleep(10);
                   1107: #ifdef DEBUGMODE
                   1108:             IOLog("PPCDACA::clockRun(%s) 2] 0x%08lx -> 0x%08lx\n", (start ? "true" : "false"), (UInt32)baseInterrupt, *baseInterrupt);
                   1109: #endif
                   1110:         }
                   1111: 
                   1112:         // we are successful if the clock actually stopped.
                   1113:         success =  ((I2SGetIntCtlReg() & kClocksStoppedPending) != 0);
                   1114:     }
                   1115: 
                   1116: #ifdef DEBUGMODE
                   1117:     if (!success)
                   1118:         IOLog("PPCDACA::clockRun(%s) failed\n", (start ? "true" : "false"));
                   1119: #endif
                   1120: 
                   1121:     return success;
                   1122: }
                   1123: 
                   1124: // --------------------------------------------------------------------------
                   1125: // Method: setSampleRate
                   1126: //
                   1127: // Purpose:
                   1128: //        Sets the sample rate on the I2S bus
                   1129: bool
                   1130: PPCDACA::setSampleParameters(UInt32 sampleRate, UInt32 mclkToFsRatio)
                   1131: {
                   1132:     UInt32     mclkRatio;
                   1133:     UInt32     reqMClkRate;
                   1134: 
                   1135:     mclkRatio = mclkToFsRatio;                 // remember the MClk ratio required
                   1136: 
                   1137:     if ( mclkRatio == 0 )                                                                                                                                                             // or make one up if MClk not required
                   1138:         mclkRatio = 64;                                // use 64 x ratio since that will give us the best characteristics
                   1139:     
                   1140:     reqMClkRate = sampleRate * mclkRatio;      // this is the required MClk rate
                   1141: 
                   1142:     // look for a source clock that divides down evenly into the MClk
                   1143:     if ((kClock18MHz % reqMClkRate) == 0) {
                   1144:         // preferential source is 18 MHz
                   1145:         dacaClockSource = kClock18MHz;
                   1146:     }
                   1147:     else if ((kClock45MHz % reqMClkRate) == 0) {
                   1148:         // next check 45 MHz clock
                   1149:         dacaClockSource = kClock45MHz;
                   1150:     }
                   1151:     else if ((kClock49MHz % reqMClkRate) == 0) {
                   1152:         // last, try 49 Mhz clock
                   1153:         dacaClockSource = kClock49MHz;
                   1154:     }
                   1155:     else {
                   1156:         IOLog("PPCDACA::setSampleParameters Unable to find a suitable source clock (no globals changes take effect)\n");
                   1157:         return false;
                   1158:     }
                   1159: 
                   1160:     // get the MClk divisor
                   1161:     IOLog("PPCDACA:setSampleParameters %ld / %ld =", (UInt32)dacaClockSource, (UInt32)reqMClkRate); 
                   1162:     dacaMclkDivisor = dacaClockSource / reqMClkRate;
                   1163:     IOLog("%ld\n", dacaMclkDivisor);
                   1164:     switch (dacaSerialFormat)                                  // SClk depends on format
                   1165:     {
                   1166:         case kSndIOFormatI2SSony:
                   1167:         case kSndIOFormatI2S64x:
                   1168:             dacaSclkDivisor = mclkRatio / k64TicksPerFrame;    // SClk divisor is MClk ratio/64
                   1169:             break;
                   1170:         case kSndIOFormatI2S32x:
                   1171:             dacaSclkDivisor = mclkRatio / k32TicksPerFrame;    // SClk divisor is MClk ratio/32
                   1172:             break;
                   1173:         default:
                   1174:             IOLog("PPCDACA::setSampleParameters Invalid serial format\n");
                   1175:             return false;
                   1176:             break;
                   1177:     }
                   1178: 
                   1179:     return true;
                   1180:  }
                   1181: 
                   1182: 
                   1183: // --------------------------------------------------------------------------
                   1184: // Method: setSerialFormatRegister
                   1185: //
                   1186: // Purpose:
                   1187: //        Set global values to the serial format register
                   1188: void
                   1189: PPCDACA::setSerialFormatRegister(ClockSource clockSource, UInt32 mclkDivisor, UInt32 sclkDivisor, SoundFormat serialFormat)
                   1190: {
                   1191:     UInt32     regValue = 0;
                   1192: 
                   1193: #ifdef DEBUGMODE
                   1194:     IOLog("PPCDACA::SetSerialFormatRegister(%d,%d,%d,%d)\n",(int)clockSource, (int)mclkDivisor, (int)sclkDivisor, (int)serialFormat);
                   1195: #endif // DEBUGMODE
                   1196: 
                   1197:     switch ((int)clockSource)
                   1198:     {
                   1199:         case kClock18MHz:
                   1200:             regValue = kClockSource18MHz;
                   1201:             break;
                   1202:         case kClock45MHz:
                   1203:             regValue = kClockSource45MHz;
                   1204:             break;
                   1205:         case kClock49MHz:
                   1206:             regValue = kClockSource49MHz;
                   1207:             break;
                   1208:         default:
                   1209:             IOLog("PPCDACA::SetSerialFormatRegister(%d,%d,%d,%d): Invalid clock source\n",(int)clockSource, (int)mclkDivisor, (int)sclkDivisor, (int)serialFormat);
                   1210:             break;
                   1211:     }
                   1212: 
                   1213:     switch (mclkDivisor)
                   1214:     {
                   1215:         case 1:
                   1216:             regValue |= kMClkDivisor1;
                   1217:             break;
                   1218:         case 3:
                   1219:             regValue |= kMClkDivisor3;
                   1220:             break;
                   1221:         case 5:
                   1222:             regValue |= kMClkDivisor5;
                   1223:             break;
                   1224:         default:
                   1225:             regValue |= (((mclkDivisor / 2) - 1) << kMClkDivisorShift) & kMClkDivisorMask;
                   1226:             break;
                   1227:     }
                   1228: 
                   1229:     switch ((int)sclkDivisor)
                   1230:     {
                   1231:         case 1:
                   1232:             regValue |= kSClkDivisor1;
                   1233:             break;
                   1234:         case 3:
                   1235:             regValue |= kSClkDivisor3;
                   1236:             break;
                   1237:         default:
                   1238:             regValue |= (((sclkDivisor / 2) - 1) << kSClkDivisorShift) & kSClkDivisorMask;
                   1239:             break;
                   1240:     }
                   1241:     regValue |= kSClkMaster;                                                                           // force master mode
                   1242: 
                   1243:     switch (serialFormat)
                   1244:     {
                   1245:         case kSndIOFormatI2SSony:
                   1246:             regValue |= kSerialFormatSony;
                   1247:             break;
                   1248:         case kSndIOFormatI2S64x:
                   1249:             regValue |= kSerialFormat64x;
                   1250:             break;
                   1251:         case kSndIOFormatI2S32x:
                   1252:             regValue |= kSerialFormat32x;
                   1253:             break;
                   1254:         default:
                   1255:             IOLog("PPCDACA::SetSerialFormatRegister(%d,%d,%d,%d): Invalid serial format\n",(int)clockSource, (int)mclkDivisor, (int)sclkDivisor, (int)serialFormat);
                   1256:             break;
                   1257:     }
                   1258: 
                   1259:     // This is a 3 step process:
                   1260: 
                   1261:     // 1] Stop the clock:
                   1262:     clockRun(false);
                   1263: 
                   1264:     // 2] Setup the serial format register
                   1265:     I2SSetSerialFormatReg(regValue);
                   1266: 
                   1267:     // 3 restarts the clock:
                   1268:     clockRun(true);    
                   1269: }
                   1270: 
                   1271: // --------------------------------------------------------------------------
                   1272: // Method: setDACASampleRate
                   1273: //
                   1274: // Purpose:
                   1275: //        Gets the sample rate and makes it in a format that is compatible
                   1276: //        with the adac register. The funtion returs false if it fails.
                   1277: bool
                   1278: PPCDACA::setDACASampleRate(UInt rate)
                   1279: {
                   1280:     UInt32 dacRate = 0;
                   1281: 
                   1282: #ifdef DEBUGMODE
                   1283:     IOLog("PPCDACA::setDACASampleRate(%d)\n", rate);
                   1284: #endif // DEBUGMODE
                   1285: 
                   1286:         switch (rate)
                   1287:         {
                   1288:                 case 44100:                            // 32 kHz - 48 kHz
                   1289:                         dacRate = kSRC_48SR_REG;
                   1290:                         break;
                   1291: 
                   1292:                 default:
                   1293:                 IOLog("PPCDACA::setDACASampleRate, supports only 44100 Hz (for now)\n");
                   1294:                         break;
                   1295:         }
                   1296: 
                   1297:         return(writeRegisterBits(i2cBusSubAddrSR_REG, dacRate, kSampleRateControlMask));
                   1298: }
                   1299: 
                   1300: 
                   1301: // --------------------------------------------------------------------------
                   1302: // Method: setDACAVolume
                   1303: //
                   1304: // Purpose:
                   1305: //        sets the volume for the left or right channel. The first argument is
                   1306: //        the wnated volume (as a range from 0 to 255), while the second argument
                   1307: //        is a boolean (true for the right channel, false for the left channel).
                   1308: bool
                   1309: PPCDACA::setDACAVolume(UInt16 volume, bool isLeft)
                   1310: {
                   1311:     UInt8 newVolume = ((UInt32)((UInt32)volume * (UInt32)kVolumeRangeLevel_VOL) / (UInt32)65535 + (UInt32)kMinVolumeLevel_VOL);
                   1312:     bool success = true;
                   1313: 
                   1314:     if (isLeft) // Sets the volume on the right channel
                   1315:         success = writeRegisterBits(i2cBusSubAddrAVOL, (newVolume << kLeftAVOLShift), kLeftAVOLMask);
                   1316:     else       // Sets the volume on the left channel
                   1317:         success = writeRegisterBits(i2cBusSubAddrAVOL, (newVolume << kRightAVOLShift), kRightAVOLMask);
                   1318: 
                   1319:     return success;
                   1320: }
                   1321: 
                   1322: // ---------------------------------------------------------------------------------------
                   1323: // Method: writeRegisterBits
                   1324: //
                   1325: // Purpose:
                   1326: //      This function sets or clears bits in the Daca registers.  The first argument is the
                   1327: //      register sub-address, the second argument is a mask for turning bits on, while the third
                   1328: //      argument is a mask for turning bits off.
                   1329: bool
                   1330: PPCDACA::writeRegisterBits(UInt8 subAddress, UInt32 bitMaskOn, UInt32 bitMaskOff)
                   1331: {
                   1332:     UInt8 bitsOn = 0, bitsOff = 0, value;
                   1333:     UInt16 shortBitsOn = 0, shortBitsOff = 0, value16;
                   1334:     bool success = false;
                   1335: 
                   1336: #ifdef DEBUGMODE
                   1337:     IOLog("PPCDACA::writeRegisterBits(0x%x, 0x%08lx, 0x%08lx)\n", (UInt16)subAddress, bitMaskOn, bitMaskOff);
                   1338: #endif // DEBUGMODE
                   1339: 
                   1340:     // mask off irrelevant bytes
                   1341:     if (subAddress == i2cBusSubAddrAVOL) {
                   1342:         // 16-bit register
                   1343:         shortBitsOn = bitMaskOn & 0x0000FFFF;
                   1344:         shortBitsOff = bitMaskOff & 0x0000FFFF;
                   1345:     }
                   1346:     else {
                   1347:         // 8-bit registers
                   1348:         bitsOn = bitMaskOn & 0x000000FF;
                   1349:         bitsOff = bitMaskOff & 0x000000FF;
                   1350:     }
                   1351: 
                   1352:     switch (subAddress)
                   1353:     {
                   1354:         case i2cBusSubAddrSR_REG:
                   1355:             value = sampleRateReg | bitsOn;
                   1356:             value &= ~bitsOff;
                   1357:             // continue only if on bits are not already on and off bits are not already off
                   1358:             if (value != sampleRateReg) {
                   1359:                 success = interface->writeI2CBus((UInt8)i2cBusAddrDAC3550A, subAddress, &value, sizeof(value));
                   1360: 
                   1361:                 if (success)
                   1362:                     sampleRateReg = value;
                   1363:             }
                   1364:                 else {
                   1365:                     // If the sample rate is already set at the wanted value
                   1366:                     // we do not do anything, but we return success since from the
                   1367:                     // caller point of view it is as the sample rate was correctly
                   1368:                     // set.
                   1369:                     success = true;
                   1370:                 }
                   1371:                 break;
                   1372: 
                   1373:         case i2cBusSubAddrAVOL:
                   1374:             value16 = analogVolumeReg;
                   1375:             value16 &= ~shortBitsOff;
                   1376:             value16 |= shortBitsOn;
                   1377:             // continue only if on bits are not already on and off bits are not already off
                   1378:             if (value16 !=analogVolumeReg)
                   1379:             {
                   1380:                 // It changes the volume for real only if the current output is not muted.
                   1381:                 if (((!headphonesInserted()) && (!internalSpeakerMuted)) ||
                   1382:                     (headphonesInserted() && (!internalHeadphonesMuted)))
                   1383:                     success = interface->writeI2CBus((UInt8)i2cBusAddrDAC3550A, subAddress, (UInt8*)&value16, sizeof(value16));
                   1384:                 else
                   1385:                     success = true;
                   1386: 
                   1387:                 if (success)
                   1388:                     analogVolumeReg = value16;
                   1389:             }
                   1390:                 else {
                   1391:                     // If the volume is already set at the wanted value
                   1392:                     // we do not do anything, but we return success since from the
                   1393:                     // caller point of view it is as the volume was correctly
                   1394:                     // set.
                   1395:                     success = true;
                   1396:                 }
                   1397:                 break;
                   1398: 
                   1399:         case i2cBusSubaddrGCFG:
                   1400:             value = configurationReg | bitsOn;
                   1401:             value &= ~bitsOff;
                   1402:             // continue only if on bits are not already on and off bits are not already off
                   1403:             if (value != configurationReg)
                   1404:             {
                   1405:                 success = interface->writeI2CBus((UInt8)i2cBusAddrDAC3550A, subAddress, &value, sizeof(value));
                   1406:                 if (success)
                   1407:                     configurationReg = value;
                   1408:             }
                   1409:                 else {
                   1410:                     // If the config register is already set at the wanted value
                   1411:                     // we do not do anything, but we return success since from the
                   1412:                     // caller point of view it is as the configuration was correctly
                   1413:                     // set.
                   1414:                     success = true;
                   1415:                 }
                   1416:                 break;
                   1417: 
                   1418:         default:
                   1419:             IOLog("PPCDACA::writeRegisterBits 0x%x unknown subaddress\n", (UInt16)subAddress);
                   1420:             break;
                   1421:     }
                   1422:     return success;
                   1423: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.