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_read
  11. audio_write
  12. audio_open
  13. audio_release
  14. audio_ioctl
  15. audio_lseek
  16. 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 
  37 #define ON              1
  38 #define OFF             0
  39 
  40 static int      wr_buff_no[MAX_AUDIO_DEV];      /*
  41                                                  * != -1, if there is
  42                                                  * a incomplete output
  43                                                  * block in the queue.
  44                                                  */
  45 static int      wr_buff_size[MAX_AUDIO_DEV], wr_buff_ptr[MAX_AUDIO_DEV];
  46 
  47 static int      audio_mode[MAX_AUDIO_DEV];
  48 
  49 #define         AM_NONE         0
  50 #define         AM_WRITE        1
  51 #define         AM_READ         2
  52 
  53 static char    *wr_dma_buf[MAX_AUDIO_DEV];
  54 static int      audio_format[MAX_AUDIO_DEV];
  55 static int      local_conversion[MAX_AUDIO_DEV];
  56 
  57 static int
  58 set_format (int dev, int fmt)
     /* [previous][next][first][last][top][bottom][index][help] */
  59 {
  60   if (fmt != AFMT_QUERY)
  61     {
  62 
  63       local_conversion[dev] = 0;
  64 
  65       if (!(audio_devs[dev]->format_mask & fmt))        /* Not supported */
  66         if (fmt == AFMT_MU_LAW)
  67           {
  68             fmt = AFMT_U8;
  69             local_conversion[dev] = AFMT_MU_LAW;
  70           }
  71         else
  72           fmt = AFMT_U8;        /* This is always supported */
  73 
  74       audio_format[dev] = DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, fmt, 1);
  75     }
  76 
  77   if (local_conversion[dev])    /* This shadows the HW format */
  78     return local_conversion[dev];
  79 
  80   return audio_format[dev];
  81 }
  82 
  83 int
  84 audio_open (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
  85 {
  86   int             ret;
  87   int             bits;
  88   int             dev_type = dev & 0x0f;
  89   int             mode = file->mode & O_ACCMODE;
  90 
  91   dev = dev >> 4;
  92 
  93   if (dev_type == SND_DEV_DSP16)
  94     bits = 16;
  95   else
  96     bits = 8;
  97 
  98   if ((ret = DMAbuf_open (dev, mode)) < 0)
  99     return ret;
 100 
 101   local_conversion[dev] = 0;
 102 
 103   if (DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, bits, 1) != bits)
 104     {
 105       audio_release (dev, file);
 106       return RET_ERROR (ENXIO);
 107     }
 108 
 109   if (dev_type == SND_DEV_AUDIO)
 110     {
 111       set_format (dev, AFMT_MU_LAW);
 112     }
 113   else
 114     set_format (dev, bits);
 115 
 116   wr_buff_no[dev] = -1;
 117   audio_mode[dev] = AM_NONE;
 118 
 119   return ret;
 120 }
 121 
 122 void
 123 audio_release (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 124 {
 125   int             mode;
 126 
 127   dev = dev >> 4;
 128   mode = file->mode & O_ACCMODE;
 129 
 130   if (wr_buff_no[dev] >= 0)
 131     {
 132       DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
 133 
 134       wr_buff_no[dev] = -1;
 135     }
 136 
 137   DMAbuf_release (dev, mode);
 138 }
 139 
 140 #ifdef NO_INLINE_ASM
 141 static void
 142 translate_bytes (const unsigned char *table, unsigned char *buff, unsigned long n)
     /* [previous][next][first][last][top][bottom][index][help] */
 143 {
 144   unsigned long   i;
 145 
 146   for (i = 0; i < n; ++i)
 147     buff[i] = table[buff[i]];
 148 }
 149 
 150 #else
 151 extern inline void
 152 translate_bytes (const void *table, void *buff, unsigned long n)
     /* [previous][next][first][last][top][bottom][index][help] */
 153 {
 154   __asm__ ("cld\n"
 155            "1:\tlodsb\n\t"
 156            "xlatb\n\t"
 157            "stosb\n\t"
 158            "loop 1b\n\t":
 159            :"b" ((long) table), "c" (n), "D" ((long) buff), "S" ((long) buff)
 160            :"bx", "cx", "di", "si", "ax");
 161 }
 162 
 163 #endif
 164 
 165 int
 166 audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 167 {
 168   int             c, p, l;
 169   int             err;
 170 
 171   dev = dev >> 4;
 172 
 173   p = 0;
 174   c = count;
 175 
 176   if (audio_mode[dev] == AM_READ)       /*
 177                                          * Direction changed
 178                                          */
 179     {
 180       wr_buff_no[dev] = -1;
 181     }
 182 
 183   audio_mode[dev] = AM_WRITE;
 184 
 185   if (!count)                   /*
 186                                  * Flush output
 187                                  */
 188     {
 189       if (wr_buff_no[dev] >= 0)
 190         {
 191           DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
 192 
 193           wr_buff_no[dev] = -1;
 194         }
 195       return 0;
 196     }
 197 
 198   while (c)
 199     {                           /*
 200                                  * Perform output blocking
 201                                  */
 202       if (wr_buff_no[dev] < 0)  /*
 203                                  * There is no incomplete buffers
 204                                  */
 205         {
 206           if ((wr_buff_no[dev] = DMAbuf_getwrbuffer (dev, &wr_dma_buf[dev], &wr_buff_size[dev])) < 0)
 207             {
 208               return wr_buff_no[dev];
 209             }
 210           wr_buff_ptr[dev] = 0;
 211         }
 212 
 213       l = c;
 214       if (l > (wr_buff_size[dev] - wr_buff_ptr[dev]))
 215         l = (wr_buff_size[dev] - wr_buff_ptr[dev]);
 216 
 217       if (!audio_devs[dev]->copy_from_user)
 218         {                       /*
 219                                  * No device specific copy routine
 220                                  */
 221           COPY_FROM_USER (&wr_dma_buf[dev][wr_buff_ptr[dev]], buf, p, l);
 222         }
 223       else
 224         audio_devs[dev]->copy_from_user (dev,
 225                               wr_dma_buf[dev], wr_buff_ptr[dev], buf, p, l);
 226 
 227 
 228       /*
 229        * Insert local processing here
 230        */
 231 
 232       if (local_conversion[dev] == AFMT_MU_LAW)
 233         {
 234 #ifdef linux
 235           /*
 236            * This just allows interrupts while the conversion is running
 237            */
 238           __asm__ ("sti");
 239 #endif
 240           translate_bytes (ulaw_dsp, (unsigned char *) &wr_dma_buf[dev][wr_buff_ptr[dev]], l);
 241         }
 242 
 243       c -= l;
 244       p += l;
 245       wr_buff_ptr[dev] += l;
 246 
 247       if (wr_buff_ptr[dev] >= wr_buff_size[dev])
 248         {
 249           if ((err = DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev])) < 0)
 250             {
 251               return err;
 252             }
 253 
 254           wr_buff_no[dev] = -1;
 255         }
 256 
 257     }
 258 
 259   return count;
 260 }
 261 
 262 int
 263 audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 264 {
 265   int             c, p, l;
 266   char           *dmabuf;
 267   int             buff_no;
 268 
 269   dev = dev >> 4;
 270   p = 0;
 271   c = count;
 272 
 273   if (audio_mode[dev] == AM_WRITE)
 274     {
 275       if (wr_buff_no[dev] >= 0)
 276         {
 277           DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
 278 
 279           wr_buff_no[dev] = -1;
 280         }
 281     }
 282 
 283   audio_mode[dev] = AM_READ;
 284 
 285   while (c)
 286     {
 287       if ((buff_no = DMAbuf_getrdbuffer (dev, &dmabuf, &l)) < 0)
 288         return buff_no;
 289 
 290       if (l > c)
 291         l = c;
 292 
 293       /*
 294        * Insert any local processing here.
 295        */
 296 
 297       if (local_conversion[dev] == AFMT_MU_LAW)
 298         {
 299 #ifdef linux
 300           /*
 301            * This just allows interrupts while the conversion is running
 302            */
 303           __asm__ ("sti");
 304 #endif
 305 
 306           translate_bytes (dsp_ulaw, (unsigned char *) dmabuf, l);
 307         }
 308 
 309       COPY_TO_USER (buf, p, dmabuf, l);
 310 
 311       DMAbuf_rmchars (dev, buff_no, l);
 312 
 313       p += l;
 314       c -= l;
 315     }
 316 
 317   return count - c;
 318 }
 319 
 320 int
 321 audio_ioctl (int dev, struct fileinfo *file,
     /* [previous][next][first][last][top][bottom][index][help] */
 322              unsigned int cmd, unsigned int arg)
 323 {
 324 
 325   dev = dev >> 4;
 326 
 327   switch (cmd)
 328     {
 329     case SNDCTL_DSP_SYNC:
 330       if (wr_buff_no[dev] >= 0)
 331         {
 332           DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
 333 
 334           wr_buff_no[dev] = -1;
 335         }
 336       return DMAbuf_ioctl (dev, cmd, arg, 0);
 337       break;
 338 
 339     case SNDCTL_DSP_POST:
 340       if (wr_buff_no[dev] >= 0)
 341         {
 342           DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
 343 
 344           wr_buff_no[dev] = -1;
 345         }
 346       return 0;
 347       break;
 348 
 349     case SNDCTL_DSP_RESET:
 350       wr_buff_no[dev] = -1;
 351       return DMAbuf_ioctl (dev, cmd, arg, 0);
 352       break;
 353 
 354     case SNDCTL_DSP_GETFMTS:
 355       return IOCTL_OUT (arg, audio_devs[dev]->format_mask);
 356       break;
 357 
 358     case SNDCTL_DSP_SETFMT:
 359       return IOCTL_OUT (arg, set_format (dev, IOCTL_IN (arg)));
 360 
 361     default:
 362       return DMAbuf_ioctl (dev, cmd, arg, 0);
 363       break;
 364     }
 365 }
 366 
 367 long
 368 audio_init (long mem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
 369 {
 370   /*
 371  * NOTE! This routine could be called several times during boot.
 372  */
 373   return mem_start;
 374 }
 375 
 376 #else
 377 /*
 378  * Stub versions
 379  */
 380 
 381 int
 382 audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 383 {
 384   return RET_ERROR (EIO);
 385 }
 386 
 387 int
 388 audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 389 {
 390   return RET_ERROR (EIO);
 391 }
 392 
 393 int
 394 audio_open (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 395 {
 396   return RET_ERROR (ENXIO);
 397 }
 398 
 399 void
 400 audio_release (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 401 {
 402 };
 403 int
 404 audio_ioctl (int dev, struct fileinfo *file,
     /* [previous][next][first][last][top][bottom][index][help] */
 405              unsigned int cmd, unsigned int arg)
 406 {
 407   return RET_ERROR (EIO);
 408 }
 409 
 410 int
 411 audio_lseek (int dev, struct fileinfo *file, off_t offset, int orig)
     /* [previous][next][first][last][top][bottom][index][help] */
 412 {
 413   return RET_ERROR (EIO);
 414 }
 415 
 416 long
 417 audio_init (long mem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
 418 {
 419   return mem_start;
 420 }
 421 
 422 #endif
 423 
 424 #endif

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