|
|
1.1 root 1: /*
2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
24: *
25: * Interface implementation for the DAC 3550A audio Controller
26: *
27: * HISTORY
28: *
29: *
30: */
31:
32: #include <IOKit/assert.h>
33: #include <IOKit/system.h>
34:
35: #include <IOKit/IOLib.h>
36: #include <IOKit/IODeviceTreeSupport.h>
37: #include <IOKit/IOPlatformExpert.h>
38: #include <IOKit/ppc/IODBDMA.h>
39:
40: // Driver headers
41: #include "daca_hw.h"
42: #include "PPCDACA_inlined.h"
43: #include "PPCDACA.h"
44:
45: #define super IOAudioBus
46: OSDefineMetaClassAndStructors( PPCDACA, IOAudioBus )
47:
48: /* ==============
49: * Public Methods
50: * ============== */
51: bool
52: PPCDACA::init(OSDictionary * properties)
53: {
54: if (!super::init(properties))
55: return false;
56:
57: // Nulls the pointers for the arrays we allocate:
58: fOutputComponents = NULL;
59: numOutputComponents = NULL;
60:
61: // Initialize the defualt registers to non zero values (so they will be revitten)
62: sampleRateReg = 0xFF;
63: analogVolumeReg = kPowerOnDefaultAVOL;
64: configurationReg = 0xFF;
65:
66: // Mirror the analogVolumeReg for the speaker and for the headphones.
67: internalSpeakerVolume = analogVolumeReg;
68: internalHeadphonesVolume = analogVolumeReg;
69:
70: // Last value of the status is 0
71: lastStatus = 0;
72:
73: // Clears the interface
74: interface = NULL;
75:
76: // Forget the provider:
77: sound = NULL;
78:
79: // Initialize the sound format:
80: dacaSerialFormat = kSndIOFormatUnknown;
81:
82: return true;
83: }
84:
85: void
86: PPCDACA::free()
87: {
88: // Releases the sound:
89: if(sound != NULL)
90: sound->release();
91: sound = NULL;
92:
93: super::free();
94: }
95:
96: IOService*
97: PPCDACA::probe(IOService* provider, SInt32* score)
98: {
99: // Finds the possible candidate for sound, to be used in
100: // reading the caracteristics of this hardware:
101: IORegistryEntry *soundCandidate = provider->childFromPath("sound", gIODTPlane);
102:
103: if (super::probe(provider, score) && implementsDACA(soundCandidate)) {
104: #ifdef DEBUGMODE
105: IOLog("PPCDACA::probe we are on a PPCDACA device !!\n");
106: #endif // DEBUGMODE
107:
108: // we did not fail:
109: *score = kIODefaultProbeScore;
110: sound = soundCandidate;
111: return this;
112: }
113:
114: return (NULL);
115: }
116:
117: #define kNumDMAStreams 1
118: bool
119: PPCDACA::start(IOService* provider)
120: {
121: // Gets the base for the DAC-3550 registers:
122: IOMemoryMap *map;
123: int i;
124:
125: #ifdef DEBUGMODE
126: // Delay for 30 seconds so we have the time to attach the debugger and look at
127: // what is going on here (only if DEBUGMODE of course).
128: IOLog("Starting DAC-3550 with provider %s ...", provider->getName());
129: IOSleep(30 * 1000);
130: IOLog("...\n");
131: #endif // DEBUGMODE
132:
133: if(!super::start(provider)) {
134: #ifdef DEBUGMODE
135: IOLog("PPCDACA::start if(!super::start(provider)) fails !!\n");
136: #endif // DEBUGMODE
137: return (false);
138: }
139:
140: if (!findAndAttachI2C(provider)) {
141: #ifdef DEBUGMODE
142: IOLog("PPCDACA::start if (!findAndAttachI2C(IOService *provider)) fails !!\n");
143: #endif // DEBUGMODE
144: return (false);
145: }
146:
147: map = provider->mapDeviceMemoryWithIndex(kAudioDMAdeviceInt);
148: if(!map) {
149: #ifdef DEBUGMODE
150: IOLog("PPCDACA::start if(!map) %d fails !!\n",kAudioDMAdeviceInt);
151: #endif // DEBUGMODE
152: return (false);
153: }
154: soundConfigSpace = (UInt8 *)map->getPhysicalAddress();
155:
156: if (!AllocateStreams(kNumDMAStreams)) {
157: #ifdef DEBUGMODE
158: IOLog("PPCDACA::start if (!AllocateStreams(kNumDMAStreams)) fails !!\n");
159: #endif // DEBUGMODE
160: return (false);
161: }
162:
163: map = provider->mapDeviceMemoryWithIndex(kAudioDMAtxInt);
164: if(!map) {
165: #ifdef DEBUGMODE
166: IOLog("PPCDACA::start if(!map) %d fails !!\n",kAudioDMAtxInt);
167: #endif // DEBUGMODE
168: return (false);
169: }
170: DefineStream(kAudioDMAOutputStream, kOutput, frameRate(0), (IODBDMAChannelRegisters*)map->getVirtualAddress());
171:
172: // Creates the array of output components
173: numOutputComponents = numberOfInputComponents();
174:
175: fOutputComponents = (IOAudioComponentImplPtr*)IOMalloc(sizeof(IOAudioComponentImplPtr) * numOutputComponents);
176: if (fOutputComponents == NULL) {
177: #ifdef DEBUGMODE
178: IOLog("PPCDACA::start if (fOutputComponents == NULL) fails !!\n");
179: #endif // DEBUGMODE
180:
181: // Free the DMA and exit:
182: FreeStreams();
183: return false;
184: }
185:
186: // Initalizes all the components:
187: for (i = 0; i < numOutputComponents; i++)
188: fOutputComponents[i] = NULL;
189:
190: // sets the clock base address figuring out which I2S cell we're on
191: if ((((UInt32)soundConfigSpace ^ kI2S0BaseOffset) & 0x0001FFFF) == 0) {
192: ioBaseAddress = (void *)((UInt32)soundConfigSpace - kI2S0BaseOffset);
193: i2SInterfaceNumber = 0;
194: }
195: else if ((((UInt32)soundConfigSpace ^ kI2S1BaseOffset) & 0x0001FFFF) == 0) {
196: ioBaseAddress = (void *)((UInt32)soundConfigSpace - kI2S1BaseOffset);
197: i2SInterfaceNumber = 1;
198: }
199: else {
200: IOLog("PPCDACA::start failed to setup ioBaseAddress and ioClockBaseAddress\n");
201: }
202:
203: // This is the keylargo FC1 (Feature configuration 1)
204: ioClockBaseAddress = (void *)((UInt32)ioBaseAddress + kI2SClockOffset);
205:
206: // Finds the position of the status register:
207: ioStatusRegister_GPIO12 = (void *)((UInt32)ioBaseAddress + kGPio12);
208:
209: // Enables the I2S Interface:
210: KLSetRegister(ioClockBaseAddress, KLGetRegister(ioClockBaseAddress) | kI2S0InterfaceEnable);
211:
212: // Starts the workloop and exit since there is nothing we can be interested about anymore
213: startWorkLoop();
214:
215: return true;
216: }
217:
218: void
219: PPCDACA::stop(IOService *provider)
220: {
221: // Releases all DMA streams:
222: FreeStreams();
223:
224: // Releases the output components
225: if (fOutputComponents != NULL) {
226: IOFree(fOutputComponents, sizeof(IOAudioComponentImplPtr) * numOutputComponents);
227: fOutputComponents = NULL;
228: numOutputComponents = 0;
229: }
230:
231: // Call the parent stop:
232: super::stop(provider);
233: }
234:
235: void
236: PPCDACA::CreateAudioTopology(IOCommandQueue *queue)
237: {
238: IOAudioComponentImpl *mixerOut;
239: IOAudioComponentImpl *modem;
240: IOAudioComponentImpl *headphones;
241: IOAudioComponentImpl *cd;
242: IOAudioComponentImpl *speaker;
243: IOAudioComponentImpl *passthru;
244:
245: AudioStreamIndex outputStream;
246:
247: if (!fStreams)
248: return;
249:
250: outputStream = firstStreamAfter(kOutput, 0);
251:
252: if (outputStream == kInvalidStreamIndex) {
253: IOLog("PPCDACA::CreateAudioTopology called without available DMA streams\n");
254: return;
255: }
256: else
257: IOLog("PPCDACA::CreateAudioTopology output stream is %d\n", outputStream);
258:
259: mixerOut = buildComponentAndAttach(GetStream(outputStream), NULL, componentDictionaryMixerOut(), queue);
260: headphones = buildComponentAndAttach(mixerOut, NULL, componentDictionaryHeadphones(), queue);
261: speaker = buildComponentAndAttach(mixerOut, NULL, componentDictionarySpeaker(), queue);
262:
263: cd = buildComponentAndAttach(NULL, NULL, componentDictionaryCD(), queue);
264: modem = buildComponentAndAttach(NULL, NULL, componentDictionaryModem(), queue);
265:
266: passthru = buildComponentAndAttach(NULL, mixerOut, componentDictionaryPassThru(), queue);
267:
268: // FIXME: the component connection could be done better than so
269: if (fOutputComponents != NULL) {
270: fOutputComponents[kSpeaker] = speaker;
271:
272: if (numOutputComponents > 1)
273: fOutputComponents[kHeadphones] = headphones;
274: }
275:
276: // Sets ups the DAC-3550 as required by this machine wiring
277: // configuration:
278: if (!dependentSetup())
279: IOLog("PPCDACA::CreateAudioTopology DAC-3550 setup failed\n");
280: }
281:
282: void
283: PPCDACA::DoClockTick(IOTimerEventSource *t)
284: {
285: checkStatusRegister();
286: super::DoClockTick(t);
287: }
288:
289: void
290: PPCDACA::calculateTickInterval(AbsoluteTime *tickInterval)
291: {
292: AbsoluteTime maxInterval;
293:
294: // We want to check the status at least one a second
295: nanoseconds_to_absolutetime(NSEC_PER_SEC, &maxInterval);
296: if(CMP_ABSOLUTETIME(&maxInterval, tickInterval) < 0) {
297: *tickInterval = maxInterval;
298: }
299: super::calculateTickInterval(tickInterval);
300: }
301:
302: IOReturn
303: PPCDACA::SetControl(UInt16 id, int val)
304: {
305: IOReturn res = kIOReturnSuccess;
306:
307: switch(id) {
308: case kSpeakerMute:
309: muteInternalSpeaker(val != 0);
310: muteHeadphones(val == 0);
311: break;
312:
313: case kHeadphonesMute:
314: muteHeadphones(val != 0);
315: muteInternalSpeaker(val == 0);
316: break;
317:
318: case kModemMute:
319: setModemInput(val == 0);
320: break;
321:
322: case kSpeakerVolLeft:
323: volumeInternalSpeakerLeft(val);
324: break;
325:
326: case kSpeakerVolRight:
327: volumeInternalSpeakerRight(val);
328: break;
329:
330: case kHeadphonesVolLeft:
331: volumeHeadphonesLeft(val);
332: break;
333:
334: case kHeadphonesVolRight:
335: volumeHeadphonesRight(val);
336: break;
337:
338: case kCDMute:
339: muteCDLine(val != 0);
340: break;
341:
342: case kPassThruVolLeft:
343: break;
344:
345: case kPassThruVolRight:
346: break;
347:
348: case kPassThruMute:
349: break;
350:
351: default:
352: res = kIOReturnUnsupported;
353: }
354: return res;
355: }
356:
357: /* ===============
358: * Private Methods
359: * =============== */
360:
361: // --------------------------------------------------------------------------
362: // Method: findAndAttachI2C
363: //
364: // Purpose:
365: // Attaches to the i2c interface:
366: bool
367: PPCDACA::findAndAttachI2C(IOService *provider)
368: {
369: OSData *t;
370: UInt32 baseAddress;
371: UInt32 addressSteps;
372: UInt32 rate;
373: IORegistryEntry *i2cCandidate;
374:
375: // Searches the i2c:
376: for (i2cCandidate = NULL;
377: (provider != NULL) && (i2cCandidate == NULL);
378: provider = provider->getProvider()) {
379: i2cCandidate = provider->childFromPath("i2c", gIODTPlane);
380: #ifdef DEBUGMODE
381: IOLog("Looking for i2c in %s -> 0x%08lx\n", provider->getName(), (UInt32)i2cCandidate);
382: #endif // DEBUGMODE
383: }
384:
385: if (i2cCandidate == NULL) {
386: #ifdef DEBUGMODE
387: IOLog("PPCDACA::findAndAttachI2C can't find the i2c in the registry\n");
388: #endif // DEBUGMODE
389: return false;
390: }
391:
392: // creates the interface for real:
393: interface = new PPCI2CInterface;
394: if (interface == NULL) {
395: #ifdef DEBUGMODE
396: IOLog("PPCDACA::findAndAttachI2C can't allocate memory for the PPCI2CInterface\n");
397: #endif // DEBUGMODE
398: return false;
399: }
400:
401: // sets up the interface:
402: t = OSDynamicCast(OSData, i2cCandidate->getProperty("AAPL,address"));
403: if (t != NULL)
404: baseAddress = *((UInt32*)t->getBytesNoCopy());
405: else {
406: #ifdef DEBUGMODE
407: IOLog( "PPCDACA::findAndAttachI2C missing property AAPL,address in i2c registry\n");
408: #endif
409: return false;
410: }
411:
412: t = OSDynamicCast(OSData, i2cCandidate->getProperty("AAPL,address-step"));
413: if (t != NULL)
414: addressSteps = *((UInt32*)t->getBytesNoCopy());
415: else {
416: #ifdef DEBUGMODE
417: IOLog( "PPCDACA::findAndAttachI2C missing property AAPL,address-step in i2c registry\n");
418: #endif
419: return false;
420: }
421:
422: t = OSDynamicCast(OSData, i2cCandidate->getProperty("AAPL,i2c-rate"));
423: if (t != NULL)
424: rate = *((UInt32*)t->getBytesNoCopy());
425: else {
426: #ifdef DEBUGMODE
427: IOLog( "PPCDACA::findAndAttachI2C missing property AAPL,i2c-rate in i2c registry\n");
428: #endif
429: return false;
430: }
431:
432: if (!interface->initI2CBus((UInt8*)baseAddress, (UInt8)addressSteps))
433: return false;
434:
435: if (!interface->setKhzSpeed((UInt)rate))
436: return false;
437:
438: // Also sets the default mode
439: interface->setStandardSubMode();
440:
441: // Finds the port to use:
442: return(interface->openI2CBus(getI2CPort()));
443: }
444:
445: // --------------------------------------------------------------------------
446: // Method: detachFromI2C
447: //
448: // Purpose:
449: // detaches from the I2C
450: bool
451: PPCDACA::detachFromI2C(IOService* /*provider*/)
452: {
453: if (interface)
454: delete interface;
455:
456: return (true);
457: }
458:
459: // --------------------------------------------------------------------------
460: // Method: implementsDACA
461: //
462: // Purpose:
463: // Attempts to discover if the device implements DAC-3550:
464: bool
465: PPCDACA::implementsDACA(IORegistryEntry *device)
466: {
467: if (device != NULL) {
468: OSData *s = NULL;
469:
470: #ifdef DEBUGMODE
471: IOLog("Matching DAC-3550 compatibility with %s\n", device->getName());
472: #endif // DEBUGMODE
473: s = OSDynamicCast(OSData, device->getProperty("compatible"));
474:
475: if (s != NULL) {
476: if(s->isEqualTo("daca", sizeof("daca")-1)) {
477: return true;
478: }
479: else {
480: #ifdef DEBUGMODE
481: IOLog("PPCDAC-3550::probe sound is compatible with %s.\n", (char*)s->getBytesNoCopy(0, sizeof("daca")-1));
482: #endif // DEBUGMODE
483: }
484: }
485: else {
486: #ifdef DEBUGMODE
487: IOLog("PPCDAC-3550::probe sound does not have a compatible property.\n");
488: #endif // DEBUGMODE
489: }
490: }
491: else{
492: #ifdef DEBUGMODE
493: IOLog("PPCDAC-3550::probe this hardware does not have a sound chip\n");
494: #endif // DEBUGMODE
495: }
496: return false;
497: }
498:
499: // --------------------------------------------------------------------------
500: // Method: numberOfInputComponents
501: //
502: // Purpose:
503: // returns the number of components for the input lines
504: // the name registry describes the CHIP (which has 3 inputs
505: // however, the iBook has no inputs, so I have to force 0
506: // as output).
507: #define kCommonNumberOfInputComponents 0
508:
509: int
510: PPCDACA::numberOfInputComponents()
511: {
512: return kCommonNumberOfInputComponents;
513: }
514:
515: // --------------------------------------------------------------------------
516: // Method: numberOfOutputComponents
517: //
518: // Purpose:
519: // returns the number of components for the output lines
520: // usually are 2 one is the internal speacker and the other
521: // is the headphone line.
522: #define kCommonNumberOfOutputComponents 2
523:
524: int
525: PPCDACA::numberOfOutputComponents()
526: {
527: if(sound) {
528: OSData *t;
529:
530: t = OSDynamicCast(OSData, sound->getProperty("#-outputs"));
531: if (t != NULL) {
532: return *(UInt32*)(t->getBytesNoCopy());
533: }
534: }
535: return kCommonNumberOfOutputComponents;
536: }
537:
538:
539: // --------------------------------------------------------------------------
540: // Method: frameRate
541: //
542: // Purpose:
543: // returns the frame rate as in the registry, if it is
544: // not found in the registry, it returns the default value.
545: #define kCommonFrameRate 44100
546:
547: UInt32
548: PPCDACA::frameRate(UInt32 index)
549: {
550: if(sound) {
551: OSData *t;
552:
553: t = OSDynamicCast(OSData, sound->getProperty("sample-rates"));
554: if (t != NULL) {
555: UInt32 *fArray = (UInt32*)(t->getBytesNoCopy());
556:
557: if ((fArray != NULL) && (index < fArray[0])){
558: // I could do >> 16, but in this way the code is portable and
559: // however any decent compiler will recognize this as a shift
560: // and do the right thing.
561: UInt32 fR = fArray[index + 1] / (UInt32)65536;
562:
563: #ifdef DEBUGMODE
564: IOLog( "PPCDACA::frameRate (%ld)\n", fR);
565: #endif
566: return fR;
567: }
568: }
569: }
570:
571: return (UInt32)kCommonFrameRate;
572: }
573:
574: // --------------------------------------------------------------------------
575: // Method: getI2CPort
576: //
577: // Purpose:
578: // returns the i2c port to use for the audio chip.
579: UInt32
580: PPCDACA::getI2CPort()
581: {
582: if(sound) {
583: OSData *t;
584:
585: t = OSDynamicCast(OSData, sound->getProperty("AAPL,i2c-port-select"));
586: if (t != NULL) {
587: UInt32 myPort = *((UInt32*)t->getBytesNoCopy());
588: return myPort;
589: }
590: #ifdef DEBUGMODE
591: else
592: IOLog( "PPCDACA::getI2CPort missing property port\n");
593: #endif
594: }
595:
596: return 0;
597: }
598:
599: // --------------------------------------------------------------------------
600: // Method(s): componentDictionaryXXXXXX
601: //
602: // Purpose:
603: // the next N methods return the strings for the component dictionaries
604: // for each kind of component. As stated in the AWACS driver, these should
605: // end in the driver resources.
606:
607: // NOTE: (This is important !!!) the soundControls enum in the header file is
608: // bounded to the following stings in this way:
609: // for each component the control Id in the string must have the same value
610: // of the corrispondent soundControls enum item. For example the sound control
611: // enum item kHeadphonesVolLeft has value 4, so in sHeadphones the ID of the
612: // volume left control must be 4.
613:
614: char*
615: PPCDACA::componentDictionarySpeaker()
616: {
617: static const char *sSpeaker =
618: "{
619: 'Type' = 'Speaker';
620: 'Channels' = 2:8;
621: 'Master' = 1:8;
622: 'Controls' = {
623: 'MuteAll' = {
624: 'Type' = 'Mute';
625: 'Id' = 0:16;
626: 'Val' = 0:8;
627: 'Min' = 0:8;
628: 'Max' = 1:8;
629: 'Chan' = 0:8;
630: };
631: 'VolumeLeft' = {
632: 'Type' = 'Volume';
633: 'Id' = 1:16;
634: 'Val' = 65535:16;
635: 'Min' = 0:16;
636: 'Max' = 65535:16;
637: 'Chan' = 1:8;
638: };
639: 'VolumeRight' = {
640: 'Type' = 'Volume';
641: 'Id' = 2:16;
642: 'Val' = 65535:16;
643: 'Min' = 0:16;
644: 'Max' = 65535:16;
645: 'Chan' = 2:8;
646: };
647: };
648: }";
649: return (char*)sSpeaker;
650: }
651:
652: char*
653: PPCDACA::componentDictionaryHeadphones()
654: {
655: static const char *sHeadphones =
656: "{
657: 'Type' = 'Headphones';
658: 'Channels' = 2:8;
659: 'Master' = 1:8;
660: 'Controls' = {
661: 'MuteAll' = {
662: 'Type' = 'Mute';
663: 'Id' = 3:16;
664: 'Val' = 0:8;
665: 'Min' = 0:8;
666: 'Max' = 1:8;
667: 'Chan' = 0:8;
668: };
669: 'VolumeLeft' = {
670: 'Type' = 'Volume';
671: 'Id' = 4:16;
672: 'Val' = 65535:16;
673: 'Min' = 0:16;
674: 'Max' = 65535:16;
675: 'Chan' = 1:8;
676: };
677: 'VolumeRight' = {
678: 'Type' = 'Volume';
679: 'Id' = 5:16;
680: 'Val' = 65535:16;
681: 'Min' = 0:16;
682: 'Max' = 65535:16;
683: 'Chan' = 2:8;
684: };
685: };
686: 'Inputs' = {
687: 'Jack' = {
688: 'Val' = 0:8;
689: 'Min' = 0:8;
690: 'Max' = 1:8;
691: };
692: };
693: }";
694: return (char*)sHeadphones;
695: }
696:
697: char*
698: PPCDACA::componentDictionaryModem()
699: {
700: static const char *sModem =
701: "{
702: 'Type' = 'Modem';
703: 'Channels' = 2:8;
704: 'Controls' = {
705: 'MuteAll' = {
706: 'Type' = 'Mute';
707: 'Id' = 6:16;
708: 'Val' = 0:8;
709: 'Min' = 0:8;
710: 'Max' = 1:8;
711: 'Chan' = 0:8;
712: };
713: };
714: 'Inputs' = {
715: 'Jack' = {
716: 'Val' = 0:8;
717: 'Min' = 0:8;
718: 'Max' = 1:8;
719: };
720: };
721: }";
722: return (char*)sModem;
723: }
724:
725: char*
726: PPCDACA::componentDictionaryCD()
727: {
728: static const char *sCD =
729: "{
730: 'Type' = 'CD';
731: 'Channels' = 2:8;
732: 'Controls' = {
733: 'MuteAll' = {
734: 'Type' = 'Mute';
735: 'Id' = 7:16;
736: 'Val' = 0:8;
737: 'Min' = 0:8;
738: 'Max' = 1:8;
739: 'Chan' = 0:8;
740: };
741: };
742: }";
743: return (char*)sCD;
744: }
745:
746: char*
747: PPCDACA::componentDictionaryMixerOut()
748: {
749: static const char *sMixerOut =
750: "{
751: 'Type' = 'Mixer';
752: 'Channels' = 2:8;
753: }";
754: return (char*)sMixerOut;
755: }
756:
757: char*
758: PPCDACA::componentDictionaryPassThru()
759: {
760: static const char *sPassThru =
761: "{
762: 'Type' = 'Feature';
763: 'Channels' = 2:8;
764: 'Controls' = {
765: 'MuteAll' = {
766: 'Type' = 'Mute';
767: 'Id' = 12:16;
768: 'Val' = 1:8;
769: 'Min' = 0:8;
770: 'Max' = 1:8;
771: 'Chan' = 0:8;
772: };
773: 'VolumeLeft' = {
774: 'Type' = 'Volume';
775: 'Id' = 10:16;
776: 'Val' = 65535:16;
777: 'Min' = 0:16;
778: 'Max' = 65535:16;
779: 'Chan' = 1:8;
780: };
781: 'VolumeRight' = {
782: 'Type' = 'Volume';
783: 'Id' = 11:16;
784: 'Val' = 65535:16;
785: 'Min' = 0:16;
786: 'Max' = 65535:16;
787: 'Chan' = 2:8;
788: };
789: };
790: }";
791: return (char*)sPassThru;
792: }
793:
794: // --------------------------------------------------------------------------
795: // Method: dependentSetup
796: //
797: // Purpose:
798: // this handles the setup of the DAC-3550 chip for each kind of
799: // hosting hardware.
800: bool
801: PPCDACA::dependentSetup()
802: {
803: // Sets the frame rate:
804: UInt32 myFrameRate = frameRate(0);
805:
806: dacaSerialFormat = kSndIOFormatI2SSony; // start out in Sony format
807:
808: // Reads the initial status of the DAC3550A registers:
809: // The following functions return "false" on the first generation of iBooks. However I wish to
810: // keep them, since:
811: // 1] it is bad to make assumptions on what the hardware can do and can not do here (eventually these
812: // assumptions should be made in the i2c driver).
813: // 2] the next generation of iBook may supprot reading the DACA registers, and we will have more precise
814: // values in the "mirror" registers.
815: if (interface != NULL) {
816: interface->readI2CBus((UInt8)i2cBusAddrDAC3550A, i2cBusSubAddrSR_REG, & sampleRateReg, sizeof(sampleRateReg));
817: interface->readI2CBus((UInt8)i2cBusAddrDAC3550A, i2cBusSubAddrAVOL, (UInt8*)& analogVolumeReg, sizeof(analogVolumeReg));
818: interface->readI2CBus((UInt8)i2cBusAddrDAC3550A, i2cBusSubaddrGCFG, & configurationReg, sizeof(configurationReg));
819: }
820:
821: // If nobody set a format before choose one:
822: if (dacaSerialFormat == kSndIOFormatUnknown)
823: dacaSerialFormat = kSndIOFormatI2SSony;
824:
825: // This call will set the next of the drame parametes
826: // (dacaClockSource, dacaMclkDivisor, dacaSclkDivisor)
827: if (!setSampleParameters(myFrameRate, 0)) {
828: IOLog("PPCDACA::dependentSetup can not set i2s sample rate\n");
829: return false;
830: }
831: else if (!setDACASampleRate(myFrameRate)) {
832: IOLog("PPCDACA::dependentSetup can not set DACA sample rate\n");
833: return false;
834: }
835: else
836: setSerialFormatRegister(dacaClockSource, dacaMclkDivisor, dacaSclkDivisor, dacaSerialFormat);
837:
838: // Sets the molumes to max as in the audio registry:
839: volumeInternalSpeakerLeft(65535);
840: volumeInternalSpeakerRight(65535);
841: volumeHeadphonesLeft(65535);
842: volumeHeadphonesRight(65535);
843: volumeCDLineLeft(65535);
844: volumeCDLineRight(65535);
845:
846: return true;
847: }
848:
849: // --------------------------------------------------------------------------
850: // Method: checkStatusRegister
851: //
852: // Purpose:
853: // if the argument is true mutes the internal speaker, otherwise
854: // it "unmutes" it.
855: void
856: PPCDACA::checkStatusRegister()
857: {
858: if (statusChanged()) {
859: int i;
860:
861: OSNumber * num = OSNumber::withNumber(lastStatus, 8);
862: setProperty("Status", num);
863: num->release();
864:
865: #ifdef DEBUGMODE
866: IOLog("New Status = 0x%02x\n", lastStatus);
867: #endif
868:
869: for (i = 0; i < numOutputComponents; i++)
870: if (fOutputComponents[i] != NULL)
871: fOutputComponents[i]->Set(gInputsSym, gJackSym, outputComponentStatus(i));
872: }
873: }
874:
875: // --------------------------------------------------------------------------
876: // Method: outputComponentStatus
877: //
878: // Purpose:
879: // checks the status of the jack line of the ith output component:
880: bool
881: PPCDACA::outputComponentStatus(int index)
882: {
883: switch(index)
884: {
885: case kSpeaker:
886: return false; // the internal speaker does not have a jack
887:
888: case kHeadphones: // check the headphones:
889: return headphonesInserted();
890: }
891:
892: return false; // by deafult there is no jack
893: }
894:
895: // --------------------------------------------------------------------------
896: // Method: muteInternalSpeaker
897: //
898: // Purpose:
899: // if the argument is true mutes the internal speaker, otherwise
900: // it "unmutes" it.
901: void
902: PPCDACA::muteInternalSpeaker(bool mute)
903: {
904: if (mute){
905: if (!headphonesInserted())
906: writeRegisterBits(i2cBusSubAddrAVOL, 0, kRightAVOLMask | kLeftAVOLMask);
907: internalSpeakerMuted = mute;
908: }
909: else {
910: internalSpeakerMuted = mute;
911:
912: if (!headphonesInserted())
913: writeRegisterBits(i2cBusSubAddrAVOL, internalSpeakerVolume, kRightAVOLMask | kLeftAVOLMask);
914: }
915: }
916:
917: // --------------------------------------------------------------------------
918: // Method: muteHeadphones
919: //
920: // Purpose:
921: // if the argument is true mutes the rear panel mini jack, otherwise
922: // it "unmutes" it.
923: void
924: PPCDACA::muteHeadphones(bool mute)
925: {
926: if (mute){
927: if (headphonesInserted())
928: writeRegisterBits(i2cBusSubAddrAVOL, 0, kRightAVOLMask | kLeftAVOLMask);
929: internalHeadphonesMuted = mute;
930: }
931: else {
932: internalHeadphonesMuted = mute;
933:
934: if (headphonesInserted())
935: writeRegisterBits(i2cBusSubAddrAVOL, internalHeadphonesVolume, kRightAVOLMask | kLeftAVOLMask);
936: }
937: }
938:
939: // --------------------------------------------------------------------------
940: // Method: muteCDLine
941: //
942: // Purpose:
943: // if the argument is true mutes the line of the cd player
944: void
945: PPCDACA::muteCDLine(bool mute)
946: {
947: // FIXME: Figure out how this is wired up:
948: }
949:
950: // --------------------------------------------------------------------------
951: // Method: setModemInput
952: //
953: // Purpose:
954: // selects the modem as input source (if bool = true)
955: void
956: PPCDACA::setModemInput(bool mod)
957: {
958: #ifdef DEBUGMODE
959: IOLog( "PPCDACA::setModemInput: %s\n", (mod ? "True" : "False"));
960: #endif
961: }
962:
963:
964: // --------------------------------------------------------------------------
965: // Method: statusChanged()
966: //
967: // Purpose:
968: // returns true if something changed in the status register:.
969: bool
970: PPCDACA::statusChanged()
971: {
972: UInt8 currentStatusRegister = *(UInt8*)ioStatusRegister_GPIO12;
973:
974: if (lastStatus == currentStatusRegister)
975: return (false);
976:
977: // Otherwise refresh the value of the last status register read and
978: // returns that the value changed:
979: lastStatus = currentStatusRegister;
980: return (true);
981: }
982:
983: // --------------------------------------------------------------------------
984: // Method: headphonesInserted
985: //
986: // Purpose:
987: // returns true if the headphones are inserted.
988: bool
989: PPCDACA::headphonesInserted()
990: {
991: return((lastStatus & kHeadphoneBit) == 0);
992: }
993:
994: // --------------------------------------------------------------------------
995: // Method: volumeHeadphonesLeft & volumeHeadphonesRight
996: //
997: // Purpose:
998: // sets the volume for the left and right channel of the internal
999: // headphones.
1000: void
1001: PPCDACA::volumeHeadphonesLeft(int vol)
1002: {
1003: analogVolumeReg = internalHeadphonesVolume;
1004: setDACAVolume(vol, true);
1005: internalHeadphonesVolume = analogVolumeReg;
1006: }
1007:
1008: void
1009: PPCDACA::volumeHeadphonesRight(int vol)
1010: {
1011: analogVolumeReg = internalHeadphonesVolume;
1012: setDACAVolume(vol, false);
1013: internalHeadphonesVolume = analogVolumeReg;
1014: }
1015:
1016: // --------------------------------------------------------------------------
1017: // Method: volumeInternalSpeakerLeft & volumeInternalSpeakerRight
1018: //
1019: // Purpose:
1020: // sets the volume for the left and right channel of the internal
1021: // speaker.
1022: void
1023: PPCDACA::volumeInternalSpeakerLeft(int vol)
1024: {
1025: analogVolumeReg = internalSpeakerVolume;
1026: setDACAVolume(vol, true);
1027: internalSpeakerVolume = analogVolumeReg;
1028: }
1029:
1030: void
1031: PPCDACA::volumeInternalSpeakerRight(int vol)
1032: {
1033: analogVolumeReg = internalSpeakerVolume;
1034: setDACAVolume(vol, false);
1035: internalSpeakerVolume = analogVolumeReg;
1036: }
1037:
1038: // --------------------------------------------------------------------------
1039: // Method: volumeCDLineLeft & volumeCDLineRight
1040: //
1041: // Purpose:
1042: // sets the volume for the left and right channel of the CD
1043: // line.
1044: void
1045: PPCDACA::volumeCDLineLeft(int vol)
1046: {
1047: }
1048:
1049: void
1050: PPCDACA::volumeCDLineRight(int vol)
1051: {
1052: }
1053:
1054: /* =============================================================
1055: * VERY Private Methods used to access to the DAC-3550 registers
1056: * ============================================================= */
1057:
1058: // --------------------------------------------------------------------------
1059: // Method: enableInterrupts
1060: //
1061: // Purpose:
1062: // enable the interrupts for the I2S interface:
1063: bool
1064: PPCDACA::enableInterrupts()
1065: {
1066: I2SSetIntCtlReg(kFrameCountEnable | kClocksStoppedEnable);
1067: return true;
1068: }
1069:
1070: // Method: disableInterrupts
1071: //
1072: // Purpose:
1073: // disable the interrupts for the I2S interface:
1074: bool
1075: PPCDACA::disableInterrupts()
1076: {
1077: I2SSetIntCtlReg(I2SGetIntCtlReg() & (~(kFrameCountEnable | kClocksStoppedEnable)));
1078: return true;
1079: }
1080:
1081: // --------------------------------------------------------------------------
1082: // Method: clockRun
1083: //
1084: // Purpose:
1085: // starts and stops the clock count:
1086: bool
1087: PPCDACA::clockRun(bool start)
1088: {
1089: bool success = true;
1090: UInt32 *baseInterrupt = (UInt32*)soundConfigSpace + kI2SIntCtlOffset;
1091:
1092: #ifdef DEBUGMODE
1093: IOLog("PPCDACA::clockRun(%s) 1] 0x%08lx -> 0x%08lx\n", (start ? "true" : "false"), (UInt32)baseInterrupt, *baseInterrupt);
1094: #endif
1095:
1096: if (start) {
1097: KLSetRegister(ioClockBaseAddress, KLGetRegister(ioClockBaseAddress) | kI2S0ClockEnable);
1098: }
1099: else {
1100: UInt16 loop = 50;
1101: KLSetRegister(ioClockBaseAddress, KLGetRegister(ioClockBaseAddress) & (~kI2S0ClockEnable));
1102:
1103: while (((I2SGetIntCtlReg() & kClocksStoppedPending) == 0) && (loop--)) {
1104: // it does not do anything, jut waites for the clock
1105: // to stop
1106: IOSleep(10);
1107: #ifdef DEBUGMODE
1108: IOLog("PPCDACA::clockRun(%s) 2] 0x%08lx -> 0x%08lx\n", (start ? "true" : "false"), (UInt32)baseInterrupt, *baseInterrupt);
1109: #endif
1110: }
1111:
1112: // we are successful if the clock actually stopped.
1113: success = ((I2SGetIntCtlReg() & kClocksStoppedPending) != 0);
1114: }
1115:
1116: #ifdef DEBUGMODE
1117: if (!success)
1118: IOLog("PPCDACA::clockRun(%s) failed\n", (start ? "true" : "false"));
1119: #endif
1120:
1121: return success;
1122: }
1123:
1124: // --------------------------------------------------------------------------
1125: // Method: setSampleRate
1126: //
1127: // Purpose:
1128: // Sets the sample rate on the I2S bus
1129: bool
1130: PPCDACA::setSampleParameters(UInt32 sampleRate, UInt32 mclkToFsRatio)
1131: {
1132: UInt32 mclkRatio;
1133: UInt32 reqMClkRate;
1134:
1135: mclkRatio = mclkToFsRatio; // remember the MClk ratio required
1136:
1137: if ( mclkRatio == 0 ) // or make one up if MClk not required
1138: mclkRatio = 64; // use 64 x ratio since that will give us the best characteristics
1139:
1140: reqMClkRate = sampleRate * mclkRatio; // this is the required MClk rate
1141:
1142: // look for a source clock that divides down evenly into the MClk
1143: if ((kClock18MHz % reqMClkRate) == 0) {
1144: // preferential source is 18 MHz
1145: dacaClockSource = kClock18MHz;
1146: }
1147: else if ((kClock45MHz % reqMClkRate) == 0) {
1148: // next check 45 MHz clock
1149: dacaClockSource = kClock45MHz;
1150: }
1151: else if ((kClock49MHz % reqMClkRate) == 0) {
1152: // last, try 49 Mhz clock
1153: dacaClockSource = kClock49MHz;
1154: }
1155: else {
1156: IOLog("PPCDACA::setSampleParameters Unable to find a suitable source clock (no globals changes take effect)\n");
1157: return false;
1158: }
1159:
1160: // get the MClk divisor
1161: IOLog("PPCDACA:setSampleParameters %ld / %ld =", (UInt32)dacaClockSource, (UInt32)reqMClkRate);
1162: dacaMclkDivisor = dacaClockSource / reqMClkRate;
1163: IOLog("%ld\n", dacaMclkDivisor);
1164: switch (dacaSerialFormat) // SClk depends on format
1165: {
1166: case kSndIOFormatI2SSony:
1167: case kSndIOFormatI2S64x:
1168: dacaSclkDivisor = mclkRatio / k64TicksPerFrame; // SClk divisor is MClk ratio/64
1169: break;
1170: case kSndIOFormatI2S32x:
1171: dacaSclkDivisor = mclkRatio / k32TicksPerFrame; // SClk divisor is MClk ratio/32
1172: break;
1173: default:
1174: IOLog("PPCDACA::setSampleParameters Invalid serial format\n");
1175: return false;
1176: break;
1177: }
1178:
1179: return true;
1180: }
1181:
1182:
1183: // --------------------------------------------------------------------------
1184: // Method: setSerialFormatRegister
1185: //
1186: // Purpose:
1187: // Set global values to the serial format register
1188: void
1189: PPCDACA::setSerialFormatRegister(ClockSource clockSource, UInt32 mclkDivisor, UInt32 sclkDivisor, SoundFormat serialFormat)
1190: {
1191: UInt32 regValue = 0;
1192:
1193: #ifdef DEBUGMODE
1194: IOLog("PPCDACA::SetSerialFormatRegister(%d,%d,%d,%d)\n",(int)clockSource, (int)mclkDivisor, (int)sclkDivisor, (int)serialFormat);
1195: #endif // DEBUGMODE
1196:
1197: switch ((int)clockSource)
1198: {
1199: case kClock18MHz:
1200: regValue = kClockSource18MHz;
1201: break;
1202: case kClock45MHz:
1203: regValue = kClockSource45MHz;
1204: break;
1205: case kClock49MHz:
1206: regValue = kClockSource49MHz;
1207: break;
1208: default:
1209: IOLog("PPCDACA::SetSerialFormatRegister(%d,%d,%d,%d): Invalid clock source\n",(int)clockSource, (int)mclkDivisor, (int)sclkDivisor, (int)serialFormat);
1210: break;
1211: }
1212:
1213: switch (mclkDivisor)
1214: {
1215: case 1:
1216: regValue |= kMClkDivisor1;
1217: break;
1218: case 3:
1219: regValue |= kMClkDivisor3;
1220: break;
1221: case 5:
1222: regValue |= kMClkDivisor5;
1223: break;
1224: default:
1225: regValue |= (((mclkDivisor / 2) - 1) << kMClkDivisorShift) & kMClkDivisorMask;
1226: break;
1227: }
1228:
1229: switch ((int)sclkDivisor)
1230: {
1231: case 1:
1232: regValue |= kSClkDivisor1;
1233: break;
1234: case 3:
1235: regValue |= kSClkDivisor3;
1236: break;
1237: default:
1238: regValue |= (((sclkDivisor / 2) - 1) << kSClkDivisorShift) & kSClkDivisorMask;
1239: break;
1240: }
1241: regValue |= kSClkMaster; // force master mode
1242:
1243: switch (serialFormat)
1244: {
1245: case kSndIOFormatI2SSony:
1246: regValue |= kSerialFormatSony;
1247: break;
1248: case kSndIOFormatI2S64x:
1249: regValue |= kSerialFormat64x;
1250: break;
1251: case kSndIOFormatI2S32x:
1252: regValue |= kSerialFormat32x;
1253: break;
1254: default:
1255: IOLog("PPCDACA::SetSerialFormatRegister(%d,%d,%d,%d): Invalid serial format\n",(int)clockSource, (int)mclkDivisor, (int)sclkDivisor, (int)serialFormat);
1256: break;
1257: }
1258:
1259: // This is a 3 step process:
1260:
1261: // 1] Stop the clock:
1262: clockRun(false);
1263:
1264: // 2] Setup the serial format register
1265: I2SSetSerialFormatReg(regValue);
1266:
1267: // 3 restarts the clock:
1268: clockRun(true);
1269: }
1270:
1271: // --------------------------------------------------------------------------
1272: // Method: setDACASampleRate
1273: //
1274: // Purpose:
1275: // Gets the sample rate and makes it in a format that is compatible
1276: // with the adac register. The funtion returs false if it fails.
1277: bool
1278: PPCDACA::setDACASampleRate(UInt rate)
1279: {
1280: UInt32 dacRate = 0;
1281:
1282: #ifdef DEBUGMODE
1283: IOLog("PPCDACA::setDACASampleRate(%d)\n", rate);
1284: #endif // DEBUGMODE
1285:
1286: switch (rate)
1287: {
1288: case 44100: // 32 kHz - 48 kHz
1289: dacRate = kSRC_48SR_REG;
1290: break;
1291:
1292: default:
1293: IOLog("PPCDACA::setDACASampleRate, supports only 44100 Hz (for now)\n");
1294: break;
1295: }
1296:
1297: return(writeRegisterBits(i2cBusSubAddrSR_REG, dacRate, kSampleRateControlMask));
1298: }
1299:
1300:
1301: // --------------------------------------------------------------------------
1302: // Method: setDACAVolume
1303: //
1304: // Purpose:
1305: // sets the volume for the left or right channel. The first argument is
1306: // the wnated volume (as a range from 0 to 255), while the second argument
1307: // is a boolean (true for the right channel, false for the left channel).
1308: bool
1309: PPCDACA::setDACAVolume(UInt16 volume, bool isLeft)
1310: {
1311: UInt8 newVolume = ((UInt32)((UInt32)volume * (UInt32)kVolumeRangeLevel_VOL) / (UInt32)65535 + (UInt32)kMinVolumeLevel_VOL);
1312: bool success = true;
1313:
1314: if (isLeft) // Sets the volume on the right channel
1315: success = writeRegisterBits(i2cBusSubAddrAVOL, (newVolume << kLeftAVOLShift), kLeftAVOLMask);
1316: else // Sets the volume on the left channel
1317: success = writeRegisterBits(i2cBusSubAddrAVOL, (newVolume << kRightAVOLShift), kRightAVOLMask);
1318:
1319: return success;
1320: }
1321:
1322: // ---------------------------------------------------------------------------------------
1323: // Method: writeRegisterBits
1324: //
1325: // Purpose:
1326: // This function sets or clears bits in the Daca registers. The first argument is the
1327: // register sub-address, the second argument is a mask for turning bits on, while the third
1328: // argument is a mask for turning bits off.
1329: bool
1330: PPCDACA::writeRegisterBits(UInt8 subAddress, UInt32 bitMaskOn, UInt32 bitMaskOff)
1331: {
1332: UInt8 bitsOn = 0, bitsOff = 0, value;
1333: UInt16 shortBitsOn = 0, shortBitsOff = 0, value16;
1334: bool success = false;
1335:
1336: #ifdef DEBUGMODE
1337: IOLog("PPCDACA::writeRegisterBits(0x%x, 0x%08lx, 0x%08lx)\n", (UInt16)subAddress, bitMaskOn, bitMaskOff);
1338: #endif // DEBUGMODE
1339:
1340: // mask off irrelevant bytes
1341: if (subAddress == i2cBusSubAddrAVOL) {
1342: // 16-bit register
1343: shortBitsOn = bitMaskOn & 0x0000FFFF;
1344: shortBitsOff = bitMaskOff & 0x0000FFFF;
1345: }
1346: else {
1347: // 8-bit registers
1348: bitsOn = bitMaskOn & 0x000000FF;
1349: bitsOff = bitMaskOff & 0x000000FF;
1350: }
1351:
1352: switch (subAddress)
1353: {
1354: case i2cBusSubAddrSR_REG:
1355: value = sampleRateReg | bitsOn;
1356: value &= ~bitsOff;
1357: // continue only if on bits are not already on and off bits are not already off
1358: if (value != sampleRateReg) {
1359: success = interface->writeI2CBus((UInt8)i2cBusAddrDAC3550A, subAddress, &value, sizeof(value));
1360:
1361: if (success)
1362: sampleRateReg = value;
1363: }
1364: else {
1365: // If the sample rate is already set at the wanted value
1366: // we do not do anything, but we return success since from the
1367: // caller point of view it is as the sample rate was correctly
1368: // set.
1369: success = true;
1370: }
1371: break;
1372:
1373: case i2cBusSubAddrAVOL:
1374: value16 = analogVolumeReg;
1375: value16 &= ~shortBitsOff;
1376: value16 |= shortBitsOn;
1377: // continue only if on bits are not already on and off bits are not already off
1378: if (value16 !=analogVolumeReg)
1379: {
1380: // It changes the volume for real only if the current output is not muted.
1381: if (((!headphonesInserted()) && (!internalSpeakerMuted)) ||
1382: (headphonesInserted() && (!internalHeadphonesMuted)))
1383: success = interface->writeI2CBus((UInt8)i2cBusAddrDAC3550A, subAddress, (UInt8*)&value16, sizeof(value16));
1384: else
1385: success = true;
1386:
1387: if (success)
1388: analogVolumeReg = value16;
1389: }
1390: else {
1391: // If the volume is already set at the wanted value
1392: // we do not do anything, but we return success since from the
1393: // caller point of view it is as the volume was correctly
1394: // set.
1395: success = true;
1396: }
1397: break;
1398:
1399: case i2cBusSubaddrGCFG:
1400: value = configurationReg | bitsOn;
1401: value &= ~bitsOff;
1402: // continue only if on bits are not already on and off bits are not already off
1403: if (value != configurationReg)
1404: {
1405: success = interface->writeI2CBus((UInt8)i2cBusAddrDAC3550A, subAddress, &value, sizeof(value));
1406: if (success)
1407: configurationReg = value;
1408: }
1409: else {
1410: // If the config register is already set at the wanted value
1411: // we do not do anything, but we return success since from the
1412: // caller point of view it is as the configuration was correctly
1413: // set.
1414: success = true;
1415: }
1416: break;
1417:
1418: default:
1419: IOLog("PPCDACA::writeRegisterBits 0x%x unknown subaddress\n", (UInt16)subAddress);
1420: break;
1421: }
1422: return success;
1423: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.