summaryrefslogtreecommitdiffstats
path: root/sys/dev/sound/pcm/channel.h
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/sound/pcm/channel.h')
-rw-r--r--sys/dev/sound/pcm/channel.h221
1 files changed, 149 insertions, 72 deletions
diff --git a/sys/dev/sound/pcm/channel.h b/sys/dev/sound/pcm/channel.h
index 8f9f8f6..6effec3 100644
--- a/sys/dev/sound/pcm/channel.h
+++ b/sys/dev/sound/pcm/channel.h
@@ -1,5 +1,7 @@
/*-
- * Copyright (c) 1999 Cameron Grant <cg@freebsd.org>
+ * Copyright (c) 2005-2009 Ariff Abdullah <ariff@FreeBSD.org>
+ * Portions Copyright (c) Ryan Beasley <ryan.beasley@gmail.com> - GSoC 2006
+ * Copyright (c) 1999 Cameron Grant <cg@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,6 +34,17 @@ struct pcmchan_caps {
u_int32_t caps;
};
+struct pcmchan_matrix {
+ int id;
+ uint8_t channels, ext;
+ struct {
+ int type;
+ uint32_t members;
+ } map[SND_CHN_T_MAX + 1];
+ uint32_t mask;
+ int8_t offset[SND_CHN_T_MAX];
+};
+
/* Forward declarations */
struct pcm_channel;
struct pcmchan_syncgroup;
@@ -63,7 +76,10 @@ struct pcmchan_syncmember {
struct pcm_channel *ch;
};
-#define CHN_NAMELEN 32
+#define CHN_NAMELEN 32
+#define CHN_COMM_UNUSED "<UNUSED>"
+#define CHN_COMM_UNKNOWN "<UNKNOWN>"
+
struct pcm_channel {
kobj_t methods;
@@ -72,13 +88,12 @@ struct pcm_channel {
struct pcm_feeder *feeder;
u_int32_t align;
- int volume;
int latency;
u_int32_t speed;
u_int32_t format;
u_int32_t flags;
u_int32_t feederflags;
- u_int32_t blocks;
+ u_int64_t blocks;
int direction;
unsigned int interrupts, xruns, feedcount;
@@ -90,6 +105,7 @@ struct pcm_channel {
device_t dev;
int unit;
char name[CHN_NAMELEN];
+ char comm[MAXCOMLEN + 1];
struct mtx *lock;
int trigger;
/**
@@ -139,9 +155,16 @@ struct pcm_channel {
struct {
SLIST_ENTRY(pcm_channel) link;
} busy;
+ struct {
+ SLIST_ENTRY(pcm_channel) link;
+ } opened;
} pcm;
} channels;
+ struct pcmchan_matrix matrix;
+
+ int volume[SND_VOL_C_MAX][SND_CHN_T_VOL_MAX];
+
void *data1, *data2;
};
@@ -172,10 +195,9 @@ struct pcm_channel {
if (t == y) \
break; \
} \
- if (t != y) { \
+ if (t != y) \
CHN_INSERT_HEAD(x, y, z); \
- } \
-} while(0)
+} while (0)
#define CHN_INSERT_AFTER_SAFE(w, x, y, z) do { \
struct pcm_channel *t = NULL; \
@@ -183,10 +205,9 @@ struct pcm_channel {
if (t == y) \
break; \
} \
- if (t != y) { \
+ if (t != y) \
CHN_INSERT_AFTER(x, y, z); \
- } \
-} while(0)
+} while (0)
#define CHN_REMOVE_SAFE(x, y, z) do { \
struct pcm_channel *t = NULL; \
@@ -194,10 +215,26 @@ struct pcm_channel {
if (t == y) \
break; \
} \
- if (t == y) { \
+ if (t == y) \
CHN_REMOVE(x, y, z); \
+} while (0)
+
+#define CHN_INSERT_SORT(w, x, y, z) do { \
+ struct pcm_channel *t, *a = NULL; \
+ CHN_FOREACH(t, x, z) { \
+ if ((y)->unit w t->unit) \
+ a = t; \
+ else \
+ break; \
} \
-} while(0)
+ if (a != NULL) \
+ CHN_INSERT_AFTER(a, y, z); \
+ else \
+ CHN_INSERT_HEAD(x, y, z); \
+} while (0)
+
+#define CHN_INSERT_SORT_ASCEND(x, y, z) CHN_INSERT_SORT(>, x, y, z)
+#define CHN_INSERT_SORT_DESCEND(x, y, z) CHN_INSERT_SORT(<, x, y, z)
#define CHN_UNIT(x) (snd_unit2u((x)->unit))
#define CHN_DEV(x) (snd_unit2d((x)->unit))
@@ -211,7 +248,7 @@ struct pcm_channel {
#define CHN_BROADCAST(x) do { \
if ((x)->cv_waiters != 0) \
cv_broadcastpri(x, PRIBIO); \
-} while(0)
+} while (0)
#include "channel_if.h"
@@ -225,79 +262,72 @@ int chn_poll(struct pcm_channel *c, int ev, struct thread *td);
int chn_init(struct pcm_channel *c, void *devinfo, int dir, int direction);
int chn_kill(struct pcm_channel *c);
-int chn_setdir(struct pcm_channel *c, int dir);
-int chn_reset(struct pcm_channel *c, u_int32_t fmt);
+int chn_reset(struct pcm_channel *c, u_int32_t fmt, u_int32_t spd);
int chn_setvolume(struct pcm_channel *c, int left, int right);
-int chn_setspeed(struct pcm_channel *c, int speed);
-int chn_setformat(struct pcm_channel *c, u_int32_t fmt);
+int chn_setvolume_multi(struct pcm_channel *c, int vc, int left, int right,
+ int center);
+int chn_setvolume_matrix(struct pcm_channel *c, int vc, int vt, int val);
+int chn_getvolume_matrix(struct pcm_channel *c, int vc, int vt);
+void chn_vpc_reset(struct pcm_channel *c, int vc, int force);
+int chn_setparam(struct pcm_channel *c, uint32_t format, uint32_t speed);
+int chn_setspeed(struct pcm_channel *c, uint32_t speed);
+int chn_setformat(struct pcm_channel *c, uint32_t format);
int chn_setblocksize(struct pcm_channel *c, int blkcnt, int blksz);
int chn_setlatency(struct pcm_channel *c, int latency);
+void chn_syncstate(struct pcm_channel *c);
int chn_trigger(struct pcm_channel *c, int go);
int chn_getptr(struct pcm_channel *c);
struct pcmchan_caps *chn_getcaps(struct pcm_channel *c);
u_int32_t chn_getformats(struct pcm_channel *c);
+struct pcmchan_matrix *chn_getmatrix(struct pcm_channel *);
+int chn_setmatrix(struct pcm_channel *, struct pcmchan_matrix *);
+
+int chn_oss_getorder(struct pcm_channel *, unsigned long long *);
+int chn_oss_setorder(struct pcm_channel *, unsigned long long *);
+int chn_oss_getmask(struct pcm_channel *, uint32_t *);
+
void chn_resetbuf(struct pcm_channel *c);
+void chn_intr_locked(struct pcm_channel *c);
void chn_intr(struct pcm_channel *c);
-int chn_wrfeed(struct pcm_channel *c);
-int chn_rdfeed(struct pcm_channel *c);
int chn_abort(struct pcm_channel *c);
-void chn_wrupdate(struct pcm_channel *c);
-void chn_rdupdate(struct pcm_channel *c);
-
int chn_notify(struct pcm_channel *c, u_int32_t flags);
-void chn_lock(struct pcm_channel *c);
-void chn_unlock(struct pcm_channel *c);
int chn_getrates(struct pcm_channel *c, int **rates);
int chn_syncdestroy(struct pcm_channel *c);
-#ifdef OSSV4_EXPERIMENT
-int chn_getpeaks(struct pcm_channel *c, int *lpeak, int *rpeak);
+#define CHN_SETVOLUME(...) chn_setvolume_matrix(__VA_ARGS__)
+#if defined(SND_DIAGNOSTIC) || defined(INVARIANTS)
+#define CHN_GETVOLUME(...) chn_getvolume_matrix(__VA_ARGS__)
+#else
+#define CHN_GETVOLUME(x, y, z) ((x)->volume[y][z])
#endif
-#ifdef USING_MUTEX
-#define CHN_LOCK_OWNED(c) mtx_owned((struct mtx *)((c)->lock))
-#define CHN_LOCK(c) mtx_lock((struct mtx *)((c)->lock))
-#define CHN_UNLOCK(c) mtx_unlock((struct mtx *)((c)->lock))
-#define CHN_TRYLOCK(c) mtx_trylock((struct mtx *)((c)->lock))
-#define CHN_LOCKASSERT(c) mtx_assert((struct mtx *)((c)->lock), MA_OWNED)
-#else
-#define CHN_LOCK_OWNED(c) 0
-#define CHN_LOCK(c)
-#define CHN_UNLOCK(c)
-#define CHN_TRYLOCK(c)
-#define CHN_LOCKASSERT(c)
+#ifdef OSSV4_EXPERIMENT
+int chn_getpeaks(struct pcm_channel *c, int *lpeak, int *rpeak);
#endif
-int fmtvalid(u_int32_t fmt, u_int32_t *fmtlist);
+#define CHN_LOCKOWNED(c) mtx_owned((c)->lock)
+#define CHN_LOCK(c) mtx_lock((c)->lock)
+#define CHN_UNLOCK(c) mtx_unlock((c)->lock)
+#define CHN_TRYLOCK(c) mtx_trylock((c)->lock)
+#define CHN_LOCKASSERT(c) mtx_assert((c)->lock, MA_OWNED)
+#define CHN_UNLOCKASSERT(c) mtx_assert((c)->lock, MA_NOTOWNED)
-#define AFMTSTR_NONE 0 /* "s16le" */
-#define AFMTSTR_SIMPLE 1 /* "s16le:s" */
-#define AFMTSTR_NUM 2 /* "s16le:2" */
-#define AFMTSTR_FULL 3 /* "s16le:stereo" */
+int snd_fmtvalid(uint32_t fmt, uint32_t *fmtlist);
-#define AFMTSTR_MAXSZ 13 /* include null terminator */
+uint32_t snd_str2afmt(const char *);
+uint32_t snd_afmt2str(uint32_t, char *, size_t);
-#define AFMTSTR_MONO_RETURN 0
-#define AFMTSTR_STEREO_RETURN 1
+#define AFMTSTR_LEN 16
-struct afmtstr_table {
- char *fmtstr;
- u_int32_t format;
-};
-
-int afmtstr_swap_sign(char *);
-int afmtstr_swap_endian(char *);
-u_int32_t afmtstr2afmt(struct afmtstr_table *, const char *, int);
-u_int32_t afmt2afmtstr(struct afmtstr_table *, u_int32_t, char *, size_t, int, int);
extern int chn_latency;
extern int chn_latency_profile;
extern int report_soft_formats;
+extern int report_soft_matrix;
-#define PCMDIR_FAKE 0
#define PCMDIR_PLAY 1
#define PCMDIR_PLAY_VIRTUAL 2
#define PCMDIR_REC -1
@@ -313,26 +343,60 @@ extern int report_soft_formats;
(x) == PCMTRIG_STOP || \
(x) == PCMTRIG_ABORT)
-#define CHN_F_CLOSING 0x00000004 /* a pending close */
-#define CHN_F_ABORTING 0x00000008 /* a pending abort */
-#define CHN_F_RUNNING 0x00000010 /* dma is running */
-#define CHN_F_TRIGGERED 0x00000020
-#define CHN_F_NOTRIGGER 0x00000040
-#define CHN_F_SLEEPING 0x00000080
-
-#define CHN_F_BUSY 0x00001000 /* has been opened */
-#define CHN_F_HAS_SIZE 0x00002000 /* user set block size */
-#define CHN_F_NBIO 0x00004000 /* do non-blocking i/o */
-#define CHN_F_MAPPED 0x00010000 /* has been mmap()ed */
-#define CHN_F_DEAD 0x00020000
-#define CHN_F_BADSETTING 0x00040000
-#define CHN_F_SETBLOCKSIZE 0x00080000
-#define CHN_F_HAS_VCHAN 0x00100000
+#define CHN_F_CLOSING 0x00000001 /* a pending close */
+#define CHN_F_ABORTING 0x00000002 /* a pending abort */
+#define CHN_F_RUNNING 0x00000004 /* dma is running */
+#define CHN_F_TRIGGERED 0x00000008
+#define CHN_F_NOTRIGGER 0x00000010
+#define CHN_F_SLEEPING 0x00000020
+
+#define CHN_F_NBIO 0x00000040 /* do non-blocking i/o */
+#define CHN_F_MMAP 0x00000080 /* has been mmap()ed */
+
+#define CHN_F_BUSY 0x00000100 /* has been opened */
+#define CHN_F_DIRTY 0x00000200 /* need re-config */
+#define CHN_F_DEAD 0x00000400 /* too many errors, dead, mdk */
+#define CHN_F_SILENCE 0x00000800 /* silence, nil, null, yada */
+
+#define CHN_F_HAS_SIZE 0x00001000 /* user set block size */
+#define CHN_F_HAS_VCHAN 0x00002000 /* vchan master */
+
+#define CHN_F_VCHAN_PASSTHROUGH 0x00004000 /* digital ac3/dts passthrough */
+#define CHN_F_VCHAN_ADAPTIVE 0x00008000 /* adaptive format/rate selection */
+#define CHN_F_VCHAN_DYNAMIC (CHN_F_VCHAN_PASSTHROUGH | CHN_F_VCHAN_ADAPTIVE)
#define CHN_F_VIRTUAL 0x10000000 /* not backed by hardware */
+#define CHN_F_BITPERFECT 0x20000000 /* un-cooked, Heh.. */
+#define CHN_F_PASSTHROUGH 0x40000000 /* passthrough re-config */
+#define CHN_F_EXCLUSIVE 0x80000000 /* exclusive access */
+
+#define CHN_F_BITS "\020" \
+ "\001CLOSING" \
+ "\002ABORTING" \
+ "\003RUNNING" \
+ "\004TRIGGERED" \
+ "\005NOTRIGGER" \
+ "\006SLEEPING" \
+ "\007NBIO" \
+ "\010MMAP" \
+ "\011BUSY" \
+ "\012DIRTY" \
+ "\013DEAD" \
+ "\014SILENCE" \
+ "\015HAS_SIZE" \
+ "\016HAS_VCHAN" \
+ "\017VCHAN_PASSTHROUGH" \
+ "\020VCHAN_ADAPTIVE" \
+ "\035VIRTUAL" \
+ "\036BITPERFECT" \
+ "\037PASSTHROUGH" \
+ "\040EXCLUSIVE"
+
#define CHN_F_RESET (CHN_F_BUSY | CHN_F_DEAD | \
- CHN_F_HAS_VCHAN | CHN_F_VIRTUAL)
+ CHN_F_VIRTUAL | CHN_F_HAS_VCHAN | \
+ CHN_F_VCHAN_DYNAMIC | \
+ CHN_F_PASSTHROUGH | CHN_F_EXCLUSIVE)
#define CHN_F_MMAP_INVALID (CHN_F_DEAD | CHN_F_RUNNING)
@@ -359,6 +423,8 @@ extern int report_soft_formats;
#define CHN_STOPPED(c) (!CHN_STARTED(c))
#define CHN_DIRSTR(c) (((c)->direction == PCMDIR_PLAY) ? \
"PCMDIR_PLAY" : "PCMDIR_REC")
+#define CHN_BITPERFECT(c) ((c)->flags & CHN_F_BITPERFECT)
+#define CHN_PASSTHROUGH(c) ((c)->flags & CHN_F_PASSTHROUGH)
#define CHN_TIMEOUT 5
#define CHN_TIMEOUT_MIN 1
@@ -375,4 +441,15 @@ extern int report_soft_formats;
/* The size of a whole secondary bufhard. */
#define CHN_2NDBUFMAXSIZE (131072)
+#ifdef SND_DEBUG
+#define CHANNEL_DECLARE(channel) \
+ static struct kobj_class channel##_class = { \
+ .name = #channel, \
+ .methods = channel##_methods, \
+ .size = sizeof(struct kobj), \
+ .baseclasses = NULL, \
+ .refs = 0 \
+ }
+#else
#define CHANNEL_DECLARE(name) static DEFINE_CLASS(name, name ## _methods, sizeof(struct kobj))
+#endif
OpenPOWER on IntegriCloud