The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/sound/pcm/channel.h

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1999 Cameron Grant <cg@freebsd.org>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  * $FreeBSD$
   27  */
   28 
   29 struct pcmchan_caps {
   30         u_int32_t minspeed, maxspeed;
   31         u_int32_t *fmtlist;
   32         u_int32_t caps;
   33 };
   34 
   35 /* Forward declarations */
   36 struct pcm_channel;
   37 struct pcmchan_syncgroup;
   38 struct pcmchan_syncmember;
   39 
   40 extern struct mtx snd_pcm_syncgroups_mtx;
   41 extern SLIST_HEAD(pcm_synclist, pcmchan_syncgroup) snd_pcm_syncgroups;
   42 
   43 #define PCM_SG_LOCK()       mtx_lock(&snd_pcm_syncgroups_mtx)
   44 #define PCM_SG_TRYLOCK()    mtx_trylock(&snd_pcm_syncgroups_mtx)
   45 #define PCM_SG_UNLOCK()     mtx_unlock(&snd_pcm_syncgroups_mtx)
   46 #define PCM_SG_LOCKASSERT(arg)  mtx_assert(&snd_pcm_syncgroups_mtx, arg)
   47 
   48 /**
   49  * @brief Specifies an audio device sync group
   50  */
   51 struct pcmchan_syncgroup {
   52         SLIST_ENTRY(pcmchan_syncgroup) link;
   53         SLIST_HEAD(, pcmchan_syncmember) members;
   54         int id; /**< Group identifier; set to address of group. */
   55 };
   56 
   57 /**
   58  * @brief Specifies a container for members of a sync group
   59  */
   60 struct pcmchan_syncmember {
   61         SLIST_ENTRY(pcmchan_syncmember) link;
   62         struct pcmchan_syncgroup *parent; /**< group head */
   63         struct pcm_channel *ch;
   64 };
   65 
   66 #define CHN_NAMELEN     32
   67 struct pcm_channel {
   68         kobj_t methods;
   69 
   70         pid_t pid;
   71         int refcount;
   72         struct pcm_feeder *feeder;
   73         u_int32_t align;
   74 
   75         int volume;
   76         int latency;
   77         u_int32_t speed;
   78         u_int32_t format;
   79         u_int32_t flags;
   80         u_int32_t feederflags;
   81         u_int32_t blocks;
   82 
   83         int direction;
   84         unsigned int interrupts, xruns, feedcount;
   85         unsigned int timeout;
   86         struct snd_dbuf *bufhard, *bufsoft;
   87         struct snddev_info *parentsnddev;
   88         struct pcm_channel *parentchannel;
   89         void *devinfo;
   90         device_t dev;
   91         int unit;
   92         char name[CHN_NAMELEN];
   93         struct mtx *lock;
   94         int trigger;
   95         /**
   96          * For interrupt manipulations.
   97          */
   98         struct cv intr_cv;
   99         /**
  100          * Increment,decrement this around operations that temporarily yield
  101          * lock.
  102          */
  103         unsigned int inprog;
  104         /**
  105          * Special channel operations should examine @c inprog after acquiring
  106          * lock.  If zero, operations may continue.  Else, thread should
  107          * wait on this cv for previous operation to finish.
  108          */
  109         struct cv cv;
  110         /**
  111          * Low water mark for select()/poll().
  112          *
  113          * This is initialized to the channel's fragment size, and will be
  114          * overwritten if a new fragment size is set.  Users may alter this
  115          * value directly with the @c SNDCTL_DSP_LOW_WATER ioctl.
  116          */
  117         unsigned int lw;
  118         /**
  119          * If part of a sync group, this will point to the syncmember
  120          * container.
  121          */
  122         struct pcmchan_syncmember *sm;
  123 #ifdef OSSV4_EXPERIMENT
  124         u_int16_t lpeak, rpeak; /**< Peak value from 0-32767. */
  125 #endif
  126 
  127         struct {
  128                 SLIST_HEAD(, pcm_channel) head;
  129                 SLIST_ENTRY(pcm_channel) link;
  130                 struct {
  131                         SLIST_HEAD(, pcm_channel) head;
  132                         SLIST_ENTRY(pcm_channel) link;
  133                 } busy;
  134         } children;
  135 
  136         struct {
  137                 struct {
  138                         SLIST_ENTRY(pcm_channel) link;
  139                         struct {
  140                                 SLIST_ENTRY(pcm_channel) link;
  141                         } busy;
  142                 } pcm;
  143         } channels;
  144 
  145         void *data1, *data2;
  146 };
  147 
  148 #define CHN_HEAD(x, y)                  &(x)->y.head
  149 #define CHN_INIT(x, y)                  SLIST_INIT(CHN_HEAD(x, y))
  150 #define CHN_LINK(y)                     y.link
  151 #define CHN_EMPTY(x, y)                 SLIST_EMPTY(CHN_HEAD(x, y))
  152 #define CHN_FIRST(x, y)                 SLIST_FIRST(CHN_HEAD(x, y))
  153 
  154 #define CHN_FOREACH(x, y, z)                                            \
  155         SLIST_FOREACH(x, CHN_HEAD(y, z), CHN_LINK(z))
  156 
  157 #define CHN_FOREACH_SAFE(w, x, y, z)                                    \
  158         SLIST_FOREACH_SAFE(w, CHN_HEAD(x, z), CHN_LINK(z), y)
  159 
  160 #define CHN_INSERT_HEAD(x, y, z)                                        \
  161         SLIST_INSERT_HEAD(CHN_HEAD(x, z), y, CHN_LINK(z))
  162 
  163 #define CHN_INSERT_AFTER(x, y, z)                                       \
  164         SLIST_INSERT_AFTER(x, y, CHN_LINK(z))
  165 
  166 #define CHN_REMOVE(x, y, z)                                             \
  167         SLIST_REMOVE(CHN_HEAD(x, z), y, pcm_channel, CHN_LINK(z))
  168 
  169 #define CHN_INSERT_HEAD_SAFE(x, y, z)           do {                    \
  170         struct pcm_channel *t = NULL;                                   \
  171         CHN_FOREACH(t, x, z) {                                          \
  172                 if (t == y)                                             \
  173                         break;                                          \
  174         }                                                               \
  175         if (t != y) {                                                   \
  176                 CHN_INSERT_HEAD(x, y, z);                               \
  177         }                                                               \
  178 } while(0)
  179 
  180 #define CHN_INSERT_AFTER_SAFE(w, x, y, z)       do {                    \
  181         struct pcm_channel *t = NULL;                                   \
  182         CHN_FOREACH(t, w, z) {                                          \
  183                 if (t == y)                                             \
  184                         break;                                          \
  185         }                                                               \
  186         if (t != y) {                                                   \
  187                 CHN_INSERT_AFTER(x, y, z);                              \
  188         }                                                               \
  189 } while(0)
  190 
  191 #define CHN_REMOVE_SAFE(x, y, z)                do {                    \
  192         struct pcm_channel *t = NULL;                                   \
  193         CHN_FOREACH(t, x, z) {                                          \
  194                 if (t == y)                                             \
  195                         break;                                          \
  196         }                                                               \
  197         if (t == y) {                                                   \
  198                 CHN_REMOVE(x, y, z);                                    \
  199         }                                                               \
  200 } while(0)
  201 
  202 #define CHN_UNIT(x)     (snd_unit2u((x)->unit))
  203 #define CHN_DEV(x)      (snd_unit2d((x)->unit))
  204 #define CHN_CHAN(x)     (snd_unit2c((x)->unit))
  205 
  206 #define CHN_BUF_PARENT(x, y)                                            \
  207         (((x) != NULL && (x)->parentchannel != NULL &&                  \
  208         (x)->parentchannel->bufhard != NULL) ?                          \
  209         (x)->parentchannel->bufhard : (y))
  210 
  211 #define CHN_BROADCAST(x)        do {                                    \
  212         if ((x)->cv_waiters != 0)                                       \
  213                 cv_broadcastpri(x, PRIBIO);                             \
  214 } while(0)
  215 
  216 #include "channel_if.h"
  217 
  218 int chn_reinit(struct pcm_channel *c);
  219 int chn_write(struct pcm_channel *c, struct uio *buf);
  220 int chn_read(struct pcm_channel *c, struct uio *buf);
  221 u_int32_t chn_start(struct pcm_channel *c, int force);
  222 int chn_sync(struct pcm_channel *c, int threshold);
  223 int chn_flush(struct pcm_channel *c);
  224 int chn_poll(struct pcm_channel *c, int ev, struct thread *td);
  225 
  226 int chn_init(struct pcm_channel *c, void *devinfo, int dir, int direction);
  227 int chn_kill(struct pcm_channel *c);
  228 int chn_setdir(struct pcm_channel *c, int dir);
  229 int chn_reset(struct pcm_channel *c, u_int32_t fmt);
  230 int chn_setvolume(struct pcm_channel *c, int left, int right);
  231 int chn_setspeed(struct pcm_channel *c, int speed);
  232 int chn_setformat(struct pcm_channel *c, u_int32_t fmt);
  233 int chn_setblocksize(struct pcm_channel *c, int blkcnt, int blksz);
  234 int chn_setlatency(struct pcm_channel *c, int latency);
  235 int chn_trigger(struct pcm_channel *c, int go);
  236 int chn_getptr(struct pcm_channel *c);
  237 struct pcmchan_caps *chn_getcaps(struct pcm_channel *c);
  238 u_int32_t chn_getformats(struct pcm_channel *c);
  239 
  240 void chn_resetbuf(struct pcm_channel *c);
  241 void chn_intr(struct pcm_channel *c);
  242 int chn_wrfeed(struct pcm_channel *c);
  243 int chn_rdfeed(struct pcm_channel *c);
  244 int chn_abort(struct pcm_channel *c);
  245 
  246 void chn_wrupdate(struct pcm_channel *c);
  247 void chn_rdupdate(struct pcm_channel *c);
  248 
  249 int chn_notify(struct pcm_channel *c, u_int32_t flags);
  250 void chn_lock(struct pcm_channel *c);
  251 void chn_unlock(struct pcm_channel *c);
  252 
  253 int chn_getrates(struct pcm_channel *c, int **rates);
  254 int chn_syncdestroy(struct pcm_channel *c);
  255 
  256 #ifdef OSSV4_EXPERIMENT
  257 int chn_getpeaks(struct pcm_channel *c, int *lpeak, int *rpeak);
  258 #endif
  259 
  260 #ifdef  USING_MUTEX
  261 #define CHN_LOCK(c) mtx_lock((struct mtx *)((c)->lock))
  262 #define CHN_UNLOCK(c) mtx_unlock((struct mtx *)((c)->lock))
  263 #define CHN_TRYLOCK(c) mtx_trylock((struct mtx *)((c)->lock))
  264 #define CHN_LOCKASSERT(c) mtx_assert((struct mtx *)((c)->lock), MA_OWNED)
  265 #else
  266 #define CHN_LOCK(c)
  267 #define CHN_UNLOCK(c)
  268 #define CHN_TRYLOCK(c)
  269 #define CHN_LOCKASSERT(c)
  270 #endif
  271 
  272 int fmtvalid(u_int32_t fmt, u_int32_t *fmtlist);
  273 
  274 #define AFMTSTR_NONE            0 /* "s16le" */
  275 #define AFMTSTR_SIMPLE          1 /* "s16le:s" */
  276 #define AFMTSTR_NUM             2 /* "s16le:2" */
  277 #define AFMTSTR_FULL            3 /* "s16le:stereo" */
  278 
  279 #define AFMTSTR_MAXSZ           13 /* include null terminator */
  280 
  281 #define AFMTSTR_MONO_RETURN     0
  282 #define AFMTSTR_STEREO_RETURN   1
  283 
  284 struct afmtstr_table {
  285         char *fmtstr;
  286         u_int32_t format;
  287 };
  288 
  289 int afmtstr_swap_sign(char *);
  290 int afmtstr_swap_endian(char *);
  291 u_int32_t afmtstr2afmt(struct afmtstr_table *, const char *, int);
  292 u_int32_t afmt2afmtstr(struct afmtstr_table *, u_int32_t, char *, size_t, int, int);
  293 
  294 extern int chn_latency;
  295 extern int chn_latency_profile;
  296 extern int report_soft_formats;
  297 
  298 #define PCMDIR_FAKE             0
  299 #define PCMDIR_PLAY             1
  300 #define PCMDIR_PLAY_VIRTUAL     2
  301 #define PCMDIR_REC              -1
  302 #define PCMDIR_REC_VIRTUAL      -2
  303 
  304 #define PCMTRIG_START 1
  305 #define PCMTRIG_EMLDMAWR 2
  306 #define PCMTRIG_EMLDMARD 3
  307 #define PCMTRIG_STOP 0
  308 #define PCMTRIG_ABORT -1
  309 
  310 #define PCMTRIG_COMMON(x)       ((x) == PCMTRIG_START ||                \
  311                                  (x) == PCMTRIG_STOP ||                 \
  312                                  (x) == PCMTRIG_ABORT)
  313 
  314 #define CHN_F_CLOSING           0x00000004  /* a pending close */
  315 #define CHN_F_ABORTING          0x00000008  /* a pending abort */
  316 #define CHN_F_RUNNING           0x00000010  /* dma is running */
  317 #define CHN_F_TRIGGERED         0x00000020
  318 #define CHN_F_NOTRIGGER         0x00000040
  319 #define CHN_F_SLEEPING          0x00000080
  320 
  321 #define CHN_F_BUSY              0x00001000  /* has been opened  */
  322 #define CHN_F_HAS_SIZE          0x00002000  /* user set block size */
  323 #define CHN_F_NBIO              0x00004000  /* do non-blocking i/o */
  324 #define CHN_F_MAPPED            0x00010000  /* has been mmap()ed */
  325 #define CHN_F_DEAD              0x00020000
  326 #define CHN_F_BADSETTING        0x00040000
  327 #define CHN_F_SETBLOCKSIZE      0x00080000
  328 #define CHN_F_HAS_VCHAN         0x00100000
  329 
  330 #define CHN_F_VIRTUAL           0x10000000  /* not backed by hardware */
  331 
  332 #define CHN_F_RESET             (CHN_F_BUSY | CHN_F_DEAD |              \
  333                                  CHN_F_HAS_VCHAN | CHN_F_VIRTUAL)
  334 
  335 #define CHN_F_MMAP_INVALID      (CHN_F_DEAD | CHN_F_RUNNING)
  336 
  337                                         
  338 
  339 #define CHN_N_RATE              0x00000001
  340 #define CHN_N_FORMAT            0x00000002
  341 #define CHN_N_VOLUME            0x00000004
  342 #define CHN_N_BLOCKSIZE         0x00000008
  343 #define CHN_N_TRIGGER           0x00000010
  344 
  345 #define CHN_LATENCY_MIN         0
  346 #define CHN_LATENCY_MAX         10
  347 #define CHN_LATENCY_DEFAULT     5
  348 #define CHN_POLICY_MIN          CHN_LATENCY_MIN
  349 #define CHN_POLICY_MAX          CHN_LATENCY_MAX
  350 #define CHN_POLICY_DEFAULT      CHN_LATENCY_DEFAULT
  351 
  352 #define CHN_LATENCY_PROFILE_MIN         0
  353 #define CHN_LATENCY_PROFILE_MAX         1
  354 #define CHN_LATENCY_PROFILE_DEFAULT     CHN_LATENCY_PROFILE_MAX
  355 
  356 #define CHN_STARTED(c)          ((c)->flags & CHN_F_TRIGGERED)
  357 #define CHN_STOPPED(c)          (!CHN_STARTED(c))
  358 #define CHN_DIRSTR(c)           (((c)->direction == PCMDIR_PLAY) ? \
  359                                 "PCMDIR_PLAY" : "PCMDIR_REC")
  360 
  361 #define CHN_TIMEOUT             5
  362 #define CHN_TIMEOUT_MIN         1
  363 #define CHN_TIMEOUT_MAX         10
  364 
  365 /*
  366  * This should be large enough to hold all pcm data between
  367  * tsleeps in chn_{read,write} at the highest sample rate.
  368  * (which is usually 48kHz * 16bit * stereo = 192000 bytes/sec)
  369  */
  370 #define CHN_2NDBUFBLKSIZE       (2 * 1024)
  371 /* The total number of blocks per secondary bufhard. */
  372 #define CHN_2NDBUFBLKNUM        (32)
  373 /* The size of a whole secondary bufhard. */
  374 #define CHN_2NDBUFMAXSIZE       (131072)
  375 
  376 #define CHANNEL_DECLARE(name) static DEFINE_CLASS(name, name ## _methods, sizeof(struct kobj))

Cache object: fc416d0ce293a6b1409a23b3f24a7548


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.