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

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