home *** CD-ROM | disk | FTP | other *** search
/ OpenStep 4.2J (Developer) / os42jdev.iso / NextDeveloper / Examples / DriverKit / SoundBlaster8 / SoundBlaster8_reloc.tproj / SoundBlaster8Inline.h < prev    next >
C/C++ Source or Header  |  1996-03-27  |  18KB  |  792 lines

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