Deleted Added
sdiff udiff text old ( 168243 ) new ( 170161 )
full compact
1/*-
2 * Copyright (c) 1999 Cameron Grant <cg@freebsd.org>
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:

--- 17 unchanged lines hidden (view full) ---

26 */
27
28#include "opt_isa.h"
29
30#include <dev/sound/pcm/sound.h>
31
32#include "feeder_if.h"
33
34SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pcm/channel.c 168243 2007-04-02 03:03:06Z ariff $");
35
36#define MIN_CHUNK_SIZE 256 /* for uiomove etc. */
37#if 0
38#define DMA_ALIGN_THRESHOLD 4
39#define DMA_ALIGN_MASK (~(DMA_ALIGN_THRESHOLD - 1))
40#endif
41
42#define CHN_STARTED(c) ((c)->flags & CHN_F_TRIGGERED)

--- 122 unchanged lines hidden (view full) ---

165
166static void
167chn_lockinit(struct pcm_channel *c, int dir)
168{
169 switch(dir) {
170 case PCMDIR_PLAY:
171 c->lock = snd_mtxcreate(c->name, "pcm play channel");
172 break;
173 case PCMDIR_REC:
174 c->lock = snd_mtxcreate(c->name, "pcm record channel");
175 break;
176 case PCMDIR_VIRTUAL:
177 c->lock = snd_mtxcreate(c->name, "pcm virtual play channel");
178 break;
179 case 0:
180 c->lock = snd_mtxcreate(c->name, "pcm fake channel");
181 break;
182 }
183
184 cv_init(&c->cv, c->name);
185}

--- 43 unchanged lines hidden (view full) ---

229 sndbuf_updateprevtotal(bs);
230 return 1;
231}
232
233static void
234chn_wakeup(struct pcm_channel *c)
235{
236 struct snd_dbuf *bs = c->bufsoft;
237 struct pcmchan_children *pce;
238
239 CHN_LOCKASSERT(c);
240 if (SLIST_EMPTY(&c->children)) {
241 if (SEL_WAITING(sndbuf_getsel(bs)) && chn_polltrigger(c))
242 selwakeuppri(sndbuf_getsel(bs), PRIBIO);
243 wakeup_one(bs);
244 } else {
245 SLIST_FOREACH(pce, &c->children, link) {
246 CHN_LOCK(pce->channel);
247 chn_wakeup(pce->channel);
248 CHN_UNLOCK(pce->channel);
249 }
250 }
251}
252
253static int
254chn_sleep(struct pcm_channel *c, char *str, int timeout)
255{
256 struct snd_dbuf *bs = c->bufsoft;
257 int ret;
258
259 CHN_LOCKASSERT(c);
260#ifdef USING_MUTEX
261 ret = msleep(bs, c->lock, PRIBIO | PCATCH, str, timeout);
262#else
263 ret = tsleep(bs, PRIBIO | PCATCH, str, timeout);
264#endif
265
266 return ret;
267}
268
269/*
270 * chn_dmaupdate() tracks the status of a dma transfer,
271 * updating pointers.
272 */

--- 219 unchanged lines hidden (view full) ---

492#if 0
493 amt = sndbuf_getready(b);
494 if (sndbuf_getfree(bs) < amt) {
495 c->xruns++;
496 amt = sndbuf_getfree(bs);
497 }
498#endif
499 amt = sndbuf_getfree(bs);
500 ret = (amt > 0) ? sndbuf_feed(b, bs, c, c->feeder, amt) : 0;
501
502 amt = sndbuf_getready(b);
503 if (amt > 0) {
504 c->xruns++;
505 sndbuf_dispose(b, NULL, amt);
506 }
507
508 if (sndbuf_getready(bs) > 0)

--- 5 unchanged lines hidden (view full) ---

514void
515chn_rdupdate(struct pcm_channel *c)
516{
517 int ret;
518
519 CHN_LOCKASSERT(c);
520 KASSERT(c->direction == PCMDIR_REC, ("chn_rdupdate on bad channel"));
521
522 if ((c->flags & CHN_F_MAPPED) || CHN_STOPPED(c))
523 return;
524 chn_trigger(c, PCMTRIG_EMLDMARD);
525 chn_dmaupdate(c);
526 ret = chn_rdfeed(c);
527 DEB(if (ret)
528 printf("chn_rdfeed: %d\n", ret);)
529
530}

--- 109 unchanged lines hidden (view full) ---

640 } else {
641 struct snd_dbuf *pb;
642
643 pb = BUF_PARENT(c, b);
644 i = sndbuf_xbytes(sndbuf_getready(bs), bs, pb);
645 j = sndbuf_getbps(pb);
646 }
647 }
648 if (snd_verbose > 3 && SLIST_EMPTY(&c->children))
649 printf("%s: %s (%s) threshold i=%d j=%d\n",
650 __func__, CHN_DIRSTR(c),
651 (c->flags & CHN_F_VIRTUAL) ? "virtual" : "hardware",
652 i, j);
653 }
654
655 if (i >= j) {
656 c->flags |= CHN_F_TRIGGERED;

--- 432 unchanged lines hidden (view full) ---

1089
1090 if (chn_timeout < CHN_TIMEOUT_MIN || chn_timeout > CHN_TIMEOUT_MAX)
1091 chn_timeout = CHN_TIMEOUT;
1092
1093 chn_lockinit(c, dir);
1094
1095 b = NULL;
1096 bs = NULL;
1097 c->devinfo = NULL;
1098 c->feeder = NULL;
1099 c->latency = -1;
1100 c->timeout = 1;
1101
1102 ret = ENOMEM;
1103 b = sndbuf_create(c->dev, c->name, "primary", c);
1104 if (b == NULL)

--- 83 unchanged lines hidden (view full) ---

1188}
1189
1190int
1191chn_kill(struct pcm_channel *c)
1192{
1193 struct snd_dbuf *b = c->bufhard;
1194 struct snd_dbuf *bs = c->bufsoft;
1195
1196 if (CHN_STARTED(c))
1197 chn_trigger(c, PCMTRIG_ABORT);
1198 while (chn_removefeeder(c) == 0);
1199 if (CHANNEL_FREE(c->methods, c->devinfo))
1200 sndbuf_free(b);
1201 c->flags |= CHN_F_DEAD;
1202 sndbuf_destroy(bs);
1203 sndbuf_destroy(b);
1204 chn_lockdestroy(c);
1205 return 0;
1206}

--- 316 unchanged lines hidden (view full) ---

1523 CHN_UNLOCK(c);
1524 if (chn_usefrags == 0 ||
1525 CHANNEL_SETFRAGMENTS(c->methods, c->devinfo,
1526 hblksz, hblkcnt) < 1)
1527 sndbuf_setblksz(b, CHANNEL_SETBLOCKSIZE(c->methods,
1528 c->devinfo, hblksz));
1529 CHN_LOCK(c);
1530
1531 if (!SLIST_EMPTY(&c->children)) {
1532 sblksz = round_blksz(
1533 sndbuf_xbytes(sndbuf_getsize(b) >> 1, b, bs),
1534 sndbuf_getbps(bs));
1535 sblkcnt = 2;
1536 limit = 0;
1537 } else if (limit != 0)
1538 limit = sndbuf_xbytes(sndbuf_getsize(b), b, bs);
1539

--- 205 unchanged lines hidden (view full) ---

1745}
1746
1747int
1748chn_trigger(struct pcm_channel *c, int go)
1749{
1750#ifdef DEV_ISA
1751 struct snd_dbuf *b = c->bufhard;
1752#endif
1753 int ret;
1754
1755 CHN_LOCKASSERT(c);
1756#ifdef DEV_ISA
1757 if (SND_DMA(b) && (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD))
1758 sndbuf_dmabounce(b);
1759#endif
1760 ret = CHANNEL_TRIGGER(c->methods, c->devinfo, go);
1761
1762 return ret;
1763}
1764
1765/**
1766 * @brief Queries sound driver for sample-aligned hardware buffer pointer index
1767 *
1768 * This function obtains the hardware pointer location, then aligns it to
1769 * the current bytes-per-sample value before returning. (E.g., a channel

--- 65 unchanged lines hidden (view full) ---

1835
1836 CHN_LOCKASSERT(c);
1837 while (chn_removefeeder(c) == 0)
1838 ;
1839 KASSERT((c->feeder == NULL), ("feeder chain not empty"));
1840
1841 c->align = sndbuf_getalign(c->bufsoft);
1842
1843 if (SLIST_EMPTY(&c->children)) {
1844 fc = feeder_getclass(NULL);
1845 KASSERT(fc != NULL, ("can't find root feeder"));
1846
1847 err = chn_addfeeder(c, fc, NULL);
1848 if (err) {
1849 DEB(printf("can't add root feeder, err %d\n", err));
1850
1851 return err;
1852 }
1853 c->feeder->desc->out = c->format;
1854 } else {
1855 if (c->flags & CHN_F_HAS_VCHAN) {
1856 desc.type = FEEDER_MIXER;
1857 desc.in = c->format;
1858 } else {
1859 DEB(printf("can't decide which feeder type to use!\n"));
1860 return EOPNOTSUPP;
1861 }
1862 desc.out = c->format;

--- 6 unchanged lines hidden (view full) ---

1869 }
1870
1871 err = chn_addfeeder(c, fc, &desc);
1872 if (err) {
1873 DEB(printf("can't add vchan feeder, err %d\n", err));
1874
1875 return err;
1876 }
1877 }
1878 c->feederflags &= ~(1 << FEEDER_VOLUME);
1879 if (c->direction == PCMDIR_PLAY &&
1880 !(c->flags & CHN_F_VIRTUAL) && c->parentsnddev &&
1881 (c->parentsnddev->flags & SD_F_SOFTPCMVOL) &&
1882 c->parentsnddev->mixer_dev)
1883 c->feederflags |= 1 << FEEDER_VOLUME;
1884 if (!(c->flags & CHN_F_VIRTUAL) && c->parentsnddev &&
1885 ((c->direction == PCMDIR_PLAY &&

--- 83 unchanged lines hidden (view full) ---

1969 tmp[1] = 0;
1970 hwfmt = chn_fmtchain(c, tmp);
1971 } else
1972 hwfmt = chn_fmtchain(c, fmtlist);
1973
1974 if (hwfmt == 0 || !fmtvalid(hwfmt, fmtlist)) {
1975 DEB(printf("Invalid hardware format: 0x%08x\n", hwfmt));
1976 return ENODEV;
1977 }
1978
1979 sndbuf_setfmt(c->bufhard, hwfmt);
1980
1981 if ((flags & (1 << FEEDER_VOLUME))) {
1982 u_int32_t parent = SOUND_MIXER_NONE;
1983 int vol, left, right;
1984

--- 30 unchanged lines hidden (view full) ---

2015 }
2016
2017 return 0;
2018}
2019
2020int
2021chn_notify(struct pcm_channel *c, u_int32_t flags)
2022{
2023 struct pcmchan_children *pce;
2024 struct pcm_channel *child;
2025 int run;
2026
2027 CHN_LOCK(c);
2028
2029 if (SLIST_EMPTY(&c->children)) {
2030 CHN_UNLOCK(c);
2031 return ENODEV;
2032 }
2033
2034 run = (CHN_STARTED(c)) ? 1 : 0;
2035 /*
2036 * if the hwchan is running, we can't change its rate, format or
2037 * blocksize

--- 21 unchanged lines hidden (view full) ---

2059 if (flags & CHN_N_BLOCKSIZE) {
2060 /*
2061 * Set to default latency profile
2062 */
2063 chn_setlatency(c, chn_latency);
2064 }
2065 if (flags & CHN_N_TRIGGER) {
2066 int nrun;
2067 /*
2068 * scan the children, and figure out if any are running
2069 * if so, we need to be running, otherwise we need to be stopped
2070 * if we aren't in our target sstate, move to it
2071 */
2072 nrun = 0;
2073 SLIST_FOREACH(pce, &c->children, link) {
2074 child = pce->channel;
2075 CHN_LOCK(child);
2076 nrun = CHN_STARTED(child);
2077 CHN_UNLOCK(child);
2078 if (nrun)
2079 break;
2080 }
2081 if (nrun && !run)
2082 chn_start(c, 1);
2083 if (!nrun && run)
2084 chn_abort(c);
2085 }
2086 CHN_UNLOCK(c);
2087 return 0;
2088}

--- 92 unchanged lines hidden ---