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, 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, bits, 1) != bits)
 117     {
 118       audio_release (dev, file);
 119       return RET_ERROR (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 #ifdef NO_INLINE_ASM
 158 static void
 159 translate_bytes (const unsigned char *table, unsigned char *buff, unsigned long n)
     /* [previous][next][first][last][top][bottom][index][help] */
 160 {
 161   unsigned long   i;
 162 
 163   for (i = 0; i < n; ++i)
 164     buff[i] = table[buff[i]];
 165 }
 166 
 167 #else
 168 extern inline void
 169 translate_bytes (const void *table, void *buff, unsigned long n)
     /* [previous][next][first][last][top][bottom][index][help] */
 170 {
 171   __asm__ ("cld\n"
 172            "1:\tlodsb\n\t"
 173            "xlatb\n\t"
 174            "stosb\n\t"
 175 "loop 1b\n\t":
 176 :          "b" ((long) table), "c" (n), "D" ((long) buff), "S" ((long) buff)
 177 :          "bx", "cx", "di", "si", "ax");
 178 }
 179 
 180 #endif
 181 
 182 int
 183 audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 184 {
 185   int             c, p, l;
 186   int             err;
 187 
 188   dev = dev >> 4;
 189 
 190   p = 0;
 191   c = count;
 192 
 193   if (audio_mode[dev] == AM_READ)       /*
 194                                          * Direction changed
 195                                          */
 196     {
 197       wr_buff_no[dev] = -1;
 198     }
 199 
 200   audio_mode[dev] = AM_WRITE;
 201 
 202   if (!count)                   /*
 203                                  * Flush output
 204                                  */
 205     {
 206       if (wr_buff_no[dev] >= 0)
 207         {
 208           DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
 209 
 210           wr_buff_no[dev] = -1;
 211         }
 212       return 0;
 213     }
 214 
 215   while (c)
 216     {                           /*
 217                                  * Perform output blocking
 218                                  */
 219       if (wr_buff_no[dev] < 0)  /*
 220                                  * There is no incomplete buffers
 221                                  */
 222         {
 223           if ((wr_buff_no[dev] = DMAbuf_getwrbuffer (dev, &wr_dma_buf[dev],
 224                                                      &wr_buff_size[dev],
 225                                                      dev_nblock[dev])) < 0)
 226             {
 227               /* Handle nonblocking mode */
 228               if (dev_nblock[dev] && wr_buff_no[dev] == RET_ERROR (EAGAIN))
 229                 return p;       /* No more space. Return # of accepted bytes */
 230               return wr_buff_no[dev];
 231             }
 232           wr_buff_ptr[dev] = 0;
 233         }
 234 
 235       l = c;
 236       if (l > (wr_buff_size[dev] - wr_buff_ptr[dev]))
 237         l = (wr_buff_size[dev] - wr_buff_ptr[dev]);
 238 
 239       if (!audio_devs[dev]->copy_from_user)
 240         {                       /*
 241                                  * No device specific copy routine
 242                                  */
 243           COPY_FROM_USER (&wr_dma_buf[dev][wr_buff_ptr[dev]], buf, p, l);
 244         }
 245       else
 246         audio_devs[dev]->copy_from_user (dev,
 247                               wr_dma_buf[dev], wr_buff_ptr[dev], buf, p, l);
 248 
 249 
 250       /*
 251        * Insert local processing here
 252        */
 253 
 254       if (local_conversion[dev] == AFMT_MU_LAW)
 255         {
 256 #ifdef linux
 257           /*
 258            * This just allows interrupts while the conversion is running
 259            */
 260           __asm__ ("sti");
 261 #endif
 262           translate_bytes (ulaw_dsp, (unsigned char *) &wr_dma_buf[dev][wr_buff_ptr[dev]], l);
 263         }
 264 
 265       c -= l;
 266       p += l;
 267       wr_buff_ptr[dev] += l;
 268 
 269       if (wr_buff_ptr[dev] >= wr_buff_size[dev])
 270         {
 271           if ((err = DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev])) < 0)
 272             {
 273               return err;
 274             }
 275 
 276           wr_buff_no[dev] = -1;
 277         }
 278 
 279     }
 280 
 281   return count;
 282 }
 283 
 284 int
 285 audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 286 {
 287   int             c, p, l;
 288   char           *dmabuf;
 289   int             buff_no;
 290 
 291   dev = dev >> 4;
 292   p = 0;
 293   c = count;
 294 
 295   if (audio_mode[dev] == AM_WRITE)
 296     {
 297       if (wr_buff_no[dev] >= 0)
 298         {
 299           DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
 300 
 301           wr_buff_no[dev] = -1;
 302         }
 303     }
 304 
 305   audio_mode[dev] = AM_READ;
 306 
 307   while (c)
 308     {
 309       if ((buff_no = DMAbuf_getrdbuffer (dev, &dmabuf, &l,
 310                                          dev_nblock[dev])) < 0)
 311         {
 312           /* Nonblocking mode handling. Return current # of bytes */
 313 
 314           if (dev_nblock[dev] && buff_no == RET_ERROR (EAGAIN))
 315             return p;
 316 
 317           return buff_no;
 318         }
 319 
 320       if (l > c)
 321         l = c;
 322 
 323       /*
 324        * Insert any local processing here.
 325        */
 326 
 327       if (local_conversion[dev] == AFMT_MU_LAW)
 328         {
 329 #ifdef linux
 330           /*
 331            * This just allows interrupts while the conversion is running
 332            */
 333           __asm__ ("sti");
 334 #endif
 335 
 336           translate_bytes (dsp_ulaw, (unsigned char *) dmabuf, l);
 337         }
 338 
 339       COPY_TO_USER (buf, p, dmabuf, l);
 340 
 341       DMAbuf_rmchars (dev, buff_no, l);
 342 
 343       p += l;
 344       c -= l;
 345     }
 346 
 347   return count - c;
 348 }
 349 
 350 int
 351 audio_ioctl (int dev, struct fileinfo *file,
     /* [previous][next][first][last][top][bottom][index][help] */
 352              unsigned int cmd, unsigned int arg)
 353 {
 354 
 355   dev = dev >> 4;
 356 
 357   if (((cmd >> 8) & 0xff) == 'C')
 358     {
 359       if (audio_devs[dev]->coproc)      /* Coprocessor ioctl */
 360         return audio_devs[dev]->coproc->ioctl (audio_devs[dev]->coproc->devc, cmd, arg, 0);
 361       else
 362         printk ("/dev/dsp%d: No coprocessor for this device\n", dev);
 363 
 364       return RET_ERROR (EREMOTEIO);
 365     }
 366   else
 367     switch (cmd)
 368       {
 369       case SNDCTL_DSP_SYNC:
 370         if (wr_buff_no[dev] >= 0)
 371           {
 372             DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
 373 
 374             wr_buff_no[dev] = -1;
 375           }
 376         return DMAbuf_ioctl (dev, cmd, arg, 0);
 377         break;
 378 
 379       case SNDCTL_DSP_POST:
 380         if (wr_buff_no[dev] >= 0)
 381           {
 382             DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
 383 
 384             wr_buff_no[dev] = -1;
 385           }
 386         return 0;
 387         break;
 388 
 389       case SNDCTL_DSP_RESET:
 390         wr_buff_no[dev] = -1;
 391         return DMAbuf_ioctl (dev, cmd, arg, 0);
 392         break;
 393 
 394       case SNDCTL_DSP_GETFMTS:
 395         return IOCTL_OUT (arg, audio_devs[dev]->format_mask);
 396         break;
 397 
 398       case SNDCTL_DSP_SETFMT:
 399         return IOCTL_OUT (arg, set_format (dev, IOCTL_IN (arg)));
 400 
 401       case SNDCTL_DSP_GETISPACE:
 402         if (audio_mode[dev] == AM_WRITE)
 403           return RET_ERROR (EBUSY);
 404 
 405         {
 406           audio_buf_info  info;
 407 
 408           int             err = DMAbuf_ioctl (dev, cmd, (unsigned long) &info, 1);
 409 
 410           if (err < 0)
 411             return err;
 412 
 413           if (wr_buff_no[dev] != -1)
 414             info.bytes += wr_buff_ptr[dev];
 415 
 416           IOCTL_TO_USER ((char *) arg, 0, (char *) &info, sizeof (info));
 417           return 0;
 418         }
 419 
 420       case SNDCTL_DSP_GETOSPACE:
 421         if (audio_mode[dev] == AM_READ)
 422           return RET_ERROR (EBUSY);
 423 
 424         {
 425           audio_buf_info  info;
 426 
 427           int             err = DMAbuf_ioctl (dev, cmd, (unsigned long) &info, 1);
 428 
 429           if (err < 0)
 430             return err;
 431 
 432           if (wr_buff_no[dev] != -1)
 433             info.bytes += wr_buff_size[dev] - wr_buff_ptr[dev];
 434 
 435           IOCTL_TO_USER ((char *) arg, 0, (char *) &info, sizeof (info));
 436           return 0;
 437         }
 438 
 439       case SNDCTL_DSP_NONBLOCK:
 440         dev_nblock[dev] = 1;
 441         return 0;
 442         break;
 443 
 444       default:
 445         return DMAbuf_ioctl (dev, cmd, arg, 0);
 446       }
 447 }
 448 
 449 long
 450 audio_init (long mem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
 451 {
 452   /*
 453      * NOTE! This routine could be called several times during boot.
 454    */
 455   return mem_start;
 456 }
 457 
 458 #ifdef ALLOW_SELECT
 459 int
 460 audio_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 461 {
 462   int             l;
 463   char           *dmabuf;
 464 
 465   dev = dev >> 4;
 466 
 467   switch (sel_type)
 468     {
 469     case SEL_IN:
 470       if (audio_mode[dev] != AM_READ)   /* Wrong direction */
 471         return 0;
 472 
 473       if (DMAbuf_getrdbuffer (dev, &dmabuf, &l,
 474                               1 /* Don't block */ ) >= 0)
 475         return 1;               /* We have data */
 476 
 477       return DMAbuf_select (dev, file, sel_type, wait);
 478       break;
 479 
 480     case SEL_OUT:
 481       if (audio_mode[dev] != AM_WRITE)  /* Wrong direction */
 482         return 0;
 483 
 484       if (wr_buff_no[dev] != -1)
 485         return 1;               /* There is space in the current buffer */
 486 
 487       return DMAbuf_select (dev, file, sel_type, wait);
 488       break;
 489 
 490     case SEL_EX:
 491       return 0;
 492     }
 493 
 494   return 0;
 495 }
 496 
 497 #endif /* ALLOW_SELECT */
 498 
 499 #else /* EXCLUDE_AUDIO */
 500 /*
 501  * Stub versions
 502  */
 503 
 504 int
 505 audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 506 {
 507   return RET_ERROR (EIO);
 508 }
 509 
 510 int
 511 audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 512 {
 513   return RET_ERROR (EIO);
 514 }
 515 
 516 int
 517 audio_open (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 518 {
 519   return RET_ERROR (ENXIO);
 520 }
 521 
 522 void
 523 audio_release (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 524 {
 525 };
 526 int
 527 audio_ioctl (int dev, struct fileinfo *file,
     /* [previous][next][first][last][top][bottom][index][help] */
 528              unsigned int cmd, unsigned int arg)
 529 {
 530   return RET_ERROR (EIO);
 531 }
 532 
 533 int
 534 audio_lseek (int dev, struct fileinfo *file, off_t offset, int orig)
     /* [previous][next][first][last][top][bottom][index][help] */
 535 {
 536   return RET_ERROR (EIO);
 537 }
 538 
 539 long
 540 audio_init (long mem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
 541 {
 542   return mem_start;
 543 }
 544 
 545 #endif
 546 
 547 #endif

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