|
|
1.1 root 1: /*
2: * Copyright (c) 1994 NeXT Computer, Inc. All rights reserved.
3: *
4: * HISTORY
5: * 4-Mar-94 Rakesh Dubey at NeXT
6: * Created.
7: */
8:
9: /*
10: * Base address.
11: */
12: static unsigned int sbBaseRegisterAddress = 0;
13:
14: /*
15: * Register addresses. The base register addressess are determined at
16: * run-time.
17: */
18:
19: static unsigned int sbResetReg = 0;
20: static unsigned int sbReadDataReg = 0;
21: static unsigned int sbWriteDataOrCommandReg = 0;
22:
23: static unsigned int sbWriteBufferStatusReg = 0;
24: static unsigned int sbDataAvailableStatusReg = 0;
25:
26: static __inline__
27: void
28: assignDSPRegAddresses(void)
29: {
30: sbResetReg =
31: (sbBaseRegisterAddress + SB_DSP_RESET_OFFSET);
32: sbReadDataReg =
33: (sbBaseRegisterAddress + SB_DSP_READ_DATA_OFFSET);
34: sbWriteDataOrCommandReg =
35: (sbBaseRegisterAddress + SB_DSP_WRITE_DATA_OR_COMMAND_OFFSET);
36:
37: sbWriteBufferStatusReg =
38: (sbBaseRegisterAddress + SB_DSP_WRITE_BUFFER_STATUS_OFFSET);
39: sbDataAvailableStatusReg =
40: (sbBaseRegisterAddress + SB_DSP_DATA_AVAILABLE_STATUS_OFFSET);
41: }
42:
43:
44: /*
45: * Print what is being written.
46: */
47: static __inline__
48: void
49: outbV(unsigned int address, unsigned int data)
50: {
51: #ifdef DEBUG
52: IOLog("SoundBlaster8: Writing %x at address %x\n", data, address);
53: #endif DEBUG
54: outb(address, data);
55: }
56:
57: static unsigned int sbMixerAddressReg = 0;
58: static unsigned int sbMixerDataReg = 0;
59:
60: static __inline__
61: void
62: assignMixerRegAddresses(void)
63: {
64: sbMixerAddressReg =
65: (sbBaseRegisterAddress + SB_MIXER_ADDRESS_OFFSET);
66: sbMixerDataReg =
67: (sbBaseRegisterAddress + SB_MIXER_DATA_OFFSET);
68: }
69:
70: /*
71: * Shadow registers for volume. Add more to this list when necessary.
72: */
73:
74: static sbStereoMixerRegister_t volMaster = {0};
75: static sbStereoMixerRegister_t volFM = {0};
76: static sbStereoMixerRegister_t volLine = {0};
77: static sbStereoMixerRegister_t volVoc = {0};
78:
79: static sbMonoMixerRegister_t volMic = {0};
80: static sbMonoMixerRegister_t volCD = {0};
81:
82: static sbRecordingMode_t sbRecord = {0};
83: static sbPlaybackMode_t sbPlayback = {0};
84:
85:
86: #define MAX_WAIT_FOR_DATA_AVAILABLE 2000
87: #define SB_WAIT_DELAY 10
88: #define SB_RESET_DELAY 100
89:
90: static __inline__
91: BOOL
92: dspReadWait()
93: {
94: int i;
95: unsigned int val;
96:
97: for (i = 0; i < MAX_WAIT_FOR_DATA_AVAILABLE; i++) {
98: IODelay(SB_WAIT_DELAY);
99: val = inb(sbDataAvailableStatusReg);
100: if (val & 0x080) /* MSB == 1 before reading */
101: return YES;
102: }
103:
104: /* Reset DSP, hopefully we will recover. */
105: outbV(sbResetReg, 0x01);
106: IODelay(SB_ADDRESS_WRITE_DELAY);
107: outbV(sbResetReg, 0x00);
108: IODelay(SB_ADDRESS_WRITE_DELAY);
109: IODelay(SB_RESET_DELAY);
110:
111: #ifdef DEBUG
112: IOLog("SoundBlaster8: DSP not ready for reading!\n");
113: #endif DEBUG
114:
115: return NO;
116: }
117:
118: static __inline__
119: BOOL
120: dspWriteWait()
121: {
122: int i;
123: unsigned int val;
124:
125: for (i = 0; i < MAX_WAIT_FOR_DATA_AVAILABLE; i++) {
126: IODelay(SB_WAIT_DELAY);
127: val = inb(sbWriteBufferStatusReg);
128: if (!(val & 0x080)) /* MSB == 0 before writing */
129: return YES;
130: }
131:
132: /* Reset DSP */
133: outbV(sbResetReg, 0x01);
134: IODelay(SB_ADDRESS_WRITE_DELAY);
135: outbV(sbResetReg, 0x00);
136: IODelay(SB_ADDRESS_WRITE_DELAY);
137: IODelay(SB_RESET_DELAY);
138:
139: #ifdef DEBUG
140: IOLog("SoundBlaster8: DSP not ready for writing!\n");
141: #endif DEBUG
142:
143: return NO;
144: }
145:
146: /*
147: * Send some data or command to SoundBlaster8 DSP.
148: */
149: static
150: BOOL
151: writeToDSP(unsigned int dataOrCommand)
152: {
153: outbV(sbWriteDataOrCommandReg, dataOrCommand);
154: IODelay(SB_DATA_WRITE_DELAY);
155:
156: #ifdef DEBUG
157: //IOLog("SoundBlaster8: Wrote DSP command %x\n", dataOrCommand);
158: #endif DEBUG
159:
160: return YES;
161: }
162:
163: /*
164: * Read from the SoundBlaster DSP.
165: */
166: static
167: unsigned int
168: readFromDSP(void)
169: {
170: unsigned int val;
171:
172: val = inb(sbReadDataReg);
173: IODelay(SB_DATA_READ_DELAY);
174:
175: #ifdef DEBUG
176: IOLog("SoundBlaster8: read from DSP %x\n", val);
177: #endif DEBUG
178:
179: return val;
180: }
181:
182: /*
183: * Function to read from the Mixer registers.
184: */
185: static __inline__
186: unsigned int
187: inbIXMixer(unsigned int address)
188: {
189: unsigned int val = 0xff;
190:
191: outbV(sbMixerAddressReg, address);
192: IODelay(SB_ADDRESS_WRITE_DELAY);
193: val = inb(sbMixerDataReg);
194:
195: #ifdef DEBUG
196: IOLog("SoundBlaster8: Mixer address %x. Read %x\n", address, val);
197: #endif DEBUG
198: return val;
199: }
200:
201: /*
202: * Function to write to the Mixer registers.
203: */
204: static __inline__
205: void
206: outbIXMixer(unsigned int address, unsigned int val)
207: {
208: outbV(sbMixerAddressReg, address);
209: IODelay(SB_ADDRESS_WRITE_DELAY);
210: outbV(sbMixerDataReg, val);
211: IODelay(SB_DATA_WRITE_DELAY);
212:
213: #ifdef DEBUG
214: IOLog("SoundBlaster8: Mixer address %x. Wrote %x\n", address, val);
215: #endif DEBUG
216: }
217:
218: /*
219: * Initialize DSP registers. There aren't any.
220: */
221:
222: static __inline__
223: void
224: initDSPRegisters(void)
225: {
226: }
227:
228: /*
229: * Initialize the registers on the Mixer.
230: */
231:
232: static __inline__
233: void
234: initMixerRegisters(void)
235: {
236: if (sbCardType.mixerPresent == NO)
237: return;
238:
239: #ifdef DEBUG
240: IOLog("SoundBlaster8: Initializing mixer registers.\n");
241: #endif DEBUG
242:
243: /*
244: * First set the volume controlling registers to their default values.
245: */
246: volMaster.reg.left = 10;
247: volMaster.reg.right = 10;
248: outbIXMixer(MC_MASTER_VOLUME, volMaster.data);
249:
250: volFM.reg.left = 0;
251: volFM.reg.right = 0;
252: outbIXMixer(MC_FM_VOLUME, volFM.data);
253:
254: volCD = 0;
255: outbIXMixer(MC_CD_VOLUME, volCD);
256:
257: volLine.reg.left = 0;
258: volLine.reg.right = 0;
259: outbIXMixer(MC_LINE_VOLUME, volLine.data);
260:
261: volVoc.reg.left = 10;
262: volVoc.reg.right = 10;
263: outbIXMixer(MC_VOC_VOLUME, volVoc.data);
264:
265: /* Microphone can go only upto 7. */
266: volMic = 6;
267: outbIXMixer(MC_MICROPHONE_VOLUME, volMic);
268:
269: /*
270: * Now set the record and playback mode registers.
271: */
272: sbRecord.data = 0;
273: sbRecord.reg.source = SB_RECORD_SOURCE_MIC;
274: sbRecord.reg.inputFilter = SB_RECORD_ANFI_OFF;
275: sbRecord.reg.highFreq = SB_RECORD_FREQ_HIGH;
276: outbIXMixer(MC_RECORD_CONTROL, sbRecord.data);
277:
278: sbPlayback.data = 0;
279: sbPlayback.reg.outputFilter = SB_PLAYBACK_DNFI_OFF;
280: sbPlayback.reg.stereo = SB_PLAYBACK_STEREO;
281: outbIXMixer(MC_PLAYBACK_CONTROL, sbPlayback.data);
282: }
283:
284: /*
285: * Input can be either microphone level or line level. We don't support other
286: * inputs.
287: */
288:
289: static __inline__
290: void
291: setInputLevel(unsigned int level)
292: {
293: if (sbCardType.mixerPresent == NO)
294: return;
295:
296: if (level == LINE_LEVEL_INPUT) {
297: sbRecord.reg.source = SB_RECORD_SOURCE_LINE;
298: } else {
299: sbRecord.reg.source = SB_RECORD_SOURCE_MIC;
300: }
301:
302: outbIXMixer(MC_RECORD_CONTROL, sbRecord.data);
303: }
304:
305: /*
306: * Output level cannot be changed.
307: */
308:
309: static __inline__
310: void
311: setOutputLevel(unsigned int channel, unsigned int level)
312: {
313: #ifdef DEBUG
314: IOLog("SoundBlaster8: Audio output level is fixed.\n");
315: #endif DEBUG
316: }
317:
318: /*
319: * Initialize the hardware registers.
320: */
321: static __inline__
322: void
323: initRegisters(void)
324: {
325: initDSPRegisters();
326: initMixerRegisters();
327: }
328:
329:
330: /*
331: * These two routines are used to avoid clicks.
332: */
333:
334: static __inline__
335: void
336: muteOutput(void)
337: {
338: sbStereoMixerRegister_t volMaster = {0};
339:
340: if (sbCardType.mixerPresent == NO)
341: return;
342:
343: volMaster.reg.left = 0;
344: volMaster.reg.right = 0;
345:
346: outbIXMixer(MC_MASTER_VOLUME, volMaster.data);
347: }
348:
349: /*
350: * This takes it back to the old values. So it is not exactly unmute.
351: */
352: static __inline__
353: void
354: unMuteOutput(void)
355: {
356: if (sbCardType.mixerPresent == NO)
357: return;
358:
359: outbIXMixer(MC_MASTER_VOLUME, volMaster.data);
360: }
361:
362: /*
363: * This routine does a quick reset of the card. This is needed because
364: * apparently the SoundBlaster8 cards need to be reset if you go from the
365: * high speed to the low speed mode (wonderful world of hardware).
366: */
367:
368: static __inline__
369: void
370: resetDSPQuick(void)
371: {
372: outbV(sbResetReg, 0x01);
373: IODelay(SB_ADDRESS_WRITE_DELAY);
374: outbV(sbResetReg, 0x00);
375: IODelay(SB_ADDRESS_WRITE_DELAY);
376:
377: /* It takes about 100us to reset */
378: dspReadWait();
379: if (readFromDSP() != 0xaa) {
380: IOLog("SoundBlaster8: Can not reset DSP.\n");
381: }
382: }
383:
384:
385: #define SB_DELAY 100
386: #define MAX_RESET_WAIT 1000
387:
388: /*
389: * Reset the SoundBlaster card. This routine also detects if the card is
390: * present and the type of card.
391: */
392: static __inline__
393: void
394: resetDSP(void)
395: {
396: unsigned int val;
397:
398: /*
399: * Assume no sound card in the system.
400: */
401: sbCardType.version = SB_NONE;
402: sbCardType.name = "";
403: sbCardType.majorVersion = 0;
404: sbCardType.minorVersion = 0;
405: sbCardType.mixerPresent = NO;
406:
407: outbV(sbResetReg, 0x01);
408: IODelay(SB_ADDRESS_WRITE_DELAY);
409: outbV(sbResetReg, 0x00);
410: IODelay(SB_ADDRESS_WRITE_DELAY);
411:
412: /* Now we can read the data. */
413: dspReadWait();
414: val = readFromDSP();
415: if (val == 0xaa) {
416: #ifdef DEBUG
417: IOLog("SoundBlaster8: DSP detected.\n");
418: #endif DEBUG
419: IOSleep(1);
420: } else {
421: #ifdef DEBUG
422: IOLog("SoundBlaster8: Read ID %x is wrong.\n", val);
423: IOLog("SoundBlaster8: SoundBlaster not detected at address 0x%0x.\n",
424: sbBaseRegisterAddress);
425: #endif DEBUG
426: return;
427: }
428:
429: /*
430: * We have a SoundBlaster card. We will upgrade it to a pro if we detect
431: * a mixer as well.
432: */
433: sbCardType.version = SB_CLASSIC;
434:
435: /*
436: * Another confirmatory test here. This is not documented in the SB SDK
437: * so it might fail on some compatible cards. Maybe we should just print
438: * a warning message if this test fails.
439: */
440: dspWriteWait();
441: writeToDSP(DC_INVERT_BYTE);
442:
443: dspWriteWait();
444: writeToDSP(0x43); /* Send some test pattern. */
445:
446: dspReadWait();
447: val = readFromDSP();
448:
449: if (val == 0xbc) {
450: #ifdef DEBUG
451: IOLog("SoundBlaster8: Invert test passed.\n");
452: #endif DEBUG
453: } else {
454: #ifdef DEBUG
455: IOLog("SoundBlaster8: Invert test failed!!\n");
456: IOLog("SoundBlaster8: SoundBlaster not detected at address 0x%0x.\n",
457: sbBaseRegisterAddress);
458: #endif DEBUG
459: }
460:
461: /*
462: * Reset the DSP here because sometimes you may get crazy values as
463: * version. So just to be on the safe side..
464: */
465: resetDSPQuick();
466:
467: /*
468: * Now we know that a SoundBlaster or compatible card exists. We need to
469: * find the version number to decide the type of card.
470: */
471: dspWriteWait();
472: writeToDSP(DC_GET_VERSION);
473:
474: dspReadWait();
475: sbCardType.majorVersion = readFromDSP() & 0x0f;
476: sbCardType.minorVersion = readFromDSP() & 0x0f;
477:
478: #ifdef DEBUG
479: //IOLog("SoundBlaster8: Major 0x%x Minor 0x%x\n", sbCardType.majorVersion, sbCardType.minorVersion);
480: #endif DEBUG
481:
482: /*
483: * Upgrade the card to SB_20 or SB_16 depending upon what the version
484: * number reads.
485: */
486: if (sbCardType.majorVersion >= 2)
487: sbCardType.version = SB_20;
488:
489: if (sbCardType.majorVersion >= 4)
490: sbCardType.version = SB_16;
491: }
492:
493:
494:
495: static __inline__
496: void
497: resetMixer(void)
498: {
499: unsigned int val1, val2;
500:
501: /*
502: * Reset the mixer by sending zero to both address and data ports.
503: */
504: outbIXMixer(0x0, 0x0);
505:
506: /*
507: * Now try to write and then read from one of the mixer registers.
508: */
509: outbIXMixer(MC_MASTER_VOLUME, 0x15);
510: outbIXMixer(MC_MICROPHONE_VOLUME, 0x13);
511:
512: val1 = inbIXMixer(MC_MASTER_VOLUME);
513: val2 = inbIXMixer(MC_MICROPHONE_VOLUME);
514:
515: if ((val1 == 0x15) && (val2 == 0x13)) {
516: sbCardType.mixerPresent = YES;
517: } else {
518: sbCardType.mixerPresent = NO;
519: }
520:
521: /*
522: * Try once more, so that we are really sure.
523: */
524: outbIXMixer(MC_LINE_VOLUME, 0x17);
525: outbIXMixer(MC_FM_VOLUME, 0x19);
526:
527: val1 = inbIXMixer(MC_LINE_VOLUME);
528: val2 = inbIXMixer(MC_FM_VOLUME);
529:
530: if ((val1 == 0x17) && (val2 == 0x19)) {
531: sbCardType.mixerPresent = YES;
532: } else {
533: sbCardType.mixerPresent = NO;
534: }
535:
536: /*
537: * We have a pro card if we found the mixer.
538: */
539: if (sbCardType.mixerPresent == YES) {
540: sbCardType.version = SB_PRO;
541: outbIXMixer(0x0, 0x0); /* reset the mixer to a good state */
542: }
543:
544: #ifdef DEBUG
545: if (sbCardType.mixerPresent == YES)
546: IOLog("SoundBlaster8: Mixer detected.\n");
547: else
548: IOLog("SoundBlaster8: Mixer not detected.\n");
549: #endif DEBUG
550: }
551:
552:
553: /*
554: * Reset all hardware and bring us back to the default state.
555: */
556: static __inline__
557: void
558: resetHardware(void)
559: {
560: resetDSP();
561: resetMixer();
562: initRegisters();
563: }
564:
565: /*
566: * There seems to be no way to change input gain.
567: */
568: static __inline__
569: void
570: setInputGain(unsigned int channel, unsigned int gain)
571: {
572: if (sbCardType.mixerPresent == NO)
573: return;
574:
575: volMic = gain;
576: outbIXMixer(MC_MICROPHONE_VOLUME, volMic);
577:
578: #ifdef DEBUG
579: IOLog("SoundBlaster8: set input gain %d\n", gain);
580: #endif DEBUG
581: }
582:
583: static __inline__
584: void
585: setOutputAttenuation(unsigned int channel, unsigned int attenuation)
586: {
587: if (sbCardType.mixerPresent == NO)
588: return;
589:
590: if (channel == LEFT_CHANNEL) {
591: volMaster.reg.left = attenuation;
592: outbIXMixer(MC_MASTER_VOLUME, volMaster.data);
593:
594: } else {
595: volMaster.reg.right = attenuation;
596: outbIXMixer(MC_MASTER_VOLUME, volMaster.data);
597: }
598: #ifdef DEBUG
599: IOLog("SoundBlaster8: set output attenuation %d\n", attenuation);
600: #endif DEBUG
601: }
602:
603: /*
604: * This will not work for SB16 running in SBPro compatibility mode. The mixer
605: * registers need to be written to mute output.
606: */
607:
608: static __inline__
609: void
610: enableAudioOutput(BOOL enable)
611: {
612: dspWriteWait();
613: if (enable) {
614: writeToDSP(DC_TURN_ON_SPEAKER);
615: } else {
616: writeToDSP(DC_TURN_OFF_SPEAKER);
617: }
618: }
619:
620: static __inline__
621: void setSampleBufferCounter(unsigned int count)
622: {
623: if (!lowSpeedDMA) {
624: dspWriteWait();
625: writeToDSP(DC_SET_BLOCK_SIZE);
626: }
627:
628: count -= 1;
629: dspWriteWait();
630: writeToDSP(count & 0x0ff);
631: dspWriteWait();
632: writeToDSP((count >> 8) & 0x0ff);
633: #ifdef DEBUG
634: //IOLog("SoundBlaster8: buffer counter set to %x\n", count);
635: #endif DEBUG
636: }
637:
638: /*
639: * Start DMA. Command patterns are different depending upon whether we are
640: * doing low speed or high speed transfers.
641: */
642:
643: static __inline__
644: void startDMA(unsigned int direction)
645: {
646: dspWriteWait();
647: if (lowSpeedDMA) {
648: if (direction == DMA_DIRECTION_IN)
649: writeToDSP(DC_START_LS_DMA_ADC_8);
650: else
651: writeToDSP(DC_START_LS_DMA_DAC_8);
652: } else {
653: if (direction == DMA_DIRECTION_IN)
654: writeToDSP(DC_START_HS_DMA_ADC_8);
655: else
656: writeToDSP(DC_START_HS_DMA_DAC_8);
657: }
658: }
659:
660: /* No can do */
661: static __inline__
662: void enableCodecInterrupts(void)
663: {
664: }
665:
666: static __inline__
667: void disableCodecInterrupts(void)
668: {
669: }
670:
671: static __inline__
672: void stopDMA(void)
673: {
674: writeToDSP(DC_HALT_DMA);
675: }
676:
677: /*
678: * This routine will stop input dma.
679: */
680: static __inline__
681: void stopDMAInput(void)
682: {
683: stopDMA();
684: }
685:
686: /*
687: * Likewise, but for output dma.
688: */
689: static __inline__
690: void stopDMAOutput(void)
691: {
692: stopDMA();
693: }
694:
695: /*
696: * Select between DSP_MONO_MODE and DSP_STEREO_MODE mode. Note that stereo
697: * recording is undocumented so it could potentially break on some clone
698: * cards.
699: */
700: static __inline__
701: void setCodecDataMode(unsigned int mode, unsigned int dir)
702: {
703: if (sbCardType.mixerPresent == NO)
704: return;
705:
706: if (dir == DMA_DIRECTION_OUT) {
707: if (mode == DSP_STEREO_MODE) {
708: sbPlayback.reg.stereo = SB_PLAYBACK_STEREO;
709: } else {
710: sbPlayback.reg.stereo = SB_PLAYBACK_MONO;
711: }
712: outbIXMixer(MC_PLAYBACK_CONTROL, sbPlayback.data);
713: } else if (dir == DMA_DIRECTION_IN) {
714: dspWriteWait();
715: if (mode == DSP_STEREO_MODE) {
716: writeToDSP(DC_RECORD_IN_STEREO);
717: } else {
718: writeToDSP(DC_RECORD_IN_MONO);
719: }
720: }
721: }
722:
723:
724: static __inline__
725: void setCodecSamplingRate(unsigned int rate)
726: {
727: unsigned int timeConstant;
728:
729: /* Sanity check. */
730: if (rate < SB_MIN_SAMPLE_RATE)
731: rate = SB_MIN_SAMPLE_RATE;
732: else if (rate > SB_MAX_SAMPLE_RATE)
733: rate = SB_MAX_SAMPLE_RATE;
734:
735: dspWriteWait();
736: if (lowSpeedDMA) {
737: timeConstant = 256 - (1000*1000)/rate;
738: writeToDSP(DC_SET_TIME_CONSTANT);
739: dspWriteWait();
740: writeToDSP(timeConstant);
741: #ifdef DEBUG
742: IOLog("SoundBlaster8: Sample rate = %u, timeConstant = %x\n", rate, timeConstant);
743: #endif DEBUG
744: } else {
745: timeConstant = 65536 - (256*1000*1000)/rate;
746: writeToDSP(DC_SET_TIME_CONSTANT);
747: dspWriteWait();
748: writeToDSP(timeConstant >> 8);
749: #ifdef DEBUG
750: IOLog("SoundBlaster8: Sample rate = %u, timeConstant = %x\n", rate, timeConstant >> 8);
751: #endif DEBUG
752: }
753: }
754:
755: /*
756: * We test here if the user supplied dma/irq selections are correct. Actually
757: * it is more complicated than this because not all kinds of cards can use
758: * all dma/irq combinations. We simply allow the superset and avoid
759: * complicated version dependent verification. (Available interrupts are 3,
760: * 5, 7 for SBPro and 5, 7, 10 for other kinds, clone cards may have slight
761: * differences.)
762: */
763:
764: static __inline__
765: BOOL
766: checkSelectedDMAAndIRQ(unsigned int channel, unsigned int irq)
767: {
768: BOOL status = YES;
769:
770: if ((channel != 0) && (channel != 1) && (channel != 3)) {
771: IOLog("SoundBlaster8: Audio DMA channel is %d.\n", channel);
772: IOLog("SoundBlaster8: Audio DMA channel must be one of 0, 1, 3.\n");
773: status = NO;
774: }
775: if ((irq != 3) && (irq != 5) &&
776: (irq != 7) && (irq != 10)) {
777: IOLog("SoundBlaster8: Audio irq is %d.\n", irq);
778: IOLog("SoundBlaster8: Audio IRQ must be one of 3, 5, 7, 10.\n");
779: status = NO;
780: }
781:
782: return status;
783: }
784:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.