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

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