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

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