diff options
author | cg <cg@FreeBSD.org> | 2000-08-20 22:18:56 +0000 |
---|---|---|
committer | cg <cg@FreeBSD.org> | 2000-08-20 22:18:56 +0000 |
commit | cc65486f22393469327f3952efc2526af719e4a2 (patch) | |
tree | f4dad15d15847c43242bb2f8e08bd8143dae99e5 | |
parent | b648921accec69a7e5c83e915ded3037cbca7f3d (diff) | |
download | FreeBSD-src-cc65486f22393469327f3952efc2526af719e4a2.zip FreeBSD-src-cc65486f22393469327f3952efc2526af719e4a2.tar.gz |
rework feeder sytem to allow feeders in klds
modify driver capability reporting format to list every audio format
seperately- required for above and because we could not previously indicate
that mono was unsupported.
there should be no functional impact.
-rw-r--r-- | sys/dev/sound/isa/ad1816.c | 16 | ||||
-rw-r--r-- | sys/dev/sound/isa/ess.c | 32 | ||||
-rw-r--r-- | sys/dev/sound/isa/mss.c | 43 | ||||
-rw-r--r-- | sys/dev/sound/isa/sb.c | 51 | ||||
-rw-r--r-- | sys/dev/sound/isa/sb16.c | 51 | ||||
-rw-r--r-- | sys/dev/sound/isa/sb8.c | 51 | ||||
-rw-r--r-- | sys/dev/sound/pci/aureal.c | 24 | ||||
-rw-r--r-- | sys/dev/sound/pci/csapcm.c | 22 | ||||
-rw-r--r-- | sys/dev/sound/pci/ds1.c | 28 | ||||
-rw-r--r-- | sys/dev/sound/pci/emu10k1.c | 34 | ||||
-rw-r--r-- | sys/dev/sound/pci/es137x.c | 24 | ||||
-rw-r--r-- | sys/dev/sound/pci/neomagic.c | 11 | ||||
-rw-r--r-- | sys/dev/sound/pci/solo.c | 30 | ||||
-rw-r--r-- | sys/dev/sound/pci/t4dwave.c | 32 | ||||
-rw-r--r-- | sys/dev/sound/pci/via82c686.c | 24 | ||||
-rw-r--r-- | sys/dev/sound/pcm/channel.c | 53 | ||||
-rw-r--r-- | sys/dev/sound/pcm/channel.h | 6 | ||||
-rw-r--r-- | sys/dev/sound/pcm/datatypes.h | 19 | ||||
-rw-r--r-- | sys/dev/sound/pcm/dsp.c | 6 | ||||
-rw-r--r-- | sys/dev/sound/pcm/fake.c | 18 | ||||
-rw-r--r-- | sys/dev/sound/pcm/feeder.c | 397 | ||||
-rw-r--r-- | sys/dev/sound/pcm/feeder.h | 36 | ||||
-rw-r--r-- | sys/dev/sound/pcm/sound.h | 1 |
23 files changed, 705 insertions, 304 deletions
diff --git a/sys/dev/sound/isa/ad1816.c b/sys/dev/sound/isa/ad1816.c index a041ba9..ec7a61e 100644 --- a/sys/dev/sound/isa/ad1816.c +++ b/sys/dev/sound/isa/ad1816.c @@ -85,12 +85,20 @@ static int ad1816chan_trigger(void *data, int go); static int ad1816chan_getptr(void *data); static pcmchan_caps *ad1816chan_getcaps(void *data); -static pcmchan_caps ad1816_caps = { - 4000, 55200, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW, - AFMT_STEREO | AFMT_S16_LE +static u_int32_t ad1816_fmt[] = { + AFMT_U8, + AFMT_STEREO | AFMT_U8, + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + AFMT_MU_LAW, + AFMT_STEREO | AFMT_MU_LAW, + AFMT_A_LAW, + AFMT_STEREO | AFMT_A_LAW, + 0 }; +static pcmchan_caps ad1816_caps = {4000, 55200, ad1816_fmt, 0}; + static pcm_channel ad1816_chantemplate = { ad1816chan_init, ad1816chan_setdir, diff --git a/sys/dev/sound/isa/ess.c b/sys/dev/sound/isa/ess.c index 709549b..2252cd9 100644 --- a/sys/dev/sound/isa/ess.c +++ b/sys/dev/sound/isa/ess.c @@ -55,18 +55,34 @@ static int esschan_trigger(void *data, int go); static int esschan_getptr(void *data); static pcmchan_caps *esschan_getcaps(void *data); -static pcmchan_caps ess_playcaps = { - 5000, 49000, - AFMT_STEREO | AFMT_U8 | AFMT_S8 | AFMT_U16_LE | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE +static u_int32_t ess_pfmt[] = { + AFMT_U8, + AFMT_STEREO | AFMT_U8, + AFMT_S8, + AFMT_STEREO | AFMT_S8, + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + AFMT_U16_LE, + AFMT_STEREO | AFMT_U16_LE, + 0 }; -static pcmchan_caps ess_reccaps = { - 5000, 49000, - AFMT_STEREO | AFMT_U8 | AFMT_S8 | AFMT_U16_LE | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE +static pcmchan_caps ess_playcaps = {5000, 49000, ess_pfmt, 0}; + +static u_int32_t ess_rfmt[] = { + AFMT_U8, + AFMT_STEREO | AFMT_U8, + AFMT_S8, + AFMT_STEREO | AFMT_S8, + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + AFMT_U16_LE, + AFMT_STEREO | AFMT_U16_LE, + 0 }; +static pcmchan_caps ess_reccaps = {5000, 49000, ess_rfmt, 0}; + static pcm_channel ess_chantemplate = { esschan_init, esschan_setdir, diff --git a/sys/dev/sound/isa/mss.c b/sys/dev/sound/isa/mss.c index 5240938..71f9dd5 100644 --- a/sys/dev/sound/isa/mss.c +++ b/sys/dev/sound/isa/mss.c @@ -136,23 +136,38 @@ static int msschan_trigger(void *data, int go); static int msschan_getptr(void *data); static pcmchan_caps *msschan_getcaps(void *data); -static pcmchan_caps mss_caps = { - 4000, 48000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW, - AFMT_STEREO | AFMT_S16_LE +static u_int32_t mss_fmt[] = { + AFMT_U8, + AFMT_STEREO | AFMT_U8, + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + AFMT_MU_LAW, + AFMT_STEREO | AFMT_MU_LAW, + AFMT_A_LAW, + AFMT_STEREO | AFMT_A_LAW, + 0 }; - -static pcmchan_caps guspnp_caps = { - 4000, 48000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE | AFMT_A_LAW, - AFMT_STEREO | AFMT_S16_LE +static pcmchan_caps mss_caps = {4000, 48000, mss_fmt, 0}; + +static u_int32_t guspnp_fmt[] = { + AFMT_U8, + AFMT_STEREO | AFMT_U8, + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + AFMT_A_LAW, + AFMT_STEREO | AFMT_A_LAW, + 0 }; - -static pcmchan_caps opti931_caps = { - 4000, 48000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE +static pcmchan_caps guspnp_caps = {4000, 48000, guspnp_fmt, 0}; + +static u_int32_t opti931_fmt[] = { + AFMT_U8, + AFMT_STEREO | AFMT_U8, + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + 0 }; +static pcmchan_caps opti931_caps = {4000, 48000, opti931_fmt, 0}; static pcm_channel mss_chantemplate = { msschan_init, diff --git a/sys/dev/sound/isa/sb.c b/sys/dev/sound/isa/sb.c index f984d5c..d975311 100644 --- a/sys/dev/sound/isa/sb.c +++ b/sys/dev/sound/isa/sb.c @@ -49,47 +49,54 @@ static int sbchan_trigger(void *data, int go); static int sbchan_getptr(void *data); static pcmchan_caps *sbchan_getcaps(void *data); -static pcmchan_caps sb_playcaps = { - 4000, 22050, +static u_int32_t sb_playfmt[] = { AFMT_U8, - AFMT_U8 + 0 }; +static pcmchan_caps sb_playcaps = {4000, 22050, sb_playfmt, 0}; -static pcmchan_caps sb_reccaps = { - 4000, 13000, +static u_int32_t sb_recfmt[] = { AFMT_U8, - AFMT_U8 + 0 }; +static pcmchan_caps sb_reccaps = {4000, 13000, sb_recfmt, 0}; -static pcmchan_caps sbpro_playcaps = { - 4000, 45000, +static u_int32_t sbpro_playfmt[] = { + AFMT_U8, AFMT_STEREO | AFMT_U8, - AFMT_STEREO | AFMT_U8 + 0 }; +static pcmchan_caps sbpro_playcaps = {4000, 45000, sbpro_playfmt, 0}; -static pcmchan_caps sbpro_reccaps = { - 4000, 15000, +static u_int32_t sbpro_recfmt[] = { + AFMT_U8, AFMT_STEREO | AFMT_U8, - AFMT_STEREO | AFMT_U8 + 0 }; +static pcmchan_caps sbpro_reccaps = {4000, 15000, sbpro_recfmt, 0}; -static pcmchan_caps sb16_hcaps = { - 5000, 45000, +static u_int32_t sb16_hfmt[] = { + AFMT_S16_LE, AFMT_STEREO | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE + 0 }; +static pcmchan_caps sb16_hcaps = {5000, 45000, sb16_hfmt, 0}; -static pcmchan_caps sb16_lcaps = { - 5000, 45000, +static u_int32_t sb16_lfmt[] = { + AFMT_U8, AFMT_STEREO | AFMT_U8, - AFMT_STEREO | AFMT_U8 + 0 }; +static pcmchan_caps sb16_lcaps = {5000, 45000, sb16_lfmt, 0}; -static pcmchan_caps sb16x_caps = { - 5000, 49000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE +static u_int32_t sb16x_fmt[] = { + AFMT_U8, + AFMT_STEREO | AFMT_U8, + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + 0 }; +static pcmchan_caps sb16x_caps = {5000, 49000, sb16x_fmt, 0}; static pcm_channel sb_chantemplate = { sbchan_init, diff --git a/sys/dev/sound/isa/sb16.c b/sys/dev/sound/isa/sb16.c index f984d5c..d975311 100644 --- a/sys/dev/sound/isa/sb16.c +++ b/sys/dev/sound/isa/sb16.c @@ -49,47 +49,54 @@ static int sbchan_trigger(void *data, int go); static int sbchan_getptr(void *data); static pcmchan_caps *sbchan_getcaps(void *data); -static pcmchan_caps sb_playcaps = { - 4000, 22050, +static u_int32_t sb_playfmt[] = { AFMT_U8, - AFMT_U8 + 0 }; +static pcmchan_caps sb_playcaps = {4000, 22050, sb_playfmt, 0}; -static pcmchan_caps sb_reccaps = { - 4000, 13000, +static u_int32_t sb_recfmt[] = { AFMT_U8, - AFMT_U8 + 0 }; +static pcmchan_caps sb_reccaps = {4000, 13000, sb_recfmt, 0}; -static pcmchan_caps sbpro_playcaps = { - 4000, 45000, +static u_int32_t sbpro_playfmt[] = { + AFMT_U8, AFMT_STEREO | AFMT_U8, - AFMT_STEREO | AFMT_U8 + 0 }; +static pcmchan_caps sbpro_playcaps = {4000, 45000, sbpro_playfmt, 0}; -static pcmchan_caps sbpro_reccaps = { - 4000, 15000, +static u_int32_t sbpro_recfmt[] = { + AFMT_U8, AFMT_STEREO | AFMT_U8, - AFMT_STEREO | AFMT_U8 + 0 }; +static pcmchan_caps sbpro_reccaps = {4000, 15000, sbpro_recfmt, 0}; -static pcmchan_caps sb16_hcaps = { - 5000, 45000, +static u_int32_t sb16_hfmt[] = { + AFMT_S16_LE, AFMT_STEREO | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE + 0 }; +static pcmchan_caps sb16_hcaps = {5000, 45000, sb16_hfmt, 0}; -static pcmchan_caps sb16_lcaps = { - 5000, 45000, +static u_int32_t sb16_lfmt[] = { + AFMT_U8, AFMT_STEREO | AFMT_U8, - AFMT_STEREO | AFMT_U8 + 0 }; +static pcmchan_caps sb16_lcaps = {5000, 45000, sb16_lfmt, 0}; -static pcmchan_caps sb16x_caps = { - 5000, 49000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE +static u_int32_t sb16x_fmt[] = { + AFMT_U8, + AFMT_STEREO | AFMT_U8, + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + 0 }; +static pcmchan_caps sb16x_caps = {5000, 49000, sb16x_fmt, 0}; static pcm_channel sb_chantemplate = { sbchan_init, diff --git a/sys/dev/sound/isa/sb8.c b/sys/dev/sound/isa/sb8.c index f984d5c..d975311 100644 --- a/sys/dev/sound/isa/sb8.c +++ b/sys/dev/sound/isa/sb8.c @@ -49,47 +49,54 @@ static int sbchan_trigger(void *data, int go); static int sbchan_getptr(void *data); static pcmchan_caps *sbchan_getcaps(void *data); -static pcmchan_caps sb_playcaps = { - 4000, 22050, +static u_int32_t sb_playfmt[] = { AFMT_U8, - AFMT_U8 + 0 }; +static pcmchan_caps sb_playcaps = {4000, 22050, sb_playfmt, 0}; -static pcmchan_caps sb_reccaps = { - 4000, 13000, +static u_int32_t sb_recfmt[] = { AFMT_U8, - AFMT_U8 + 0 }; +static pcmchan_caps sb_reccaps = {4000, 13000, sb_recfmt, 0}; -static pcmchan_caps sbpro_playcaps = { - 4000, 45000, +static u_int32_t sbpro_playfmt[] = { + AFMT_U8, AFMT_STEREO | AFMT_U8, - AFMT_STEREO | AFMT_U8 + 0 }; +static pcmchan_caps sbpro_playcaps = {4000, 45000, sbpro_playfmt, 0}; -static pcmchan_caps sbpro_reccaps = { - 4000, 15000, +static u_int32_t sbpro_recfmt[] = { + AFMT_U8, AFMT_STEREO | AFMT_U8, - AFMT_STEREO | AFMT_U8 + 0 }; +static pcmchan_caps sbpro_reccaps = {4000, 15000, sbpro_recfmt, 0}; -static pcmchan_caps sb16_hcaps = { - 5000, 45000, +static u_int32_t sb16_hfmt[] = { + AFMT_S16_LE, AFMT_STEREO | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE + 0 }; +static pcmchan_caps sb16_hcaps = {5000, 45000, sb16_hfmt, 0}; -static pcmchan_caps sb16_lcaps = { - 5000, 45000, +static u_int32_t sb16_lfmt[] = { + AFMT_U8, AFMT_STEREO | AFMT_U8, - AFMT_STEREO | AFMT_U8 + 0 }; +static pcmchan_caps sb16_lcaps = {5000, 45000, sb16_lfmt, 0}; -static pcmchan_caps sb16x_caps = { - 5000, 49000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE +static u_int32_t sb16x_fmt[] = { + AFMT_U8, + AFMT_STEREO | AFMT_U8, + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + 0 }; +static pcmchan_caps sb16x_caps = {5000, 49000, sb16x_fmt, 0}; static pcm_channel sb_chantemplate = { sbchan_init, diff --git a/sys/dev/sound/pci/aureal.c b/sys/dev/sound/pci/aureal.c index e97b689..5b5e47c 100644 --- a/sys/dev/sound/pci/aureal.c +++ b/sys/dev/sound/pci/aureal.c @@ -46,17 +46,23 @@ static int auchan_trigger(void *data, int go); static int auchan_getptr(void *data); static pcmchan_caps *auchan_getcaps(void *data); -static pcmchan_caps au_playcaps = { - 4000, 48000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE +static u_int32_t au_playfmt[] = { + AFMT_U8, + AFMT_STEREO | AFMT_U8, + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + 0 }; - -static pcmchan_caps au_reccaps = { - 4000, 48000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE +static pcmchan_caps au_playcaps = {4000, 48000, au_playfmt, 0}; + +static u_int32_t au_recfmt[] = { + AFMT_U8, + AFMT_STEREO | AFMT_U8, + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + 0 }; +static pcmchan_caps au_reccaps = {4000, 48000, au_recfmt, 0}; static pcm_channel au_chantemplate = { auchan_init, diff --git a/sys/dev/sound/pci/csapcm.c b/sys/dev/sound/pci/csapcm.c index 6eb67c4..f0ea0a3 100644 --- a/sys/dev/sound/pci/csapcm.c +++ b/sys/dev/sound/pci/csapcm.c @@ -96,17 +96,25 @@ static int csachan_trigger(void *data, int go); static int csachan_getptr(void *data); static pcmchan_caps *csachan_getcaps(void *data); -static pcmchan_caps csa_playcaps = { - 8000, 48000, - AFMT_STEREO | AFMT_U8 | AFMT_S8 | AFMT_S16_LE | AFMT_S16_BE, - AFMT_STEREO | AFMT_S16_LE +static u_int32_t csa_playfmt[] = { + AFMT_U8, + AFMT_STEREO | AFMT_U8, + AFMT_S8, + AFMT_STEREO | AFMT_S8, + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + AFMT_S16_BE, + AFMT_STEREO | AFMT_S16_BE, + 0 }; +static pcmchan_caps csa_playcaps = {8000, 48000, csa_playfmt, 0}; -static pcmchan_caps csa_reccaps = { - 11025, 48000, +static u_int32_t csa_recfmt[] = { + AFMT_S16_LE, AFMT_STEREO | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE + 0 }; +static pcmchan_caps csa_reccaps = {11025, 48000, csa_recfmt, 0}; static pcm_channel csa_chantemplate = { csachan_init, diff --git a/sys/dev/sound/pci/ds1.c b/sys/dev/sound/pci/ds1.c index 07b0918..6932ee0 100644 --- a/sys/dev/sound/pci/ds1.c +++ b/sys/dev/sound/pci/ds1.c @@ -184,17 +184,27 @@ static void ds_wr(struct sc_info *, int, u_int32_t, int); /* -------------------------------------------------------------------- */ -static pcmchan_caps ds_reccaps = { - 4000, 48000, - AFMT_STEREO | AFMT_U8 | AFMT_S8 | AFMT_S16_LE | AFMT_U16_LE, - AFMT_STEREO | AFMT_S16_LE +static u_int32_t ds_recfmt[] = { + AFMT_U8, + AFMT_STEREO | AFMT_U8, + AFMT_S8, + AFMT_STEREO | AFMT_S8, + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + AFMT_U16_LE, + AFMT_STEREO | AFMT_U16_LE, + 0 }; - -static pcmchan_caps ds_playcaps = { - 4000, 96000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE +static pcmchan_caps ds_reccaps = {4000, 48000, ds_recfmt, 0}; + +static u_int32_t ds_playfmt[] = { + AFMT_U8, + AFMT_STEREO | AFMT_U8, + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + 0 }; +static pcmchan_caps ds_playcaps = {4000, 96000, ds_playfmt, 0}; static pcm_channel ds_pchantemplate = { ds1pchan_init, diff --git a/sys/dev/sound/pci/emu10k1.c b/sys/dev/sound/pci/emu10k1.c index d31b21c..584c2a7 100644 --- a/sys/dev/sound/pci/emu10k1.c +++ b/sys/dev/sound/pci/emu10k1.c @@ -154,18 +154,38 @@ static void emu_wr(struct sc_info *, int, u_int32_t, int); /* -------------------------------------------------------------------- */ +static u_int32_t emu_rfmt_ac97[] = { + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + 0 +}; + +static u_int32_t emu_rfmt_mic[] = { + AFMT_U8, + 0 +}; + +static u_int32_t emu_rfmt_efx[] = { + AFMT_STEREO | AFMT_S16_LE, + 0 +}; + static pcmchan_caps emu_reccaps[3] = { - {8000, 48000, AFMT_STEREO | AFMT_S16_LE, AFMT_STEREO | AFMT_S16_LE}, - {8000, 8000, AFMT_U8, AFMT_U8}, - {48000, 48000, AFMT_STEREO | AFMT_S16_LE, AFMT_STEREO | AFMT_S16_LE}, + {8000, 48000, emu_rfmt_ac97, 0}, + {8000, 8000, emu_rfmt_mic, 0}, + {48000, 48000, emu_rfmt_efx, 0}, }; -static pcmchan_caps emu_playcaps = { - 4000, 48000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE +static u_int32_t emu_pfmt[] = { + AFMT_U8, + AFMT_STEREO | AFMT_U8, + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + 0 }; +static pcmchan_caps emu_playcaps = {4000, 48000, emu_pfmt, 0}; + static pcm_channel emu_chantemplate = { emupchan_init, emupchan_setdir, diff --git a/sys/dev/sound/pci/es137x.c b/sys/dev/sound/pci/es137x.c index 0664dbc..b4ce4da 100644 --- a/sys/dev/sound/pci/es137x.c +++ b/sys/dev/sound/pci/es137x.c @@ -122,17 +122,23 @@ static int eschan_trigger(void *data, int go); static int eschan_getptr(void *data); static pcmchan_caps *eschan_getcaps(void *data); -static pcmchan_caps es_playcaps = { - 4000, 48000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE +static u_int32_t es_playfmt[] = { + AFMT_U8, + AFMT_STEREO | AFMT_U8, + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + 0 }; - -static pcmchan_caps es_reccaps = { - 4000, 48000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE +static pcmchan_caps es_playcaps = {4000, 48000, es_playfmt, 0}; + +static u_int32_t es_recfmt[] = { + AFMT_U8, + AFMT_STEREO | AFMT_U8, + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + 0 }; +static pcmchan_caps es_reccaps = {4000, 48000, es_recfmt, 0}; static pcm_channel es1370_chantemplate = { eschan_init, diff --git a/sys/dev/sound/pci/neomagic.c b/sys/dev/sound/pci/neomagic.c index 90006b7..f7a864f 100644 --- a/sys/dev/sound/pci/neomagic.c +++ b/sys/dev/sound/pci/neomagic.c @@ -125,11 +125,14 @@ static int samplerates[9] = { /* -------------------------------------------------------------------- */ -static pcmchan_caps nm_caps = { - 4000, 48000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE +static u_int32_t nm_fmt[] = { + AFMT_U8, + AFMT_STEREO | AFMT_U8, + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + 0 }; +static pcmchan_caps nm_caps = {4000, 48000, nm_fmt, 0}; static pcm_channel nm_chantemplate = { nmchan_init, diff --git a/sys/dev/sound/pci/solo.c b/sys/dev/sound/pci/solo.c index 8c1f7bb..cd69868 100644 --- a/sys/dev/sound/pci/solo.c +++ b/sys/dev/sound/pci/solo.c @@ -52,20 +52,34 @@ static int esschan_trigger(void *data, int go); static int esschan_getptr(void *data); static pcmchan_caps *esschan_getcaps(void *data); -static pcmchan_caps ess_playcaps = { - 5000, 49000, - AFMT_STEREO | AFMT_U8 | AFMT_S8 | AFMT_U16_LE | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE +static u_int32_t ess_playfmt[] = { + AFMT_U8, + AFMT_STEREO | AFMT_U8, + AFMT_S8, + AFMT_STEREO | AFMT_S8, + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + AFMT_U16_LE, + AFMT_STEREO | AFMT_U16_LE, + 0 }; +static pcmchan_caps ess_playcaps = {5000, 49000, ess_playfmt, 0}; /* * Recording output is byte-swapped */ -static pcmchan_caps ess_reccaps = { - 5000, 49000, - AFMT_STEREO | AFMT_U8 | AFMT_S8 | AFMT_U16_BE | AFMT_S16_BE, - AFMT_STEREO | AFMT_S16_BE +static u_int32_t ess_recfmt[] = { + AFMT_U8, + AFMT_STEREO | AFMT_U8, + AFMT_S8, + AFMT_STEREO | AFMT_S8, + AFMT_S16_BE, + AFMT_STEREO | AFMT_S16_BE, + AFMT_U16_BE, + AFMT_STEREO | AFMT_U16_BE, + 0 }; +static pcmchan_caps ess_reccaps = {5000, 49000, ess_recfmt, 0}; static pcm_channel ess_chantemplate = { esschan_init, diff --git a/sys/dev/sound/pci/t4dwave.c b/sys/dev/sound/pci/t4dwave.c index 01c6220..83b38aa 100644 --- a/sys/dev/sound/pci/t4dwave.c +++ b/sys/dev/sound/pci/t4dwave.c @@ -115,17 +115,31 @@ static void tr_stopch(struct tr_info *, char); /* -------------------------------------------------------------------- */ -static pcmchan_caps tr_reccaps = { - 4000, 48000, - AFMT_STEREO | AFMT_U8 | AFMT_S8 | AFMT_S16_LE | AFMT_U16_LE, - AFMT_STEREO | AFMT_S16_LE +static u_int32_t tr_recfmt[] = { + AFMT_U8, + AFMT_STEREO | AFMT_U8, + AFMT_S8, + AFMT_STEREO | AFMT_S8, + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + AFMT_U16_LE, + AFMT_STEREO | AFMT_U16_LE, + 0 }; - -static pcmchan_caps tr_playcaps = { - 4000, 48000, - AFMT_STEREO | AFMT_U8 | AFMT_S8 | AFMT_S16_LE | AFMT_U16_LE, - AFMT_STEREO | AFMT_S16_LE +static pcmchan_caps tr_reccaps = {4000, 48000, tr_recfmt, 0}; + +static u_int32_t tr_playfmt[] = { + AFMT_U8, + AFMT_STEREO | AFMT_U8, + AFMT_S8, + AFMT_STEREO | AFMT_S8, + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + AFMT_U16_LE, + AFMT_STEREO | AFMT_U16_LE, + 0 }; +static pcmchan_caps tr_playcaps = {4000, 48000, tr_playfmt, 0}; static pcm_channel tr_chantemplate = { trchan_init, diff --git a/sys/dev/sound/pci/via82c686.c b/sys/dev/sound/pci/via82c686.c index 98ca7bf..5c9c6c5 100644 --- a/sys/dev/sound/pci/via82c686.c +++ b/sys/dev/sound/pci/via82c686.c @@ -85,17 +85,23 @@ static int viachan_trigger(void *data, int go); static int viachan_getptr(void *data); static pcmchan_caps *viachan_getcaps(void *data); -static pcmchan_caps via_playcaps = { - 4000, 48000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE +static u_int32_t via_playfmt[] = { + AFMT_U8, + AFMT_STEREO | AFMT_U8, + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + 0 }; - -static pcmchan_caps via_reccaps = { - 4000, 48000, - AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE +static pcmchan_caps via_playcaps = {4000, 48000, via_playfmt, 0}; + +static u_int32_t via_recfmt[] = { + AFMT_U8, + AFMT_STEREO | AFMT_U8, + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + 0 }; +static pcmchan_caps via_reccaps = {4000, 48000, via_recfmt, 0}; static pcm_channel via_chantemplate = { viachan_init, diff --git a/sys/dev/sound/pcm/channel.c b/sys/dev/sound/pcm/channel.c index cd40903..d461ba3 100644 --- a/sys/dev/sound/pcm/channel.c +++ b/sys/dev/sound/pcm/channel.c @@ -1127,8 +1127,18 @@ chn_init(pcm_channel *c, void *devinfo, int dir) snd_dbuf *bs = &c->buffer2nd; /* Initialize the hardware and DMA buffer first. */ + c->feeder = malloc(sizeof(*(c->feeder)), M_DEVBUF, M_NOWAIT); + *(c->feeder) = *feeder_getroot(); + c->feederdesc = malloc(sizeof(*(c->feeder)), M_DEVBUF, M_NOWAIT); + c->feederdesc->type = FEEDER_ROOT; + c->feederdesc->in = 0; + c->feederdesc->out = 0; + c->feederdesc->flags = 0; + c->feederdesc->idx = 0; + c->feeder->desc = c->feederdesc; + c->feeder->source = NULL; + c->flags = 0; - c->feeder = &feeder_root; c->buffer.chan = -1; c->devinfo = c->init(devinfo, &c->buffer, c, dir); if (c->devinfo == NULL || c->buffer.bufsize == 0) @@ -1182,6 +1192,18 @@ chn_setspeed(pcm_channel *c, int speed) } int +fmtvalid(u_int32_t fmt, u_int32_t *fmtlist) +{ + int i; + + for (i = 0; fmtlist[i]; i++) + if (fmt == fmtlist[i]) + return 1; + + return 0; +} + +int chn_setformat(pcm_channel *c, u_int32_t fmt) { snd_dbuf *b = &c->buffer; @@ -1189,10 +1211,17 @@ chn_setformat(pcm_channel *c, u_int32_t fmt) u_int32_t hwfmt; if (CANCHANGE(c)) { + while (chn_removefeeder(c) == 0); c->format = fmt; - hwfmt = chn_feedchain(c); - if ((c->flags & CHN_F_MAPPED) && c->format != hwfmt) - return EINVAL; + c->feederdesc->out = c->format; + hwfmt = c->format; + if (!fmtvalid(hwfmt, chn_getcaps(c)->fmtlist)) { + if (c->flags & CHN_F_MAPPED) + return EINVAL; + hwfmt = chn_feedchain(c, chn_getcaps(c)->fmtlist); + if (hwfmt == 0) + return EINVAL; + } b->fmt = hwfmt; bs->fmt = hwfmt; chn_resetbuf(c); @@ -1287,3 +1316,19 @@ chn_getcaps(pcm_channel *c) { return c->getcaps(c->devinfo); } + +u_int32_t +chn_getformats(pcm_channel *c) +{ + u_int32_t *fmtlist, fmts; + int i; + + fmtlist = chn_getcaps(c)->fmtlist; + fmts = 0; + for (i = 0; fmtlist[i]; i++) + fmts |= fmtlist[i]; + + return fmts; +} + + diff --git a/sys/dev/sound/pcm/channel.h b/sys/dev/sound/pcm/channel.h index 23e31df..3f6a359 100644 --- a/sys/dev/sound/pcm/channel.h +++ b/sys/dev/sound/pcm/channel.h @@ -43,6 +43,7 @@ int chn_setblocksize(pcm_channel *c, int blkcnt, int blksz); int chn_trigger(pcm_channel *c, int go); int chn_getptr(pcm_channel *c); pcmchan_caps *chn_getcaps(pcm_channel *c); +u_int32_t chn_getformats(pcm_channel *c); int chn_allocbuf(snd_dbuf *b, bus_dma_tag_t parent_dmat); void chn_resetbuf(pcm_channel *c); @@ -52,11 +53,10 @@ int chn_wrfeed(pcm_channel *c); int chn_rdfeed(pcm_channel *c); int chn_abort(pcm_channel *c); +int fmtvalid(u_int32_t fmt, u_int32_t *fmtlist); + void buf_isadma(snd_dbuf *b, int go); int buf_isadmaptr(snd_dbuf *b); -int chn_feedchain(pcm_channel *c); - -extern pcm_feeder feeder_root; #define PCMDIR_PLAY 1 #define PCMDIR_REC -1 diff --git a/sys/dev/sound/pcm/datatypes.h b/sys/dev/sound/pcm/datatypes.h index 716c21b..6f831e5 100644 --- a/sys/dev/sound/pcm/datatypes.h +++ b/sys/dev/sound/pcm/datatypes.h @@ -78,9 +78,24 @@ typedef int (pcmfeed_free_t)(pcm_feeder *feeder); typedef int (pcmfeed_feed_t)(pcm_feeder *feeder, pcm_channel *c, u_int8_t *buffer, u_int32_t count, struct uio *stream); +#define FEEDER_ROOT 1 +#define FEEDER_FMT 2 +#define FEEDER_RATE 3 +#define FEEDER_FILTER 4 + +struct pcm_feederdesc { + u_int32_t type; + u_int32_t in, out; + u_int32_t flags; + int idx; +}; + +#define MAXFEEDERS 256 + struct _pcm_feeder { char name[16]; int align; + struct pcm_feederdesc *desc; pcmfeed_init_t *init; pcmfeed_free_t *free; pcmfeed_feed_t *feed; @@ -90,7 +105,8 @@ struct _pcm_feeder { struct _pcmchan_caps { u_int32_t minspeed, maxspeed; - u_int32_t formats, bestfmt; + u_int32_t *fmtlist; + u_int32_t caps; }; typedef void *(pcmchan_init_t)(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); @@ -112,6 +128,7 @@ struct _pcm_channel { pcmchan_getptr_t *getptr; pcmchan_getcaps_t *getcaps; pcm_feeder *feeder; + struct pcm_feederdesc *feederdesc; u_int32_t align; int volume; diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c index 19bfd96..9bd8bc5 100644 --- a/sys/dev/sound/pcm/dsp.c +++ b/sys/dev/sound/pcm/dsp.c @@ -283,8 +283,8 @@ dsp_ioctl(snddev_info *d, int chan, u_long cmd, caddr_t arg) p->bufsize = min(rdch? rdch->buffer2nd.bufsize : 1000000, wrch? wrch->buffer2nd.bufsize : 1000000); /* XXX bad on sb16 */ - p->formats = (rcaps? rcaps->formats : 0xffffffff) & - (pcaps? pcaps->formats : 0xffffffff); + p->formats = (rdch? chn_getformats(rdch) : 0xffffffff) & + (wrch? chn_getformats(wrch) : 0xffffffff); if (rdch && wrch) p->formats |= (d->flags & SD_F_SIMPLEX)? 0 : AFMT_FULLDUPLEX; p->mixers = 1; /* default: one mixer */ @@ -406,7 +406,7 @@ dsp_ioctl(snddev_info *d, int chan, u_long cmd, caddr_t arg) break; case SNDCTL_DSP_GETFMTS: /* returns a mask of supported fmts */ - *arg_i = wrch? chn_getcaps(wrch)->formats : chn_getcaps(rdch)->formats; + *arg_i = wrch? chn_getformats(wrch) : chn_getformats(rdch); break ; case SNDCTL_DSP_SETFMT: /* sets _one_ format */ diff --git a/sys/dev/sound/pcm/fake.c b/sys/dev/sound/pcm/fake.c index d3368c0..9cdb1f6 100644 --- a/sys/dev/sound/pcm/fake.c +++ b/sys/dev/sound/pcm/fake.c @@ -38,10 +38,22 @@ static int fkchan_trigger(void *data, int go); static int fkchan_getptr(void *data); static pcmchan_caps *fkchan_getcaps(void *data); -static pcmchan_caps fk_caps = { - 4000, 48000, - AFMT_STEREO | AFMT_U8 | AFMT_S8 | AFMT_S16_LE | AFMT_S16_BE | AFMT_U16_LE | AFMT_U16_BE +static u_int32_t fk_fmt[] = { + AFMT_U8, + AFMT_STEREO | AFMT_U8, + AFMT_S8, + AFMT_STEREO | AFMT_S8, + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + AFMT_U16_LE, + AFMT_STEREO | AFMT_U16_LE, + AFMT_S16_BE, + AFMT_STEREO | AFMT_S16_BE, + AFMT_U16_BE, + AFMT_STEREO | AFMT_U16_BE, + 0 }; +static pcmchan_caps fk_caps = {4000, 48000, fk_fmt, 0}; static pcm_channel fk_chantemplate = { fkchan_init, diff --git a/sys/dev/sound/pcm/feeder.c b/sys/dev/sound/pcm/feeder.c index 5eaf89a..91049e6 100644 --- a/sys/dev/sound/pcm/feeder.c +++ b/sys/dev/sound/pcm/feeder.c @@ -28,9 +28,6 @@ #include <dev/sound/pcm/sound.h> -static int chn_addfeeder(pcm_channel *c, pcm_feeder *f); -static int chn_removefeeder(pcm_channel *c); - #define FEEDBUFSZ 8192 static unsigned char ulaw_to_u8[] = { @@ -103,15 +100,65 @@ static unsigned char u8_to_ulaw[] = { 129, 129, 129, 129, 128, 128, 128, 128, }; +struct feedertab_entry { + SLIST_ENTRY(feedertab_entry) link; + pcm_feeder *feeder; + struct pcm_feederdesc *desc; + + int idx; +}; +static SLIST_HEAD(, feedertab_entry) feedertab; + +/*****************************************************************************/ + +void +feeder_register(void *p) +{ + pcm_feeder *f = p; + struct feedertab_entry *fte; + static int feedercnt = 0; + int i; + + if (feedercnt == 0) { + if (f->desc) + panic("FIRST FEEDER NOT ROOT: %s\n", f->name); + SLIST_INIT(&feedertab); + fte = malloc(sizeof(*fte), M_DEVBUF, M_NOWAIT); + fte->feeder = f; + fte->desc = NULL; + fte->idx = feedercnt; + SLIST_INSERT_HEAD(&feedertab, fte, link); + feedercnt++; + return; + } + /* printf("installing feeder: %s\n", f->name); */ + + i = 0; + while ((feedercnt < MAXFEEDERS) && (f->desc[i].type > 0)) { + fte = malloc(sizeof(*fte), M_DEVBUF, M_NOWAIT); + fte->feeder = f; + fte->desc = &f->desc[i]; + fte->idx = feedercnt; + fte->desc->idx = feedercnt; + SLIST_INSERT_HEAD(&feedertab, fte, link); + i++; + } + feedercnt++; + if (feedercnt >= MAXFEEDERS) + printf("MAXFEEDERS exceeded\n"); +} + /*****************************************************************************/ static int feed_root(pcm_feeder *feeder, pcm_channel *ch, u_int8_t *buffer, u_int32_t count, struct uio *stream) { - int ret, c = 0, s; + int ret, s; + KASSERT(count, ("feed_root: count == 0")); count &= ~((1 << ch->align) - 1); KASSERT(count, ("feed_root: aligned count == 0")); + s = spltty(); count = min(count, stream->uio_resid); if (count) { @@ -119,16 +166,19 @@ feed_root(pcm_feeder *feeder, pcm_channel *ch, u_int8_t *buffer, u_int32_t count KASSERT(ret == 0, ("feed_root: uiomove failed")); } splx(s); - return c + count; + + return count; } -pcm_feeder feeder_root = { "root", 0, NULL, NULL, feed_root }; +static pcm_feeder feeder_root = { "root", 0, NULL, NULL, NULL, feed_root }; +SYSINIT(feeder_root, SI_SUB_DRIVERS, SI_ORDER_FIRST, feeder_register, &feeder_root); /*****************************************************************************/ static int -feed_8to16(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct uio *stream) +feed_8to16le(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct uio *stream) { int i, j, k; + k = f->source->feed(f->source, c, b, count / 2, stream); j = k - 1; i = j * 2 + 1; @@ -138,7 +188,17 @@ feed_8to16(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct u } return k * 2; } -static pcm_feeder feeder_8to16 = { "8to16", 0, NULL, NULL, feed_8to16 }; + +static struct pcm_feederdesc desc_8to16le[] = { + {FEEDER_FMT, AFMT_U8, AFMT_U16_LE, 0}, + {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0}, + {FEEDER_FMT, AFMT_S8, AFMT_S16_LE, 0}, + {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0}, + {0}, +}; +static pcm_feeder feeder_8to16le = + { "8to16le", 0, desc_8to16le, NULL, NULL, feed_8to16le }; +SYSINIT(feeder_8to16le, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, feeder_register, &feeder_8to16le); /*****************************************************************************/ @@ -158,10 +218,11 @@ feed_16to8_free(pcm_feeder *f) } static int -feed_16to8le(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct uio *stream) +feed_16leto8(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct uio *stream) { u_int32_t i = 0, toget = count * 2; int j = 1, k; + k = f->source->feed(f->source, c, f->data, min(toget, FEEDBUFSZ), stream); while (j < k) { b[i++] = ((u_int8_t *)f->data)[j]; @@ -169,8 +230,17 @@ feed_16to8le(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct } return i; } -static pcm_feeder feeder_16to8le = - { "16to8le", 1, feed_16to8_init, feed_16to8_free, feed_16to8le }; + +static struct pcm_feederdesc desc_16leto8[] = { + {FEEDER_FMT, AFMT_U16_LE, AFMT_U8, 0}, + {FEEDER_FMT, AFMT_U16_LE | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0}, + {FEEDER_FMT, AFMT_S16_LE, AFMT_S8, 0}, + {FEEDER_FMT, AFMT_S16_LE | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0}, + {0}, +}; +static pcm_feeder feeder_16leto8 = + { "16leto8", 1, desc_16leto8, feed_16to8_init, feed_16to8_free, feed_16leto8 }; +SYSINIT(feeder_16leto8, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, feeder_register, &feeder_16leto8); /*****************************************************************************/ @@ -178,6 +248,7 @@ static int feed_monotostereo8(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct uio *stream) { int i, j, k = f->source->feed(f->source, c, b, count / 2, stream); + j = k - 1; i = j * 2 + 1; while (i > 0 && j >= 0) { @@ -187,8 +258,15 @@ feed_monotostereo8(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, } return k * 2; } + +static struct pcm_feederdesc desc_monotostereo8[] = { + {FEEDER_FMT, AFMT_U8, AFMT_U8 | AFMT_STEREO, 0}, + {FEEDER_FMT, AFMT_S8, AFMT_S8 | AFMT_STEREO, 0}, + {0}, +}; static pcm_feeder feeder_monotostereo8 = - { "monotostereo8", 0, NULL, NULL, feed_monotostereo8 }; + { "monotostereo8", 0, desc_monotostereo8, NULL, NULL, feed_monotostereo8 }; +SYSINIT(feeder_monotostereo8, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, feeder_register, &feeder_monotostereo8); /*****************************************************************************/ @@ -212,6 +290,7 @@ feed_stereotomono8(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, { u_int32_t i = 0, toget = count * 2; int j = 0, k; + k = f->source->feed(f->source, c, f->data, min(toget, FEEDBUFSZ), stream); while (j < k) { b[i++] = ((u_int8_t *)f->data)[j]; @@ -219,9 +298,15 @@ feed_stereotomono8(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, } return i; } + +static struct pcm_feederdesc desc_stereotomono8[] = { + {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_U8, 0}, + {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_S8, 0}, + {0}, +}; static pcm_feeder feeder_stereotomono8 = - { "stereotomono8", 1, feed_stereotomono8_init, feed_stereotomono8_free, - feed_stereotomono8 }; + { "stereotomono8", 1, desc_stereotomono8, feed_stereotomono8_init, feed_stereotomono8_free, feed_stereotomono8 }; +SYSINIT(feeder_stereotomono8, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, feeder_register, &feeder_stereotomono8); /*****************************************************************************/ @@ -230,6 +315,7 @@ feed_endian(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct { u_int8_t t; int i = 0, j = f->source->feed(f->source, c, b, count, stream); + while (i < j) { t = b[i]; b[i] = b[i + 1]; @@ -238,7 +324,20 @@ feed_endian(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct } return i; } -static pcm_feeder feeder_endian = { "endian", -1, NULL, NULL, feed_endian }; + +static struct pcm_feederdesc desc_endian[] = { + {FEEDER_FMT, AFMT_U16_LE, AFMT_U16_BE, 0}, + {FEEDER_FMT, AFMT_U16_LE | AFMT_STEREO, AFMT_U16_BE | AFMT_STEREO, 0}, + {FEEDER_FMT, AFMT_S16_LE, AFMT_S16_BE, 0}, + {FEEDER_FMT, AFMT_S16_LE | AFMT_STEREO, AFMT_S16_BE | AFMT_STEREO, 0}, + {FEEDER_FMT, AFMT_U16_BE, AFMT_U16_LE, 0}, + {FEEDER_FMT, AFMT_U16_BE | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0}, + {FEEDER_FMT, AFMT_S16_BE, AFMT_S16_LE, 0}, + {FEEDER_FMT, AFMT_S16_BE | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0}, + {0}, +}; +static pcm_feeder feeder_endian = { "endian", -1, desc_endian, NULL, NULL, feed_endian }; +SYSINIT(feeder_endian, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, feeder_register, &feeder_endian); /*****************************************************************************/ @@ -247,16 +346,35 @@ feed_sign(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct ui { int i = 0, j = f->source->feed(f->source, c, b, count, stream); int ssz = (int)f->data, ofs = ssz - 1; + while (i < j) { b[i + ofs] ^= 0x80; i += ssz; } return i; } + +static struct pcm_feederdesc desc_sign8[] = { + {FEEDER_FMT, AFMT_U8, AFMT_S8, 0}, + {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0}, + {FEEDER_FMT, AFMT_S8, AFMT_U8, 0}, + {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0}, + {0}, +}; static pcm_feeder feeder_sign8 = - { "sign8", 0, NULL, NULL, feed_sign, (void *)1 }; -static pcm_feeder feeder_sign16 = - { "sign16", -1, NULL, NULL, feed_sign, (void *)2 }; + { "sign8", 0, desc_sign8, NULL, NULL, feed_sign, (void *)1 }; +SYSINIT(feeder_sign8, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, feeder_register, &feeder_sign8); + +static struct pcm_feederdesc desc_sign16le[] = { + {FEEDER_FMT, AFMT_U16_LE, AFMT_S16_LE, 0}, + {FEEDER_FMT, AFMT_U16_LE | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0}, + {FEEDER_FMT, AFMT_S16_LE, AFMT_U16_LE, 0}, + {FEEDER_FMT, AFMT_S16_LE | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0}, + {0}, +}; +static pcm_feeder feeder_sign16le = + { "sign16le", -1, desc_sign16le, NULL, NULL, feed_sign, (void *)2 }; +SYSINIT(feeder_sign16le, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, feeder_register, &feeder_sign16le); /*****************************************************************************/ @@ -264,147 +382,172 @@ static int feed_table(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct uio *stream) { int i = 0, j = f->source->feed(f->source, c, b, count, stream); + while (i < j) { b[i] = ((u_int8_t *)f->data)[b[i]]; i++; } return i; } -static pcm_feeder feeder_ulawtou8 = - { "ulawtou8", 0, NULL, NULL, feed_table, ulaw_to_u8 }; -static pcm_feeder feeder_u8toulaw = - { "u8toulaw", 0, NULL, NULL, feed_table, u8_to_ulaw }; -/*****************************************************************************/ - -struct fmtspec { - int stereo; - int sign; - int bit16; - int bigendian; - int ulaw; - int bad; +static struct pcm_feederdesc desc_ulawtou8[] = { + {FEEDER_FMT, AFMT_MU_LAW, AFMT_U8, 0}, + {FEEDER_FMT, AFMT_MU_LAW | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0}, + {0}, }; +static pcm_feeder feeder_ulawtou8 = + { "ulawtou8", 0, desc_ulawtou8, NULL, NULL, feed_table, ulaw_to_u8 }; +SYSINIT(feeder_ulawtou8, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, feeder_register, &feeder_ulawtou8); -struct fmtcvt { - pcm_feeder *f; - struct fmtspec ispec, ospec; +static struct pcm_feederdesc desc_u8toulaw[] = { + {FEEDER_FMT, AFMT_U8, AFMT_MU_LAW, 0}, + {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_MU_LAW | AFMT_STEREO, 0}, + {0}, }; +static pcm_feeder feeder_u8toulaw = + { "u8toulaw", 0, desc_u8toulaw, NULL, NULL, feed_table, u8_to_ulaw }; +SYSINIT(feeder_u8toulaw, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, feeder_register, &feeder_u8toulaw); -struct fmtcvt cvttab[] = { - {&feeder_ulawtou8, {-1, 0, 0, 0, 1}, {-1, 0, 0, 0, 0}}, - {&feeder_u8toulaw, {-1, 0, 0, 0, 0}, {-1, 0, 0, 0, 1}}, - {&feeder_sign8, {-1, 0, 0, 0, 0}, {-1, 1, 0, 0, 0}}, - {&feeder_sign8, {-1, 1, 0, 0, 0}, {-1, 0, 0, 0, 0}}, - {&feeder_monotostereo8, { 0, -1, 0, 0, -1}, { 1, -1, 0, 0, -1}}, - {&feeder_stereotomono8, { 1, -1, 0, 0, -1}, { 0, -1, 0, 0, -1}}, - {&feeder_sign16, {-1, 0, 1, 0, 0}, {-1, 1, 1, 0, 0}}, - {&feeder_sign16, {-1, 1, 1, 0, 0}, {-1, 0, 1, 0, 0}}, - {&feeder_8to16, {-1, -1, 0, 0, 0}, {-1, -1, 1, 0, 0}}, - {&feeder_16to8le, {-1, -1, 1, 0, 0}, {-1, -1, 0, 0, 0}}, - {&feeder_endian, {-1, -1, 1, 0, 0}, {-1, -1, 1, 1, 0}}, - {&feeder_endian, {-1, -1, 1, 1, 0}, {-1, -1, 1, 0, 0}}, -}; -#define FEEDERTABSZ (sizeof(cvttab) / sizeof(struct fmtcvt)) +/*****************************************************************************/ static int -getspec(u_int32_t fmt, struct fmtspec *spec) +cmpdesc(struct pcm_feederdesc *n, struct pcm_feederdesc *m) { - spec->stereo = (fmt & AFMT_STEREO)? 1 : 0; - spec->sign = (fmt & AFMT_SIGNED)? 1 : 0; - spec->bit16 = (fmt & AFMT_16BIT)? 1 : 0; - spec->bigendian = (fmt & AFMT_BIGENDIAN)? 1 : 0; - spec->ulaw = (fmt & AFMT_MU_LAW)? 1 : 0; - spec->bad = (fmt & (AFMT_A_LAW | AFMT_MPEG))? 1 : 0; - return 0; + return ((n->type == m->type) && (n->in == m->in) && (n->out == m->out) && (n->flags == m->flags)); } -static int -cmp(int x, int y) +pcm_feeder * +feeder_get(struct pcm_feederdesc *desc) { - return (x == -1 || x == y || y == -1)? 1 : 0; -} + struct feedertab_entry *fte; -static int -cmpspec(struct fmtspec *x, struct fmtspec *y) -{ - int i = 0; - if (cmp(x->stereo, y->stereo)) i |= 0x01; - if (cmp(x->sign, y->sign)) i |= 0x02; - if (cmp(x->bit16, y->bit16)) i |= 0x04; - if (cmp(x->bigendian, y->bigendian)) i |= 0x08; - if (cmp(x->ulaw, y->ulaw)) i |= 0x10; - return i; + SLIST_FOREACH(fte, &feedertab, link) { + if ((fte->desc != NULL) && cmpdesc(desc, fte->desc)) + return fte->feeder; + } + return NULL; } -static int -cvtapply(pcm_channel *c, struct fmtcvt *cvt, struct fmtspec *s) +pcm_feeder * +feeder_getroot() { - int i = cmpspec(s, &cvt->ospec); - chn_addfeeder(c, cvt->f); - if (cvt->ospec.stereo != -1) s->stereo = cvt->ospec.stereo; - if (cvt->ospec.sign != -1) s->sign = cvt->ospec.sign; - if (cvt->ospec.bit16 != -1) s->bit16 = cvt->ospec.bit16; - if (cvt->ospec.bigendian != -1) s->bigendian = cvt->ospec.bigendian; - if (cvt->ospec.ulaw != -1) s->ulaw = cvt->ospec.ulaw; - return i; + struct feedertab_entry *fte; + + SLIST_FOREACH(fte, &feedertab, link) { + if (fte->desc == NULL) + return fte->feeder; + } + return NULL; } int -chn_feedchain(pcm_channel *c) +chn_removefeeder(pcm_channel *c) { - int i, chosen, iter; - u_int32_t mask; - struct fmtspec s, t; - struct fmtcvt *e; + pcm_feeder *f; - while (chn_removefeeder(c) != -1); - c->align = 0; - if ((c->format & chn_getcaps(c)->formats) == c->format) - return c->format; - getspec(c->format, &s); - if (s.bad) return -1; - getspec(chn_getcaps(c)->bestfmt, &t); - mask = (~cmpspec(&s, &t)) & 0x1f; - iter = 0; - do { - if (mask == 0 || iter >= 8) break; - chosen = -1; - for (i = 0; i < FEEDERTABSZ && chosen == -1; i++) { - e = &cvttab[i]; - if ((cmpspec(&s, &e->ispec) == 0x1f) && - ((~cmpspec(&e->ispec, &e->ospec)) & mask)) - chosen = i; - } - if (chosen != -1) mask &= cvtapply(c, &cvttab[chosen], &s); - iter++; - } while (chosen != -1); - return (iter < 8)? chn_getcaps(c)->bestfmt : -1; + if (c->feeder->source == NULL) + return -1; + f = c->feeder->source; + if (c->feeder->free) + c->feeder->free(c->feeder); + free(c->feeder, M_DEVBUF); + c->feeder = f; + return 0; } static int -chn_addfeeder(pcm_channel *c, pcm_feeder *f) +chainok(pcm_feeder *test, pcm_feeder *stop) { - pcm_feeder *n; - n = malloc(sizeof(pcm_feeder), M_DEVBUF, M_NOWAIT); - *n = *f; - n->source = c->feeder; - c->feeder = n; - if (n->init) n->init(n); - if (n->align > 0) c->align += n->align; - else if (n->align < 0 && c->align < -n->align) c->align -= n->align; - return 0; + u_int32_t visited[MAXFEEDERS / 32]; + u_int32_t idx, mask; + + bzero(visited, sizeof(visited)); + while (test && (test != stop)) { + idx = test->desc->idx; + if (idx < 0) + panic("bad idx %d", idx); + if (idx >= MAXFEEDERS) + panic("bad idx %d", idx); + mask = 1 << (idx & 31); + idx >>= 5; + if (visited[idx] & mask) + return 0; + visited[idx] |= mask; + test = test->source; + } + return 1; } -static int -chn_removefeeder(pcm_channel *c) +static pcm_feeder * +feeder_fmtchain(u_int32_t *to, pcm_feeder *source, pcm_feeder *stop, int maxdepth) { - pcm_feeder *f; - if (c->feeder == &feeder_root) return -1; - f = c->feeder->source; - if (c->feeder->free) c->feeder->free(c->feeder); - free(c->feeder, M_DEVBUF); - c->feeder = f; - return 0; + struct feedertab_entry *fte; + pcm_feeder *try, *ret; + struct pcm_feederdesc *trydesc; + + /* printf("trying %s...\n", source->name); */ + if (fmtvalid(source->desc->out, to)) { + /* printf("got it\n"); */ + return source; + } + + if (maxdepth < 0) + return NULL; + + try = malloc(sizeof(*try), M_DEVBUF, M_NOWAIT); + trydesc = malloc(sizeof(*trydesc), M_DEVBUF, M_NOWAIT); + trydesc->type = FEEDER_FMT; + trydesc->in = source->desc->out; + trydesc->out = 0; + trydesc->flags = 0; + trydesc->idx = -1; + + SLIST_FOREACH(fte, &feedertab, link) { + if ((fte->desc) && (fte->desc->in == source->desc->out)) { + *try = *(fte->feeder); + try->source = source; + try->desc = trydesc; + trydesc->out = fte->desc->out; + trydesc->idx = fte->idx; + ret = chainok(try, stop)? feeder_fmtchain(to, try, stop, maxdepth - 1) : NULL; + if (ret != NULL) + return ret; + } + } + free(try, M_DEVBUF); + free(trydesc, M_DEVBUF); + /* printf("giving up %s...\n", source->name); */ + return NULL; } +u_int32_t +chn_feedchain(pcm_channel *c, u_int32_t *to) +{ + pcm_feeder *try, *stop; + int max; + + stop = c->feeder; + try = NULL; + max = 0; + while (try == NULL && max++ < 8) + try = feeder_fmtchain(to, c->feeder, stop, max); + if (try == NULL) + return 0; + c->feeder = try; + c->align = 0; + /* printf("chain: "); */ + while (try && (try != stop)) { + /* printf("%s [%d]", try->name, try->desc->idx); */ + /* if (try->source) */ + /* printf(" -> "); */ + if (try->init) + try->init(try); + if (try->align > 0) + c->align += try->align; + else if (try->align < 0 && c->align < -try->align) + c->align = -try->align; + try = try->source; + } + /* printf("%s [%d]", try->name, try->desc->idx); */ + return c->feeder->desc->out; +} diff --git a/sys/dev/sound/pcm/feeder.h b/sys/dev/sound/pcm/feeder.h new file mode 100644 index 0000000..b6890e6 --- /dev/null +++ b/sys/dev/sound/pcm/feeder.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +void feeder_register(void *p); +pcm_feeder *feeder_get(struct pcm_feederdesc *desc); +pcm_feeder *feeder_getroot(void); + +u_int32_t chn_feedchain(pcm_channel *c, u_int32_t *to); +int chn_removefeeder(pcm_channel *c); + + diff --git a/sys/dev/sound/pcm/sound.h b/sys/dev/sound/pcm/sound.h index 90394ba..0e50926 100644 --- a/sys/dev/sound/pcm/sound.h +++ b/sys/dev/sound/pcm/sound.h @@ -81,6 +81,7 @@ struct isa_device { int dummy; }; #include <dev/sound/pcm/datatypes.h> #include <dev/sound/pcm/channel.h> +#include <dev/sound/pcm/feeder.h> #include <dev/sound/pcm/mixer.h> #include <dev/sound/pcm/dsp.h> |