1/* 2 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk> 3 * Portions Copyright by Luigi Rizzo - 1997-99 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 10 unchanged lines hidden (view full) --- 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * |
27 * $FreeBSD: head/sys/dev/sound/pcm/channel.c 75319 2001-04-08 20:20:52Z cg $ |
28 */ 29 30#include <dev/sound/pcm/sound.h> 31 32#include "feeder_if.h" 33 34#define MIN_CHUNK_SIZE 256 /* for uiomove etc. */ 35#define DMA_ALIGN_THRESHOLD 4 --- 143 unchanged lines hidden (view full) --- 179 DEB( 180 if (c->flags & CHN_F_CLOSING) { 181 sndbuf_dump(b, "b", 0x02); 182 sndbuf_dump(bs, "bs", 0x02); 183 }) 184 185 amt = sndbuf_getfree(b); 186 ret = (amt > 0)? sndbuf_feed(bs, b, c, c->feeder, amt) : ENOSPC; |
187 if (ret == 0 && sndbuf_getfree(b) < amt) |
188 chn_wakeup(c); 189/* 190 if (!(irqc & 63) || (ret != 0)) 191 sndbuf_dump(b, "b:wrfeed", 0x03); 192*/ 193 return ret; 194} 195 --- 523 unchanged lines hidden (view full) --- 719 DEB(printf("want speed %d, ", speed)); 720 if (speed <= 0) 721 return EINVAL; 722 if (CANCHANGE(c)) { 723 r = 0; 724 c->speed = speed; 725 sndbuf_setspd(bs, speed); 726 RANGE(speed, chn_getcaps(c)->minspeed, chn_getcaps(c)->maxspeed); |
727 DEB(printf("try speed %d, ", speed)); 728 sndbuf_setspd(b, CHANNEL_SETSPEED(c->methods, c->devinfo, speed)); |
729 DEB(printf("got speed %d, ", sndbuf_getspd(b))); 730 731 delta = sndbuf_getspd(b) - sndbuf_getspd(bs); 732 if (delta < 0) 733 delta = -delta; 734 735 c->feederflags &= ~(1 << FEEDER_RATE); 736 if (delta > 500) --- 46 unchanged lines hidden (view full) --- 783} 784 785static int 786chn_tryformat(struct pcm_channel *c, u_int32_t fmt) 787{ 788 struct snd_dbuf *b = c->bufhard; 789 struct snd_dbuf *bs = c->bufsoft; 790 int r; |
791 792 CHN_LOCKASSERT(c); 793 if (CANCHANGE(c)) { 794 DEB(printf("want format %d\n", fmt)); 795 c->format = fmt; |
796 r = chn_buildfeeder(c); 797 if (r == 0) { |
798 sndbuf_setfmt(b, c->feeder->desc->out); |
799 sndbuf_setfmt(bs, fmt); 800 chn_resetbuf(c); |
801 CHANNEL_SETFORMAT(c->methods, c->devinfo, sndbuf_getfmt(b)); |
802 r = chn_tryspeed(c, c->speed); 803 } 804 return r; 805 } else 806 return EINVAL; 807} 808 809int --- 136 unchanged lines hidden (view full) --- 946 return fmts; 947} 948 949static int 950chn_buildfeeder(struct pcm_channel *c) 951{ 952 struct feeder_class *fc; 953 struct pcm_feederdesc desc; |
954 u_int32_t tmp[2], type, flags; |
955 956 CHN_LOCKASSERT(c); 957 while (chn_removefeeder(c) == 0); 958 KASSERT((c->feeder == NULL), ("feeder chain not empty")); |
959 |
960 c->align = sndbuf_getalign(c->bufsoft); |
961 |
962 fc = feeder_getclass(NULL); |
963 if (fc == NULL) { 964 DEB(printf("can't find root feeder\n")); |
965 return EINVAL; |
966 } 967 if (chn_addfeeder(c, fc, NULL)) { 968 DEB(printf("can't add root feeder\n")); |
969 return EINVAL; |
970 } |
971 c->feeder->desc->out = c->format; 972 973 flags = c->feederflags; |
974 975 if ((c->flags & CHN_F_MAPPED) && (flags != 0)) { 976 DEB(printf("can't build feeder chain on mapped channel\n")); |
977 return EINVAL; |
978 } 979 DEB(printf("not mapped, flags %x\n", flags)); 980 |
981 for (type = FEEDER_RATE; type <= FEEDER_LAST; type++) { 982 if (flags & (1 << type)) { 983 desc.type = type; 984 desc.in = 0; 985 desc.out = 0; 986 desc.flags = 0; 987 DEB(printf("find feeder type %d, ", type)); 988 fc = feeder_getclass(&desc); 989 DEB(printf("got %p\n", fc)); |
990 if (fc == NULL) { 991 DEB(printf("can't find required feeder type %d\n", type)); |
992 return EINVAL; |
993 } 994 995 if (c->feeder->desc->out != fc->desc->in) { 996 DEB(printf("build fmtchain from %x to %x: ", c->feeder->desc->out, fc->desc->in)); 997 tmp[0] = fc->desc->in; |
998 tmp[1] = 0; |
999 if (chn_fmtchain(c, tmp) == 0) { 1000 DEB(printf("failed\n")); |
1001 return EINVAL; |
1002 } |
1003 DEB(printf("ok\n")); 1004 } |
1005 1006 if (chn_addfeeder(c, fc, fc->desc)) { 1007 DEB(printf("can't add feeder %p, output %x\n", fc, fc->desc->out)); |
1008 return EINVAL; |
1009 } 1010 DEB(printf("added feeder %p, output %x\n", fc, c->feeder->desc->out)); |
1011 } 1012 } |
1013 1014 if (!fmtvalid(c->feeder->desc->out, chn_getcaps(c)->fmtlist)) { 1015 if (chn_fmtchain(c, chn_getcaps(c)->fmtlist) == 0) { 1016 DEB(printf("can't build fmtchain from %x\n", c->feeder->desc->out)); |
1017 return EINVAL; |
1018 } 1019 DEB(printf("built fmtchain from %x\n", c->feeder->desc->out)); |
1020 } |
1021 |
1022 return 0; 1023} 1024 |