Annotation of XNU/iokit/Drivers/audio/drvPPCAwacs/PPCAwacs.cpp, revision 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.