|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.