root/drivers/sound/sb16_dsp.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sb_dsp_command01
  2. dsp_set_speed
  3. dsp_set_stereo
  4. dsp_set_bits
  5. sb16_dsp_ioctl
  6. sb16_dsp_open
  7. sb16_dsp_close
  8. sb16_dsp_output_block
  9. sb16_dsp_start_input
  10. sb16_dsp_prepare_for_input
  11. sb16_dsp_prepare_for_output
  12. dsp_cleanup
  13. sb16_dsp_reset
  14. sb16_dsp_halt
  15. set_irq_hw
  16. sb16_dsp_init
  17. sb16_dsp_detect
  18. sb16_dsp_interrupt

   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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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))
 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))
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 408 {
 409   irq_mode = IMODE_NONE;
 410   intr_active = 0;
 411 }
 412 
 413 static void
 414 sb16_dsp_reset (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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

/* [previous][next][first][last][top][bottom][index][help] */