home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / drivers / sound / sb16_dsp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-23  |  12.6 KB  |  569 lines

  1. /*
  2.  * sound/sb16_dsp.c
  3.  *
  4.  * The low level driver for the SoundBlaster DSP chip.
  5.  *
  6.  * (C) 1993 J. Schubert (jsb@sth.ruhr-uni-bochum.de)
  7.  *
  8.  * based on SB-driver by (C) Hannu Savolainen
  9.  *
  10.  * Redistribution and use in source and binary forms, with or without
  11.  * modification, are permitted provided that the following conditions are
  12.  * met: 1. Redistributions of source code must retain the above copyright
  13.  * notice, this list of conditions and the following disclaimer. 2.
  14.  * Redistributions in binary form must reproduce the above copyright notice,
  15.  * this list of conditions and the following disclaimer in the documentation
  16.  * and/or other materials provided with the distribution.
  17.  *
  18.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
  19.  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21.  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  22.  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  23.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  24.  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  25.  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  27.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28.  * SUCH DAMAGE.
  29.  *
  30.  */
  31.  
  32. #define DEB(x)
  33. #define DEB1(x)
  34. /*
  35.  * #define DEB_DMARES
  36.  */
  37. #include "sound_config.h"
  38. #include "sb.h"
  39. #include "sb_mixer.h"
  40.  
  41. #if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB16) && !defined(EXCLUDE_SB) && !defined(EXCLUDE_AUDIO) && !defined(EXCLUDE_SBPRO)
  42.  
  43. extern int      sbc_base;
  44.  
  45. static int      sb16_dsp_ok = 0;/*
  46.  
  47.  
  48.                      * *  * * Set to 1 after successful *
  49.                      * * initialization   */
  50. static int      dsp_16bit = 0;
  51. static int      dsp_stereo = 0;
  52. static int      dsp_current_speed = 8000;    /*
  53.  
  54.  
  55.                          * *  * * DSP_DEFAULT_SPEED;  */
  56. static int      dsp_busy = 0;
  57. static int      dma16, dma8;
  58. static unsigned long dsp_count = 0;
  59.  
  60. static int      irq_mode = IMODE_NONE;    /*
  61.  
  62.  
  63.                      * *  * * IMODE_INPUT, IMODE_OUTPUT
  64.                      * or * * IMODE_NONE   */
  65. static int      my_dev = 0;
  66.  
  67. static volatile int intr_active = 0;
  68.  
  69. static int      sb16_dsp_open (int dev, int mode);
  70. static void     sb16_dsp_close (int dev);
  71. static void     sb16_dsp_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart);
  72. static void     sb16_dsp_start_input (int dev, unsigned long buf, int count, int intrflag, int dma_restart);
  73. static int      sb16_dsp_ioctl (int dev, unsigned int cmd, unsigned int arg, int local);
  74. static int      sb16_dsp_prepare_for_input (int dev, int bsize, int bcount);
  75. static int      sb16_dsp_prepare_for_output (int dev, int bsize, int bcount);
  76. static void     sb16_dsp_reset (int dev);
  77. static void     sb16_dsp_halt (int dev);
  78. static int      dsp_set_speed (int);
  79. static int      dsp_set_stereo (int);
  80. static void     dsp_cleanup (void);
  81. int             sb_reset_dsp (void);
  82.  
  83. static struct audio_operations sb16_dsp_operations =
  84. {
  85.   "SoundBlaster 16",
  86.   DMA_AUTOMODE,
  87.   AFMT_U8 | AFMT_S16_LE,
  88.   NULL,
  89.   sb16_dsp_open,
  90.   sb16_dsp_close,
  91.   sb16_dsp_output_block,
  92.   sb16_dsp_start_input,
  93.   sb16_dsp_ioctl,
  94.   sb16_dsp_prepare_for_input,
  95.   sb16_dsp_prepare_for_output,
  96.   sb16_dsp_reset,
  97.   sb16_dsp_halt,
  98.   NULL,
  99.   NULL
  100. };
  101.  
  102. static int
  103. sb_dsp_command01 (unsigned char val)
  104. {
  105.   int             i = 1 << 16;
  106.  
  107.   while (--i & (!INB (DSP_STATUS) & 0x80));
  108.   if (!i)
  109.     printk ("SB16 sb_dsp_command01 Timeout\n");
  110.   return sb_dsp_command (val);
  111. }
  112.  
  113. static int
  114. dsp_set_speed (int mode)
  115. {
  116.   DEB (printk ("dsp_set_speed(%d)\n", mode));
  117.   if (mode)
  118.     {
  119.       if (mode < 5000)
  120.     mode = 5000;
  121.       if (mode > 44100)
  122.     mode = 44100;
  123.       dsp_current_speed = mode;
  124.     }
  125.   return mode;
  126. }
  127.  
  128. static int
  129. dsp_set_stereo (int mode)
  130. {
  131.   DEB (printk ("dsp_set_stereo(%d)\n", mode));
  132.  
  133.   dsp_stereo = mode;
  134.  
  135.   return mode;
  136. }
  137.  
  138. static int
  139. dsp_set_bits (int arg)
  140. {
  141.   DEB (printk ("dsp_set_bits(%d)\n", arg));
  142.  
  143.   if (arg)
  144.     switch (arg)
  145.       {
  146.       case 8:
  147.     dsp_16bit = 0;
  148.     break;
  149.       case 16:
  150.     dsp_16bit = 1;
  151.     break;
  152.       default:
  153.     dsp_16bit = 0;
  154.       }
  155.   return dsp_16bit ? 16 : 8;
  156. }
  157.  
  158. static int
  159. sb16_dsp_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
  160. {
  161.   switch (cmd)
  162.     {
  163.     case SOUND_PCM_WRITE_RATE:
  164.       if (local)
  165.     return dsp_set_speed (arg);
  166.       return IOCTL_OUT (arg, dsp_set_speed (IOCTL_IN (arg)));
  167.  
  168.     case SOUND_PCM_READ_RATE:
  169.       if (local)
  170.     return dsp_current_speed;
  171.       return IOCTL_OUT (arg, dsp_current_speed);
  172.  
  173.     case SNDCTL_DSP_STEREO:
  174.       if (local)
  175.     return dsp_set_stereo (arg);
  176.       return IOCTL_OUT (arg, dsp_set_stereo (IOCTL_IN (arg)));
  177.  
  178.     case SOUND_PCM_WRITE_CHANNELS:
  179.       if (local)
  180.     return dsp_set_stereo (arg - 1) + 1;
  181.       return IOCTL_OUT (arg, dsp_set_stereo (IOCTL_IN (arg) - 1) + 1);
  182.  
  183.     case SOUND_PCM_READ_CHANNELS:
  184.       if (local)
  185.     return dsp_stereo + 1;
  186.       return IOCTL_OUT (arg, dsp_stereo + 1);
  187.  
  188.     case SNDCTL_DSP_SETFMT:
  189.       if (local)
  190.     return dsp_set_bits (arg);
  191.       return IOCTL_OUT (arg, dsp_set_bits (IOCTL_IN (arg)));
  192.  
  193.     case SOUND_PCM_READ_BITS:
  194.       if (local)
  195.     return dsp_16bit ? 16 : 8;
  196.       return IOCTL_OUT (arg, dsp_16bit ? 16 : 8);
  197.  
  198.     case SOUND_PCM_WRITE_FILTER:    /*
  199.                      * NOT YET IMPLEMENTED
  200.                      */
  201.       if (IOCTL_IN (arg) > 1)
  202.     return IOCTL_OUT (arg, RET_ERROR (EINVAL));
  203.     default:
  204.       return RET_ERROR (EINVAL);
  205.     }
  206.  
  207.   return RET_ERROR (EINVAL);
  208. }
  209.  
  210. static int
  211. sb16_dsp_open (int dev, int mode)
  212. {
  213.   int             retval;
  214.  
  215.   DEB (printk ("sb16_dsp_open()\n"));
  216.   if (!sb16_dsp_ok)
  217.     {
  218.       printk ("SB16 Error: SoundBlaster board not installed\n");
  219.       return RET_ERROR (ENXIO);
  220.     }
  221.  
  222.   if (intr_active)
  223.     return RET_ERROR (EBUSY);
  224.  
  225.   retval = sb_get_irq ();
  226.   if (retval < 0)
  227.     return retval;
  228.  
  229.   sb_reset_dsp ();
  230.  
  231.   if (ALLOC_DMA_CHN (dma8,"sb16 8bit"))
  232.     {
  233.       printk ("SB16: Unable to grab DMA%d\n", dma8);
  234.       sb_free_irq ();
  235.       return RET_ERROR (EBUSY);
  236.     }
  237.  
  238.   if (dma16 != dma8)
  239.     if (ALLOC_DMA_CHN (dma16,"sb16 16bit"))
  240.       {
  241.     printk ("SB16: Unable to grab DMA%d\n", dma16);
  242.     sb_free_irq ();
  243.     RELEASE_DMA_CHN (dma8);
  244.     return RET_ERROR (EBUSY);
  245.       }
  246.  
  247.   irq_mode = IMODE_NONE;
  248.   dsp_busy = 1;
  249.  
  250.   return 0;
  251. }
  252.  
  253. static void
  254. sb16_dsp_close (int dev)
  255. {
  256.   unsigned long   flags;
  257.  
  258.   DEB (printk ("sb16_dsp_close()\n"));
  259.   sb_dsp_command01 (0xd9);
  260.   sb_dsp_command01 (0xd5);
  261.  
  262.   DISABLE_INTR (flags);
  263.   RELEASE_DMA_CHN (dma8);
  264.  
  265.   if (dma16 != dma8)
  266.     RELEASE_DMA_CHN (dma16);
  267.   sb_free_irq ();
  268.   dsp_cleanup ();
  269.   dsp_busy = 0;
  270.   RESTORE_INTR (flags);
  271. }
  272.  
  273. static void
  274. sb16_dsp_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart)
  275. {
  276.   unsigned long   flags, cnt;
  277.  
  278.   cnt = count;
  279.   if (dsp_16bit)
  280.     cnt >>= 1;
  281.   cnt--;
  282.  
  283. #ifdef DEB_DMARES
  284.   printk ("output_block: %x %d %d\n", buf, count, intrflag);
  285.   if (intrflag)
  286.     {
  287.       int             pos, chan = audio_devs[dev]->dmachan;
  288.  
  289.       DISABLE_INTR (flags);
  290.       clear_dma_ff (chan);
  291.       disable_dma (chan);
  292.       pos = get_dma_residue (chan);
  293.       enable_dma (chan);
  294.       RESTORE_INTR (flags);
  295.       printk ("dmapos=%d %x\n", pos, pos);
  296.     }
  297. #endif
  298.   if (audio_devs[dev]->flags & DMA_AUTOMODE &&
  299.       intrflag &&
  300.       cnt == dsp_count)
  301.     {
  302.       irq_mode = IMODE_OUTPUT;
  303.       intr_active = 1;
  304.       return;            /*
  305.                  * Auto mode on. No need to react
  306.                  */
  307.     }
  308.   DISABLE_INTR (flags);
  309.  
  310.   if (dma_restart)
  311.     {
  312.       sb16_dsp_halt (dev);
  313.       DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE);
  314.     }
  315.   sb_dsp_command (0x41);
  316.   sb_dsp_command ((unsigned char) ((dsp_current_speed >> 8) & 0xff));
  317.   sb_dsp_command ((unsigned char) (dsp_current_speed & 0xff));
  318.   sb_dsp_command ((unsigned char) (dsp_16bit ? 0xb6 : 0xc6));
  319.   sb_dsp_command ((unsigned char) ((dsp_stereo ? 0x20 : 0) +
  320.                    (dsp_16bit ? 0x10 : 0)));
  321.   sb_dsp_command01 ((unsigned char) (cnt & 0xff));
  322.   sb_dsp_command ((unsigned char) (cnt >> 8));
  323.  
  324.   dsp_count = cnt;
  325.   irq_mode = IMODE_OUTPUT;
  326.   intr_active = 1;
  327.   RESTORE_INTR (flags);
  328. }
  329.  
  330. static void
  331. sb16_dsp_start_input (int dev, unsigned long buf, int count, int intrflag, int dma_restart)
  332. {
  333.   unsigned long   flags, cnt;
  334.  
  335.   cnt = count;
  336.   if (dsp_16bit)
  337.     cnt >>= 1;
  338.   cnt--;
  339.  
  340. #ifdef DEB_DMARES
  341.   printk ("start_input: %x %d %d\n", buf, count, intrflag);
  342.   if (intrflag)
  343.     {
  344.       int             pos, chan = audio_devs[dev]->dmachan;
  345.  
  346.       DISABLE_INTR (flags);
  347.       clear_dma_ff (chan);
  348.       disable_dma (chan);
  349.       pos = get_dma_residue (chan);
  350.       enable_dma (chan);
  351.       RESTORE_INTR (flags);
  352.       printk ("dmapos=%d %x\n", pos, pos);
  353.     }
  354. #endif
  355.   if (audio_devs[dev]->flags & DMA_AUTOMODE &&
  356.       intrflag &&
  357.       cnt == dsp_count)
  358.     {
  359.       irq_mode = IMODE_INPUT;
  360.       intr_active = 1;
  361.       return;            /*
  362.                  * Auto mode on. No need to react
  363.                  */
  364.     }
  365.   DISABLE_INTR (flags);
  366.  
  367.   if (dma_restart)
  368.     {
  369.       sb_reset_dsp ();
  370.       DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
  371.     }
  372.  
  373.   sb_dsp_command (0x42);
  374.   sb_dsp_command ((unsigned char) ((dsp_current_speed >> 8) & 0xff));
  375.   sb_dsp_command ((unsigned char) (dsp_current_speed & 0xff));
  376.   sb_dsp_command ((unsigned char) (dsp_16bit ? 0xbe : 0xce));
  377.   sb_dsp_command ((unsigned char) ((dsp_stereo ? 0x20 : 0) +
  378.                    (dsp_16bit ? 0x10 : 0)));
  379.   sb_dsp_command01 ((unsigned char) (cnt & 0xff));
  380.   sb_dsp_command ((unsigned char) (cnt >> 8));
  381.  
  382.   dsp_count = cnt;
  383.   irq_mode = IMODE_INPUT;
  384.   intr_active = 1;
  385.   RESTORE_INTR (flags);
  386. }
  387.  
  388. static int
  389. sb16_dsp_prepare_for_input (int dev, int bsize, int bcount)
  390. {
  391.   audio_devs[my_dev]->dmachan = dsp_16bit ? dma16 : dma8;
  392.   dsp_count = 0;
  393.   dsp_cleanup ();
  394.   return 0;
  395. }
  396.  
  397. static int
  398. sb16_dsp_prepare_for_output (int dev, int bsize, int bcount)
  399. {
  400.   audio_devs[my_dev]->dmachan = dsp_16bit ? dma16 : dma8;
  401.   dsp_count = 0;
  402.   dsp_cleanup ();
  403.   return 0;
  404. }
  405.  
  406. static void
  407. dsp_cleanup (void)
  408. {
  409.   irq_mode = IMODE_NONE;
  410.   intr_active = 0;
  411. }
  412.  
  413. static void
  414. sb16_dsp_reset (int dev)
  415. {
  416.   unsigned long   flags;
  417.  
  418.   DISABLE_INTR (flags);
  419.  
  420.   sb_reset_dsp ();
  421.   dsp_cleanup ();
  422.  
  423.   RESTORE_INTR (flags);
  424. }
  425.  
  426. static void
  427. sb16_dsp_halt (int dev)
  428. {
  429.   if (dsp_16bit)
  430.     {
  431.       sb_dsp_command01 (0xd9);
  432.       sb_dsp_command01 (0xd5);
  433.     }
  434.   else
  435.     {
  436.       sb_dsp_command01 (0xda);
  437.       sb_dsp_command01 (0xd0);
  438.     }
  439. }
  440.  
  441. static void
  442. set_irq_hw (int level)
  443. {
  444.   int             ival;
  445.  
  446.   switch (level)
  447.     {
  448.     case 5:
  449.       ival = 2;
  450.       break;
  451.     case 7:
  452.       ival = 4;
  453.       break;
  454.     case 9:
  455.       ival = 1;
  456.       break;
  457.     case 10:
  458.       ival = 8;
  459.       break;
  460.     default:
  461.       printk ("SB16_IRQ_LEVEL %d does not exist\n", level);
  462.       return;
  463.     }
  464.   sb_setmixer (IRQ_NR, ival);
  465. }
  466.  
  467. long
  468. sb16_dsp_init (long mem_start, struct address_info *hw_config)
  469. {
  470.   extern int      sbc_major, sbc_minor;
  471.  
  472.   if (sbc_major < 4)
  473.     return mem_start;        /* Not a SB16 */
  474.  
  475. #ifndef SCO
  476.   sprintf (sb16_dsp_operations.name, "SoundBlaster 16 %d.%d", sbc_major, sbc_minor);
  477. #endif
  478.  
  479.   printk (" <%s>", sb16_dsp_operations.name);
  480.  
  481.   if (num_audiodevs < MAX_AUDIO_DEV)
  482.     {
  483.       audio_devs[my_dev = num_audiodevs++] = &sb16_dsp_operations;
  484.       audio_devs[my_dev]->dmachan = hw_config->dma;
  485.       audio_devs[my_dev]->buffcount = 1;
  486.       audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;
  487.     }
  488.   else
  489.     printk ("SB: Too many DSP devices available\n");
  490.   sb16_dsp_ok = 1;
  491.   return mem_start;
  492. }
  493.  
  494. int
  495. sb16_dsp_detect (struct address_info *hw_config)
  496. {
  497.   struct address_info *sb_config;
  498.   extern int      sbc_major;
  499.  
  500.   if (sb16_dsp_ok)
  501.     return 1;            /* Can't drive two cards */
  502.  
  503.   if (!(sb_config = sound_getconf (SNDCARD_SB)))
  504.     {
  505.       printk ("SB16 Error: Plain SB not configured\n");
  506.       return 0;
  507.     }
  508.  
  509.   /*
  510.    * sb_setmixer(OPSW,0xf); if(sb_getmixer(OPSW)!=0xf) return 0;
  511.    */
  512.  
  513.   if (!sb_reset_dsp ())
  514.     return 0;
  515.  
  516.   if (sbc_major < 4)        /* Set by the plain SB driver */
  517.     return 0;            /* Not a SB16 */
  518.  
  519.   if (hw_config->dma < 4)
  520.     if (hw_config->dma != sb_config->dma)
  521.       {
  522.     printk ("SB16 Error: Invalid DMA channel %d/%d\n",
  523.         sb_config->dma, hw_config->dma);
  524.     return 0;
  525.       }
  526.  
  527.   dma16 = hw_config->dma;
  528.   dma8 = sb_config->dma;
  529.   set_irq_hw (sb_config->irq);
  530.   sb_setmixer (DMA_NR, (1 << hw_config->dma) | (1 << sb_config->dma));
  531.  
  532.   DEB (printk ("SoundBlaster 16: IRQ %d DMA %d OK\n", sb_config->irq, hw_config->dma));
  533.  
  534.   /*
  535.  * dsp_showmessage(0xe3,99);
  536.  */
  537.   sb16_dsp_ok = 1;
  538.   return 1;
  539. }
  540.  
  541. void
  542. sb16_dsp_interrupt (int unused)
  543. {
  544.   int             data;
  545.  
  546.   data = INB (DSP_DATA_AVL16);    /*
  547.                  * Interrupt acknowledge
  548.                  */
  549.  
  550.   if (intr_active)
  551.     switch (irq_mode)
  552.       {
  553.       case IMODE_OUTPUT:
  554.     intr_active = 0;
  555.     DMAbuf_outputintr (my_dev, 1);
  556.     break;
  557.  
  558.       case IMODE_INPUT:
  559.     intr_active = 0;
  560.     DMAbuf_inputintr (my_dev);
  561.     break;
  562.  
  563.       default:
  564.     printk ("SoundBlaster: Unexpected interrupt\n");
  565.       }
  566. }
  567.  
  568. #endif
  569.