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

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