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. sync_output
  4. audio_release
  5. translate_bytes
  6. translate_bytes
  7. audio_write
  8. audio_read
  9. audio_ioctl
  10. audio_init
  11. audio_select

   1 /*
   2  * sound/audio.c
   3  *
   4  * Device file manager for /dev/audio
   5  */
   6 
   7 /*
   8  * Copyright by Hannu Savolainen 1993-1996
   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 #include <linux/config.h>
  31 
  32 
  33 #include "sound_config.h"
  34 
  35 #ifdef CONFIG_AUDIO
  36 
  37 #include "ulaw.h"
  38 #include "coproc.h"
  39 
  40 #define ON              1
  41 #define OFF             0
  42 
  43 static int      audio_mode[MAX_AUDIO_DEV];
  44 static int      dev_nblock[MAX_AUDIO_DEV];      /* 1 if in noblocking mode */
  45 
  46 #define         AM_NONE         0
  47 #define         AM_WRITE        1
  48 #define         AM_READ         2
  49 
  50 static int      audio_format[MAX_AUDIO_DEV];
  51 static int      local_conversion[MAX_AUDIO_DEV];
  52 
  53 static int
  54 set_format (int dev, long fmt)
     /* [previous][next][first][last][top][bottom][index][help] */
  55 {
  56   if (fmt != AFMT_QUERY)
  57     {
  58 
  59       local_conversion[dev] = 0;
  60 
  61       if (!(audio_devs[dev]->format_mask & fmt))        /* Not supported */
  62         if (fmt == AFMT_MU_LAW)
  63           {
  64             fmt = AFMT_U8;
  65             local_conversion[dev] = AFMT_MU_LAW;
  66           }
  67         else
  68           fmt = AFMT_U8;        /* This is always supported */
  69 
  70       audio_format[dev] = DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, (caddr_t) fmt, 1);
  71     }
  72 
  73   if (local_conversion[dev])    /* This shadows the HW format */
  74     return local_conversion[dev];
  75 
  76   return audio_format[dev];
  77 }
  78 
  79 int
  80 audio_open (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
  81 {
  82   int             ret;
  83   long            bits;
  84   int             dev_type = dev & 0x0f;
  85   int             mode = file->mode & O_ACCMODE;
  86 
  87   dev = dev >> 4;
  88 
  89   if (dev_type == SND_DEV_DSP16)
  90     bits = 16;
  91   else
  92     bits = 8;
  93 
  94   if ((ret = DMAbuf_open (dev, mode)) < 0)
  95     return ret;
  96 
  97   if (audio_devs[dev]->coproc)
  98     if ((ret = audio_devs[dev]->coproc->
  99          open (audio_devs[dev]->coproc->devc, COPR_PCM)) < 0)
 100       {
 101         audio_release (dev, file);
 102         printk ("Sound: Can't access coprocessor device\n");
 103 
 104         return ret;
 105       }
 106 
 107   local_conversion[dev] = 0;
 108 
 109   if (DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, (caddr_t) bits, 1) != bits)
 110     {
 111       audio_release (dev, file);
 112       return -ENXIO;
 113     }
 114 
 115   if (dev_type == SND_DEV_AUDIO)
 116     {
 117       set_format (dev, AFMT_MU_LAW);
 118     }
 119   else
 120     set_format (dev, bits);
 121 
 122   audio_mode[dev] = AM_NONE;
 123   dev_nblock[dev] = 0;
 124 
 125   return ret;
 126 }
 127 
 128 void
 129 sync_output (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 130 {
 131   int             buf_no, buf_ptr, buf_size;
 132   char           *dma_buf;
 133 
 134   if (DMAbuf_get_curr_buffer (dev, &buf_no, &dma_buf, &buf_ptr, &buf_size) >= 0)
 135     {
 136       DMAbuf_start_output (dev, buf_no, buf_ptr);
 137     }
 138 }
 139 
 140 void
 141 audio_release (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 142 {
 143   int             mode;
 144 
 145   dev = dev >> 4;
 146   mode = file->mode & O_ACCMODE;
 147 
 148   audio_devs[dev]->dmap_out->closing = 1;
 149   audio_devs[dev]->dmap_in->closing = 1;
 150 
 151   sync_output (dev);
 152 
 153   if (audio_devs[dev]->coproc)
 154     audio_devs[dev]->coproc->close (audio_devs[dev]->coproc->devc, COPR_PCM);
 155   DMAbuf_release (dev, mode);
 156 }
 157 
 158 #if defined(NO_INLINE_ASM) || !defined(i386)
 159 static void
 160 translate_bytes (const unsigned char *table, unsigned char *buff, int n)
     /* [previous][next][first][last][top][bottom][index][help] */
 161 {
 162   unsigned long   i;
 163 
 164   if (n <= 0)
 165     return;
 166 
 167   for (i = 0; i < n; ++i)
 168     buff[i] = table[buff[i]];
 169 }
 170 
 171 #else
 172 extern inline void
 173 translate_bytes (const void *table, void *buff, int n)
     /* [previous][next][first][last][top][bottom][index][help] */
 174 {
 175   if (n > 0)
 176     {
 177       __asm__ ("cld\n"
 178                "1:\tlodsb\n\t"
 179                "xlatb\n\t"
 180                "stosb\n\t"
 181     "loop 1b\n\t":
 182     :      "b" ((long) table), "c" (n), "D" ((long) buff), "S" ((long) buff)
 183     :          "bx", "cx", "di", "si", "ax");
 184     }
 185 }
 186 
 187 #endif
 188 
 189 int
 190 audio_write (int dev, struct fileinfo *file, const char *buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 191 {
 192   int             c, p, l, buf_no, buf_ptr, buf_size;
 193   int             err;
 194   char           *dma_buf;
 195 
 196   dev = dev >> 4;
 197 
 198   p = 0;
 199   c = count;
 200 
 201   if ((audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX))
 202     {                           /* Direction change */
 203     }
 204 
 205   if (audio_devs[dev]->flags & DMA_DUPLEX)
 206     audio_mode[dev] |= AM_WRITE;
 207   else
 208     audio_mode[dev] = AM_WRITE;
 209 
 210   if (!count)                   /* Flush output */
 211     {
 212       sync_output (dev);
 213       return 0;
 214     }
 215 
 216   while (c)
 217     {
 218       if (DMAbuf_get_curr_buffer (dev, &buf_no, &dma_buf, &buf_ptr, &buf_size) < 0)
 219         {
 220           if ((buf_no = DMAbuf_getwrbuffer (dev, &dma_buf,
 221                                             &buf_size,
 222                                             dev_nblock[dev])) < 0)
 223             {
 224               /* Handle nonblocking mode */
 225               if (dev_nblock[dev] && buf_no == -EAGAIN)
 226                 return p;       /* No more space. Return # of accepted bytes */
 227               return buf_no;
 228             }
 229           buf_ptr = 0;
 230         }
 231 
 232       l = c;
 233       if (l > (buf_size - buf_ptr))
 234         l = (buf_size - buf_ptr);
 235 
 236       if (!audio_devs[dev]->copy_from_user)
 237         {                       /*
 238                                  * No device specific copy routine
 239                                  */
 240           memcpy_fromfs (&dma_buf[buf_ptr], &((buf)[p]), l);
 241         }
 242       else
 243         audio_devs[dev]->copy_from_user (dev,
 244                                          dma_buf, buf_ptr, buf, p, l);
 245 
 246       if (local_conversion[dev] == AFMT_MU_LAW)
 247         {
 248           /*
 249            * This just allows interrupts while the conversion is running
 250            */
 251           sti ();
 252           translate_bytes (ulaw_dsp, (unsigned char *) &dma_buf[buf_ptr], l);
 253         }
 254 
 255       c -= l;
 256       p += l;
 257       buf_ptr += l;
 258 
 259       if (buf_ptr >= buf_size)
 260         {
 261           if ((err = DMAbuf_start_output (dev, buf_no, buf_ptr)) < 0)
 262             {
 263               return err;
 264             }
 265 
 266         }
 267       else
 268         DMAbuf_set_count (dev, buf_no, buf_ptr);
 269 
 270     }
 271 
 272   return count;
 273 }
 274 
 275 int
 276 audio_read (int dev, struct fileinfo *file, char *buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 277 {
 278   int             c, p, l;
 279   char           *dmabuf;
 280   int             buf_no;
 281 
 282   dev = dev >> 4;
 283   p = 0;
 284   c = count;
 285 
 286   if ((audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
 287     {
 288       sync_output (dev);
 289     }
 290 
 291   if (audio_devs[dev]->flags & DMA_DUPLEX)
 292     audio_mode[dev] |= AM_READ;
 293   else
 294     audio_mode[dev] = AM_READ;
 295 
 296   while (c)
 297     {
 298       if ((buf_no = DMAbuf_getrdbuffer (dev, &dmabuf, &l,
 299                                         dev_nblock[dev])) < 0)
 300         {
 301           /* Nonblocking mode handling. Return current # of bytes */
 302 
 303           if (dev_nblock[dev] && buf_no == -EAGAIN)
 304             return p;
 305 
 306           return buf_no;
 307         }
 308 
 309       if (l > c)
 310         l = c;
 311 
 312       /*
 313        * Insert any local processing here.
 314        */
 315 
 316       if (local_conversion[dev] == AFMT_MU_LAW)
 317         {
 318           /*
 319            * This just allows interrupts while the conversion is running
 320            */
 321           sti ();
 322 
 323           translate_bytes (dsp_ulaw, (unsigned char *) dmabuf, l);
 324         }
 325 
 326       memcpy_tofs (&((buf)[p]), dmabuf, l);
 327 
 328       DMAbuf_rmchars (dev, buf_no, l);
 329 
 330       p += l;
 331       c -= l;
 332     }
 333 
 334   return count - c;
 335 }
 336 
 337 int
 338 audio_ioctl (int dev, struct fileinfo *file,
     /* [previous][next][first][last][top][bottom][index][help] */
 339              unsigned int cmd, caddr_t arg)
 340 {
 341 
 342   dev = dev >> 4;
 343 
 344   if (((cmd >> 8) & 0xff) == 'C')
 345     {
 346       if (audio_devs[dev]->coproc)      /* Coprocessor ioctl */
 347         return audio_devs[dev]->coproc->ioctl (audio_devs[dev]->coproc->devc, cmd, arg, 0);
 348       else
 349         printk ("/dev/dsp%d: No coprocessor for this device\n", dev);
 350 
 351       return -ENXIO;
 352     }
 353   else
 354     switch (cmd)
 355       {
 356       case SNDCTL_DSP_SYNC:
 357         sync_output (dev);
 358         return DMAbuf_ioctl (dev, cmd, arg, 0);
 359         break;
 360 
 361       case SNDCTL_DSP_POST:
 362         sync_output (dev);
 363         return 0;
 364         break;
 365 
 366       case SNDCTL_DSP_RESET:
 367         audio_mode[dev] = AM_NONE;
 368         return DMAbuf_ioctl (dev, cmd, arg, 0);
 369         break;
 370 
 371       case SNDCTL_DSP_GETFMTS:
 372         return snd_ioctl_return ((int *) arg, audio_devs[dev]->format_mask | AFMT_MU_LAW);
 373         break;
 374 
 375       case SNDCTL_DSP_SETFMT:
 376         return snd_ioctl_return ((int *) arg, set_format (dev, get_fs_long ((long *) arg)));
 377 
 378       case SNDCTL_DSP_GETISPACE:
 379         if ((audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
 380           return -EBUSY;
 381 
 382         {
 383           audio_buf_info  info;
 384 
 385           int             err = DMAbuf_ioctl (dev, cmd, (caddr_t) & info, 1);
 386 
 387           if (err < 0)
 388             return err;
 389 
 390           memcpy_tofs ((&((char *) arg)[0]), (char *) &info, sizeof (info));
 391           return 0;
 392         }
 393 
 394       case SNDCTL_DSP_GETOSPACE:
 395         if ((audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX))
 396           return -EBUSY;
 397 
 398         {
 399           audio_buf_info  info;
 400           char           *dma_buf;
 401           int             buf_no, buf_ptr, buf_size;
 402 
 403           int             err = DMAbuf_ioctl (dev, cmd, (caddr_t) & info, 1);
 404 
 405           if (err < 0)
 406             return err;
 407 
 408           if (DMAbuf_get_curr_buffer (dev, &buf_no, &dma_buf, &buf_ptr, &buf_size) >= 0)
 409             info.bytes += buf_size - buf_ptr;
 410 
 411           memcpy_tofs ((&((char *) arg)[0]), (char *) &info, sizeof (info));
 412           return 0;
 413         }
 414 
 415       case SNDCTL_DSP_NONBLOCK:
 416         dev_nblock[dev] = 1;
 417         return 0;
 418         break;
 419 
 420       case SNDCTL_DSP_GETCAPS:
 421         {
 422           int             info = 1;     /* Revision level of this ioctl() */
 423 
 424           if (audio_devs[dev]->flags & DMA_DUPLEX)
 425             info |= DSP_CAP_DUPLEX;
 426 
 427           if (audio_devs[dev]->coproc)
 428             info |= DSP_CAP_COPROC;
 429 
 430           if (audio_devs[dev]->local_qlen)      /* Device has hidden buffers */
 431             info |= DSP_CAP_BATCH;
 432 
 433           if (audio_devs[dev]->trigger)         /* Supports SETTRIGGER */
 434             info |= DSP_CAP_TRIGGER;
 435 
 436           info |= DSP_CAP_MMAP;
 437 
 438           memcpy_tofs ((&((char *) arg)[0]), (char *) &info, sizeof (info));
 439           return 0;
 440         }
 441         break;
 442 
 443       default:
 444         return DMAbuf_ioctl (dev, cmd, arg, 0);
 445       }
 446 }
 447 
 448 long
 449 audio_init (long mem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
 450 {
 451   /*
 452      * NOTE! This routine could be called several times during boot.
 453    */
 454   return mem_start;
 455 }
 456 
 457 int
 458 audio_select (int dev, struct fileinfo *file, int sel_type, select_table_handle * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 459 {
 460   char           *dma_buf;
 461   int             buf_no, buf_ptr, buf_size;
 462 
 463   dev = dev >> 4;
 464 
 465   switch (sel_type)
 466     {
 467     case SEL_IN:
 468       if (audio_mode[dev] & AM_WRITE && !(audio_devs[dev]->flags & DMA_DUPLEX))
 469         {
 470           return 0;             /* Not recording */
 471         }
 472 
 473       return DMAbuf_select (dev, file, sel_type, wait);
 474       break;
 475 
 476     case SEL_OUT:
 477       if (audio_mode[dev] & AM_READ && !(audio_devs[dev]->flags & DMA_DUPLEX))
 478         {
 479           return 0;             /* Wrong direction */
 480         }
 481 
 482       if (DMAbuf_get_curr_buffer (dev, &buf_no, &dma_buf, &buf_ptr, &buf_size) >= 0)
 483         {
 484           return 1;             /* There is space in the current buffer */
 485         }
 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 
 498 #endif

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