|
|
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.