root/drivers/sound/audio.c

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

DEFINITIONS

This source file includes following definitions.
  1. set_format
  2. audio_open
  3. audio_release
  4. translate_bytes
  5. translate_bytes
  6. audio_write
  7. audio_read
  8. audio_ioctl
  9. audio_init
  10. audio_select
  11. audio_read
  12. audio_write
  13. audio_open
  14. audio_release
  15. audio_ioctl
  16. audio_lseek
  17. audio_init

   1 /*
   2  * sound/audio.c
   3  *
   4  * Device file manager for /dev/audio
   5  *
   6  * Copyright by Hannu Savolainen 1993
   7  *
   8  * Redistribution and use in source and binary forms, with or without
   9  * modification, are permitted provided that the following conditions are
  10  * met: 1. Redistributions of source code must retain the above copyright
  11  * notice, this list of conditions and the following disclaimer. 2.
  12  * Redistributions in binary form must reproduce the above copyright notice,
  13  * this list of conditions and the following disclaimer in the documentation
  14  * and/or other materials provided with the distribution.
  15  *
  16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
  17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  22  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  23  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  26  * SUCH DAMAGE.
  27  *
  28  */
  29 
  30 #include "sound_config.h"
  31 
  32 #ifdef CONFIGURE_SOUNDCARD
  33 #ifndef EXCLUDE_AUDIO
  34 
  35 #include "ulaw.h"
  36 #include "coproc.h"
  37 
  38 #define ON              1
  39 #define OFF             0
  40 
  41 static int      wr_buff_no[MAX_AUDIO_DEV];      /*
  42 
  43                                                  * != -1, if there is
  44                                                  * a incomplete output
  45                                                  * block in the queue.
  46                                                  */
  47 static int      wr_buff_size[MAX_AUDIO_DEV], wr_buff_ptr[MAX_AUDIO_DEV];
  48 
  49 static int      audio_mode[MAX_AUDIO_DEV];
  50 static int      dev_nblock[MAX_AUDIO_DEV];      /* 1 if in noblocking mode */
  51 
  52 #define         AM_NONE         0
  53 #define         AM_WRITE        1
  54 #define         AM_READ         2
  55 
  56 static char    *wr_dma_buf[MAX_AUDIO_DEV];
  57 static int      audio_format[MAX_AUDIO_DEV];
  58 static int      local_conversion[MAX_AUDIO_DEV];
  59 
  60 static int
  61 set_format (int dev, int fmt)
     /* [previous][next][first][last][top][bottom][index][help] */
  62 {
  63   if (fmt != AFMT_QUERY)
  64     {
  65 
  66       local_conversion[dev] = 0;
  67 
  68       if (!(audio_devs[dev]->format_mask & fmt))        /* Not supported */
  69         if (fmt == AFMT_MU_LAW)
  70           {
  71             fmt = AFMT_U8;
  72             local_conversion[dev] = AFMT_MU_LAW;
  73           }
  74         else
  75           fmt = AFMT_U8;        /* This is always supported */
  76 
  77       audio_format[dev] = DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, (ioctl_arg) fmt, 1);
  78     }
  79 
  80   if (local_conversion[dev])    /* This shadows the HW format */
  81     return local_conversion[dev];
  82 
  83   return audio_format[dev];
  84 }
  85 
  86 int
  87 audio_open (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
  88 {
  89   int             ret;
  90   int             bits;
  91   int             dev_type = dev & 0x0f;
  92   int             mode = file->mode & O_ACCMODE;
  93 
  94   dev = dev >> 4;
  95 
  96   if (dev_type == SND_DEV_DSP16)
  97     bits = 16;
  98   else
  99     bits = 8;
 100 
 101   if ((ret = DMAbuf_open (dev, mode)) < 0)
 102     return ret;
 103 
 104   if (audio_devs[dev]->coproc)
 105     if ((ret = audio_devs[dev]->coproc->
 106          open (audio_devs[dev]->coproc->devc, COPR_PCM)) < 0)
 107       {
 108         audio_release (dev, file);
 109         printk ("Sound: Can't access coprocessor device\n");
 110 
 111         return ret;
 112       }
 113 
 114   local_conversion[dev] = 0;
 115 
 116   if (DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, (ioctl_arg) bits, 1) != bits)
 117     {
 118       audio_release (dev, file);
 119       return -ENXIO;
 120     }
 121 
 122   if (dev_type == SND_DEV_AUDIO)
 123     {
 124       set_format (dev, AFMT_MU_LAW);
 125     }
 126   else
 127     set_format (dev, bits);
 128 
 129   wr_buff_no[dev] = -1;
 130   audio_mode[dev] = AM_NONE;
 131   wr_buff_size[dev] = wr_buff_ptr[dev] = 0;
 132   dev_nblock[dev] = 0;
 133 
 134   return ret;
 135 }
 136 
 137 void
 138 audio_release (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 139 {
 140   int             mode;
 141 
 142   dev = dev >> 4;
 143   mode = file->mode & O_ACCMODE;
 144 
 145   if (wr_buff_no[dev] >= 0)
 146     {
 147       DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
 148 
 149       wr_buff_no[dev] = -1;
 150     }
 151 
 152   if (audio_devs[dev]->coproc)
 153     audio_devs[dev]->coproc->close (audio_devs[dev]->coproc->devc, COPR_PCM);
 154   DMAbuf_release (dev, mode);
 155 }
 156 
 157 #if !defined(i386)
 158 static void
 159 translate_bytes (const unsigned char *table, unsigned char *buff, int n)
     /* [previous][next][first][last][top][bottom][index][help] */
 160 {
 161   unsigned long   i;
 162 
 163   if (n <= 0)
 164     return;
 165 
 166   for (i = 0; i < n; ++i)
 167     buff[i] = table[buff[i]];
 168 }
 169 
 170 #else
 171 extern inline void
 172 translate_bytes (const void *table, void *buff, int n)
     /* [previous][next][first][last][top][bottom][index][help] */
 173 {
 174   if (n > 0)
 175     {
 176       __asm__ ("cld\n"
 177                "1:\tlodsb\n\t"
 178                "xlatb\n\t"
 179                "stosb\n\t"
 180     "loop 1b\n\t":
 181     :      "b" ((long) table), "c" (n), "D" ((long) buff), "S" ((long) buff)
 182     :          "bx", "cx", "di", "si", "ax");
 183     }
 184 }
 185 #endif
 186 
 187 int
 188 audio_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 189 {
 190   int             c, p, l;
 191   int             err;
 192 
 193   dev = dev >> 4;
 194 
 195   p = 0;
 196   c = count;
 197 
 198   if ((audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX))
 199     {                           /* Direction change */
 200       wr_buff_no[dev] = -1;
 201     }
 202 
 203   if (audio_devs[dev]->flags & DMA_DUPLEX)
 204     audio_mode[dev] |= AM_WRITE;
 205   else
 206     audio_mode[dev] = AM_WRITE;
 207 
 208   if (!count)                   /*
 209                                  * Flush output
 210                                  */
 211     {
 212       if (wr_buff_no[dev] >= 0)
 213         {
 214           DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
 215 
 216           wr_buff_no[dev] = -1;
 217         }
 218       return 0;
 219     }
 220 
 221   while (c)
 222     {                           /*
 223                                  * Perform output blocking
 224                                  */
 225       if (wr_buff_no[dev] < 0)  /*
 226                                  * There is no incomplete buffers
 227                                  */
 228         {
 229           if ((wr_buff_no[dev] = DMAbuf_getwrbuffer (dev, &wr_dma_buf[dev],
 230                                                      &wr_buff_size[dev],
 231                                                      dev_nblock[dev])) < 0)
 232             {
 233               /* Handle nonblocking mode */
 234               if (dev_nblock[dev] && wr_buff_no[dev] == -EAGAIN)
 235                 return p;       /* No more space. Return # of accepted bytes */
 236               return wr_buff_no[dev];
 237             }
 238           wr_buff_ptr[dev] = 0;
 239         }
 240 
 241       l = c;
 242       if (l > (wr_buff_size[dev] - wr_buff_ptr[dev]))
 243         l = (wr_buff_size[dev] - wr_buff_ptr[dev]);
 244 
 245       if (!audio_devs[dev]->copy_from_user)
 246         {                       /*
 247                                  * No device specific copy routine
 248                                  */
 249           memcpy_fromfs (&wr_dma_buf[dev][wr_buff_ptr[dev]], &((buf)[p]), l);
 250         }
 251       else
 252         audio_devs[dev]->copy_from_user (dev,
 253                               wr_dma_buf[dev], wr_buff_ptr[dev], buf, p, l);
 254 
 255 
 256       /*
 257        * Insert local processing here
 258        */
 259 
 260       if (local_conversion[dev] == AFMT_MU_LAW)
 261         {
 262           /*
 263            * This just allows interrupts while the conversion is running
 264            */
 265           sti();
 266           translate_bytes (ulaw_dsp, (unsigned char *) &wr_dma_buf[dev][wr_buff_ptr[dev]], l);
 267         }
 268 
 269       c -= l;
 270       p += l;
 271       wr_buff_ptr[dev] += l;
 272 
 273       if (wr_buff_ptr[dev] >= wr_buff_size[dev])
 274         {
 275           if ((err = DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev])) < 0)
 276             {
 277               return err;
 278             }
 279 
 280           wr_buff_no[dev] = -1;
 281         }
 282 
 283     }
 284 
 285   return count;
 286 }
 287 
 288 int
 289 audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 290 {
 291   int             c, p, l;
 292   char           *dmabuf;
 293   int             buff_no;
 294 
 295   dev = dev >> 4;
 296   p = 0;
 297   c = count;
 298 
 299   if ((audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
 300     {
 301       if (wr_buff_no[dev] >= 0)
 302         {
 303           DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
 304 
 305           if (!(audio_devs[dev]->flags & DMA_DUPLEX))
 306             wr_buff_no[dev] = -1;
 307         }
 308     }
 309 
 310   if (audio_devs[dev]->flags & DMA_DUPLEX)
 311     audio_mode[dev] |= AM_READ;
 312   else
 313     audio_mode[dev] = AM_READ;
 314 
 315   while (c)
 316     {
 317       if ((buff_no = DMAbuf_getrdbuffer (dev, &dmabuf, &l,
 318                                          dev_nblock[dev])) < 0)
 319         {
 320           /* Nonblocking mode handling. Return current # of bytes */
 321 
 322           if (dev_nblock[dev] && buff_no == -EAGAIN)
 323             return p;
 324 
 325           return buff_no;
 326         }
 327 
 328       if (l > c)
 329         l = c;
 330 
 331       /*
 332        * Insert any local processing here.
 333        */
 334 
 335       if (local_conversion[dev] == AFMT_MU_LAW)
 336         {
 337           /*
 338            * This just allows interrupts while the conversion is running
 339            */
 340           sti();
 341 
 342           translate_bytes (dsp_ulaw, (unsigned char *) dmabuf, l);
 343         }
 344 
 345       memcpy_tofs (&((buf)[p]), dmabuf, l);
 346 
 347       DMAbuf_rmchars (dev, buff_no, l);
 348 
 349       p += l;
 350       c -= l;
 351     }
 352 
 353   return count - c;
 354 }
 355 
 356 int
 357 audio_ioctl (int dev, struct fileinfo *file,
     /* [previous][next][first][last][top][bottom][index][help] */
 358              unsigned int cmd, ioctl_arg arg)
 359 {
 360 
 361   dev = dev >> 4;
 362 
 363   if (((cmd >> 8) & 0xff) == 'C')
 364     {
 365       if (audio_devs[dev]->coproc)      /* Coprocessor ioctl */
 366         return audio_devs[dev]->coproc->ioctl (audio_devs[dev]->coproc->devc, cmd, arg, 0);
 367       else
 368         printk ("/dev/dsp%d: No coprocessor for this device\n", dev);
 369 
 370       return -ENXIO;
 371     }
 372   else
 373     switch (cmd)
 374       {
 375       case SNDCTL_DSP_SYNC:
 376         if (wr_buff_no[dev] >= 0)
 377           {
 378             DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
 379 
 380             wr_buff_no[dev] = -1;
 381           }
 382         return DMAbuf_ioctl (dev, cmd, arg, 0);
 383         break;
 384 
 385       case SNDCTL_DSP_POST:
 386         if (wr_buff_no[dev] >= 0)
 387           {
 388             DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
 389 
 390             wr_buff_no[dev] = -1;
 391           }
 392         return 0;
 393         break;
 394 
 395       case SNDCTL_DSP_RESET:
 396         wr_buff_no[dev] = -1;
 397         audio_mode[dev] = AM_NONE;
 398         return DMAbuf_ioctl (dev, cmd, arg, 0);
 399         break;
 400 
 401       case SNDCTL_DSP_GETFMTS:
 402         return snd_ioctl_return ((int *) arg, audio_devs[dev]->format_mask);
 403         break;
 404 
 405       case SNDCTL_DSP_SETFMT:
 406         return snd_ioctl_return ((int *) arg, set_format (dev, get_fs_long ((long *) arg)));
 407 
 408       case SNDCTL_DSP_GETISPACE:
 409         if ((audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
 410           return -EBUSY;
 411 
 412         {
 413           audio_buf_info  info;
 414 
 415           int             err = DMAbuf_ioctl (dev, cmd, (ioctl_arg) & info, 1);
 416 
 417           if (err < 0)
 418             return err;
 419 
 420           memcpy_tofs ((&((char *) arg)[0]), (char *) &info, sizeof (info));
 421           return 0;
 422         }
 423 
 424       case SNDCTL_DSP_GETOSPACE:
 425         if ((audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX))
 426           return -EBUSY;
 427 
 428         {
 429           audio_buf_info  info;
 430 
 431           int             err = DMAbuf_ioctl (dev, cmd, (ioctl_arg) & info, 1);
 432 
 433           if (err < 0)
 434             return err;
 435 
 436           if (wr_buff_no[dev] != -1)
 437             info.bytes += wr_buff_size[dev] - wr_buff_ptr[dev];
 438 
 439           memcpy_tofs ((&((char *) arg)[0]), (char *) &info, sizeof (info));
 440           return 0;
 441         }
 442 
 443       case SNDCTL_DSP_NONBLOCK:
 444         dev_nblock[dev] = 1;
 445         return 0;
 446         break;
 447 
 448       case SNDCTL_DSP_GETCAPS:
 449         {
 450           int             info = 1;     /* Revision level of this ioctl() */
 451 
 452           if (audio_devs[dev]->flags & DMA_DUPLEX)
 453             info |= DSP_CAP_DUPLEX;
 454 
 455           if (audio_devs[dev]->coproc)
 456             info |= DSP_CAP_COPROC;
 457 
 458           if (audio_devs[dev]->local_qlen)      /* Device has hidden buffers */
 459             info |= DSP_CAP_BATCH;
 460 
 461           if (audio_devs[dev]->trigger)         /* Supports SETTRIGGER */
 462             info |= DSP_CAP_TRIGGER;
 463 
 464           memcpy_tofs ((&((char *) arg)[0]), (char *) &info, sizeof (info));
 465           return 0;
 466         }
 467         break;
 468 
 469       default:
 470         return DMAbuf_ioctl (dev, cmd, arg, 0);
 471       }
 472 }
 473 
 474 long
 475 audio_init (long mem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
 476 {
 477   /*
 478      * NOTE! This routine could be called several times during boot.
 479    */
 480   return mem_start;
 481 }
 482 
 483 int
 484 audio_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 485 {
 486 
 487   dev = dev >> 4;
 488 
 489   switch (sel_type)
 490     {
 491     case SEL_IN:
 492       if (!(audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX))
 493         return 0;               /* Not recording */
 494 
 495 
 496       return DMAbuf_select (dev, file, sel_type, wait);
 497       break;
 498 
 499     case SEL_OUT:
 500       if (!(audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
 501         return 0;               /* Wrong direction */
 502 
 503       if (wr_buff_no[dev] != -1)
 504         return 1;               /* There is space in the current buffer */
 505 
 506       return DMAbuf_select (dev, file, sel_type, wait);
 507       break;
 508 
 509     case SEL_EX:
 510       return 0;
 511     }
 512 
 513   return 0;
 514 }
 515 
 516 
 517 #else /* EXCLUDE_AUDIO */
 518 /*
 519  * Stub versions
 520  */
 521 
 522 int
 523 audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 524 {
 525   return -EIO;
 526 }
 527 
 528 int
 529 audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 530 {
 531   return -EIO;
 532 }
 533 
 534 int
 535 audio_open (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 536 {
 537   return -ENXIO;
 538 }
 539 
 540 void
 541 audio_release (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 542 {
 543 };
 544 int
 545 audio_ioctl (int dev, struct fileinfo *file,
     /* [previous][next][first][last][top][bottom][index][help] */
 546              unsigned int cmd, unsigned int arg)
 547 {
 548   return -EIO;
 549 }
 550 
 551 int
 552 audio_lseek (int dev, struct fileinfo *file, off_t offset, int orig)
     /* [previous][next][first][last][top][bottom][index][help] */
 553 {
 554   return -EIO;
 555 }
 556 
 557 long
 558 audio_init (long mem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
 559 {
 560   return mem_start;
 561 }
 562 
 563 #endif
 564 
 565 #endif

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