home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.0 / LINUX-1.0 / LINUX-1 / linux / drivers / sound / sb16_dsp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-21  |  13.6 KB  |  609 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;    /* Set to 1 after successful initialization */
  46. static int dsp_16bit = 0;
  47. static int dsp_stereo = 0;
  48. static int dsp_current_speed = 8000;/*DSP_DEFAULT_SPEED;*/
  49. static int dsp_busy  = 0;
  50. static int dma16, dma8;
  51. static unsigned long dsp_count = 0;
  52.  
  53. static int irq_mode = IMODE_NONE;    /* IMODE_INPUT, IMODE_OUTPUT or
  54.                        IMODE_NONE */
  55. static int my_dev = 0;
  56.  
  57. static volatile int intr_active = 0;
  58.  
  59. static int sb16_dsp_open (int dev, int mode);
  60. static void sb16_dsp_close (int dev);
  61. static void sb16_dsp_output_block (int dev, unsigned long buf, int count,int intrflag, int dma_restart);
  62. static void sb16_dsp_start_input (int dev, unsigned long buf, int count,int intrflag, int dma_restart);
  63. static int sb16_dsp_ioctl (int dev, unsigned int cmd, unsigned int arg,int local);
  64. static int sb16_dsp_prepare_for_input (int dev, int bsize, int bcount);
  65. static int sb16_dsp_prepare_for_output (int dev, int bsize, int bcount);
  66. static void sb16_dsp_reset (int dev);
  67. static void sb16_dsp_halt (int dev);
  68. static int dsp_set_speed (int);
  69. static int dsp_set_stereo (int);
  70. static void dsp_cleanup (void);
  71. int sb_reset_dsp (void);
  72.  
  73. static struct audio_operations sb16_dsp_operations =
  74. {
  75.   "SoundBlaster 16",
  76.   sb16_dsp_open,
  77.   sb16_dsp_close,
  78.   sb16_dsp_output_block,
  79.   sb16_dsp_start_input,
  80.   sb16_dsp_ioctl,
  81.   sb16_dsp_prepare_for_input,
  82.   sb16_dsp_prepare_for_output,
  83.   sb16_dsp_reset,
  84.   sb16_dsp_halt,
  85.   NULL,
  86.   NULL
  87. };
  88.  
  89. static int sb_dsp_command01 (unsigned char val)
  90. {
  91.   int i=1<<16;
  92.  
  93.   while(--i & (!INB (DSP_STATUS) & 0x80));
  94.   if(!i)
  95.     printk("SB16 sb_dsp_command01 Timeout\n");
  96.   return sb_dsp_command(val);
  97. }
  98.  
  99. static int wait_data_avail(int t)
  100. {
  101.   int loopc=5000000;
  102.   t+=GET_TIME();
  103.   do {
  104.     if(INB(DSP_DATA_AVAIL) & 0x80)
  105.       return 1;
  106.   } while(--loopc && GET_TIME()<t);
  107.   printk("!data_avail l=%d\n",loopc);
  108.   return 0;
  109. }
  110.  
  111. static int read_dsp(int t)
  112. {
  113.   if(!wait_data_avail(t))
  114.     return -1;
  115.   else
  116.     return INB(DSP_READ);
  117. }                                    
  118.  
  119. static int dsp_ini2(void)
  120. {
  121. #if 0
  122.   /* sb_setmixer(0x83, sb_getmixer(0x83) | 0x03);    */
  123.   sb_dsp_command(0xe2);
  124.   sb_dsp_command(0x76);    /* E0 ??? */
  125.   sb_dsp_command(0xe2);
  126.   sb_dsp_command(0x30);    /* A0 ??? */
  127.   sb_dsp_command(0xe4);
  128.   sb_dsp_command(0xaa);
  129.   sb_dsp_command(0xe8);
  130.   if(read_dsp(100)!=0xaa)
  131.     printk("Error dsp_ini2\n");
  132. #endif
  133.   return 0;
  134. }
  135. /*
  136. static char *dsp_getmessage(unsigned char command,int maxn)
  137. {
  138.   static char buff[100];
  139.   int n=0;
  140.  
  141.   sb_dsp_command(command);
  142.   while(n<maxn && wait_data_avail(2)) {
  143.     buff[++n]=INB(DSP_READ);
  144.     if(!buff[n])
  145.       break;
  146.   }
  147.   buff[0]=n;
  148.   return buff;
  149. }
  150.  
  151. static void dsp_showmessage(unsigned char command,int len)
  152. {
  153.   int n;
  154.   unsigned char *c;
  155.   c=dsp_getmessage(command,len);
  156.   printk("DSP C=%x l=%d,lr=%d b=",command,len,c[0]);
  157.   for(n=1;n<=c[0];n++)
  158.     if(c[n]>=' ' & c[n]<='z')
  159.       printk("%c",c[n]);
  160.     else
  161.       printk("|%x|",c[n]);
  162.   printk("\n");
  163. }
  164. */
  165. static int dsp_set_speed(int mode)
  166. {
  167. DEB(printk("dsp_set_speed(%d)\n",mode));
  168.   if (mode)
  169.   {
  170.     if (mode < 5000) mode = 5000;
  171.     if (mode > 44100) mode = 44100;
  172.     dsp_current_speed=mode;
  173.   }
  174.   return mode;
  175. }
  176.  
  177. static int dsp_set_stereo(int mode)
  178. {
  179. DEB(printk("dsp_set_stereo(%d)\n",mode));
  180.  
  181.   dsp_stereo=mode;
  182.  
  183.   return mode;
  184. }
  185.  
  186. static int dsp_set_bits(int arg) {
  187. DEB(printk("dsp_set_bits(%d)\n",arg));
  188.  
  189.   if (arg)
  190.   switch(arg) {
  191.   case 8:
  192.     dsp_16bit=0; break;
  193.   case 16:
  194.     dsp_16bit=1; break;
  195.   default:
  196.     return RET_ERROR(EINVAL);
  197.   }
  198.   return dsp_16bit? 16:8;
  199. }
  200.  
  201. static int
  202. sb16_dsp_ioctl (int dev, unsigned int cmd, unsigned int arg,int local)
  203. {
  204.   switch (cmd) {
  205.   case SOUND_PCM_WRITE_RATE:
  206.     if(local)
  207.       return dsp_set_speed(arg);
  208.     return IOCTL_OUT (arg, dsp_set_speed (IOCTL_IN (arg)));
  209.     
  210.   case SOUND_PCM_READ_RATE:
  211.     if(local)
  212.       return dsp_current_speed;
  213.     return IOCTL_OUT (arg, dsp_current_speed);
  214.     
  215.   case SNDCTL_DSP_STEREO:
  216.     if (local)
  217.       return dsp_set_stereo(arg);
  218.     return IOCTL_OUT (arg, dsp_set_stereo(IOCTL_IN(arg)));
  219.     
  220.   case SOUND_PCM_WRITE_CHANNELS:
  221.     if (local)
  222.       return dsp_set_stereo(arg-1)+1;
  223.     return IOCTL_OUT (arg, dsp_set_stereo (IOCTL_IN (arg) - 1) + 1);
  224.     
  225.   case SOUND_PCM_READ_CHANNELS:
  226.     if (local)
  227.       return dsp_stereo+1;
  228.     return IOCTL_OUT (arg, dsp_stereo+1);
  229.     
  230.   case SNDCTL_DSP_SAMPLESIZE:
  231.     if (local)
  232.       return dsp_set_bits (arg);
  233.     return IOCTL_OUT (arg, dsp_set_bits (IOCTL_IN (arg)));
  234.     
  235.   case SOUND_PCM_READ_BITS:
  236.     if (local)
  237.       return dsp_16bit?16:8;
  238.     return IOCTL_OUT (arg, dsp_16bit?16:8);
  239.     
  240.   case SOUND_PCM_WRITE_FILTER:    /* NOT YET IMPLEMENTED */
  241.     if (IOCTL_IN (arg) > 1)
  242.       return IOCTL_OUT (arg, RET_ERROR (EINVAL));
  243.   default:
  244.     return RET_ERROR (EINVAL);
  245.   }
  246.   
  247.   return RET_ERROR (EINVAL);
  248. }
  249.  
  250. static int
  251. sb16_dsp_open (int dev, int mode)
  252. {
  253.   int retval;
  254.  
  255. DEB(printk("sb16_dsp_open()\n"));
  256.   if (!sb16_dsp_ok)
  257.     {
  258.       printk ("SB16 Error: SoundBlaster board not installed\n");
  259.       return RET_ERROR(ENXIO);
  260.     }
  261.  
  262.   if (intr_active)
  263.     return RET_ERROR(EBUSY);
  264.  
  265.   retval = sb_get_irq ();
  266.   if (retval<0)
  267.     return retval;
  268.  
  269.   if (ALLOC_DMA_CHN (dma8))
  270.     {
  271.       printk ("SB16: Unable to grab DMA%d\n", dma8);
  272.       sb_free_irq();
  273.       return RET_ERROR(EBUSY);
  274.     }
  275.  
  276.   if (dma16 != dma8)
  277.   if (ALLOC_DMA_CHN (dma16))
  278.     {
  279.       printk ("SB16: Unable to grab DMA%d\n", dma16);
  280.       sb_free_irq();
  281.       RELEASE_DMA_CHN (dma8);
  282.       return RET_ERROR(EBUSY);
  283.     }
  284.  
  285.   dsp_ini2();
  286.  
  287.   irq_mode = IMODE_NONE;
  288.   dsp_busy = 1;
  289.  
  290.   return 0;
  291. }
  292.  
  293. static void
  294. sb16_dsp_close (int dev)
  295. {
  296.   unsigned long   flags;
  297. DEB(printk("sb16_dsp_close()\n"));
  298.   sb_dsp_command01(0xd9);
  299.   sb_dsp_command01(0xd5);
  300.  
  301.   DISABLE_INTR (flags);
  302.   RELEASE_DMA_CHN (dma8);
  303.  
  304.   if (dma16 != dma8)
  305.      RELEASE_DMA_CHN (dma16);
  306.   sb_free_irq ();
  307.   dsp_cleanup ();
  308.   dsp_busy = 0;
  309.   RESTORE_INTR (flags);
  310. }
  311.  
  312. static void
  313. sb16_dsp_output_block (int dev, unsigned long buf, int count,int intrflag, int dma_restart)
  314. {
  315.   unsigned long   flags, cnt;
  316.  
  317.   cnt = count;
  318.   if (dsp_16bit)
  319.     cnt >>= 1;
  320.   cnt--;
  321.  
  322. #ifdef DEB_DMARES
  323.   printk("output_block: %x %d %d\n",buf,count,intrflag);
  324.   if(intrflag) {
  325.     int pos,chan=sound_dsp_dmachan[dev];
  326.     DISABLE_INTR (flags);
  327.     clear_dma_ff(chan);
  328.     disable_dma(chan);
  329.     pos=get_dma_residue(chan);
  330.     enable_dma(chan);
  331.     RESTORE_INTR (flags);
  332.     printk("dmapos=%d %x\n",pos,pos);
  333.   }
  334. #endif
  335.   if (sound_dma_automode[dev] &&
  336.       intrflag &&
  337.       cnt == dsp_count) {
  338.     irq_mode = IMODE_OUTPUT;
  339.     intr_active = 1;
  340.     return;            /* Auto mode on. No need to react */
  341.   }
  342.   DISABLE_INTR (flags);
  343.   
  344.   if (dma_restart)
  345.   {
  346.      sb16_dsp_halt(dev);
  347.      DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE);
  348.   }
  349.   sb_dsp_command (0x41);
  350.   sb_dsp_command ((unsigned char)((dsp_current_speed >> 8) & 0xff));
  351.   sb_dsp_command ((unsigned char)(dsp_current_speed & 0xff));
  352.   sb_dsp_command ((unsigned char)(dsp_16bit ? 0xb6 : 0xc6));
  353.   sb_dsp_command ((unsigned char)((dsp_stereo ? 0x20 : 0) + 
  354.                   (dsp_16bit ? 0x10:0)));
  355.   sb_dsp_command01 ((unsigned char)(cnt&0xff));
  356.   sb_dsp_command ((unsigned char)(cnt>>8));
  357.   /* sb_dsp_command (0);
  358.   sb_dsp_command (0); */
  359.   
  360.   RESTORE_INTR (flags);
  361.   dsp_count=cnt;
  362.   irq_mode = IMODE_OUTPUT;
  363.   intr_active = 1;
  364. }
  365.  
  366. static void
  367. sb16_dsp_start_input (int dev, unsigned long buf, int count,int intrflag, int dma_restart)
  368. {
  369.   unsigned long   flags, cnt;
  370.  
  371.   cnt = count;
  372.   if (dsp_16bit)
  373.     cnt >>= 1;
  374.   cnt--;
  375.  
  376. #ifdef DEB_DMARES
  377. printk("start_input: %x %d %d\n",buf,count,intrflag);
  378.   if(intrflag) {
  379.     int pos,chan=sound_dsp_dmachan[dev];
  380.     DISABLE_INTR (flags);
  381.     clear_dma_ff(chan);
  382.     disable_dma(chan);
  383.     pos=get_dma_residue(chan);
  384.     enable_dma(chan);
  385.     RESTORE_INTR (flags);
  386.     printk("dmapos=%d %x\n",pos,pos);
  387.   }
  388. #endif
  389.   if (sound_dma_automode[dev] &&
  390.       intrflag &&
  391.       cnt == dsp_count) {
  392.     irq_mode = IMODE_INPUT;
  393.     intr_active = 1;
  394.     return;            /* Auto mode on. No need to react */
  395.   }
  396.   DISABLE_INTR (flags);
  397.   
  398.   if (dma_restart) 
  399.   {
  400.       sb16_dsp_halt(dev);
  401.       DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
  402.   }
  403.  
  404.   sb_dsp_command (0x42);
  405.   sb_dsp_command ((unsigned char)((dsp_current_speed >> 8) & 0xff));
  406.   sb_dsp_command ((unsigned char)(dsp_current_speed & 0xff));
  407.   sb_dsp_command ((unsigned char)(dsp_16bit ? 0xbe : 0xce));
  408.   sb_dsp_command ((unsigned char)((dsp_stereo ? 0x20 : 0) + 
  409.             (dsp_16bit ? 0x10:0)));
  410.   sb_dsp_command01 ((unsigned char)(cnt&0xff));
  411.   sb_dsp_command ((unsigned char)(cnt>>8));
  412.   
  413.   /* sb_dsp_command (0);
  414.   sb_dsp_command (0); */
  415.   RESTORE_INTR (flags);
  416.   dsp_count=cnt;
  417.   irq_mode = IMODE_INPUT;
  418.   intr_active = 1;
  419. }
  420.  
  421. static int
  422. sb16_dsp_prepare_for_input (int dev, int bsize, int bcount)
  423. {
  424.   sound_dsp_dmachan[my_dev] = dsp_16bit? dma16:dma8;
  425.   dsp_count = 0;
  426.   dsp_cleanup ();
  427.   return 0;
  428. }
  429.  
  430. static int
  431. sb16_dsp_prepare_for_output (int dev, int bsize, int bcount)
  432. {
  433.   sound_dsp_dmachan[my_dev] = dsp_16bit? dma16:dma8;
  434.   dsp_count = 0;
  435.   dsp_cleanup ();
  436.   return 0;
  437. }
  438.  
  439. static void
  440. dsp_cleanup (void)
  441. {
  442.   irq_mode = IMODE_NONE;
  443.   intr_active = 0;
  444. }
  445.  
  446. static void
  447. sb16_dsp_reset (int dev)
  448. {
  449.   unsigned long flags;
  450.  
  451.   DISABLE_INTR (flags);
  452.  
  453.   sb_reset_dsp ();
  454.   dsp_cleanup ();
  455.  
  456.   RESTORE_INTR (flags);
  457. }
  458.  
  459. static void
  460. sb16_dsp_halt (int dev)
  461. {
  462.   if (dsp_16bit)
  463.    {
  464.      sb_dsp_command01(0xd9);
  465.      sb_dsp_command01(0xd5);
  466.    }
  467.   else
  468.    {
  469.      sb_dsp_command01(0xda);
  470.      sb_dsp_command01(0xd0);
  471.    }
  472. }
  473.  
  474. static void
  475. set_irq_hw(int level) {
  476.   int ival;
  477.   switch(level) {
  478.   case 5:
  479.     ival=2; break;
  480.   case 7:
  481.     ival=4; break;
  482.   case 10:
  483.     ival=8; break;
  484.   default:
  485.     printk("SB16_IRQ_LEVEL %d does not exist\n",level);
  486.     return;
  487.   }
  488.   sb_setmixer(IRQ_NR,ival);
  489. }
  490.  
  491. long
  492. sb16_dsp_init (long mem_start, struct address_info *hw_config)
  493. {
  494.   int             i, major, minor;
  495.  
  496.   major = minor = 0;
  497.   sb_dsp_command (0xe1);        /* Get version */
  498.   
  499.   for (i = 1000; i; i--) {
  500.     if (INB (DSP_DATA_AVAIL) & 0x80)
  501.       {            /* wait for Data Ready */
  502.     if (major == 0)
  503.       major = INB (DSP_READ);
  504.     else
  505.       {
  506.         minor = INB (DSP_READ);
  507.         break;
  508.       }
  509.       }
  510.   }
  511.  
  512. #ifndef SCO 
  513.   sprintf (sb16_dsp_operations.name, "SoundBlaster 16 %d.%d", major, minor);
  514. #endif
  515.   
  516.   printk (" <%s>", sb16_dsp_operations.name);
  517.   
  518.   if (num_dspdevs < MAX_DSP_DEV)
  519.     {
  520.       dsp_devs[my_dev = num_dspdevs++] = &sb16_dsp_operations;
  521.       sound_dsp_dmachan[my_dev] = hw_config->dma;
  522.       sound_buffcounts[my_dev] = 1;
  523.       sound_buffsizes[my_dev] = DSP_BUFFSIZE;
  524.       sound_dma_automode[my_dev] = 1;
  525.     }
  526.   else
  527.     printk ("SB: Too many DSP devices available\n");
  528.   sb16_dsp_ok = 1;
  529.   return mem_start;
  530. }
  531.  
  532. int
  533. sb16_dsp_detect (struct address_info *hw_config)
  534. {
  535.   struct address_info *sb_config;
  536.  
  537.   if (sb16_dsp_ok)
  538.     return 1;            /* Already initialized */
  539.  
  540.   if (!(sb_config=sound_getconf(SNDCARD_SB)))
  541.   {
  542.       printk("SB16 Error: Plain SB not configured\n");
  543.       return 0;
  544.   }
  545.  
  546.   if (sbc_base != hw_config->io_base)
  547.      printk("Warning! SB16 I/O != SB I/O\n");
  548.  
  549.   /* sb_setmixer(OPSW,0xf);
  550.   if(sb_getmixer(OPSW)!=0xf)
  551.     return 0; */
  552.   
  553.   if (!sb_reset_dsp ())
  554.     return 0;
  555.  
  556.   if (hw_config->irq != sb_config->irq)
  557.   {
  558.      printk("SB16 Error: Invalid IRQ number %d/%d\n",
  559.               sb_config->irq, hw_config->irq);
  560.      return 0;
  561.   }
  562.  
  563.   if (hw_config->dma < 4)
  564.      if (hw_config->dma != sb_config->dma)
  565.      {
  566.          printk("SB16 Error: Invalid DMA channel %d/%d\n",
  567.              sb_config->dma, hw_config->dma);
  568.          return 0;
  569.      }
  570.  
  571.   dma16 = hw_config->dma;
  572.   dma8 = sb_config->dma;
  573.   set_irq_hw(hw_config->irq);
  574.   sb_setmixer(DMA_NR, (1<<hw_config->dma) | (1<<sb_config->dma));
  575.  
  576.   DEB(printk ("SoundBlaster 16: IRQ %d DMA %d OK\n",hw_config->irq,hw_config->dma));
  577.   
  578. /*
  579.   dsp_showmessage(0xe3,99);
  580. */
  581.   sb16_dsp_ok = 1;
  582.   return 1;
  583. }
  584.  
  585. void
  586. sb16_dsp_interrupt (int unused)
  587. {
  588.     int data;
  589.     data = INB (DSP_DATA_AVL16);    /* Interrupt acknowledge */
  590.  
  591.     if (intr_active)
  592.       switch (irq_mode)
  593.     {
  594.     case IMODE_OUTPUT:
  595.       intr_active = 0;
  596.       DMAbuf_outputintr (my_dev, 1);
  597.       break;
  598.       
  599.     case IMODE_INPUT:
  600.       intr_active = 0;
  601.       DMAbuf_inputintr (my_dev);
  602.       break;
  603.       
  604.     default:
  605.       printk ("SoundBlaster: Unexpected interrupt\n");
  606.     }
  607. }
  608. #endif
  609.