Annotation of XNU/iokit/Drivers/audio/drvPPCAwacs/PPCAwacs.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:  * Hardware independent (relatively) code for the Awacs Controller 
                     24:  *
                     25:  * HISTORY
                     26:  *
                     27:  * 14-Jan-1999  
                     28:  *     Created.
                     29:  *
                     30:  */
                     31: #include <IOKit/assert.h>
                     32: #include <IOKit/system.h>
                     33: 
                     34: #include <IOKit/IOLib.h>
                     35: #include <IOKit/IODeviceTreeSupport.h>
                     36: #include <IOKit/IOPlatformExpert.h>
                     37: #include <IOKit/ppc/IODBDMA.h>
                     38: #include "PPCAwacs.h"
                     39: #include "awacs_hw.h"
                     40: 
                     41: /*
                     42:  * From Excelsior:Toolbox:SoundMgr:Hardware:Ports:OutPorts.cp & GossamerOut.h
                     43:  */
                     44: #define kSGS7433Addr 0x8A
                     45: #define kSGSNumRegs 7
                     46: unsigned char SGSShadow[kSGSNumRegs] =
                     47:                                         { 0x09,                /* Adr:1, AutoIncr                              */
                     48:                                           0x20,        /* Reg 1: Vol  = 0dB                            */
                     49:                                           0xFF,        /* Reg 2: Bass = 0dB, Treble = 0dB              */
                     50:                                           0x00,        /* Reg 3: Internal Spkr - Left  Atten = 0dB     */
                     51:                                           0x0A,         /* Reg 4: Line Out     - Left  Atten = -10dB   */
                     52:                                           0x00,         /* Reg 5: Internal Spkr - Right Atten = 0dB    */
                     53:                                           0x0A };      /* Reg 6: Line Out      - Right Atten = -10dB   */
                     54: #define        sgsBalMuteBit           0x020   // When this bit is set in the output fader/ balance regs, the channel is muted
                     55: #define        sgsBalVolBits           0x1F    // mask for volume steps
                     56: #define        kLFAttnReg              0x03    // Left Front (ie everything except the rear spkr jack)
                     57: #define        kRFAttnReg              0x05    // Right Front
                     58: #define        kLRAttnReg              0x04    // Left Rear (the rear speaker jack only)
                     59: #define        kRRAttnReg              0x06    // Right Rear
                     60: 
                     61: 
                     62: // "deivce-id" values come from the sound block in Open Firmware on B&W G3's and later
                     63: const u_int32_t kG4WithAwacsDeviceID = 5;
                     64: const u_int32_t kiMacDVDeviceID      = 8;
                     65:  
                     66: /*
                     67:  *
                     68:  */
                     69: 
                     70: static void    writeCodecControlReg( volatile awacs_regmap_t *ioBaseAwacs, int value );
                     71: static void    writeSoundControlReg( volatile awacs_regmap_t *ioBaseAwacs, int value );
                     72: static u_int32_t readCodecStatusReg( volatile awacs_regmap_t *ioBaseAwacs );
                     73: static int     readClippingCountReg( volatile awacs_regmap_t *ioBaseAwacs );
                     74: 
                     75: static void writeCodecControlReg( volatile awacs_regmap_t *ioBaseAwacs, int value )
                     76: {
                     77:   int          CodecControlReg;
                     78: 
                     79: #if 0
                     80:       IOLog( "PPCSound(awacs): CodecControlReg @ %08x = %08x\n\r", (int)&ioBaseAwacs->CodecControlRegister, value);
                     81: #endif
                     82: 
                     83:   OSWriteLittleInt32(&ioBaseAwacs->CodecControlRegister, 0, value );
                     84:   eieio();
                     85: 
                     86:   do
                     87:     {
                     88:       CodecControlReg =  OSReadLittleInt32( &ioBaseAwacs->CodecControlRegister, 0 );
                     89:       eieio();
                     90:     }
                     91:   while ( CodecControlReg & kCodecCtlBusy );
                     92: }
                     93: 
                     94: 
                     95: static void writeSoundControlReg( volatile awacs_regmap_t *ioBaseAwacs, int value )
                     96: {
                     97: 
                     98: #if 0
                     99:       IOLog( "PPCSound(awacs): SoundControlReg = %08x\n\r", value);
                    100: #endif
                    101: 
                    102:   OSWriteLittleInt32( &ioBaseAwacs->SoundControlRegister, 0, value );
                    103:   eieio();
                    104: }
                    105: 
                    106: static u_int32_t readCodecStatusReg( volatile awacs_regmap_t *ioBaseAwacs )
                    107: {
                    108:   return OSReadLittleInt32( &ioBaseAwacs->CodecStatusRegister, 0 );
                    109: }
                    110: 
                    111: static int readClippingCountReg( volatile awacs_regmap_t *ioBaseAwacs )
                    112: {
                    113:   return OSReadLittleInt32( &ioBaseAwacs->ClippingCountRegister, 0 );
                    114: }
                    115: 
                    116: static void writeSGSRegs()
                    117: {
                    118:     int i;
                    119:     for (i = 0; i < kSGSNumRegs; i++) {
                    120:         (*PE_write_IIC)(kSGS7433Addr, i, SGSShadow[i]);
                    121:     }
                    122: }
                    123: 
                    124: #define super IOAudioBus
                    125: 
                    126: OSDefineMetaClassAndStructors( PPCAwacs, IOAudioBus )
                    127: 
                    128: /*
                    129:  * Public Instance Methods
                    130:  */
                    131: bool PPCAwacs::init(OSDictionary * properties)
                    132: {
                    133:     if (!super::init(properties))
                    134:             return false;
                    135:     if(!properties)
                    136:        return false;   // Need to know where Awacs is!
                    137: 
                    138:     return true;
                    139: }
                    140: 
                    141: void PPCAwacs::free()
                    142: {
                    143:     super::free();
                    144: }
                    145: 
                    146: bool PPCAwacs::start(IOService * provider)
                    147: {
                    148:     IOMemoryMap *      map;
                    149:     u_int32_t          awacsVersion;
                    150:     IORegistryEntry *  perch = NULL;
                    151:     IORegistryEntry *  sound = NULL;
                    152: 
                    153:     if( !super::start(provider))
                    154:         return (false);
                    155: 
                    156:     map = provider->mapDeviceMemoryWithIndex(kAudioDMAdeviceInt);
                    157:     if(!map) {
                    158:         return false;
                    159:     }
                    160:     fIOBaseAwacs = (awacs_regmap_t *)map->getVirtualAddress();
                    161: 
                    162:     if (!AllocateStreams(kNumDMAStreams))
                    163:         return false;
                    164: 
                    165:     map = provider->mapDeviceMemoryWithIndex(kAudioDMAtxInt);
                    166:     if(!map) {
                    167:         return false;
                    168:     }
                    169:     DefineStream(kAudioDMAOutputStream, kOutput, 44100L, (IODBDMAChannelRegisters*)map->getVirtualAddress());
                    170: 
                    171:     map = provider->mapDeviceMemoryWithIndex(kAudioDMArxInt);
                    172:     if(!map) {
                    173:         return false;
                    174:     }
                    175:     DefineStream(kAudioDMAInputStream, kInput, 44100L, (IODBDMAChannelRegisters*)map->getVirtualAddress());
                    176: 
                    177:     // Dig out the sound nub that's below our match
                    178:     fDetects = 2;      // Mic jack and lineout jack
                    179:     fOutputs = 2;      // internal speaker and lineout
                    180: 
                    181:     fIsG4WithAwacs = FALSE;
                    182:     fIsiMacDVWithAwacs = FALSE;
                    183: 
                    184:     sound = provider->childFromPath("sound", gIODTPlane);
                    185:     if(sound) {
                    186:         OSData *t;
                    187:         t = OSDynamicCast(OSData, sound->getProperty("#-detects"));
                    188:        if(t) {
                    189:             fDetects = *(UInt32*)(t->getBytesNoCopy());
                    190:        }
                    191:         t = OSDynamicCast(OSData, sound->getProperty("#-outputs"));
                    192:         if(t) {
                    193:             fOutputs = *(UInt32*)(t->getBytesNoCopy());
                    194:         }
                    195: 
                    196: #if 1
                    197:     IOLog( "PPCAwacs::start: about to get device-id\n" );
                    198: #endif
                    199:         // Check for G4WithAwacs & iMacDVWithAwacs
                    200:         // Note: "device-id" found on New World machines and later (B&W G3 is first such box)
                    201:         t = OSDynamicCast( OSData, sound->getProperty( "device-id" ) );
                    202:         if( t ) {
                    203:             u_int32_t deviceID = *(UInt32 *)( t->getBytesNoCopy() );
                    204: #if 1
                    205:     IOLog( "PPCAwacs::start: got deviceID = %d\n", deviceID );
                    206: #endif
                    207:             switch ( deviceID )
                    208:             {
                    209:                 case kG4WithAwacsDeviceID:
                    210:                     fIsG4WithAwacs = TRUE;
                    211:                     break;
                    212:                 case kiMacDVDeviceID:
                    213:                     fIsiMacDVWithAwacs = TRUE;
                    214:                     break;
                    215:                 default: ;// NOP         
                    216:             }
                    217:         }
                    218:     }
                    219: 
                    220:     // Debugging aids
                    221:     OSNumber *num = OSNumber::withNumber(fDetects, 32);
                    222:     setProperty("Detects", num);
                    223:     num->release();
                    224:     num = OSNumber::withNumber(fOutputs, 32);
                    225:     setProperty("Outputs", num);
                    226:     num->release();
                    227: 
                    228:     perch = IORegistryEntry::fromPath("/perch", gIODTPlane );
                    229:     fIICAudioDevPresent = perch != NULL;
                    230:     if(fIICAudioDevPresent) {
                    231:         waitForService( resourceMatching( "IOiic0" ));
                    232:     }
                    233:     fCodecStatus = readCodecStatusReg( fIOBaseAwacs );
                    234:     awacsVersion = (fCodecStatus & kRevisionNumberMask) >> kRevisionNumberShft;
                    235: 
                    236:     /*
                    237:      * Mask out the input bits in the cached status register so that the AudioComponents
                    238:      * get updated to the correct values the first time we update the device status
                    239:      * (Everything is initialized on the assumption that nothing is plugged in)
                    240:      */
                    241:     fCodecStatus &= ~kAllSense;
                    242: 
                    243:     if ( awacsVersion > kAWACSMaxVersion ) {
                    244:         fCodecControlRegister[5] = kCodecCtlAddress5 | kCodecCtlEMSelect0;
                    245:         writeCodecControlReg(  fIOBaseAwacs, fCodecControlRegister[5] );
                    246:         fCodecControlRegister[6] = kCodecCtlAddress6 | kCodecCtlEMSelect0;
                    247:         writeCodecControlReg(  fIOBaseAwacs, fCodecControlRegister[6] );
                    248:     }
                    249: 
                    250:     if ( fIICAudioDevPresent ) {
                    251:        writeSGSRegs();
                    252:     }
                    253: 
                    254:     fSoundControlRegister = ( kInSubFrame0      |
                    255:                               kOutSubFrame0     |
                    256:                               kHWRate44100        );
                    257:     writeSoundControlReg( fIOBaseAwacs, fSoundControlRegister);
                    258: 
                    259:     fCodecControlRegister[0] = kCodecCtlAddress0 | kCodecCtlEMSelect0;
                    260:     fCodecControlRegister[1] = kCodecCtlAddress1 | kCodecCtlEMSelect0;
                    261:     fCodecControlRegister[2] = kCodecCtlAddress2 | kCodecCtlEMSelect0;
                    262:     fCodecControlRegister[4] = kCodecCtlAddress4 | kCodecCtlEMSelect0;
                    263: 
                    264:     fCodecControlRegister[0] |= (kMicInput | kDefaultMicGain);
                    265: 
                    266:     // Gossamer passes sound right through to be later controlled
                    267:     // by the SGS audio processor--turn on these pass-thru ports.
                    268:     if ( fIICAudioDevPresent || fIsG4WithAwacs ) {
                    269:         fCodecControlRegister[1] |= (kParallelOutputEnable);
                    270:     }
                    271: 
                    272:     writeCodecControlReg(  fIOBaseAwacs, fCodecControlRegister[0] );
                    273:     writeCodecControlReg(  fIOBaseAwacs, fCodecControlRegister[1] );
                    274:     writeCodecControlReg(  fIOBaseAwacs, fCodecControlRegister[2] );
                    275:     writeCodecControlReg(  fIOBaseAwacs, fCodecControlRegister[4] );
                    276: 
                    277:     startWorkLoop();
                    278: 
                    279:     if(perch)
                    280:        perch->release();
                    281:     if(sound)
                    282:        sound->release();
                    283:     return true;
                    284: }
                    285: 
                    286: 
                    287: void PPCAwacs::stop(IOService *provider)
                    288: {
                    289:     super::stop(provider);
                    290:     FreeStreams();
                    291: }
                    292: 
                    293: void PPCAwacs::CreateAudioTopology(IOCommandQueue *queue)
                    294: {
                    295: /*
                    296:  * These should be resources in the loadable driver
                    297:  */
                    298: static const char *sSpeaker =
                    299: "{
                    300:     'Type' = 'Speaker';
                    301:     'Channels' = 2:8;
                    302:     'Master' = 1:8;
                    303:     'Controls' = {   
                    304:        'MuteAll' = {
                    305:             'Type' = 'Mute';
                    306:             'Id' = 0:16;
                    307:             'Val' = 0:8;
                    308:             'Min' = 0:8;
                    309:             'Max' = 1:8;
                    310:             'Chan' = 0:8;
                    311:         };
                    312:        'VolumeLeft' = {
                    313:             'Type' = 'Volume';
                    314:             'Id' = 1:16;
                    315:             'Val' = 65535:16;
                    316:             'Min' = 0:16;
                    317:             'Max' = 65535:16;
                    318:             'Chan' = 1:8;
                    319:         };
                    320:         'VolumeRight' = {
                    321:             'Type' = 'Volume';
                    322:             'Id' = 2:16;
                    323:             'Val' = 65535:16;
                    324:             'Min' = 0:16;
                    325:             'Max' = 65535:16;
                    326:             'Chan' = 2:8;
                    327:         };
                    328:     };
                    329: }";
                    330: 
                    331: static const char *sHeadphones =
                    332: "{
                    333:     'Type' = 'Headphones';
                    334:     'Channels' = 2:8;
                    335:     'Master' = 1:8;
                    336:     'Controls' = {   
                    337:        'MuteAll' = {
                    338:             'Type' = 'Mute';
                    339:             'Id' = 3:16;
                    340:             'Val' = 0:8;
                    341:             'Min' = 0:8;
                    342:             'Max' = 1:8;
                    343:             'Chan' = 0:8;
                    344:         };
                    345:        'VolumeLeft' = {
                    346:             'Type' = 'Volume';
                    347:             'Id' = 4:16;
                    348:             'Val' = 65535:16;
                    349:             'Min' = 0:16;
                    350:             'Max' = 65535:16;
                    351:             'Chan' = 1:8;
                    352:         };
                    353:         'VolumeRight' = {
                    354:             'Type' = 'Volume';
                    355:             'Id' = 5:16;
                    356:             'Val' = 65535:16;
                    357:             'Min' = 0:16;
                    358:             'Max' = 65535:16;
                    359:             'Chan' = 2:8;
                    360:         };
                    361:     };
                    362:     'Inputs' = {
                    363:         'Jack' = {
                    364:             'Val' = 0:8;
                    365:             'Min' = 0:8;
                    366:             'Max' = 1:8;
                    367:        };
                    368:     };
                    369: }";
                    370: 
                    371: static const char *sMicrophone =
                    372: "{
                    373:     'Type' = 'Microphone';
                    374:     'Channels' = 2:8;
                    375:     'Controls' = {   
                    376:        'MuteAll' = {
                    377:             'Type' = 'Mute';
                    378:             'Id' = 6:16;
                    379:             'Val' = 0:8;
                    380:             'Min' = 0:8;
                    381:             'Max' = 1:8;
                    382:             'Chan' = 0:8;
                    383:         };
                    384:     };
                    385:     'Inputs' = {
                    386:         'Jack' = {
                    387:             'Val' = 0:8;
                    388:             'Min' = 0:8;
                    389:             'Max' = 1:8;
                    390:        };
                    391:     };
                    392: }";
                    393: 
                    394: static const char *sLineout =
                    395: "{
                    396:     'Type' = 'LineOut';
                    397:     'Channels' = 2:8;
                    398:     'Controls' = {   
                    399:        'MuteAll' = {
                    400:             'Type' = 'Mute';
                    401:             'Id' = 13:16;
                    402:             'Val' = 0:8;
                    403:             'Min' = 0:8;
                    404:             'Max' = 1:8;
                    405:             'Chan' = 0:8;
                    406:         };
                    407:     };
                    408:     'Inputs' = {
                    409:         'Jack' = {
                    410:             'Val' = 0:8;
                    411:             'Min' = 0:8;
                    412:             'Max' = 1:8;
                    413:        };
                    414:     };
                    415: }";
                    416: 
                    417: static const char *sCD =
                    418: "{
                    419:     'Type' = 'CD';
                    420:     'Channels' = 2:8;
                    421:     'Controls' = {   
                    422:        'MuteAll' = {
                    423:             'Type' = 'Mute';
                    424:             'Id' = 7:16;
                    425:             'Val' = 0:8;
                    426:             'Min' = 0:8;
                    427:             'Max' = 1:8;
                    428:             'Chan' = 0:8;
                    429:         };
                    430:     };
                    431: }";
                    432: 
                    433: static const char *sMixerIn =
                    434: "{
                    435:     'Type' = 'Mixer';
                    436:     'Channels' = 2:8;
                    437:     'Controls' = {   
                    438:        'VolumeLeft' = {
                    439:             'Type' = 'Volume';
                    440:             'Id' = 8:16;
                    441:             'Val' = 65535:16;
                    442:             'Min' = 0:16;
                    443:             'Max' = 65535:16;
                    444:             'Chan' = 1:8;
                    445:         };
                    446:         'VolumeRight' = {
                    447:             'Type' = 'Volume';
                    448:             'Id' = 9:16;
                    449:             'Val' = 65535:16;
                    450:             'Min' = 0:16;
                    451:             'Max' = 65535:16;
                    452:             'Chan' = 2:8;
                    453:         };
                    454:     };
                    455: }";
                    456: 
                    457: static const char *sPassThru = 
                    458: "{
                    459:     'Type' = 'Feature';
                    460:     'Channels' = 2:8;
                    461:     'Controls' = {   
                    462:        'MuteAll' = {
                    463:             'Type' = 'Mute';
                    464:             'Id' = 12:16;
                    465:             'Val' = 1:8;
                    466:             'Min' = 0:8;
                    467:             'Max' = 1:8;
                    468:             'Chan' = 0:8;
                    469:         };
                    470:        'VolumeLeft' = {
                    471:             'Type' = 'Volume';
                    472:             'Id' = 10:16;
                    473:             'Val' = 65535:16;
                    474:             'Min' = 0:16;
                    475:             'Max' = 65535:16;
                    476:             'Chan' = 1:8;
                    477:         };
                    478:         'VolumeRight' = {
                    479:             'Type' = 'Volume';
                    480:             'Id' = 11:16;
                    481:             'Val' = 65535:16;
                    482:             'Min' = 0:16;
                    483:             'Max' = 65535:16;
                    484:             'Chan' = 2:8;
                    485:         };
                    486:     };
                    487: }";
                    488: 
                    489: static const char *sMixerOut =
                    490: "{
                    491:     'Type' = 'Mixer';
                    492:     'Channels' = 2:8;
                    493: }";
                    494: 
                    495:     IOAudioComponentImpl *mixerIn;
                    496:     IOAudioComponentImpl *mixerOut;
                    497:     IOAudioComponentImpl *microphone;
                    498:     IOAudioComponentImpl *lineout;
                    499:     IOAudioComponentImpl *headphones;
                    500:     AudioStreamIndex outputStream;
                    501:     AudioStreamIndex inputStream;
                    502: 
                    503:     if (!fStreams)
                    504:          return;
                    505: 
                    506:     outputStream = firstStreamAfter(kOutput, 0);
                    507:     inputStream = firstStreamAfter(kInput, 0);
                    508:     if ((outputStream == kInvalidStreamIndex) || (inputStream == kInvalidStreamIndex)) {
                    509:        IOLog("PPCAwacs::CreateAudioTopology called without available DMA streams\n");
                    510:         return;
                    511:     }
                    512:     else
                    513:        IOLog("PPCAwacs::CreateAudioTopology input stream is %d output is %d\n", inputStream, outputStream);
                    514: 
                    515:     mixerOut = buildComponentAndAttach(GetStream(outputStream), NULL, sMixerOut, queue);
                    516:     headphones = buildComponentAndAttach(mixerOut, NULL, sHeadphones, queue);
                    517:     buildComponentAndAttach(mixerOut, NULL, sSpeaker, queue);
                    518:     microphone = buildComponentAndAttach(NULL, NULL, sMicrophone, queue);
                    519:     mixerIn = buildComponentAndAttach(microphone, GetStream(inputStream), sMixerIn, queue);
                    520:     buildComponentAndAttach(mixerIn, mixerOut, sPassThru, queue);
                    521:     buildComponentAndAttach(NULL, mixerIn, sCD, queue);
                    522: 
                    523:     /*
                    524:      * This stuff should perhaps be table-driven, depending on how much it varies
                    525:      * between different Mac models that use versions of Awacs wired up in different ways
                    526:      *
                    527:      * 9500:           Speaker Out jack = kHeadphoneSense
                    528:      *                 Microphone jack = kAux1Sense
                    529:      *
                    530:      * AllInOne:       Line Out jack = kAux1Sense
                    531:      *                 Microphone jack = kLineInSense
                    532:      *                 Either Headphone jack = kHeadphoneSense
                    533:      *
                    534:      * Beige G3:       Line Out jack = kAux1Sense
                    535:      *                 Microphone jack = kLineInSense
                    536:      *                 
                    537:      * B&W G3:         Line Out jack = kAux1Sense
                    538:      *                 Microphone jack = kLineInSense
                    539:      *
                    540:      * A big problem is how to tell the difference between AllInOne and Beige G3,
                    541:      * and perhaps iMac and B&W G3
                    542:      */
                    543:     if ( fIICAudioDevPresent ) {
                    544:         fInputComponents[kLineInShft] = microphone;
                    545:         if(fOutputs == 3 && fDetects == 3) {
                    546:             // CPU has lineout and headphone jacks
                    547:             lineout = buildComponentAndAttach(mixerOut, NULL, sLineout, queue);
                    548:             fInputComponents[kAux1Shft] = lineout;
                    549:             fInputComponents[kHeadphoneShft] = headphones;
                    550:          }
                    551:          else {
                    552:              fInputComponents[kAux1Shft] = headphones;
                    553:          }
                    554:     }
                    555:     else if ( fIsG4WithAwacs ) {
                    556:         fInputComponents[kLineInShft] = microphone;
                    557:         fInputComponents[kAux1Shft] = headphones;    
                    558:     }
                    559:     else if ( fIsiMacDVWithAwacs ) {
                    560: #if 1
                    561:         IOLog( "PPCAwacs::CreateAudioTopology: fIsiMacDVWithAwacs\n" );
                    562: #endif
                    563:         // The DV iMac has 2 headphones outputs, 1 line out, and 1 microphone
                    564:         // The names of the bits do not match how they are actually wired :-)
                    565:         lineout = buildComponentAndAttach(mixerOut, NULL, sLineout, queue);
                    566:         fInputComponents[kNotMicShift]   = lineout;
                    567:         fInputComponents[kLineInShft]    = headphones;
                    568:         fInputComponents[kAux1Shft]      = headphones;
                    569:         fInputComponents[kHeadphoneShft] = microphone;
                    570:     }
                    571:     else {
                    572:         fInputComponents[kAux1Shft] = microphone;
                    573:         fInputComponents[kHeadphoneShft] = headphones;
                    574:     }
                    575:     // Update state of all inputs now that all the bookkeeping objects are created.
                    576:     checkStatus();
                    577: }
                    578: 
                    579: void PPCAwacs::DoClockTick(IOTimerEventSource *t)
                    580: {
                    581:     checkStatus();
                    582:     super::DoClockTick(t);
                    583: }
                    584: 
                    585: void PPCAwacs::calculateTickInterval(AbsoluteTime *tickInterval)
                    586: {
                    587:     AbsoluteTime maxInterval;
                    588: 
                    589:     // We want to check the status at least one a second
                    590:     nanoseconds_to_absolutetime(NSEC_PER_SEC, &maxInterval);
                    591:     if(CMP_ABSOLUTETIME(&maxInterval, tickInterval) < 0) {
                    592:         *tickInterval = maxInterval;
                    593:     }
                    594:     super::calculateTickInterval(tickInterval);
                    595: }
                    596: 
                    597: void PPCAwacs::checkStatus()
                    598: {
                    599:     u_int32_t       codecStatus;
                    600: 
                    601:     codecStatus = readCodecStatusReg( fIOBaseAwacs );
                    602: 
                    603:     if(fCodecStatus != codecStatus) {
                    604:         int i;
                    605:                                        // Debugging aids
                    606:        //kprintf("Awacs status: 0x%x\n", codecStatus);
                    607: #if 1
                    608:         IOLog( "PPCAwacs::checkStatusAwacs status: 0x%x\n", codecStatus );
                    609: #endif
                    610:         OSNumber * num = OSNumber::withNumber(codecStatus, 32);
                    611:         setProperty("Status", num);
                    612:         num->release();
                    613: 
                    614:        for(i=0; i<4; i++) {
                    615:             if( (fCodecStatus & (1<<i)) != (codecStatus & (1<<i)))
                    616:                 if(fInputComponents[i]) {
                    617:                     fInputComponents[i]->Set(gInputsSym, gJackSym,
                    618:                         (codecStatus & (1<<i)) >> i);
                    619:                 }
                    620:        }
                    621:     }
                    622:     fCodecStatus = codecStatus;
                    623: }
                    624: 
                    625: IOReturn
                    626: PPCAwacs::SetControl(UInt16 id, int val)
                    627: {
                    628:     IOReturn res = kIOReturnSuccess;
                    629:     switch(id) {
                    630:         case kSpeakerMute:
                    631:             if(val)
                    632:                fCodecControlRegister[1] |= kMuteInternalSpeaker;
                    633:             else
                    634:                fCodecControlRegister[1] &= ~kMuteInternalSpeaker;
                    635:             if ( fIICAudioDevPresent ) {
                    636: #if 0
                    637:                 /*
                    638:                  * Mute the left and right front channels
                    639:                  */
                    640:                 SGSShadow[kLFAttnReg] &= ~sgsBalMuteBit;
                    641:                 SGSShadow[kRFAttnReg] &= ~sgsBalMuteBit;
                    642: 
                    643:                 if ( val ) {
                    644:                     SGSShadow[kLFAttnReg] |= sgsBalMuteBit;
                    645:                     SGSShadow[kRFAttnReg] |= sgsBalMuteBit;
                    646:                 }
                    647:                 writeSGSRegs();
                    648: 
                    649: #else
                    650:                 if(val)
                    651:                     fCodecControlRegister[1] &= ~kOutputOne;
                    652:                 else
                    653:                     fCodecControlRegister[1] |= kOutputOne;
                    654: #endif
                    655:             }
                    656:             writeCodecControlReg( fIOBaseAwacs, fCodecControlRegister[1] );
                    657: 
                    658:             break;
                    659: 
                    660:         case kSpeakerVolLeft:
                    661:             if ( fIICAudioDevPresent ) {
                    662:                 // Actually sets volume of speaker and front headphone
                    663:                 val = 31 - ((val * 32 / 65536) & 31);
                    664:                 SGSShadow[kLFAttnReg] = (SGSShadow[kLFAttnReg] & sgsBalMuteBit) | val;
                    665:                 writeSGSRegs();
                    666:             }
                    667:             else {
                    668:                 val = 15 - ((val * 16 / 65536) & 15);
                    669:                 fCodecControlRegister[4] = (fCodecControlRegister[4] & ~kLeftSpeakerAttenMask) |
                    670:                             (val << kLeftSpeakerAttenShift);
                    671:                 writeCodecControlReg( fIOBaseAwacs, fCodecControlRegister[4] );
                    672:             }
                    673: 
                    674:             break;
                    675: 
                    676:         case kSpeakerVolRight:
                    677:             if ( fIICAudioDevPresent ) {
                    678:                 // Actually sets volume of speaker and front headphone
                    679:                 val = 31 - ((val * 32 / 65536) & 31);
                    680:                 SGSShadow[kRFAttnReg] = (SGSShadow[kRFAttnReg] & sgsBalMuteBit) | val;
                    681:                 writeSGSRegs();
                    682:             }
                    683:             else {
                    684:                 val = 15 - ((val * 16 / 65536) & 15);
                    685:                 fCodecControlRegister[4] = (fCodecControlRegister[4] & ~kRightSpeakerAttenMask) |
                    686:                             (val << kRightSpeakerAttenShift);
                    687:                 writeCodecControlReg( fIOBaseAwacs, fCodecControlRegister[4] );
                    688:             }
                    689:             break;
                    690: 
                    691:         case kHeadphonesMute:
                    692:             if(val)
                    693:                fCodecControlRegister[1] |= kMuteHeadphone;
                    694:             else
                    695:                fCodecControlRegister[1] &= ~kMuteHeadphone;
                    696:             if ( fIICAudioDevPresent ) {
                    697:                 if(val)
                    698:                     fCodecControlRegister[1] &= ~kOutputOne;
                    699:                 else
                    700:                     fCodecControlRegister[1] |= kOutputOne;
                    701:             }
                    702:             writeCodecControlReg( fIOBaseAwacs, fCodecControlRegister[1] );
                    703: 
                    704:             break;
                    705: 
                    706:         case kHeadphonesVolLeft:
                    707:             val = 15 - ((val * 16 / 65536) & 15);
                    708:             fCodecControlRegister[2] = (fCodecControlRegister[2] & ~kLeftHeadphoneAttenMask) |
                    709:                         (val << kLeftHeadphoneAttenShift);
                    710:             writeCodecControlReg( fIOBaseAwacs, fCodecControlRegister[2] );
                    711:             break;
                    712: 
                    713:         case kHeadphonesVolRight:
                    714:             val = 15 - ((val * 16 / 65536) & 15);
                    715:             fCodecControlRegister[2] = (fCodecControlRegister[2] & ~kRightHeadphoneAttenMask) |
                    716:                         (val << kRightHeadphoneAttenShift);
                    717:             writeCodecControlReg( fIOBaseAwacs, fCodecControlRegister[2] );
                    718:             break;
                    719: 
                    720:        case kMicrophoneMute:
                    721:             if(val)
                    722:                fCodecControlRegister[0] &= ~kMicInput;
                    723:             else
                    724:                fCodecControlRegister[0] |= kMicInput;
                    725:             writeCodecControlReg( fIOBaseAwacs, fCodecControlRegister[0] );
                    726:             break;
                    727: 
                    728:        case kCDMute:
                    729:             if(val)
                    730:                fCodecControlRegister[0] &= ~kCDInput;
                    731:             else
                    732:                fCodecControlRegister[0] |= kCDInput;
                    733:             writeCodecControlReg( fIOBaseAwacs, fCodecControlRegister[0] );
                    734:             break;
                    735: 
                    736:         case kMixerInVolLeft:
                    737:             val = (val * 16 / 65536) & 15;
                    738:             fCodecControlRegister[0] = (fCodecControlRegister[0] & ~kLeftInputGainMask) |
                    739:                         (val << kLeftInputGainShift);
                    740:             writeCodecControlReg( fIOBaseAwacs, fCodecControlRegister[0] );
                    741:             break;
                    742: 
                    743:         case kMixerInVolRight:
                    744:             val = (val * 16 / 65536) & 15;
                    745:             fCodecControlRegister[0] = (fCodecControlRegister[0] & ~kRightInputGainMask) |
                    746:                         (val << kRightInputGainShift);
                    747:             writeCodecControlReg( fIOBaseAwacs, fCodecControlRegister[0] );
                    748:             break;
                    749: 
                    750:         case kPassThruVolLeft:
                    751:             val = 15 - ((val * 16 / 65536) & 15);
                    752:             fCodecControlRegister[5] = (fCodecControlRegister[5] & ~kLeftLoopThruAttenMask) |
                    753:                         (val << kLeftLoopThruAttenShift);
                    754:             writeCodecControlReg( fIOBaseAwacs, fCodecControlRegister[5] );
                    755:             break;
                    756: 
                    757:         case kPassThruVolRight:
                    758:             val = 15 - ((val * 16 / 65536) & 15);
                    759:             fCodecControlRegister[5] = (fCodecControlRegister[5] & ~kRightLoopThruAttenMask) |
                    760:                         (val << kRightLoopThruAttenShift);
                    761:             writeCodecControlReg( fIOBaseAwacs, fCodecControlRegister[5] );
                    762:             break;
                    763: 
                    764:        case kPassThruMute:
                    765:             if(val)
                    766:                fCodecControlRegister[1] &= ~kLoopThruEnable;
                    767:             else
                    768:                fCodecControlRegister[1] |= kLoopThruEnable;
                    769:             writeCodecControlReg( fIOBaseAwacs, fCodecControlRegister[1] );
                    770:             break;
                    771: 
                    772: 
                    773:         default:
                    774:             res = kIOReturnUnsupported;
                    775:     }
                    776:     return res;
                    777: }
                    778: 

unix.superglobalmegacorp.com

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