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) (long) 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   sync_output (dev);
 149 
 150   if (audio_devs[dev]->coproc)
 151     audio_devs[dev]->coproc->close (audio_devs[dev]->coproc->devc, COPR_PCM);
 152   DMAbuf_release (dev, mode);
 153 }
 154 
 155 #if defined(NO_INLINE_ASM) || !defined(i386)
 156 static void
 157 translate_bytes (const unsigned char *table, unsigned char *buff, int n)
     /* [previous][next][first][last][top][bottom][index][help] */
 158 {
 159   unsigned long   i;
 160 
 161   if (n <= 0)
 162     return;
 163 
 164   for (i = 0; i < n; ++i)
 165     buff[i] = table[buff[i]];
 166 }
 167 
 168 #else
 169 extern inline void
 170 translate_bytes (const void *table, void *buff, int n)
     /* [previous][next][first][last][top][bottom][index][help] */
 171 {
 172   if (n > 0)
 173     {
 174       __asm__ ("cld\n"
 175                "1:\tlodsb\n\t"
 176                "xlatb\n\t"
 177                "stosb\n\t"
 178     "loop 1b\n\t":
 179     :      "b" ((long) table), "c" (n), "D" ((long) buff), "S" ((long) buff)
 180     :          "bx", "cx", "di", "si", "ax");
 181     }
 182 }
 183 
 184 #endif
 185 
 186 int
 187 audio_write (int dev, struct fileinfo *file, const char *buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 188 {
 189   int             c, p, l, buf_no, buf_ptr, buf_size;
 190   int             err;
 191   char           *dma_buf;
 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     }
 201 
 202   if (audio_devs[dev]->flags & DMA_DUPLEX)
 203     audio_mode[dev] |= AM_WRITE;
 204   else
 205     audio_mode[dev] = AM_WRITE;
 206 
 207   if (!count)                   /* Flush output */
 208     {
 209       sync_output (dev);
 210       return 0;
 211     }
 212 
 213   while (c)
 214     {
 215       if (DMAbuf_get_curr_buffer (dev, &buf_no, &dma_buf, &buf_ptr, &buf_size) < 0)
 216         {
 217           if ((buf_no = DMAbuf_getwrbuffer (dev, &dma_buf,
 218                                             &buf_size,
 219                                             dev_nblock[dev])) < 0)
 220             {
 221               /* Handle nonblocking mode */
 222               if (dev_nblock[dev] && buf_no == -EAGAIN)
 223                 return p;       /* No more space. Return # of accepted bytes */
 224               return buf_no;
 225             }
 226           buf_ptr = 0;
 227         }
 228 
 229       l = c;
 230       if (l > (buf_size - buf_ptr))
 231         l = (buf_size - buf_ptr);
 232 
 233       if (!audio_devs[dev]->copy_from_user)
 234         {                       /*
 235                                  * No device specific copy routine
 236                                  */
 237           memcpy_fromfs (&dma_buf[buf_ptr], &((buf)[p]), l);
 238         }
 239       else
 240         audio_devs[dev]->copy_from_user (dev,
 241                                          dma_buf, buf_ptr, buf, p, l);
 242 
 243       if (local_conversion[dev] == AFMT_MU_LAW)
 244         {
 245           /*
 246            * This just allows interrupts while the conversion is running
 247            */
 248           sti ();
 249           translate_bytes (ulaw_dsp, (unsigned char *) &dma_buf[buf_ptr], l);
 250         }
 251 
 252       c -= l;
 253       p += l;
 254       buf_ptr += l;
 255 
 256       if (buf_ptr >= buf_size)
 257         {
 258           if ((err = DMAbuf_start_output (dev, buf_no, buf_ptr)) < 0)
 259             {
 260               return err;
 261             }
 262 
 263         }
 264       else
 265         DMAbuf_set_count (dev, buf_no, buf_ptr);
 266 
 267     }
 268 
 269   return count;
 270 }
 271 
 272 int
 273 audio_read (int dev, struct fileinfo *file, char *buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 274 {
 275   int             c, p, l;
 276   char           *dmabuf;
 277   int             buf_no;
 278 
 279   dev = dev >> 4;
 280   p = 0;
 281   c = count;
 282 
 283   if ((audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
 284     {
 285       sync_output (dev);
 286     }
 287 
 288   if (audio_devs[dev]->flags & DMA_DUPLEX)
 289     audio_mode[dev] |= AM_READ;
 290   else
 291     audio_mode[dev] = AM_READ;
 292 
 293   while (c)
 294     {
 295       if ((buf_no = DMAbuf_getrdbuffer (dev, &dmabuf, &l,
 296                                         dev_nblock[dev])) < 0)
 297         {
 298           /* Nonblocking mode handling. Return current # of bytes */
 299 
 300           if (dev_nblock[dev] && buf_no == -EAGAIN)
 301             return p;
 302 
 303           return buf_no;
 304         }
 305 
 306       if (l > c)
 307         l = c;
 308 
 309       /*
 310        * Insert any local processing here.
 311        */
 312 
 313       if (local_conversion[dev] == AFMT_MU_LAW)
 314         {
 315           /*
 316            * This just allows interrupts while the conversion is running
 317            */
 318           sti ();
 319 
 320           translate_bytes (dsp_ulaw, (unsigned char *) dmabuf, l);
 321         }
 322 
 323       memcpy_tofs (&((buf)[p]), dmabuf, l);
 324 
 325       DMAbuf_rmchars (dev, buf_no, l);
 326 
 327       p += l;
 328       c -= l;
 329     }
 330 
 331   return count - c;
 332 }
 333 
 334 int
 335 audio_ioctl (int dev, struct fileinfo *file,
     /* [previous][next][first][last][top][bottom][index][help] */
 336              unsigned int cmd, caddr_t arg)
 337 {
 338 
 339   dev = dev >> 4;
 340 
 341   if (((cmd >> 8) & 0xff) == 'C')
 342     {
 343       if (audio_devs[dev]->coproc)      /* Coprocessor ioctl */
 344         return audio_devs[dev]->coproc->ioctl (audio_devs[dev]->coproc->devc, cmd, arg, 0);
 345       else
 346         printk ("/dev/dsp%d: No coprocessor for this device\n", dev);
 347 
 348       return -ENXIO;
 349     }
 350   else
 351     switch (cmd)
 352       {
 353       case SNDCTL_DSP_SYNC:
 354         sync_output (dev);
 355         return DMAbuf_ioctl (dev, cmd, arg, 0);
 356         break;
 357 
 358       case SNDCTL_DSP_POST:
 359         sync_output (dev);
 360         return 0;
 361         break;
 362 
 363       case SNDCTL_DSP_RESET:
 364         audio_mode[dev] = AM_NONE;
 365         return DMAbuf_ioctl (dev, cmd, arg, 0);
 366         break;
 367 
 368       case SNDCTL_DSP_GETFMTS:
 369         return snd_ioctl_return ((int *) arg, audio_devs[dev]->format_mask);
 370         break;
 371 
 372       case SNDCTL_DSP_SETFMT:
 373         return snd_ioctl_return ((int *) arg, set_format (dev, get_fs_long ((long *) arg)));
 374 
 375       case SNDCTL_DSP_GETISPACE:
 376         if ((audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
 377           return -EBUSY;
 378 
 379         {
 380           audio_buf_info  info;
 381 
 382           int             err = DMAbuf_ioctl (dev, cmd, (caddr_t) & info, 1);
 383 
 384           if (err < 0)
 385             return err;
 386 
 387           memcpy_tofs ((&((char *) arg)[0]), (char *) &info, sizeof (info));
 388           return 0;
 389         }
 390 
 391       case SNDCTL_DSP_GETOSPACE:
 392         if ((audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX))
 393           return -EBUSY;
 394 
 395         {
 396           audio_buf_info  info;
 397           char           *dma_buf;
 398           int             buf_no, buf_ptr, buf_size;
 399 
 400           int             err = DMAbuf_ioctl (dev, cmd, (caddr_t) & info, 1);
 401 
 402           if (err < 0)
 403             return err;
 404 
 405           if (DMAbuf_get_curr_buffer (dev, &buf_no, &dma_buf, &buf_ptr, &buf_size) >= 0)
 406             info.bytes += buf_size - buf_ptr;
 407 
 408           memcpy_tofs ((&((char *) arg)[0]), (char *) &info, sizeof (info));
 409           return 0;
 410         }
 411 
 412       case SNDCTL_DSP_NONBLOCK:
 413         dev_nblock[dev] = 1;
 414         return 0;
 415         break;
 416 
 417       case SNDCTL_DSP_GETCAPS:
 418         {
 419           int             info = 1;     /* Revision level of this ioctl() */
 420 
 421           if (audio_devs[dev]->flags & DMA_DUPLEX)
 422             info |= DSP_CAP_DUPLEX;
 423 
 424           if (audio_devs[dev]->coproc)
 425             info |= DSP_CAP_COPROC;
 426 
 427           if (audio_devs[dev]->local_qlen)      /* Device has hidden buffers */
 428             info |= DSP_CAP_BATCH;
 429 
 430           if (audio_devs[dev]->trigger)         /* Supports SETTRIGGER */
 431             info |= DSP_CAP_TRIGGER;
 432 
 433           memcpy_tofs ((&((char *) arg)[0]), (char *) &info, sizeof (info));
 434           return 0;
 435         }
 436         break;
 437 
 438       default:
 439         return DMAbuf_ioctl (dev, cmd, arg, 0);
 440       }
 441 }
 442 
 443 long
 444 audio_init (long mem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
 445 {
 446   /*
 447      * NOTE! This routine could be called several times during boot.
 448    */
 449   return mem_start;
 450 }
 451 
 452 int
 453 audio_select (int dev, struct fileinfo *file, int sel_type, select_table_handle * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 454 {
 455   char           *dma_buf;
 456   int             buf_no, buf_ptr, buf_size;
 457 
 458   dev = dev >> 4;
 459 
 460   switch (sel_type)
 461     {
 462     case SEL_IN:
 463       if (audio_mode[dev] & AM_WRITE && !(audio_devs[dev]->flags & DMA_DUPLEX))
 464         {
 465           return 0;             /* Not recording */
 466         }
 467 
 468       return DMAbuf_select (dev, file, sel_type, wait);
 469       break;
 470 
 471     case SEL_OUT:
 472       if (audio_mode[dev] & AM_READ && !(audio_devs[dev]->flags & DMA_DUPLEX))
 473         {
 474           return 0;             /* Wrong direction */
 475         }
 476 
 477       if (DMAbuf_get_curr_buffer (dev, &buf_no, &dma_buf, &buf_ptr, &buf_size) >= 0)
 478         {
 479           return 1;             /* There is space in the current buffer */
 480         }
 481 
 482       return DMAbuf_select (dev, file, sel_type, wait);
 483       break;
 484 
 485     case SEL_EX:
 486       return 0;
 487     }
 488 
 489   return 0;
 490 }
 491 
 492 
 493 #endif

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