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 ((int) 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 ((int) 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 ((int) 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 ((int) 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 = audio_devs[dev]->dmachan2 = 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 unsigned long trg_buf;
 264 static int      trg_bytes;
 265 static int      trg_intrflag;
 266 static int      trg_restart;
 267 
 268 static void
 269 sb16_dsp_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart)
     /* [previous][next][first][last][top][bottom][index][help] */
 270 {
 271   trg_buf = buf;
 272   trg_bytes = count;
 273   trg_intrflag = intrflag;
 274   trg_restart = dma_restart;
 275   irq_mode = IMODE_OUTPUT;
 276 }
 277 
 278 static void
 279 actually_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart)
     /* [previous][next][first][last][top][bottom][index][help] */
 280 {
 281   unsigned long   flags, cnt;
 282 
 283   cnt = count;
 284   if (dsp_16bit)
 285     cnt >>= 1;
 286   cnt--;
 287 
 288   if (audio_devs[dev]->flags & DMA_AUTOMODE &&
 289       intrflag &&
 290       cnt == dsp_count)
 291     {
 292       irq_mode = IMODE_OUTPUT;
 293       intr_active = 1;
 294       return;                   /*
 295                                  * Auto mode on. No need to react
 296                                  */
 297     }
 298   save_flags (flags);
 299   cli ();
 300 
 301   if (dma_restart)
 302     {
 303       sb16_dsp_halt (dev);
 304       DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE);
 305     }
 306   sb_dsp_command (0x41);
 307   sb_dsp_command ((unsigned char) ((dsp_current_speed >> 8) & 0xff));
 308   sb_dsp_command ((unsigned char) (dsp_current_speed & 0xff));
 309   sb_dsp_command ((unsigned char) (dsp_16bit ? 0xb6 : 0xc6));
 310   dsp_count = cnt;
 311   sb_dsp_command ((unsigned char) ((dsp_stereo ? 0x20 : 0) +
 312                                    (dsp_16bit ? 0x10 : 0)));
 313   sb_dsp_command01 ((unsigned char) (cnt & 0xff));
 314   sb_dsp_command ((unsigned char) (cnt >> 8));
 315 
 316   irq_mode = IMODE_OUTPUT;
 317   intr_active = 1;
 318   restore_flags (flags);
 319 }
 320 
 321 static void
 322 sb16_dsp_start_input (int dev, unsigned long buf, int count, int intrflag, int dma_restart)
     /* [previous][next][first][last][top][bottom][index][help] */
 323 {
 324   trg_buf = buf;
 325   trg_bytes = count;
 326   trg_intrflag = intrflag;
 327   trg_restart = dma_restart;
 328   irq_mode = IMODE_INPUT;
 329 }
 330 
 331 static void
 332 actually_start_input (int dev, unsigned long buf, int count, int intrflag, int dma_restart)
     /* [previous][next][first][last][top][bottom][index][help] */
 333 {
 334   unsigned long   flags, cnt;
 335 
 336   cnt = count;
 337   if (dsp_16bit)
 338     cnt >>= 1;
 339   cnt--;
 340 
 341   if (audio_devs[dev]->flags & DMA_AUTOMODE &&
 342       intrflag &&
 343       cnt == dsp_count)
 344     {
 345       irq_mode = IMODE_INPUT;
 346       intr_active = 1;
 347       return;                   /*
 348                                  * Auto mode on. No need to react
 349                                  */
 350     }
 351   save_flags (flags);
 352   cli ();
 353 
 354   if (dma_restart)
 355     {
 356       sb16_dsp_halt (dev);
 357       DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
 358     }
 359 
 360   sb_dsp_command (0x42);
 361   sb_dsp_command ((unsigned char) ((dsp_current_speed >> 8) & 0xff));
 362   sb_dsp_command ((unsigned char) (dsp_current_speed & 0xff));
 363 
 364   sb_dsp_command ((unsigned char) (dsp_16bit ? 0xbe : 0xce));
 365   dsp_count = cnt;
 366   sb_dsp_command ((unsigned char) ((dsp_stereo ? 0x20 : 0) +
 367                                    (dsp_16bit ? 0x10 : 0)));
 368   sb_dsp_command01 ((unsigned char) (cnt & 0xff));
 369   sb_dsp_command ((unsigned char) (cnt >> 8));
 370 
 371   irq_mode = IMODE_INPUT;
 372   intr_active = 1;
 373   restore_flags (flags);
 374 }
 375 
 376 static int
 377 sb16_dsp_prepare_for_input (int dev, int bsize, int bcount)
     /* [previous][next][first][last][top][bottom][index][help] */
 378 {
 379   audio_devs[my_dev]->dmachan1 =
 380     audio_devs[my_dev]->dmachan2 =
 381     dsp_16bit ? dma16 : dma8;
 382   dsp_count = 0;
 383   dsp_cleanup ();
 384   trigger_bits = 0;
 385   return 0;
 386 }
 387 
 388 static int
 389 sb16_dsp_prepare_for_output (int dev, int bsize, int bcount)
     /* [previous][next][first][last][top][bottom][index][help] */
 390 {
 391   audio_devs[my_dev]->dmachan1 =
 392     audio_devs[my_dev]->dmachan2 =
 393     dsp_16bit ? dma16 : dma8;
 394   dsp_count = 0;
 395   dsp_cleanup ();
 396   trigger_bits = 0;
 397   return 0;
 398 }
 399 
 400 static void
 401 sb16_dsp_trigger (int dev, int bits)
     /* [previous][next][first][last][top][bottom][index][help] */
 402 {
 403   trigger_bits = bits;
 404 
 405   if (!bits)
 406     {
 407       sb_dsp_command (0xd0);    /* Halt DMA */
 408     }
 409   else if (bits & irq_mode)
 410     switch (irq_mode)
 411       {
 412       case IMODE_INPUT:
 413         actually_start_input (my_dev, trg_buf, trg_bytes,
 414                               trg_intrflag, trg_restart);
 415 
 416         break;
 417 
 418       case IMODE_OUTPUT:
 419         actually_output_block (my_dev, trg_buf, trg_bytes,
 420                                trg_intrflag, trg_restart);
 421         break;
 422 
 423       }
 424 }
 425 
 426 static void
 427 dsp_cleanup (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 428 {
 429   irq_mode = IMODE_NONE;
 430   intr_active = 0;
 431 }
 432 
 433 static void
 434 sb16_dsp_reset (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 435 {
 436   unsigned long   flags;
 437 
 438   save_flags (flags);
 439   cli ();
 440 
 441   sb_reset_dsp ();
 442   dsp_cleanup ();
 443 
 444   restore_flags (flags);
 445 }
 446 
 447 static void
 448 sb16_dsp_halt (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 449 {
 450   if (dsp_16bit)
 451     {
 452       sb_dsp_command01 (0xd9);
 453       sb_dsp_command01 (0xd5);
 454     }
 455   else
 456     {
 457       sb_dsp_command01 (0xda);
 458       sb_dsp_command01 (0xd0);
 459     }
 460   /* DMAbuf_reset_dma (dev); */
 461 }
 462 
 463 static void
 464 set_irq_hw (int level)
     /* [previous][next][first][last][top][bottom][index][help] */
 465 {
 466   int             ival;
 467 
 468   switch (level)
 469     {
 470     case 5:
 471       ival = 2;
 472       break;
 473     case 7:
 474       ival = 4;
 475       break;
 476     case 9:
 477       ival = 1;
 478       break;
 479     case 10:
 480       ival = 8;
 481       break;
 482     default:
 483       printk ("SB16_IRQ_LEVEL %d does not exist\n", level);
 484       return;
 485     }
 486   sb_setmixer (IRQ_NR, ival);
 487 }
 488 
 489 long
 490 sb16_dsp_init (long mem_start, struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 491 {
 492   extern int      sbc_major, sbc_minor;
 493 
 494   if (sbc_major < 4)
 495     return mem_start;           /* Not a SB16 */
 496 
 497   sprintf (sb16_dsp_operations.name, "SoundBlaster 16 %d.%d", sbc_major, sbc_minor);
 498 
 499   conf_printf (sb16_dsp_operations.name, hw_config);
 500 
 501   if (num_audiodevs < MAX_AUDIO_DEV)
 502     {
 503       audio_devs[my_dev = num_audiodevs++] = &sb16_dsp_operations;
 504       audio_devs[my_dev]->dmachan1 = audio_devs[my_dev]->dmachan2 = dma8;
 505       audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;
 506 
 507       if (sound_alloc_dma (dma8, "SB16 (8bit)"))
 508         {
 509           printk ("SB16: Unable to grab DMA%d\n", dma8);
 510         }
 511 
 512       if (dma16 != dma8)
 513         if (sound_alloc_dma (dma16, "SB16 (16bit)"))
 514           {
 515             printk ("SB16: Unable to grab DMA%d\n", dma16);
 516           }
 517     }
 518   else
 519     printk ("SB: Too many DSP devices available\n");
 520   sb16_dsp_ok = 1;
 521   return mem_start;
 522 }
 523 
 524 static void
 525 set_dma (int dma)
     /* [previous][next][first][last][top][bottom][index][help] */
 526 {
 527   if (dma >= 0 && dma < 4)
 528     dma8 = dma;
 529   if (dma >= 5 && dma <= 7)
 530     dma16 = dma;
 531 }
 532 
 533 int
 534 sb16_dsp_detect (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 535 {
 536   struct address_info *sb_config;
 537   extern int      sbc_major, Jazz16_detected;
 538 
 539   extern void     Jazz16_set_dma16 (int dma);
 540   int             irq;
 541 
 542   if (sb16_dsp_ok)
 543     {
 544       return 1;                 /* Can't drive two cards */
 545     }
 546 
 547   irq = hw_config->irq;
 548   set_dma (hw_config->dma);
 549   set_dma (hw_config->dma2);
 550 
 551   if (Jazz16_detected)
 552     {
 553       Jazz16_set_dma16 (dma16);
 554       sb16_dsp_ok = 1;
 555       return 1;
 556     }
 557 
 558   if (dma8 == -1)
 559     if (!(sb_config = sound_getconf (SNDCARD_SB)))
 560       {
 561         printk ("SB16 Error: Plain SB not configured\n");
 562         return 0;
 563       }
 564     else
 565       {
 566         dma8 = sb_config->dma;
 567         irq = sb_config->irq;
 568       }
 569 
 570   if (dma16 == -1)
 571     dma16 = dma8;
 572 
 573   /*
 574    * sb_setmixer(OPSW,0xf); if(sb_getmixer(OPSW)!=0xf) return 0;
 575    */
 576 
 577   if (!sb_reset_dsp ())
 578     return 0;
 579 
 580   if (sbc_major < 4)            /* Set by the plain SB driver */
 581     return 0;                   /* Not a SB16 */
 582 
 583   if (dma16 < 4)
 584     if (dma16 != dma8)
 585       {
 586         printk ("SB16 Error: Invalid DMA channel %d/%d\n",
 587                 dma8, dma16);
 588         return 0;
 589       }
 590 
 591   set_irq_hw (irq);
 592   sb_setmixer (DMA_NR, (1 << dma16) | (1 << dma8));
 593 
 594   DEB (printk ("SoundBlaster 16: IRQ %d DMA %d OK\n", sb_config->irq, dma16));
 595 
 596   /*
 597      * dsp_showmessage(0xe3,99);
 598    */
 599   sb16_dsp_ok = 1;
 600   return 1;
 601 }
 602 
 603 void
 604 unload_sb16 (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 605 {
 606   extern int      Jazz16_detected;
 607 
 608   if (Jazz16_detected)
 609     return;
 610 
 611   sound_free_dma (dma8);
 612 
 613   if (dma16 != dma8)
 614     sound_free_dma (dma16);
 615 }
 616 
 617 void
 618 sb16_dsp_interrupt (int unused)
     /* [previous][next][first][last][top][bottom][index][help] */
 619 {
 620   int             data;
 621 
 622   data = inb (DSP_DATA_AVL16);  /*
 623                                    * Interrupt acknowledge
 624                                  */
 625 
 626   if (intr_active)
 627     switch (irq_mode)
 628       {
 629       case IMODE_OUTPUT:
 630         DMAbuf_outputintr (my_dev, 1);
 631         break;
 632 
 633       case IMODE_INPUT:
 634         DMAbuf_inputintr (my_dev);
 635         break;
 636 
 637       default:
 638         printk ("SoundBlaster: Unexpected interrupt\n");
 639       }
 640 }
 641 
 642 #endif

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