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. actually_output_block
  10. sb16_dsp_start_input
  11. actually_start_input
  12. sb16_dsp_prepare_for_input
  13. sb16_dsp_prepare_for_output
  14. sb16_dsp_trigger
  15. dsp_cleanup
  16. sb16_dsp_reset
  17. sb16_dsp_halt
  18. set_irq_hw
  19. sb16_dsp_init
  20. set_dma
  21. sb16_dsp_detect
  22. unload_sb16
  23. sb16_dsp_interrupt

   1 /*
   2  * sound/sb16_dsp.c
   3  *
   4  * The low level driver for the SoundBlaster DSP chip.
   5  */
   6 /*
   7  * Copyright by Hannu Savolainen 1993-1996
   8  *
   9  * Redistribution and use in source and binary forms, with or without
  10  * modification, are permitted provided that the following conditions are
  11  * met: 1. Redistributions of source code must retain the above copyright
  12  * notice, this list of conditions and the following disclaimer. 2.
  13  * Redistributions in binary form must reproduce the above copyright notice,
  14  * this list of conditions and the following disclaimer in the documentation
  15  * and/or other materials provided with the distribution.
  16  *
  17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
  18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  23  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  24  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27  * SUCH DAMAGE.
  28  */
  29 #include <linux/config.h>
  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(CONFIG_SB) && defined(CONFIG_AUDIO)
  42 
  43 extern int      sbc_base;
  44 extern int     *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 = -1, dma8 = -1;
  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, caddr_t 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, caddr_t 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   sb_reset_dsp ();
 250 
 251   save_flags (flags);
 252   cli ();
 253 
 254   audio_devs[dev]->dmachan1 = audio_devs[dev]->dmachan2 = dma8;
 255 
 256   if (dma16 != dma8)
 257     sound_close_dma (dma16);
 258   sb_free_irq ();
 259   dsp_cleanup ();
 260   dsp_busy = 0;
 261   restore_flags (flags);
 262 }
 263 
 264 static unsigned long trg_buf;
 265 static int      trg_bytes;
 266 static int      trg_intrflag;
 267 static int      trg_restart;
 268 
 269 static void
 270 sb16_dsp_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart)
     /* [previous][next][first][last][top][bottom][index][help] */
 271 {
 272   trg_buf = buf;
 273   trg_bytes = count;
 274   trg_intrflag = intrflag;
 275   trg_restart = dma_restart;
 276   irq_mode = IMODE_OUTPUT;
 277 }
 278 
 279 static void
 280 actually_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart)
     /* [previous][next][first][last][top][bottom][index][help] */
 281 {
 282   unsigned long   flags, cnt;
 283 
 284   cnt = count;
 285   if (dsp_16bit)
 286     cnt >>= 1;
 287   cnt--;
 288 
 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   trg_buf = buf;
 326   trg_bytes = count;
 327   trg_intrflag = intrflag;
 328   trg_restart = dma_restart;
 329   irq_mode = IMODE_INPUT;
 330 }
 331 
 332 static void
 333 actually_start_input (int dev, unsigned long buf, int count, int intrflag, int dma_restart)
     /* [previous][next][first][last][top][bottom][index][help] */
 334 {
 335   unsigned long   flags, cnt;
 336 
 337   cnt = count;
 338   if (dsp_16bit)
 339     cnt >>= 1;
 340   cnt--;
 341 
 342   if (audio_devs[dev]->flags & DMA_AUTOMODE &&
 343       intrflag &&
 344       cnt == dsp_count)
 345     {
 346       irq_mode = IMODE_INPUT;
 347       intr_active = 1;
 348       return;                   /*
 349                                  * Auto mode on. No need to react
 350                                  */
 351     }
 352   save_flags (flags);
 353   cli ();
 354 
 355   if (dma_restart)
 356     {
 357       sb16_dsp_halt (dev);
 358       DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
 359     }
 360 
 361   sb_dsp_command (0x42);
 362   sb_dsp_command ((unsigned char) ((dsp_current_speed >> 8) & 0xff));
 363   sb_dsp_command ((unsigned char) (dsp_current_speed & 0xff));
 364 
 365   sb_dsp_command ((unsigned char) (dsp_16bit ? 0xbe : 0xce));
 366   dsp_count = cnt;
 367   sb_dsp_command ((unsigned char) ((dsp_stereo ? 0x20 : 0) +
 368                                    (dsp_16bit ? 0x10 : 0)));
 369   sb_dsp_command01 ((unsigned char) (cnt & 0xff));
 370   sb_dsp_command ((unsigned char) (cnt >> 8));
 371 
 372   irq_mode = IMODE_INPUT;
 373   intr_active = 1;
 374   restore_flags (flags);
 375 }
 376 
 377 static int
 378 sb16_dsp_prepare_for_input (int dev, int bsize, int bcount)
     /* [previous][next][first][last][top][bottom][index][help] */
 379 {
 380   audio_devs[my_dev]->dmachan1 =
 381     audio_devs[my_dev]->dmachan2 =
 382     dsp_16bit ? dma16 : dma8;
 383   dsp_count = 0;
 384   dsp_cleanup ();
 385   trigger_bits = 0;
 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 =
 393     audio_devs[my_dev]->dmachan2 =
 394     dsp_16bit ? dma16 : dma8;
 395   dsp_count = 0;
 396   dsp_cleanup ();
 397   trigger_bits = 0;
 398   return 0;
 399 }
 400 
 401 static void
 402 sb16_dsp_trigger (int dev, int bits)
     /* [previous][next][first][last][top][bottom][index][help] */
 403 {
 404   trigger_bits = bits;
 405 
 406   if (!bits)
 407     {
 408       sb_dsp_command (0xd0);    /* Halt DMA */
 409     }
 410   else if (bits & irq_mode)
 411     switch (irq_mode)
 412       {
 413       case IMODE_INPUT:
 414         actually_start_input (my_dev, trg_buf, trg_bytes,
 415                               trg_intrflag, trg_restart);
 416 
 417         break;
 418 
 419       case IMODE_OUTPUT:
 420         actually_output_block (my_dev, trg_buf, trg_bytes,
 421                                trg_intrflag, trg_restart);
 422         break;
 423 
 424       }
 425 }
 426 
 427 static void
 428 dsp_cleanup (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 429 {
 430   irq_mode = IMODE_NONE;
 431   intr_active = 0;
 432 }
 433 
 434 static void
 435 sb16_dsp_reset (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 436 {
 437   unsigned long   flags;
 438 
 439   save_flags (flags);
 440   cli ();
 441 
 442   sb_reset_dsp ();
 443   dsp_cleanup ();
 444 
 445   restore_flags (flags);
 446 }
 447 
 448 static void
 449 sb16_dsp_halt (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 450 {
 451   if (dsp_16bit)
 452     {
 453       sb_dsp_command01 (0xd9);
 454       sb_dsp_command01 (0xd5);
 455     }
 456   else
 457     {
 458       sb_dsp_command01 (0xda);
 459       sb_dsp_command01 (0xd0);
 460     }
 461   /* DMAbuf_reset_dma (dev); */
 462 }
 463 
 464 static void
 465 set_irq_hw (int level)
     /* [previous][next][first][last][top][bottom][index][help] */
 466 {
 467   int             ival;
 468 
 469   switch (level)
 470     {
 471     case 5:
 472       ival = 2;
 473       break;
 474     case 7:
 475       ival = 4;
 476       break;
 477     case 9:
 478       ival = 1;
 479       break;
 480     case 10:
 481       ival = 8;
 482       break;
 483     default:
 484       printk ("SB16_IRQ_LEVEL %d does not exist\n", level);
 485       return;
 486     }
 487   sb_setmixer (IRQ_NR, ival);
 488 }
 489 
 490 long
 491 sb16_dsp_init (long mem_start, struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 492 {
 493   extern int      sbc_major, sbc_minor;
 494 
 495   if (sbc_major < 4)
 496     return mem_start;           /* Not a SB16 */
 497 
 498   sprintf (sb16_dsp_operations.name, "SoundBlaster 16 %d.%d", sbc_major, sbc_minor);
 499 
 500   conf_printf (sb16_dsp_operations.name, hw_config);
 501 
 502   if (num_audiodevs < MAX_AUDIO_DEV)
 503     {
 504       audio_devs[my_dev = num_audiodevs++] = &sb16_dsp_operations;
 505       audio_devs[my_dev]->dmachan1 = audio_devs[my_dev]->dmachan2 = dma8;
 506       audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;
 507 
 508       if (sound_alloc_dma (dma8, "SB16 (8bit)"))
 509         {
 510           printk ("SB16: Unable to grab DMA%d\n", dma8);
 511         }
 512 
 513       if (dma16 != dma8)
 514         if (sound_alloc_dma (dma16, "SB16 (16bit)"))
 515           {
 516             printk ("SB16: Unable to grab DMA%d\n", dma16);
 517           }
 518     }
 519   else
 520     printk ("SB: Too many DSP devices available\n");
 521   sb16_dsp_ok = 1;
 522   return mem_start;
 523 }
 524 
 525 static void
 526 set_dma (int dma)
     /* [previous][next][first][last][top][bottom][index][help] */
 527 {
 528   if (dma >= 0 && dma < 4)
 529     dma8 = dma;
 530   if (dma >= 5 && dma <= 7)
 531     dma16 = dma;
 532 }
 533 
 534 int
 535 sb16_dsp_detect (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 536 {
 537   struct address_info *sb_config;
 538   extern int      sbc_major, Jazz16_detected;
 539 
 540   extern void     Jazz16_set_dma16 (int dma);
 541   int             irq;
 542 
 543   if (sb16_dsp_ok)
 544     {
 545       return 1;                 /* Can't drive two cards */
 546     }
 547 
 548   irq = hw_config->irq;
 549   set_dma (hw_config->dma);
 550   set_dma (hw_config->dma2);
 551 
 552   if (Jazz16_detected)
 553     {
 554       Jazz16_set_dma16 (dma16);
 555       sb16_dsp_ok = 1;
 556       return 1;
 557     }
 558 
 559   if (dma8 == -1)
 560     if (!(sb_config = sound_getconf (SNDCARD_SB)))
 561       {
 562         printk ("SB16 Error: Plain SB not configured\n");
 563         return 0;
 564       }
 565     else
 566       {
 567         dma8 = sb_config->dma;
 568         irq = sb_config->irq;
 569       }
 570 
 571   if (dma16 == -1)
 572     dma16 = dma8;
 573 
 574   /*
 575    * sb_setmixer(OPSW,0xf); if(sb_getmixer(OPSW)!=0xf) return 0;
 576    */
 577 
 578   if (!sb_reset_dsp ())
 579     return 0;
 580 
 581   if (sbc_major < 4)            /* Set by the plain SB driver */
 582     return 0;                   /* Not a SB16 */
 583 
 584   if (dma16 < 4)
 585     if (dma16 != dma8)
 586       {
 587         printk ("SB16 Error: Invalid DMA channel %d/%d\n",
 588                 dma8, dma16);
 589         return 0;
 590       }
 591 
 592   set_irq_hw (irq);
 593   sb_setmixer (DMA_NR, (1 << dma16) | (1 << dma8));
 594 
 595   DEB (printk ("SoundBlaster 16: IRQ %d DMA %d OK\n", sb_config->irq, dma16));
 596 
 597   /*
 598      * dsp_showmessage(0xe3,99);
 599    */
 600   sb16_dsp_ok = 1;
 601   return 1;
 602 }
 603 
 604 void
 605 unload_sb16 (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 606 {
 607   extern int      Jazz16_detected;
 608 
 609   if (Jazz16_detected)
 610     return;
 611 
 612   sound_free_dma (dma8);
 613 
 614   if (dma16 != dma8)
 615     sound_free_dma (dma16);
 616 }
 617 
 618 void
 619 sb16_dsp_interrupt (int unused)
     /* [previous][next][first][last][top][bottom][index][help] */
 620 {
 621   int             data;
 622 
 623   data = inb (DSP_DATA_AVL16);  /*
 624                                    * Interrupt acknowledge
 625                                  */
 626 
 627   if (intr_active)
 628     switch (irq_mode)
 629       {
 630       case IMODE_OUTPUT:
 631         DMAbuf_outputintr (my_dev, 1);
 632         break;
 633 
 634       case IMODE_INPUT:
 635         DMAbuf_inputintr (my_dev);
 636         break;
 637 
 638       default:
 639         printk ("SoundBlaster: Unexpected interrupt\n");
 640       }
 641 }
 642 
 643 #endif

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