|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * Hardware independent (relatively) code for the Burgundy Controller ! 5: * ! 6: * HISTORY ! 7: * ! 8: * ! 9: */ ! 10: #include <IOKit/assert.h> ! 11: #include <IOKit/system.h> ! 12: ! 13: #include <IOKit/IOLib.h> ! 14: #include <IOKit/IODeviceTreeSupport.h> ! 15: #include <IOKit/IOPlatformExpert.h> ! 16: #include <IOKit/ppc/IODBDMA.h> ! 17: #include "PPCBurgundy.h" ! 18: #include "burgundy_hw.h" ! 19: ! 20: /* ! 21: * Prototyes for the "very private methods" at the end of this ! 22: * file. They provide access to the burgundy registers: ! 23: */ ! 24: static void writeSoundControlReg( volatile UInt8*, int); ! 25: static int readCodecSenseLines( volatile UInt8*); ! 26: static int readCodecReg( volatile UInt8*, int); ! 27: static void writeCodecReg( volatile UInt8*, int, int); ! 28: ! 29: #define super IOAudioBus ! 30: OSDefineMetaClassAndStructors( PPCBurgundy, IOAudioBus ) ! 31: ! 32: /* ============== ! 33: * Public Methods ! 34: * ============== */ ! 35: bool ! 36: PPCBurgundy::init(OSDictionary * properties) ! 37: { ! 38: if (!super::init(properties)) { ! 39: #ifdef DEBUGMODE ! 40: IOLog( "PPCBurgundy::init (this = 0x%08lx) super fails\n", (UInt32)this); ! 41: #endif ! 42: return false; ! 43: } ! 44: ! 45: if(!properties){ ! 46: #ifdef DEBUGMODE ! 47: IOLog( "PPCBurgundy::init (this = 0x%08lx) Need to know where Burgundy is !!\n", (UInt32)this); ! 48: #endif ! 49: return false; // Need to know where Burgundy is! ! 50: } ! 51: ! 52: // This invalidate the cache of the machine architecture ! 53: machineType = kMachineTypeUnknown; ! 54: ! 55: // Nulls the pointers for the arrays we allocate: ! 56: fInputComponents = NULL; ! 57: fOutputComponents = NULL; ! 58: sound = NULL; ! 59: ! 60: // We start with a clean status register mirror so first read will ! 61: // set the driver in the correct mode: ! 62: lastStatusRegister = 0L; ! 63: ! 64: #ifdef DEBUGMODE ! 65: IOLog( "PPCBurgundy::init (this = 0x%08lx)\n", (UInt32)this); ! 66: #endif ! 67: return true; ! 68: } ! 69: ! 70: void ! 71: PPCBurgundy::free() ! 72: { ! 73: // Releases the sound: ! 74: if(sound != NULL) ! 75: sound->release(); ! 76: sound = NULL; ! 77: ! 78: super::free(); ! 79: } ! 80: ! 81: IOService* ! 82: PPCBurgundy::probe(IOService* provider, SInt32* score) ! 83: { ! 84: IOService *myService = this; ! 85: ! 86: // We CAN fail the tye check: ! 87: super::probe(provider, score); ! 88: *score = kIODefaultProbeScore; ! 89: ! 90: // finds and cashes the hardware we are running on: ! 91: int mType = findHostingHardware(provider); ! 92: ! 93: // If it one of the machine I know supports ! 94: // burgundy I'm going to increment the score ! 95: if ((mType == kMachineTypeYosemite) || (mType == kMachineTypeiMac)) { ! 96: // One score increment because this is a burgundy-hosting motherboard ! 97: *score = *score + 1; ! 98: } ! 99: ! 100: // Figure out if this is a bugundy and if it is a bordeaux ! 101: sound = NULL; ! 102: isBordeaux = false; ! 103: ! 104: // This is likely to be the case that this is perch ! 105: if (implementsBurgundy(IORegistryEntry::fromPath("/perch", gIODTPlane))) { ! 106: *score = *score + 1; ! 107: myService = this; ! 108: } ! 109: else if ((sound = provider->childFromPath("sound", gIODTPlane)) != NULL) { ! 110: // IOLog("PPCBurgundy::probe looking for sound\n"); ! 111: if (implementsBurgundy(sound)) { ! 112: *score = *score + 1; ! 113: myService = this; ! 114: } ! 115: } ! 116: ! 117: if (myService != NULL) { ! 118: IOLog("Found Burgundy compatible chip %s\n", (isBordeaux ? "and Bordeaux card": "NON Bordeaux card")); ! 119: } ! 120: ! 121: return (myService); ! 122: } ! 123: ! 124: #define kNumDMAStreams 2 ! 125: ! 126: bool ! 127: PPCBurgundy::start(IOService* provider) ! 128: { ! 129: // Gets the base for the burgundy registers: ! 130: IOMemoryMap *map; ! 131: int i; ! 132: ! 133: if( !super::start(provider)) ! 134: return (false); ! 135: ! 136: map = provider->mapDeviceMemoryWithIndex(kAudioDMAdeviceInt); ! 137: if(!map) { ! 138: return false; ! 139: } ! 140: ioBaseBurgundy = (UInt8 *)map->getVirtualAddress(); ! 141: ! 142: if (!AllocateStreams(kNumDMAStreams)) ! 143: return false; ! 144: ! 145: map = provider->mapDeviceMemoryWithIndex(kAudioDMAtxInt); ! 146: if(!map) { ! 147: return false; ! 148: } ! 149: DefineStream(kAudioDMAOutputStream, kOutput, outputFrameRate(), (IODBDMAChannelRegisters*)map->getVirtualAddress()); ! 150: ! 151: map = provider->mapDeviceMemoryWithIndex(kAudioDMArxInt); ! 152: if(!map) { ! 153: return false; ! 154: } ! 155: DefineStream(kAudioDMAInputStream, kInput, inputFrameRate(), (IODBDMAChannelRegisters*)map->getVirtualAddress()); ! 156: ! 157: // Creates the array of input and output components ! 158: numInputComponents = numberOfOutputComponents(); ! 159: numOutputComponents = numberOfInputComponents(); ! 160: ! 161: fInputComponents = (IOAudioComponentImplPtr*)IOMalloc(sizeof(IOAudioComponentImplPtr) * numInputComponents); ! 162: if (fInputComponents == NULL) { ! 163: // Free the DMA and exit: ! 164: FreeStreams(); ! 165: return false; ! 166: } ! 167: ! 168: fOutputComponents = (IOAudioComponentImplPtr*)IOMalloc(sizeof(IOAudioComponentImplPtr) * numOutputComponents); ! 169: if (fOutputComponents == NULL) { ! 170: // Free the input components ! 171: IOFree(fInputComponents, sizeof(IOAudioComponentImplPtr) * numInputComponents); ! 172: fInputComponents = NULL; ! 173: numInputComponents = 0; ! 174: ! 175: // Free the DMA and exit: ! 176: FreeStreams(); ! 177: return false; ! 178: } ! 179: ! 180: // Initalizes all the components: ! 181: for (i = 0; i < numInputComponents; i++) ! 182: fInputComponents[i] = NULL; ! 183: ! 184: for (i = 0; i < numOutputComponents; i++) ! 185: fOutputComponents[i] = NULL; ! 186: ! 187: // Initializes the sound control register: ! 188: soundControlRegister = ( kSoundCtlReg_InSubFrame0 | \ ! 189: kSoundCtlReg_OutSubFrame0 | \ ! 190: kSoundCtlReg_Rate_44100 ); ! 191: writeSoundControlReg(ioBaseBurgundy, soundControlRegister); ! 192: ! 193: // Set Input Source A gain to default ! 194: writeCodecReg( ioBaseBurgundy, kGASALReg, kGAS_Default_Gain ); ! 195: writeCodecReg( ioBaseBurgundy, kGASARReg, kGAS_Default_Gain ); ! 196: writeCodecReg( ioBaseBurgundy, kVGA2Reg, 0x44 ); ! 197: writeCodecReg( ioBaseBurgundy, kGAS2LReg, 255 ); ! 198: writeCodecReg( ioBaseBurgundy, kGAS2RReg, 255 ); ! 199: ! 200: // Set mixer 1 input to Input Source A (Serial-in Subframe 0) ! 201: writeCodecReg( ioBaseBurgundy, kMX1Reg, kMX1Reg_Select_ISAL | kMX1Reg_Select_ISAR ); ! 202: writeCodecReg( ioBaseBurgundy, kSDInReg, kSDInReg_ASA_From_SF0 ); ! 203: ! 204: // Set mixer 0-3 outputs to default gain ! 205: writeCodecReg( ioBaseBurgundy, kMXEQ1LReg, kMXEQ_Default_Gain ); ! 206: writeCodecReg( ioBaseBurgundy, kMXEQ1RReg, kMXEQ_Default_Gain ); ! 207: writeCodecReg( ioBaseBurgundy, kMXEQ2LReg, kMXEQ_Default_Gain ); ! 208: writeCodecReg( ioBaseBurgundy, kMXEQ2RReg, kMXEQ_Default_Gain ); ! 209: writeCodecReg( ioBaseBurgundy, kMXEQ3LReg, kMXEQ_Default_Gain ); ! 210: writeCodecReg( ioBaseBurgundy, kMXEQ3RReg, kMXEQ_Default_Gain ); ! 211: ! 212: // Set Output Source 0 gain to default ! 213: writeCodecReg( ioBaseBurgundy, kGAP0LReg, kGAP_Default_Gain ); ! 214: writeCodecReg( ioBaseBurgundy, kGAP0RReg, kGAP_Default_Gain ); ! 215: ! 216: startWorkLoop(); ! 217: ! 218: return true; ! 219: } ! 220: ! 221: void ! 222: PPCBurgundy::stop(IOService *provider) ! 223: { ! 224: // Releases all DMA streams: ! 225: FreeStreams(); ! 226: ! 227: // Releases the input components ! 228: if (fInputComponents != NULL) { ! 229: IOFree(fInputComponents, sizeof(IOAudioComponentImplPtr) * numInputComponents); ! 230: fInputComponents = NULL; ! 231: numInputComponents = 0; ! 232: } ! 233: ! 234: // Releases the output components ! 235: if (fOutputComponents != NULL) { ! 236: IOFree(fOutputComponents, sizeof(IOAudioComponentImplPtr) * numOutputComponents); ! 237: fOutputComponents = NULL; ! 238: numOutputComponents = 0; ! 239: } ! 240: } ! 241: ! 242: void ! 243: PPCBurgundy::CreateAudioTopology(IOCommandQueue *queue) ! 244: { ! 245: IOAudioComponentImpl *mixerIn; ! 246: IOAudioComponentImpl *mixerOut; ! 247: IOAudioComponentImpl *microphone; ! 248: IOAudioComponentImpl *lineout; ! 249: IOAudioComponentImpl *linein; ! 250: IOAudioComponentImpl *headphones; ! 251: IOAudioComponentImpl *cd; ! 252: IOAudioComponentImpl *speaker; ! 253: IOAudioComponentImpl *passtru; ! 254: ! 255: AudioStreamIndex outputStream; ! 256: AudioStreamIndex inputStream; ! 257: ! 258: if (!fStreams) ! 259: return; ! 260: ! 261: outputStream = firstStreamAfter(kOutput, 0); ! 262: inputStream = firstStreamAfter(kInput, 0); ! 263: ! 264: if ((outputStream == kInvalidStreamIndex) || (inputStream == kInvalidStreamIndex)) { ! 265: IOLog("PPCBurgundy::CreateAudioTopology called without available DMA streams\n"); ! 266: return; ! 267: } ! 268: else ! 269: IOLog("PPCBurgundy::CreateAudioTopology input stream is %d output is %d\n", inputStream, outputStream); ! 270: ! 271: mixerOut = buildComponentAndAttach(GetStream(outputStream), NULL, componentDictionaryMixerOut(), queue); ! 272: headphones = buildComponentAndAttach(mixerOut, NULL, componentDictionaryHeadphones(), queue); ! 273: speaker = buildComponentAndAttach(mixerOut, NULL, componentDictionarySpeaker(), queue); ! 274: lineout = buildComponentAndAttach(mixerOut, NULL, componentDictionaryLineout(), queue); ! 275: ! 276: mixerIn = buildComponentAndAttach(NULL, GetStream(inputStream), componentDictionaryMixerIn(), queue); ! 277: cd = buildComponentAndAttach(NULL, NULL, componentDictionaryCD(), queue); ! 278: linein = buildComponentAndAttach(NULL, NULL, componentDictionaryLinein(), queue); ! 279: microphone = buildComponentAndAttach(NULL, mixerIn, componentDictionaryMicrophone(), queue); ! 280: ! 281: passtru = buildComponentAndAttach(mixerIn, mixerOut, componentDictionaryPassThru(), queue); ! 282: ! 283: buildComponentAndAttach(mixerIn, mixerOut, componentDictionaryPassThru(), queue); ! 284: fInputComponents[kCD] = buildComponentAndAttach(NULL, mixerIn, componentDictionaryCD(), queue); ! 285: ! 286: // FIXME: the component connection could be done better than so ! 287: if (fInputComponents != NULL) { ! 288: fInputComponents[kMicroPhone] = microphone; ! 289: ! 290: if (numInputComponents > 1) ! 291: fInputComponents[kCD] = cd; ! 292: ! 293: if (numInputComponents > 2) ! 294: fInputComponents[kLineIn] = linein; ! 295: } ! 296: ! 297: if (fOutputComponents != NULL) { ! 298: fOutputComponents[kSpeaker] = speaker; ! 299: ! 300: if (numOutputComponents > 1) ! 301: fOutputComponents[kHeadphones] = headphones; ! 302: ! 303: if (numOutputComponents > 2) ! 304: fOutputComponents[kLineOut] = lineout; ! 305: } ! 306: ! 307: // Sets ups the burgundy as required by this machine wiring ! 308: // configuration: ! 309: if (!dependentSetup()) ! 310: IOLog("PPCBurgundy::CreateAudioTopology burgundy setup failed\n"); ! 311: } ! 312: ! 313: void ! 314: PPCBurgundy::DoClockTick(IOTimerEventSource *t) ! 315: { ! 316: checkStatusRegister(); ! 317: super::DoClockTick(t); ! 318: } ! 319: ! 320: void ! 321: PPCBurgundy::calculateTickInterval(AbsoluteTime *tickInterval) ! 322: { ! 323: AbsoluteTime maxInterval; ! 324: ! 325: // We want to check the status at least one a second ! 326: nanoseconds_to_absolutetime(NSEC_PER_SEC, &maxInterval); ! 327: if(CMP_ABSOLUTETIME(&maxInterval, tickInterval) < 0) { ! 328: *tickInterval = maxInterval; ! 329: } ! 330: super::calculateTickInterval(tickInterval); ! 331: } ! 332: ! 333: IOReturn ! 334: PPCBurgundy::SetControl(UInt16 id, int val) ! 335: { ! 336: IOReturn res = kIOReturnSuccess; ! 337: ! 338: switch(id) { ! 339: case kSpeakerMute: ! 340: muteInternalSpeaker(val != 0); ! 341: muteHeadphones(val == 0); ! 342: break; ! 343: ! 344: case kHeadphonesMute: ! 345: muteHeadphones(val != 0); ! 346: muteInternalSpeaker(val == 0); ! 347: break; ! 348: ! 349: case kMicrophoneMute: ! 350: setMicInput(val == 0); ! 351: break; ! 352: ! 353: case kSpeakerVolLeft: ! 354: volumeInternalSpeakerLeft(val); ! 355: break; ! 356: ! 357: case kSpeakerVolRight: ! 358: volumeInternalSpeakerRight(val); ! 359: break; ! 360: ! 361: case kHeadphonesVolLeft: ! 362: volumeHeadphonesLeft(val); ! 363: break; ! 364: ! 365: case kHeadphonesVolRight: ! 366: volumeHeadphonesRight(val); ! 367: break; ! 368: ! 369: case kCDMute: ! 370: muteCDLine(val != 0); ! 371: break; ! 372: ! 373: case kMixerInVolLeft: ! 374: volumeMixerInLeft(val); ! 375: break; ! 376: ! 377: case kMixerInVolRight: ! 378: volumeMixerInRight(val); ! 379: break; ! 380: ! 381: case kPassThruVolLeft: ! 382: break; ! 383: ! 384: case kPassThruVolRight: ! 385: break; ! 386: ! 387: case kPassThruMute: ! 388: break; ! 389: ! 390: default: ! 391: res = kIOReturnUnsupported; ! 392: } ! 393: return res; ! 394: } ! 395: ! 396: /* =============== ! 397: * Private Methods ! 398: * =============== */ ! 399: ! 400: // -------------------------------------------------------------------------- ! 401: // Method: implementsBurgundy ! 402: // ! 403: // Purpose: ! 404: // Attempts to discover if the device implements burgundy: ! 405: bool ! 406: PPCBurgundy::implementsBurgundy(IORegistryEntry *device) ! 407: { ! 408: if (device != NULL) { ! 409: OSData *s = NULL; ! 410: ! 411: //IOLog("Matching burgundy compatibility with %s\n", device->getName()); ! 412: ! 413: s = OSDynamicCast(OSData, device->getProperty("compatible")); ! 414: ! 415: if (s != NULL) { ! 416: if(s->isEqualTo("burgundy", sizeof("burgundy")-1)) { ! 417: return true; ! 418: } ! 419: else if(s->isEqualTo("DVD-Video and Audio/Video", sizeof("DVD-Video and Audio/Video")-1)) { ! 420: // also sets the isBordeaux flag ! 421: isBordeaux = true; ! 422: return true; ! 423: } ! 424: else { ! 425: //IOLog("PPCBurgundy::probe sound is not burgundy compatible.\n"); ! 426: } ! 427: } ! 428: else { ! 429: //IOLog("PPCBurgundy::probe sound does not have a compatible property.\n"); ! 430: } ! 431: } ! 432: else{ ! 433: //IOLog("PPCBurgundy::probe this hardware does not have a sound chip\n"); ! 434: } ! 435: return false; ! 436: } ! 437: ! 438: // -------------------------------------------------------------------------- ! 439: // Method: findHostingHardware ! 440: // ! 441: // Purpose: ! 442: // Finds the kind of hardware we are running on. Since all the older machines ! 443: // do not have all the information about how burgundy is wired, knowing which ! 444: // machine we are running on helps to set up the driver correctly. ! 445: // The method recognizes more machines than the ones that use bugundy (e.g. ! 446: // "'AAPL,9500'" has an AWACS). ! 447: ! 448: int ! 449: PPCBurgundy::findHostingHardware(IOService *provider) ! 450: { ! 451: IOService *topProvider = NULL; ! 452: ! 453: // If we already found the machine the driver is running on ! 454: // just returns the value previously found: ! 455: if ((machineType >= kMachineTypeUnknown) || ! 456: (machineType == 0)) { ! 457: // if the argument is missing I've to get from myself: ! 458: if (provider == NULL) ! 459: provider = getProvider(); ! 460: ! 461: // See if we find the top of the tree (with the machine type) ! 462: // iterating all the way up: ! 463: while (provider != NULL) { ! 464: topProvider = provider; ! 465: provider = topProvider->getProvider(); ! 466: } ! 467: ! 468: // by default the hardware is unknown: ! 469: machineType = kMachineTypeUnknown; ! 470: ! 471: if (topProvider != NULL) { ! 472: if (IODTMatchNubWithKeys(topProvider, "'AAPL,9500'")) ! 473: machineType = kMachine9500; ! 474: if (IODTMatchNubWithKeys(topProvider, "'AAPL,Gossamer'")) ! 475: machineType = kMachineGenericGossamer; ! 476: if (IODTMatchNubWithKeys(topProvider, "'AAPL,PowerMac G3'")) ! 477: machineType = kMachineTypeSilk; ! 478: else if (IODTMatchNubWithKeys(topProvider, "'AAPL,PowerBook1998'")) ! 479: machineType = kMachineTypeWallstreet; ! 480: else if (IODTMatchNubWithKeys(topProvider, "'iMac,1'")) ! 481: machineType = kMachineTypeiMac; ! 482: else if (IODTMatchNubWithKeys(topProvider, "('PowerMac1,1', 'PowerMac1,2')")) ! 483: machineType = kMachineTypeYosemite; ! 484: else if (IODTMatchNubWithKeys(topProvider, "'PowerMac3,1'")) ! 485: machineType = kMachineTypeSawtooth; ! 486: else if (IODTMatchNubWithKeys(topProvider, "'PowerBook1,1'")) ! 487: machineType = kMachineType101; ! 488: else if (IODTMatchNubWithKeys(topProvider, "'PowerBook2,1'")) ! 489: machineType = kMachineTypeiBook; ! 490: else ! 491: IOLog("PPCBurgundy::findHostingHardware unknown machine type\n"); ! 492: } ! 493: else ! 494: IOLog("PPCBurgundy::findHostingHardware misses the top provider\n"); ! 495: } ! 496: ! 497: //Just to ease up the debugging ! 498: //IOLog("PPCBurgundy::findHostingHardware found %d\n", machineType); ! 499: ! 500: return (machineType); ! 501: } ! 502: ! 503: // -------------------------------------------------------------------------- ! 504: // Method: numberOfInputComponents ! 505: // ! 506: // Purpose: ! 507: // returns the number of components for the input lines ! 508: // usually are 2 one is the microphone and the other is ! 509: // microphone jack. ! 510: #define kCommonNumberOfInputComponents 2 ! 511: ! 512: int ! 513: PPCBurgundy::numberOfInputComponents() ! 514: { ! 515: if(sound) { ! 516: OSData *t; ! 517: ! 518: t = OSDynamicCast(OSData, sound->getProperty("#-detects")); ! 519: if (t != NULL) { ! 520: return *(UInt32*)(t->getBytesNoCopy()); ! 521: } ! 522: } ! 523: ! 524: return kCommonNumberOfInputComponents; ! 525: } ! 526: ! 527: // -------------------------------------------------------------------------- ! 528: // Method: numberOfOutputComponents ! 529: // ! 530: // Purpose: ! 531: // returns the number of components for the output lines ! 532: // usually are 2 one is the internal speacker and the other ! 533: // is the headphone line. ! 534: #define kCommonNumberOfOutputComponents 2 ! 535: ! 536: int ! 537: PPCBurgundy::numberOfOutputComponents() ! 538: { ! 539: if(sound) { ! 540: OSData *t; ! 541: ! 542: t = OSDynamicCast(OSData, sound->getProperty("#-outputs")); ! 543: if (t != NULL) { ! 544: return *(UInt32*)(t->getBytesNoCopy()); ! 545: } ! 546: } ! 547: return kCommonNumberOfOutputComponents; ! 548: } ! 549: ! 550: ! 551: // -------------------------------------------------------------------------- ! 552: // Method: inputFrameRate ! 553: // ! 554: // Purpose: ! 555: // returns the input frame rate as in the registry, if it is ! 556: // not found in the registry, it returns the default value. ! 557: #define kCommonInputFrameRate 44100 ! 558: ! 559: UInt16 ! 560: PPCBurgundy::inputFrameRate() ! 561: { ! 562: if(sound) { ! 563: OSData *t; ! 564: ! 565: t = OSDynamicCast(OSData, sound->getProperty("input-frame-rates")); ! 566: if (t != NULL) { ! 567: UInt16 fr = *(UInt32*)(t->getBytesNoCopy()); ! 568: ! 569: #ifdef DEBUGMODE ! 570: IOLog( "PPCBurgundy::inputFrameRate = %d\n", fr); ! 571: #endif ! 572: return fr; ! 573: } ! 574: } ! 575: ! 576: return kCommonInputFrameRate; ! 577: } ! 578: ! 579: ! 580: // -------------------------------------------------------------------------- ! 581: // Method: outputFrameRate ! 582: // ! 583: // Purpose: ! 584: // returns the output frame rate as in the registry, if it is ! 585: // not found in the registry, it returns the default value. ! 586: #define kCommonOutputFrameRate 44100 ! 587: ! 588: UInt16 ! 589: PPCBurgundy::outputFrameRate() ! 590: { ! 591: if(sound) { ! 592: OSData *t; ! 593: ! 594: t = OSDynamicCast(OSData, sound->getProperty("output-frame-rates")); ! 595: if (t != NULL) { ! 596: UInt16 fr = *(UInt32*)(t->getBytesNoCopy()); ! 597: ! 598: #ifdef DEBUGMODE ! 599: IOLog( "PPCBurgundy::outputFrameRate = %d\n", fr); ! 600: #endif ! 601: return fr; ! 602: } ! 603: } ! 604: ! 605: return kCommonOutputFrameRate; ! 606: } ! 607: ! 608: // -------------------------------------------------------------------------- ! 609: // Method(s): componentDictionaryXXXXXX ! 610: // ! 611: // Purpose: ! 612: // the next N methods return the strings for the component dictionaries ! 613: // for each kind of component. As stated in the AWACS driver, these should ! 614: // end in the driver resources. ! 615: ! 616: // NOTE: (This is important !!!) the soundControls enum in the header file is ! 617: // bounded to the following stings in this way: ! 618: // for each component the control Id in the string must have the same value ! 619: // of the corrispondent soundControls enum item. For example the sound control ! 620: // enum item kHeadphonesVolLeft has value 4, so in sHeadphones the ID of the ! 621: // volume left control must be 4. ! 622: ! 623: char* ! 624: PPCBurgundy::componentDictionarySpeaker() ! 625: { ! 626: static const char *sSpeaker = ! 627: "{ ! 628: 'Type' = 'Speaker'; ! 629: 'Channels' = 2:8; ! 630: 'Master' = 1:8; ! 631: 'Controls' = { ! 632: 'MuteAll' = { ! 633: 'Type' = 'Mute'; ! 634: 'Id' = 0:16; ! 635: 'Val' = 0:8; ! 636: 'Min' = 0:8; ! 637: 'Max' = 1:8; ! 638: 'Chan' = 0:8; ! 639: }; ! 640: 'VolumeLeft' = { ! 641: 'Type' = 'Volume'; ! 642: 'Id' = 1:16; ! 643: 'Val' = 65535:16; ! 644: 'Min' = 0:16; ! 645: 'Max' = 65535:16; ! 646: 'Chan' = 1:8; ! 647: }; ! 648: 'VolumeRight' = { ! 649: 'Type' = 'Volume'; ! 650: 'Id' = 2:16; ! 651: 'Val' = 65535:16; ! 652: 'Min' = 0:16; ! 653: 'Max' = 65535:16; ! 654: 'Chan' = 2:8; ! 655: }; ! 656: }; ! 657: }"; ! 658: return (char*)sSpeaker; ! 659: } ! 660: ! 661: char* ! 662: PPCBurgundy::componentDictionaryHeadphones() ! 663: { ! 664: static const char *sHeadphones = ! 665: "{ ! 666: 'Type' = 'Headphones'; ! 667: 'Channels' = 2:8; ! 668: 'Master' = 1:8; ! 669: 'Controls' = { ! 670: 'MuteAll' = { ! 671: 'Type' = 'Mute'; ! 672: 'Id' = 3:16; ! 673: 'Val' = 0:8; ! 674: 'Min' = 0:8; ! 675: 'Max' = 1:8; ! 676: 'Chan' = 0:8; ! 677: }; ! 678: 'VolumeLeft' = { ! 679: 'Type' = 'Volume'; ! 680: 'Id' = 4:16; ! 681: 'Val' = 65535:16; ! 682: 'Min' = 0:16; ! 683: 'Max' = 65535:16; ! 684: 'Chan' = 1:8; ! 685: }; ! 686: 'VolumeRight' = { ! 687: 'Type' = 'Volume'; ! 688: 'Id' = 5:16; ! 689: 'Val' = 65535:16; ! 690: 'Min' = 0:16; ! 691: 'Max' = 65535:16; ! 692: 'Chan' = 2:8; ! 693: }; ! 694: }; ! 695: 'Inputs' = { ! 696: 'Jack' = { ! 697: 'Val' = 0:8; ! 698: 'Min' = 0:8; ! 699: 'Max' = 1:8; ! 700: }; ! 701: }; ! 702: }"; ! 703: return (char*)sHeadphones; ! 704: } ! 705: ! 706: char* ! 707: PPCBurgundy::componentDictionaryMicrophone() ! 708: { ! 709: static const char *sMicrophone = ! 710: "{ ! 711: 'Type' = 'Microphone'; ! 712: 'Channels' = 2:8; ! 713: 'Controls' = { ! 714: 'MuteAll' = { ! 715: 'Type' = 'Mute'; ! 716: 'Id' = 6:16; ! 717: 'Val' = 0:8; ! 718: 'Min' = 0:8; ! 719: 'Max' = 1:8; ! 720: 'Chan' = 0:8; ! 721: }; ! 722: }; ! 723: 'Inputs' = { ! 724: 'Jack' = { ! 725: 'Val' = 0:8; ! 726: 'Min' = 0:8; ! 727: 'Max' = 1:8; ! 728: }; ! 729: }; ! 730: }"; ! 731: return (char*)sMicrophone; ! 732: } ! 733: ! 734: char* ! 735: PPCBurgundy::componentDictionaryLinein() ! 736: { ! 737: static const char *sLinein = ! 738: "{ ! 739: 'Type' = 'LineIn'; ! 740: 'Channels' = 2:8; ! 741: 'Controls' = { ! 742: 'MuteAll' = { ! 743: 'Type' = 'Mute'; ! 744: 'Id' = 14:16; ! 745: 'Val' = 0:8; ! 746: 'Min' = 0:8; ! 747: 'Max' = 1:8; ! 748: 'Chan' = 0:8; ! 749: }; ! 750: }; ! 751: 'Inputs' = { ! 752: 'Jack' = { ! 753: 'Val' = 0:8; ! 754: 'Min' = 0:8; ! 755: 'Max' = 1:8; ! 756: }; ! 757: }; ! 758: }"; ! 759: return (char*)sLinein; ! 760: } ! 761: ! 762: char* ! 763: PPCBurgundy::componentDictionaryLineout() ! 764: { ! 765: static const char *sLineout = ! 766: "{ ! 767: 'Type' = 'LineOut'; ! 768: 'Channels' = 2:8; ! 769: 'Controls' = { ! 770: 'MuteAll' = { ! 771: 'Type' = 'Mute'; ! 772: 'Id' = 13:16; ! 773: 'Val' = 0:8; ! 774: 'Min' = 0:8; ! 775: 'Max' = 1:8; ! 776: 'Chan' = 0:8; ! 777: }; ! 778: }; ! 779: 'Inputs' = { ! 780: 'Jack' = { ! 781: 'Val' = 0:8; ! 782: 'Min' = 0:8; ! 783: 'Max' = 1:8; ! 784: }; ! 785: }; ! 786: }"; ! 787: return (char*)sLineout; ! 788: } ! 789: ! 790: char* ! 791: PPCBurgundy::componentDictionaryCD() ! 792: { ! 793: static const char *sCD = ! 794: "{ ! 795: 'Type' = 'CD'; ! 796: 'Channels' = 2:8; ! 797: 'Controls' = { ! 798: 'MuteAll' = { ! 799: 'Type' = 'Mute'; ! 800: 'Id' = 7:16; ! 801: 'Val' = 0:8; ! 802: 'Min' = 0:8; ! 803: 'Max' = 1:8; ! 804: 'Chan' = 0:8; ! 805: }; ! 806: }; ! 807: }"; ! 808: return (char*)sCD; ! 809: } ! 810: ! 811: char* ! 812: PPCBurgundy::componentDictionaryMixerIn() ! 813: { ! 814: static const char *sMixerIn = ! 815: "{ ! 816: 'Type' = 'Mixer'; ! 817: 'Channels' = 2:8; ! 818: 'Controls' = { ! 819: 'VolumeLeft' = { ! 820: 'Type' = 'Volume'; ! 821: 'Id' = 8:16; ! 822: 'Val' = 65535:16; ! 823: 'Min' = 0:16; ! 824: 'Max' = 65535:16; ! 825: 'Chan' = 1:8; ! 826: }; ! 827: 'VolumeRight' = { ! 828: 'Type' = 'Volume'; ! 829: 'Id' = 9:16; ! 830: 'Val' = 65535:16; ! 831: 'Min' = 0:16; ! 832: 'Max' = 65535:16; ! 833: 'Chan' = 2:8; ! 834: }; ! 835: }; ! 836: }"; ! 837: return (char*)sMixerIn; ! 838: } ! 839: ! 840: char* ! 841: PPCBurgundy::componentDictionaryMixerOut() ! 842: { ! 843: static const char *sMixerOut = ! 844: "{ ! 845: 'Type' = 'Mixer'; ! 846: 'Channels' = 2:8; ! 847: }"; ! 848: return (char*)sMixerOut; ! 849: } ! 850: ! 851: char* ! 852: PPCBurgundy::componentDictionaryPassThru() ! 853: { ! 854: static const char *sPassThru = ! 855: "{ ! 856: 'Type' = 'Feature'; ! 857: 'Channels' = 2:8; ! 858: 'Controls' = { ! 859: 'MuteAll' = { ! 860: 'Type' = 'Mute'; ! 861: 'Id' = 12:16; ! 862: 'Val' = 1:8; ! 863: 'Min' = 0:8; ! 864: 'Max' = 1:8; ! 865: 'Chan' = 0:8; ! 866: }; ! 867: 'VolumeLeft' = { ! 868: 'Type' = 'Volume'; ! 869: 'Id' = 10:16; ! 870: 'Val' = 65535:16; ! 871: 'Min' = 0:16; ! 872: 'Max' = 65535:16; ! 873: 'Chan' = 1:8; ! 874: }; ! 875: 'VolumeRight' = { ! 876: 'Type' = 'Volume'; ! 877: 'Id' = 11:16; ! 878: 'Val' = 65535:16; ! 879: 'Min' = 0:16; ! 880: 'Max' = 65535:16; ! 881: 'Chan' = 2:8; ! 882: }; ! 883: }; ! 884: }"; ! 885: return (char*)sPassThru; ! 886: } ! 887: ! 888: // -------------------------------------------------------------------------- ! 889: // Method: dependentSetup ! 890: // ! 891: // Purpose: ! 892: // this handles the setup of the burgundy chip for each kind of ! 893: // hosting hardware. ! 894: bool ! 895: PPCBurgundy::dependentSetup() ! 896: { ! 897: UInt32 OSReg = 0; ! 898: ! 899: // ! 900: // G3-Gossamer DVD-card assignments (Bordeaux) ! 901: // ! 902: // Port 17 - Internal speaker ! 903: // Port 15 - Rear panel RCA Out ! 904: // Port 16 - Rear panel MiniJack Out ! 905: // ! 906: // Yosemite assignments ! 907: // ! 908: // Port 17 - Internal speaker ! 909: // Port 14 - Rear panel MiniJack Out ! 910: // ! 911: writeCodecReg( ioBaseBurgundy, kOutputLvlPort17Reg, kOutputLvl_Default ); ! 912: ! 913: switch (findHostingHardware(NULL)) ! 914: { ! 915: case kMachineTypeSilk: ! 916: // G3-Gossamer DVD-card ! 917: assert(isBordeaux); ! 918: writeCodecReg( ioBaseBurgundy, kOutputLvlPort15Reg, kOutputLvl_Default ); ! 919: writeCodecReg( ioBaseBurgundy, kOutputLvlPort16Reg, kOutputLvl_Default ); ! 920: ! 921: writeCodecReg( ioBaseBurgundy, kGAP1LReg, kGAP_Default_Gain ); ! 922: writeCodecReg( ioBaseBurgundy, kGAP1RReg, kGAP_Default_Gain ); ! 923: ! 924: currentOutputMuteReg = kOutputMuteReg_Port15L | kOutputMuteReg_Port15R | ! 925: kOutputMuteReg_Port16L | kOutputMuteReg_Port16R | ! 926: kOutputMuteReg_Port17M; ! 927: ! 928: OSReg = kOSReg_OS0_Select_MXO1 | kOSReg_OS1_Select_MXO1; ! 929: break; ! 930: ! 931: case kMachineTypeiMac: ! 932: case kMachineTypeYosemite: ! 933: // Yosemite: (FIXME as soon as newwolds works I should move this in the newworld handling ! 934: // this should be done also for the others switch statements in this file) ! 935: writeCodecReg( ioBaseBurgundy, kOutputLvlPort14Reg, kOutputLvl_Default ); ! 936: ! 937: currentOutputMuteReg = kOutputMuteReg_Port14L | kOutputMuteReg_Port14R | ! 938: kOutputMuteReg_Port17M; ! 939: ! 940: OSReg = kOSReg_OS0_Select_MXO1; ! 941: break; ! 942: default: ! 943: // FIXME: this may be a newworld, so the registry holds ! 944: // all we need to know about how the burgundy is wired: ! 945: // Add here the code to interpret it. ! 946: break; ! 947: } ! 948: ! 949: writeCodecReg( ioBaseBurgundy, kOSReg, OSReg ); ! 950: writeCodecReg( ioBaseBurgundy, kOutputMuteReg, currentOutputMuteReg ); ! 951: writeCodecReg( ioBaseBurgundy, kOutputCtl0Reg, kOutputCtl0Reg_OutCtl1_High ); ! 952: ! 953: // while this acts on the analog volume controls ! 954: writeCodecReg( ioBaseBurgundy, kOutputLvlPort13Reg, 0x00); ! 955: writeCodecReg( ioBaseBurgundy, kOutputLvlPort14Reg, 0x00); ! 956: writeCodecReg( ioBaseBurgundy, kOutputLvlPort15Reg, 0x00); ! 957: writeCodecReg( ioBaseBurgundy, kOutputLvlPort16Reg, 0x00); ! 958: writeCodecReg( ioBaseBurgundy, kOutputLvlPort17Reg, 0x00); ! 959: ! 960: // and writes the digital volumes: ! 961: writeCodecReg( ioBaseBurgundy, kGAP0LReg, 0xFF); ! 962: writeCodecReg( ioBaseBurgundy, kGAP1LReg, 0xFF); ! 963: writeCodecReg( ioBaseBurgundy, kGAP2LReg, 0xFF); ! 964: writeCodecReg( ioBaseBurgundy, kGAP3LReg, 0xFF); ! 965: ! 966: writeCodecReg( ioBaseBurgundy, kGAP0RReg, 0xFF); ! 967: writeCodecReg( ioBaseBurgundy, kGAP1RReg, 0xFF); ! 968: writeCodecReg( ioBaseBurgundy, kGAP2RReg, 0xFF); ! 969: writeCodecReg( ioBaseBurgundy, kGAP3RReg, 0xFF); ! 970: return true; ! 971: } ! 972: ! 973: // -------------------------------------------------------------------------- ! 974: // Method: checkStatusRegister ! 975: // ! 976: // Purpose: ! 977: // if the argument is true mutes the internal speaker, otherwise ! 978: // it "unmutes" it. ! 979: void ! 980: PPCBurgundy::checkStatusRegister() ! 981: { ! 982: if (burgundyStatusChanged()) { ! 983: int i; ! 984: ! 985: OSNumber * num = OSNumber::withNumber(lastStatusRegister, 32); ! 986: setProperty("Status", num); ! 987: num->release(); ! 988: ! 989: #ifdef DEBUGMODE ! 990: IOLog("Status changes in: 0x%08lx\n", lastStatusRegister); ! 991: #endif ! 992: // Something changed, act on it: ! 993: // For each sense line we call the action attached ! 994: // to thar sense line: ! 995: for (i = 0; i < numInputComponents; i++) ! 996: if (fInputComponents[i] != NULL) ! 997: fInputComponents[i]->Set(gInputsSym, gJackSym, inputComponentStatus(i)); ! 998: ! 999: for (i = 0; i < numOutputComponents; i++) ! 1000: if (fOutputComponents[i] != NULL) ! 1001: fOutputComponents[i]->Set(gInputsSym, gJackSym, outputComponentStatus(i)); ! 1002: } ! 1003: } ! 1004: ! 1005: // -------------------------------------------------------------------------- ! 1006: // Method: inputComponentStatus ! 1007: // ! 1008: // Purpose: ! 1009: // checks the status of the jack line of the ith output component: ! 1010: bool ! 1011: PPCBurgundy::inputComponentStatus(int index) ! 1012: { ! 1013: switch(index) ! 1014: { ! 1015: case kMicroPhone: // check the microphone ! 1016: return microphoneInserted(); ! 1017: ! 1018: case kCD: // the cd input is not associated to a jack ! 1019: return false; ! 1020: ! 1021: case kLineIn: // the RCA line does not have a jack ! 1022: return false; ! 1023: } ! 1024: ! 1025: return false; // by deafult there is no jack ! 1026: } ! 1027: ! 1028: ! 1029: // -------------------------------------------------------------------------- ! 1030: // Method: outputComponentStatus ! 1031: // ! 1032: // Purpose: ! 1033: // checks the status of the jack line of the ith output component: ! 1034: bool ! 1035: PPCBurgundy::outputComponentStatus(int index) ! 1036: { ! 1037: switch(index) ! 1038: { ! 1039: case kSpeaker: ! 1040: return false; // the internal speaker does not have a jack ! 1041: ! 1042: case kHeadphones: // check the headphones: ! 1043: return headphonesInserted(); ! 1044: ! 1045: case kLineOut: ! 1046: return false; // the RCA line does not have a jack ! 1047: } ! 1048: ! 1049: return false; // by deafult there is no jack ! 1050: } ! 1051: ! 1052: // -------------------------------------------------------------------------- ! 1053: // Method: muteInternalSpeaker ! 1054: // ! 1055: // Purpose: ! 1056: // if the argument is true mutes the internal speaker, otherwise ! 1057: // it "unmutes" it. ! 1058: ! 1059: void ! 1060: PPCBurgundy::muteInternalSpeaker(bool mute) ! 1061: { ! 1062: UInt32 outputSourceMask = 0; ! 1063: ! 1064: switch (findHostingHardware(NULL)) ! 1065: { ! 1066: case kMachineTypeSilk: ! 1067: // G3-Gossamer DVD-card ! 1068: assert(isBordeaux); ! 1069: outputSourceMask = kOutputMuteReg_Port17M; ! 1070: break; ! 1071: ! 1072: case kMachineTypeiMac: ! 1073: // iMac: (FIXME as soon as newwolds works I should move this in the newworld handling) ! 1074: outputSourceMask = kOutputMuteReg_Port14L | kOutputMuteReg_Port14R; ! 1075: break; ! 1076: ! 1077: case kMachineTypeYosemite: ! 1078: outputSourceMask = kOutputMuteReg_Port17M; ! 1079: break; ! 1080: ! 1081: default: ! 1082: // FIXME: this may be a newworld, so the registry holds ! 1083: // all we need to know about how the burgundy is wired: ! 1084: // Add here the code to interpret it. ! 1085: break; ! 1086: } ! 1087: ! 1088: if (mute) ! 1089: currentOutputMuteReg &= ~outputSourceMask; ! 1090: else ! 1091: currentOutputMuteReg |= outputSourceMask; ! 1092: ! 1093: writeCodecReg(ioBaseBurgundy, kOutputMuteReg, currentOutputMuteReg); ! 1094: } ! 1095: ! 1096: // -------------------------------------------------------------------------- ! 1097: // Method: muteRCAOutput ! 1098: // ! 1099: // Purpose: ! 1100: // if the argument is true mutes the rear panel RCA, otherwise ! 1101: // it "unmutes" it. ! 1102: void ! 1103: PPCBurgundy::muteRCAOutput(bool mute) ! 1104: { ! 1105: UInt32 outputSourceMask = 0; ! 1106: ! 1107: switch (findHostingHardware(NULL)) ! 1108: { ! 1109: case kMachineTypeSilk: ! 1110: // G3-Gossamer DVD-card ! 1111: assert(isBordeaux); ! 1112: outputSourceMask = kOutputMuteReg_Port15L | kOutputMuteReg_Port15R; ! 1113: break; ! 1114: ! 1115: case kMachineTypeYosemite: ! 1116: // Yosemite does not have an RCA ! 1117: outputSourceMask = 0; ! 1118: break; ! 1119: ! 1120: default: ! 1121: // FIXME: this may be a newworld, so the registry holds ! 1122: // all we need to know about how the burgundy is wired: ! 1123: // Add here the code to interpret it. ! 1124: outputSourceMask = 0; ! 1125: break; ! 1126: } ! 1127: ! 1128: if (mute) ! 1129: currentOutputMuteReg &= ~outputSourceMask; ! 1130: else ! 1131: currentOutputMuteReg |= outputSourceMask; ! 1132: ! 1133: writeCodecReg(ioBaseBurgundy, kOutputMuteReg, currentOutputMuteReg); ! 1134: } ! 1135: ! 1136: // -------------------------------------------------------------------------- ! 1137: // Method: muteHeadphones ! 1138: // ! 1139: // Purpose: ! 1140: // if the argument is true mutes the rear panel mini jack, otherwise ! 1141: // it "unmutes" it. ! 1142: void ! 1143: PPCBurgundy::muteHeadphones(bool mute) ! 1144: { ! 1145: UInt32 outputSourceMask = 0; ! 1146: ! 1147: switch (findHostingHardware(NULL)) ! 1148: { ! 1149: case kMachineTypeSilk: ! 1150: // G3-Gossamer DVD-card ! 1151: assert(isBordeaux); ! 1152: outputSourceMask = kOutputMuteReg_Port16L | kOutputMuteReg_Port16R; ! 1153: break; ! 1154: ! 1155: case kMachineTypeiMac: ! 1156: // iMac: (FIXME I do not know how this is wired, as soon as I have the iMac motherboard I should fix it) ! 1157: outputSourceMask |= kOutputMuteReg_Port15L | kOutputMuteReg_Port15R; ! 1158: outputSourceMask |= kOutputMuteReg_Port16L | kOutputMuteReg_Port16R; ! 1159: outputSourceMask |= kOutputMuteReg_Port13M | kOutputMuteReg_Port17M; ! 1160: break; ! 1161: ! 1162: case kMachineTypeYosemite: ! 1163: // Yosemite: (FIXME as soon as newwolds works I should move this in the newworld handling) ! 1164: outputSourceMask = kOutputMuteReg_Port14L | kOutputMuteReg_Port14R; ! 1165: break; ! 1166: ! 1167: default: ! 1168: // FIXME: this may be a newworld, so the registry holds ! 1169: // all we need to know about how the burgundy is wired: ! 1170: // Add here the code to interpret it. ! 1171: break; ! 1172: } ! 1173: ! 1174: if (mute) ! 1175: currentOutputMuteReg &= ~outputSourceMask; ! 1176: else ! 1177: currentOutputMuteReg |= outputSourceMask; ! 1178: ! 1179: writeCodecReg(ioBaseBurgundy, kOutputMuteReg, currentOutputMuteReg); ! 1180: } ! 1181: ! 1182: // -------------------------------------------------------------------------- ! 1183: // Method: muteCDLine ! 1184: // ! 1185: // Purpose: ! 1186: // if the argument is true mutes the line of the cd player ! 1187: void ! 1188: PPCBurgundy::muteCDLine(bool mute) ! 1189: { ! 1190: // FIXME: Figure out how this is wired up: ! 1191: } ! 1192: ! 1193: // -------------------------------------------------------------------------- ! 1194: // Method: setMicInput ! 1195: // ! 1196: // Purpose: ! 1197: // selects the microphone as input source (if bool = true) ! 1198: void ! 1199: PPCBurgundy::setMicInput(bool mic) ! 1200: { ! 1201: UInt32 reg; ! 1202: ! 1203: #ifdef DEBUGMODE ! 1204: IOLog( "PPCBurgundy::setMicInput: %s\n", (mic ? "True" : "False")); ! 1205: #endif ! 1206: ! 1207: if (mic) { ! 1208: reg = readCodecReg( ioBaseBurgundy, kMux2Reg ); ! 1209: reg |= kMux2Reg_Mux2L_SelectPort6L | kMux2Reg_Mux2R_SelectPort6R; ! 1210: writeCodecReg( ioBaseBurgundy, kMux2Reg, reg ); ! 1211: ! 1212: reg = readCodecReg( ioBaseBurgundy, kMX3Reg ); ! 1213: reg |= kMX3Reg_Select_IS2L | kMX3Reg_Select_IS2R; ! 1214: writeCodecReg( ioBaseBurgundy, kMX3Reg, reg); ! 1215: ! 1216: reg = readCodecReg( ioBaseBurgundy, kOSReg ); ! 1217: reg |= kOSReg_OSE_Select_MXO3; ! 1218: writeCodecReg( ioBaseBurgundy, kOSReg, reg ); ! 1219: ! 1220: reg = readCodecReg( ioBaseBurgundy, kSDOutReg ); ! 1221: reg |= kSDOutReg_OSE_To_SF0; ! 1222: writeCodecReg( ioBaseBurgundy, kSDOutReg, reg ); ! 1223: } ! 1224: else { ! 1225: reg = readCodecReg( ioBaseBurgundy, kMux2Reg ); ! 1226: reg &= ~(kMux2Reg_Mux2L_SelectPort6L | kMux2Reg_Mux2R_SelectPort6R); ! 1227: writeCodecReg( ioBaseBurgundy, kMux2Reg, reg ); ! 1228: ! 1229: reg = readCodecReg( ioBaseBurgundy, kMX3Reg ); ! 1230: reg &= ~(kMX3Reg_Select_IS2L | kMX3Reg_Select_IS2R); ! 1231: writeCodecReg( ioBaseBurgundy, kMX3Reg, reg); ! 1232: ! 1233: reg = readCodecReg( ioBaseBurgundy, kOSReg ); ! 1234: reg &= ~kOSReg_OSE_Select_MXO3; ! 1235: writeCodecReg( ioBaseBurgundy, kOSReg, reg ); ! 1236: ! 1237: reg = readCodecReg( ioBaseBurgundy, kSDOutReg ); ! 1238: reg &= ~kSDOutReg_OSE_To_SF0; ! 1239: writeCodecReg( ioBaseBurgundy, kSDOutReg, reg ); ! 1240: } ! 1241: } ! 1242: ! 1243: ! 1244: // -------------------------------------------------------------------------- ! 1245: // Method: burgundyStatusChanged() ! 1246: // ! 1247: // Purpose: ! 1248: // returns true if something changed in the status register:. ! 1249: bool ! 1250: PPCBurgundy::burgundyStatusChanged() ! 1251: { ! 1252: UInt32 currentStatusRegister = readCodecSenseLines(ioBaseBurgundy); ! 1253: bool returnValue = (currentStatusRegister != lastStatusRegister); ! 1254: lastStatusRegister = currentStatusRegister; ! 1255: ! 1256: return (returnValue); ! 1257: } ! 1258: ! 1259: // -------------------------------------------------------------------------- ! 1260: // Method: headphonesInserted ! 1261: // ! 1262: // Purpose: ! 1263: // returns true if the headphones are inserted. ! 1264: bool ! 1265: PPCBurgundy::headphonesInserted() ! 1266: { ! 1267: UInt32 codecSense; ! 1268: UInt32 inputSourceMask = 0; ! 1269: ! 1270: switch (findHostingHardware(NULL)) ! 1271: { ! 1272: case kMachineTypeSilk: ! 1273: // G3-Gossamer DVD-card ! 1274: assert(isBordeaux); ! 1275: inputSourceMask = kCodecStatusReg_Sense_Headphones; ! 1276: break; ! 1277: ! 1278: case kMachineTypeiMac: ! 1279: // iMac: (FIXME as soon as newwolds works I should move this in the newworld handling) ! 1280: inputSourceMask = kCodecStatusReg_Sense_Headphones | kCodecStatusReg_Sense_Headphones2 | kCodecStatusReg_Sense_Bit; ! 1281: break; ! 1282: ! 1283: case kMachineTypeYosemite: ! 1284: // Yosemite: (FIXME as soon as newwolds works I should move this in the newworld handling) ! 1285: inputSourceMask = kCodecStatusReg_Sense_Headphones; ! 1286: break; ! 1287: ! 1288: default: ! 1289: // FIXME: this may be a newworld, so the registry holds ! 1290: // all we need to know about how the burgundy is wired: ! 1291: // Add here the code to interpret it. ! 1292: break; ! 1293: } ! 1294: ! 1295: codecSense = readCodecSenseLines(ioBaseBurgundy); ! 1296: ! 1297: #ifdef DEBUGMODE ! 1298: IOLog( "PPCBurgundy::headphonesInserted = %d\n\r", (codecSense & inputSourceMask) != 0); ! 1299: #endif ! 1300: ! 1301: return (codecSense & inputSourceMask) != 0; ! 1302: } ! 1303: ! 1304: ! 1305: // -------------------------------------------------------------------------- ! 1306: // Method: microphoneInserted ! 1307: // ! 1308: // Purpose: ! 1309: // returns true if the microphone is inserted. ! 1310: bool ! 1311: PPCBurgundy::microphoneInserted() ! 1312: { ! 1313: UInt32 codecSense; ! 1314: UInt32 inputSourceMask = 0; ! 1315: ! 1316: switch (findHostingHardware(NULL)) ! 1317: { ! 1318: case kMachineTypeSilk: ! 1319: // G3-Gossamer DVD-card ! 1320: assert(isBordeaux); ! 1321: inputSourceMask = kCodecStatusReg_Sense_Mic; ! 1322: break; ! 1323: ! 1324: case kMachineTypeiMac: ! 1325: // iMac: (FIXME as soon as newwolds works I should move this in the newworld handling) ! 1326: inputSourceMask = kCodecStatusReg_Sense_Mic; ! 1327: break; ! 1328: ! 1329: case kMachineTypeYosemite: ! 1330: // Yosemite: (FIXME as soon as newwolds works I should move this in the newworld handling) ! 1331: inputSourceMask = kCodecStatusReg_Sense_Mic; ! 1332: break; ! 1333: ! 1334: default: ! 1335: // FIXME: this may be a newworld, so the registry holds ! 1336: // all we need to know about how the burgundy is wired: ! 1337: // Add here the code to interpret it. ! 1338: break; ! 1339: } ! 1340: ! 1341: codecSense = readCodecSenseLines(ioBaseBurgundy); ! 1342: ! 1343: #ifdef DEBUGMODE ! 1344: IOLog( "PPCBurgundy::microphoneInserted = %d\n\r", (codecSense & inputSourceMask) != 0); ! 1345: #endif ! 1346: ! 1347: // FIXME: This should not be necessary, but since it does not work by default ! 1348: // I'll add this call myself: ! 1349: setMicInput((codecSense & inputSourceMask) != 0); ! 1350: ! 1351: return (codecSense & inputSourceMask) != 0; ! 1352: } ! 1353: ! 1354: // -------------------------------------------------------------------------- ! 1355: // Method: scaleVolume ! 1356: // ! 1357: // Purpose: ! 1358: // Scale the volume to the range used by burgundy: ! 1359: // note, this considers that the volume can range from ! 1360: // 0 to 65536 as in the control strings above (e.g. componentDictionaryMixerIn) ! 1361: UInt8 ! 1362: PPCBurgundy::scaleVolume(int vol) ! 1363: { ! 1364: int output; ! 1365: ! 1366: output = vol / 4096; ! 1367: ! 1368: if ( output > 15 ) ! 1369: output = 15; ! 1370: ! 1371: if (output < 0 ) ! 1372: output = 0; ! 1373: ! 1374: #ifdef DEBUGMODE ! 1375: IOLog("Volume input: %d, output (scaled) %d\n", vol, output); ! 1376: #endif ! 1377: ! 1378: return (UInt8)output; ! 1379: } ! 1380: ! 1381: // -------------------------------------------------------------------------- ! 1382: // Method: volumeHeadphonesLeft & volumeHeadphonesRight ! 1383: // ! 1384: // Purpose: ! 1385: // sets the volume for the left and right channel of the internal ! 1386: // headphones. ! 1387: void ! 1388: PPCBurgundy::volumeHeadphonesLeft(int vol) ! 1389: { ! 1390: // FIXME: This sets all the output volumes, but we may wish to have ! 1391: // a more discriminating volume handling. As soon as I know for sure ! 1392: // how burgundy is wired we can do it. For now this should be fine. ! 1393: volumeAllLeft(vol); ! 1394: } ! 1395: ! 1396: void ! 1397: PPCBurgundy::volumeHeadphonesRight(int vol) ! 1398: { ! 1399: // FIXME: This sets all the output volumes, but we may wish to have ! 1400: // a more discriminating volume handling. As soon as I know for sure ! 1401: // how burgundy is wired we can do it. For now this should be fine. ! 1402: volumeAllRight(vol); ! 1403: } ! 1404: ! 1405: // -------------------------------------------------------------------------- ! 1406: // Method: volumeInternalSpeakerLeft & volumeInternalSpeakerRight ! 1407: // ! 1408: // Purpose: ! 1409: // sets the volume for the left and right channel of the internal ! 1410: // speaker. ! 1411: void ! 1412: PPCBurgundy::volumeInternalSpeakerLeft(int vol) ! 1413: { ! 1414: // FIXME: This sets all the output volumes, but we may wish to have ! 1415: // a more discriminating volume handling. As soon as I know for sure ! 1416: // how burgundy is wired we can do it. For now this should be fine. ! 1417: volumeAllLeft(vol); ! 1418: } ! 1419: ! 1420: void ! 1421: PPCBurgundy::volumeInternalSpeakerRight(int vol) ! 1422: { ! 1423: // FIXME: This sets all the output volumes, but we may wish to have ! 1424: // a more discriminating volume handling. As soon as I know for sure ! 1425: // how burgundy is wired we can do it. For now this should be fine. ! 1426: volumeAllRight(vol); ! 1427: } ! 1428: ! 1429: // -------------------------------------------------------------------------- ! 1430: // Method: volumeCDLineLeft & volumeCDLineRight ! 1431: // ! 1432: // Purpose: ! 1433: // sets the volume for the left and right channel of the CD ! 1434: // line. ! 1435: void ! 1436: PPCBurgundy::volumeCDLineLeft(int vol) ! 1437: { ! 1438: // FIXME: This sets all the output volumes, but we may wish to have ! 1439: // a more discriminating volume handling. As soon as I know for sure ! 1440: // how burgundy is wired we can do it. For now this should be fine. ! 1441: volumeAllLeft(vol); ! 1442: } ! 1443: ! 1444: void ! 1445: PPCBurgundy::volumeCDLineRight(int vol) ! 1446: { ! 1447: // FIXME: This sets all the output volumes, but we may wish to have ! 1448: // a more discriminating volume handling. As soon as I know for sure ! 1449: // how burgundy is wired we can do it. For now this should be fine. ! 1450: volumeAllRight(vol); ! 1451: } ! 1452: ! 1453: // -------------------------------------------------------------------------- ! 1454: // Method: volumeRCAOutputLeft & volumeRCAOutputRight ! 1455: // ! 1456: // Purpose: ! 1457: // sets the volume for the left and right channel of the RCA ! 1458: // line. ! 1459: void ! 1460: PPCBurgundy::volumeRCAOutputLeft(int vol) ! 1461: { ! 1462: // FIXME: This sets all the output volumes, but we may wish to have ! 1463: // a more discriminating volume handling. As soon as I know for sure ! 1464: // how burgundy is wired we can do it. For now this should be fine. ! 1465: volumeAllLeft(vol); ! 1466: } ! 1467: ! 1468: void ! 1469: PPCBurgundy::volumeRCAOutputRight(int vol) ! 1470: { ! 1471: // FIXME: This sets all the output volumes, but we may wish to have ! 1472: // a more discriminating volume handling. As soon as I know for sure ! 1473: // how burgundy is wired we can do it. For now this should be fine. ! 1474: volumeAllRight(vol); ! 1475: } ! 1476: ! 1477: // -------------------------------------------------------------------------- ! 1478: // Method: volumeAllRight & volumeAllLeft ! 1479: // ! 1480: // Purpose: ! 1481: // sets the volume to all the output ports. This is because I do not ! 1482: // really know how burgundy is wired up. (and because however the ! 1483: // OS has only one control for the volume). ! 1484: void ! 1485: PPCBurgundy::volumeAllLeft(int vol) ! 1486: { ! 1487: UInt8 newVol = scaleVolume(vol); ! 1488: ! 1489: // This changes all the digital volume controls (used only to mute and unmute the oputput) ! 1490: if (newVol > 0) { ! 1491: writeCodecReg( ioBaseBurgundy, kGAP0LReg, 0xFF); ! 1492: writeCodecReg( ioBaseBurgundy, kGAP1LReg, 0xFF); ! 1493: writeCodecReg( ioBaseBurgundy, kGAP2LReg, 0xFF); ! 1494: writeCodecReg( ioBaseBurgundy, kGAP3LReg, 0xFF); ! 1495: } ! 1496: else { ! 1497: writeCodecReg( ioBaseBurgundy, kGAP0LReg, 0x00); ! 1498: writeCodecReg( ioBaseBurgundy, kGAP1LReg, 0x00); ! 1499: writeCodecReg( ioBaseBurgundy, kGAP2LReg, 0x00); ! 1500: writeCodecReg( ioBaseBurgundy, kGAP3LReg, 0x00); ! 1501: } ! 1502: ! 1503: // while this acts on the analog volume controls ! 1504: newVol = 15 - newVol; ! 1505: writeCodecReg( ioBaseBurgundy, kOutputLvlPort13Reg, (readCodecReg(ioBaseBurgundy, kOutputLvlPort13Reg) & 0xF0) | (newVol & 0x0F)); ! 1506: writeCodecReg( ioBaseBurgundy, kOutputLvlPort14Reg, (readCodecReg(ioBaseBurgundy, kOutputLvlPort14Reg) & 0xF0) | (newVol & 0x0F)); ! 1507: writeCodecReg( ioBaseBurgundy, kOutputLvlPort15Reg, (readCodecReg(ioBaseBurgundy, kOutputLvlPort15Reg) & 0xF0) | (newVol & 0x0F)); ! 1508: writeCodecReg( ioBaseBurgundy, kOutputLvlPort16Reg, (readCodecReg(ioBaseBurgundy, kOutputLvlPort16Reg) & 0xF0) | (newVol & 0x0F)); ! 1509: writeCodecReg( ioBaseBurgundy, kOutputLvlPort17Reg, (readCodecReg(ioBaseBurgundy, kOutputLvlPort17Reg) & 0xF0) | (newVol & 0x0F)); ! 1510: } ! 1511: ! 1512: void ! 1513: PPCBurgundy::volumeAllRight(int vol) ! 1514: { ! 1515: UInt8 newVol = scaleVolume(vol); ! 1516: ! 1517: // This changes all the digital volume controls (used only to mute and unmute the oputput) ! 1518: if (newVol > 0) { ! 1519: writeCodecReg( ioBaseBurgundy, kGAP0RReg, 0xFF); ! 1520: writeCodecReg( ioBaseBurgundy, kGAP1RReg, 0xFF); ! 1521: writeCodecReg( ioBaseBurgundy, kGAP2RReg, 0xFF); ! 1522: writeCodecReg( ioBaseBurgundy, kGAP3RReg, 0xFF); ! 1523: } ! 1524: else { ! 1525: writeCodecReg( ioBaseBurgundy, kGAP0RReg, 0x00); ! 1526: writeCodecReg( ioBaseBurgundy, kGAP1RReg, 0x00); ! 1527: writeCodecReg( ioBaseBurgundy, kGAP2RReg, 0x00); ! 1528: writeCodecReg( ioBaseBurgundy, kGAP3RReg, 0x00); ! 1529: } ! 1530: ! 1531: // while this acts on the analog volume controls ! 1532: newVol = (15 - newVol) << 4; ! 1533: writeCodecReg( ioBaseBurgundy, kOutputLvlPort13Reg, (readCodecReg(ioBaseBurgundy, kOutputLvlPort13Reg) & 0x0F) | (newVol & 0xF0)); ! 1534: writeCodecReg( ioBaseBurgundy, kOutputLvlPort14Reg, (readCodecReg(ioBaseBurgundy, kOutputLvlPort14Reg) & 0x0F) | (newVol & 0xF0)); ! 1535: writeCodecReg( ioBaseBurgundy, kOutputLvlPort15Reg, (readCodecReg(ioBaseBurgundy, kOutputLvlPort15Reg) & 0x0F) | (newVol & 0xF0)); ! 1536: writeCodecReg( ioBaseBurgundy, kOutputLvlPort16Reg, (readCodecReg(ioBaseBurgundy, kOutputLvlPort16Reg) & 0x0F) | (newVol & 0xF0)); ! 1537: writeCodecReg( ioBaseBurgundy, kOutputLvlPort17Reg, (readCodecReg(ioBaseBurgundy, kOutputLvlPort17Reg) & 0x0F) | (newVol & 0xF0)); ! 1538: } ! 1539: ! 1540: ! 1541: // -------------------------------------------------------------------------- ! 1542: // Method: volumeMixerInLeft ! 1543: // ! 1544: // Purpose: ! 1545: // sets the gain for the input left line ! 1546: void ! 1547: PPCBurgundy::volumeMixerInLeft(int vol) ! 1548: { ! 1549: UInt8 left = scaleVolume(vol); ! 1550: ! 1551: writeCodecReg( ioBaseBurgundy, kVGA2Reg, 0x44 ); ! 1552: writeCodecReg( ioBaseBurgundy, kGAS2LReg, left ); ! 1553: } ! 1554: ! 1555: // -------------------------------------------------------------------------- ! 1556: // Method: volumeMixerInRight ! 1557: // ! 1558: // Purpose: ! 1559: // sets the gain for the input right line ! 1560: void ! 1561: PPCBurgundy::volumeMixerInRight(int vol) ! 1562: { ! 1563: UInt8 right = scaleVolume(vol); ! 1564: ! 1565: writeCodecReg( ioBaseBurgundy, kVGA2Reg, 0x44 ); ! 1566: writeCodecReg( ioBaseBurgundy, kGAS2RReg, right ); ! 1567: } ! 1568: ! 1569: ! 1570: /* ============================================================= ! 1571: * VERY Private Methods used to access to the burgundy registers ! 1572: * ============================================================= */ ! 1573: ! 1574: static void ! 1575: writeCodecReg( volatile UInt8 *ioBaseBurgundy, int regInfo, int value ) ! 1576: { ! 1577: u_int32_t regBits; ! 1578: u_int32_t regValue; ! 1579: u_int32_t i; ! 1580: volatile u_int32_t CodecControlReg; ! 1581: ! 1582: struct _reg ! 1583: { ! 1584: UInt8 unused0; ! 1585: UInt8 size; ! 1586: UInt8 addr; ! 1587: UInt8 offset; ! 1588: } *reg = (struct _reg *)®Info; ! 1589: ! 1590: ! 1591: regBits = (kCodecCtlReg_Write | kCodecCtlReg_Reset) ! 1592: | ((u_int32_t) reg->addr * kCodecCtlReg_Addr_Bit) ! 1593: | ((u_int32_t)(reg->size + reg->offset - 1) * kCodecCtlReg_LastByte_Bit); ! 1594: ! 1595: for ( i=0; i < reg->size; i++ ) ! 1596: { ! 1597: regValue = regBits | ((u_int32_t)(reg->offset + i) * kCodecCtlReg_CurrentByte_Bit) | (value & 0xFF); ! 1598: OSWriteLittleInt32(ioBaseBurgundy, kCodecCtlReg, regValue ); ! 1599: eieio(); ! 1600: ! 1601: #ifdef DEBUGMODE ! 1602: IOLog( "PPCSound(burgundy): CodecWrite = %08x\n\r", regValue ); ! 1603: #endif ! 1604: ! 1605: value >>= 8; ! 1606: ! 1607: regBits &= ~kCodecCtlReg_Reset; ! 1608: ! 1609: do ! 1610: { ! 1611: CodecControlReg = OSReadLittleInt32( ioBaseBurgundy, kCodecCtlReg ); ! 1612: eieio(); ! 1613: } ! 1614: while ( CodecControlReg & kCodecCtlReg_Busy ); ! 1615: } ! 1616: } ! 1617: ! 1618: ! 1619: static int ! 1620: readCodecReg( volatile UInt8 *ioBaseBurgundy, int regInfo ) ! 1621: { ! 1622: u_int32_t regBits; ! 1623: u_int32_t regValue = 0; ! 1624: u_int32_t i,j; ! 1625: int value; ! 1626: u_int32_t byteCounter; ! 1627: u_int32_t currentCounter; ! 1628: volatile u_int32_t CodecControlReg; ! 1629: volatile u_int32_t CodecStatusReg; ! 1630: ! 1631: ! 1632: struct _reg ! 1633: { ! 1634: UInt8 unused0; ! 1635: UInt8 size; ! 1636: UInt8 addr; ! 1637: UInt8 offset; ! 1638: } *reg = (struct _reg *)®Info; ! 1639: ! 1640: value = 0; ! 1641: ! 1642: regBits = (kCodecCtlReg_Reset) ! 1643: | ((u_int32_t) reg->addr * kCodecCtlReg_Addr_Bit) ! 1644: | ((u_int32_t)(reg->size + reg->offset - 1) * kCodecCtlReg_LastByte_Bit); ! 1645: ! 1646: CodecStatusReg = OSReadLittleInt32( ioBaseBurgundy, kCodecStatusReg ); ! 1647: eieio(); ! 1648: byteCounter = ((CodecStatusReg & kCodecStatusReg_ByteCounter_Mask) / kCodecStatusReg_ByteCounter_Bit + 1) & 0x03; ! 1649: ! 1650: for ( i=0; i < reg->size; i++ ) ! 1651: { ! 1652: regValue = regBits | ((u_int32_t)(reg->offset + i) * kCodecCtlReg_CurrentByte_Bit); ! 1653: OSWriteLittleInt32(ioBaseBurgundy, kCodecCtlReg, regValue ); ! 1654: eieio(); ! 1655: regBits &= ~kCodecCtlReg_Reset; ! 1656: ! 1657: do ! 1658: { ! 1659: CodecControlReg = OSReadLittleInt32( ioBaseBurgundy, kCodecCtlReg ); ! 1660: eieio(); ! 1661: } ! 1662: while ( CodecControlReg & kCodecCtlReg_Busy ); ! 1663: ! 1664: j=0; ! 1665: do ! 1666: { ! 1667: CodecStatusReg = OSReadLittleInt32( ioBaseBurgundy, kCodecStatusReg ); ! 1668: eieio(); ! 1669: currentCounter = ((CodecStatusReg & kCodecStatusReg_ByteCounter_Mask) / kCodecStatusReg_ByteCounter_Bit) & 0x03; ! 1670: } ! 1671: while ( (byteCounter != currentCounter) && (j++ < 1000)); ! 1672: ! 1673: byteCounter++; ! 1674: ! 1675: IODelay(10); ! 1676: CodecStatusReg = OSReadLittleInt32( ioBaseBurgundy, kCodecStatusReg ); ! 1677: ! 1678: value |= ((CodecStatusReg & kCodecStatusReg_Data_Mask) / kCodecStatusReg_Data_Bit) << 8*i; ! 1679: } ! 1680: ! 1681: #ifdef DEBUGMODE ! 1682: IOLog( "PPCSound(burgundy): CodecRead = %08x %08x\n\r", regValue, value ); ! 1683: #endif ! 1684: ! 1685: return value; ! 1686: } ! 1687: ! 1688: static int ! 1689: readCodecSenseLines( volatile UInt8 *ioBaseBurgundy ) ! 1690: { ! 1691: return ((OSReadLittleInt32( ioBaseBurgundy, kCodecStatusReg ) / kCodecStatusReg_Sense_Bit) & kCodecStatusReg_Sense_Mask); ! 1692: } ! 1693: ! 1694: ! 1695: static void ! 1696: writeSoundControlReg( volatile UInt8 *ioBaseBurgundy, int value ) ! 1697: { ! 1698: ! 1699: #ifdef DEBUGMODE ! 1700: IOLog( "PPCSound(burgundy): SoundControlReg = %08x\n", value); ! 1701: #endif ! 1702: ! 1703: OSWriteLittleInt32( ioBaseBurgundy, kSoundCtlReg, value ); ! 1704: eieio(); ! 1705: } ! 1706: ! 1707: ! 1708: ! 1709:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.