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: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 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 28#include "opt_isa.h" 29 30#include <dev/sound/pcm/sound.h> 31 32#include "feeder_if.h" 33
| 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: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 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 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 $");
| 34SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pcm/channel.c 170161 2007-05-31 18:43:33Z 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) 43#define CHN_STOPPED(c) (!CHN_STARTED(c)) 44#define CHN_DIRSTR(c) (((c)->direction == PCMDIR_PLAY) ? \ 45 "PCMDIR_PLAY" : "PCMDIR_REC") 46 47#define BUF_PARENT(c, b) \ 48 (((c) != NULL && (c)->parentchannel != NULL && \ 49 (c)->parentchannel->bufhard != NULL) ? \ 50 (c)->parentchannel->bufhard : (b)) 51 52#define CHN_TIMEOUT 5 53#define CHN_TIMEOUT_MIN 1 54#define CHN_TIMEOUT_MAX 10 55 56/* 57#define DEB(x) x 58*/ 59 60int report_soft_formats = 1; 61SYSCTL_INT(_hw_snd, OID_AUTO, report_soft_formats, CTLFLAG_RW, 62 &report_soft_formats, 1, "report software-emulated formats"); 63 64int chn_latency = CHN_LATENCY_DEFAULT; 65TUNABLE_INT("hw.snd.latency", &chn_latency); 66 67static int 68sysctl_hw_snd_latency(SYSCTL_HANDLER_ARGS) 69{ 70 int err, val; 71 72 val = chn_latency; 73 err = sysctl_handle_int(oidp, &val, sizeof(val), req); 74 if (err != 0 || req->newptr == NULL) 75 return err; 76 if (val < CHN_LATENCY_MIN || val > CHN_LATENCY_MAX) 77 err = EINVAL; 78 else 79 chn_latency = val; 80 81 return err; 82} 83SYSCTL_PROC(_hw_snd, OID_AUTO, latency, CTLTYPE_INT | CTLFLAG_RW, 84 0, sizeof(int), sysctl_hw_snd_latency, "I", 85 "buffering latency (0=low ... 10=high)"); 86 87int chn_latency_profile = CHN_LATENCY_PROFILE_DEFAULT; 88TUNABLE_INT("hw.snd.latency_profile", &chn_latency_profile); 89 90static int 91sysctl_hw_snd_latency_profile(SYSCTL_HANDLER_ARGS) 92{ 93 int err, val; 94 95 val = chn_latency_profile; 96 err = sysctl_handle_int(oidp, &val, sizeof(val), req); 97 if (err != 0 || req->newptr == NULL) 98 return err; 99 if (val < CHN_LATENCY_PROFILE_MIN || val > CHN_LATENCY_PROFILE_MAX) 100 err = EINVAL; 101 else 102 chn_latency_profile = val; 103 104 return err; 105} 106SYSCTL_PROC(_hw_snd, OID_AUTO, latency_profile, CTLTYPE_INT | CTLFLAG_RW, 107 0, sizeof(int), sysctl_hw_snd_latency_profile, "I", 108 "buffering latency profile (0=aggresive 1=safe)"); 109 110static int chn_timeout = CHN_TIMEOUT; 111TUNABLE_INT("hw.snd.timeout", &chn_timeout); 112#ifdef SND_DEBUG 113static int 114sysctl_hw_snd_timeout(SYSCTL_HANDLER_ARGS) 115{ 116 int err, val; 117 118 val = chn_timeout; 119 err = sysctl_handle_int(oidp, &val, sizeof(val), req); 120 if (err != 0 || req->newptr == NULL) 121 return err; 122 if (val < CHN_TIMEOUT_MIN || val > CHN_TIMEOUT_MAX) 123 err = EINVAL; 124 else 125 chn_timeout = val; 126 127 return err; 128} 129SYSCTL_PROC(_hw_snd, OID_AUTO, timeout, CTLTYPE_INT | CTLFLAG_RW, 130 0, sizeof(int), sysctl_hw_snd_timeout, "I", 131 "interrupt timeout (1 - 10) seconds"); 132#endif 133 134static int chn_usefrags = 0; 135TUNABLE_INT("hw.snd.usefrags", &chn_usefrags); 136static int chn_syncdelay = -1; 137TUNABLE_INT("hw.snd.syncdelay", &chn_syncdelay); 138#ifdef SND_DEBUG 139SYSCTL_INT(_hw_snd, OID_AUTO, usefrags, CTLFLAG_RW, 140 &chn_usefrags, 1, "prefer setfragments() over setblocksize()"); 141SYSCTL_INT(_hw_snd, OID_AUTO, syncdelay, CTLFLAG_RW, 142 &chn_syncdelay, 1, 143 "append (0-1000) millisecond trailing buffer delay on each sync"); 144#endif 145 146/** 147 * @brief Channel sync group lock 148 * 149 * Clients should acquire this lock @b without holding any channel locks 150 * before touching syncgroups or the main syncgroup list. 151 */ 152struct mtx snd_pcm_syncgroups_mtx; 153MTX_SYSINIT(pcm_syncgroup, &snd_pcm_syncgroups_mtx, "PCM channel sync group lock", MTX_DEF); 154/** 155 * @brief syncgroups' master list 156 * 157 * Each time a channel syncgroup is created, it's added to this list. This 158 * list should only be accessed with @sa snd_pcm_syncgroups_mtx held. 159 * 160 * See SNDCTL_DSP_SYNCGROUP for more information. 161 */ 162struct pcm_synclist snd_pcm_syncgroups = SLIST_HEAD_INITIALIZER(head); 163 164static int chn_buildfeeder(struct pcm_channel *c); 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;
| 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) 43#define CHN_STOPPED(c) (!CHN_STARTED(c)) 44#define CHN_DIRSTR(c) (((c)->direction == PCMDIR_PLAY) ? \ 45 "PCMDIR_PLAY" : "PCMDIR_REC") 46 47#define BUF_PARENT(c, b) \ 48 (((c) != NULL && (c)->parentchannel != NULL && \ 49 (c)->parentchannel->bufhard != NULL) ? \ 50 (c)->parentchannel->bufhard : (b)) 51 52#define CHN_TIMEOUT 5 53#define CHN_TIMEOUT_MIN 1 54#define CHN_TIMEOUT_MAX 10 55 56/* 57#define DEB(x) x 58*/ 59 60int report_soft_formats = 1; 61SYSCTL_INT(_hw_snd, OID_AUTO, report_soft_formats, CTLFLAG_RW, 62 &report_soft_formats, 1, "report software-emulated formats"); 63 64int chn_latency = CHN_LATENCY_DEFAULT; 65TUNABLE_INT("hw.snd.latency", &chn_latency); 66 67static int 68sysctl_hw_snd_latency(SYSCTL_HANDLER_ARGS) 69{ 70 int err, val; 71 72 val = chn_latency; 73 err = sysctl_handle_int(oidp, &val, sizeof(val), req); 74 if (err != 0 || req->newptr == NULL) 75 return err; 76 if (val < CHN_LATENCY_MIN || val > CHN_LATENCY_MAX) 77 err = EINVAL; 78 else 79 chn_latency = val; 80 81 return err; 82} 83SYSCTL_PROC(_hw_snd, OID_AUTO, latency, CTLTYPE_INT | CTLFLAG_RW, 84 0, sizeof(int), sysctl_hw_snd_latency, "I", 85 "buffering latency (0=low ... 10=high)"); 86 87int chn_latency_profile = CHN_LATENCY_PROFILE_DEFAULT; 88TUNABLE_INT("hw.snd.latency_profile", &chn_latency_profile); 89 90static int 91sysctl_hw_snd_latency_profile(SYSCTL_HANDLER_ARGS) 92{ 93 int err, val; 94 95 val = chn_latency_profile; 96 err = sysctl_handle_int(oidp, &val, sizeof(val), req); 97 if (err != 0 || req->newptr == NULL) 98 return err; 99 if (val < CHN_LATENCY_PROFILE_MIN || val > CHN_LATENCY_PROFILE_MAX) 100 err = EINVAL; 101 else 102 chn_latency_profile = val; 103 104 return err; 105} 106SYSCTL_PROC(_hw_snd, OID_AUTO, latency_profile, CTLTYPE_INT | CTLFLAG_RW, 107 0, sizeof(int), sysctl_hw_snd_latency_profile, "I", 108 "buffering latency profile (0=aggresive 1=safe)"); 109 110static int chn_timeout = CHN_TIMEOUT; 111TUNABLE_INT("hw.snd.timeout", &chn_timeout); 112#ifdef SND_DEBUG 113static int 114sysctl_hw_snd_timeout(SYSCTL_HANDLER_ARGS) 115{ 116 int err, val; 117 118 val = chn_timeout; 119 err = sysctl_handle_int(oidp, &val, sizeof(val), req); 120 if (err != 0 || req->newptr == NULL) 121 return err; 122 if (val < CHN_TIMEOUT_MIN || val > CHN_TIMEOUT_MAX) 123 err = EINVAL; 124 else 125 chn_timeout = val; 126 127 return err; 128} 129SYSCTL_PROC(_hw_snd, OID_AUTO, timeout, CTLTYPE_INT | CTLFLAG_RW, 130 0, sizeof(int), sysctl_hw_snd_timeout, "I", 131 "interrupt timeout (1 - 10) seconds"); 132#endif 133 134static int chn_usefrags = 0; 135TUNABLE_INT("hw.snd.usefrags", &chn_usefrags); 136static int chn_syncdelay = -1; 137TUNABLE_INT("hw.snd.syncdelay", &chn_syncdelay); 138#ifdef SND_DEBUG 139SYSCTL_INT(_hw_snd, OID_AUTO, usefrags, CTLFLAG_RW, 140 &chn_usefrags, 1, "prefer setfragments() over setblocksize()"); 141SYSCTL_INT(_hw_snd, OID_AUTO, syncdelay, CTLFLAG_RW, 142 &chn_syncdelay, 1, 143 "append (0-1000) millisecond trailing buffer delay on each sync"); 144#endif 145 146/** 147 * @brief Channel sync group lock 148 * 149 * Clients should acquire this lock @b without holding any channel locks 150 * before touching syncgroups or the main syncgroup list. 151 */ 152struct mtx snd_pcm_syncgroups_mtx; 153MTX_SYSINIT(pcm_syncgroup, &snd_pcm_syncgroups_mtx, "PCM channel sync group lock", MTX_DEF); 154/** 155 * @brief syncgroups' master list 156 * 157 * Each time a channel syncgroup is created, it's added to this list. This 158 * list should only be accessed with @sa snd_pcm_syncgroups_mtx held. 159 * 160 * See SNDCTL_DSP_SYNCGROUP for more information. 161 */ 162struct pcm_synclist snd_pcm_syncgroups = SLIST_HEAD_INITIALIZER(head); 163 164static int chn_buildfeeder(struct pcm_channel *c); 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_PLAY_VIRTUAL: 174 c->lock = snd_mtxcreate(c->name, "pcm virtual play channel"); 175 break;
|
173 case PCMDIR_REC: 174 c->lock = snd_mtxcreate(c->name, "pcm record channel"); 175 break;
| 176 case PCMDIR_REC: 177 c->lock = snd_mtxcreate(c->name, "pcm record channel"); 178 break;
|
176 case PCMDIR_VIRTUAL: 177 c->lock = snd_mtxcreate(c->name, "pcm virtual play channel");
| 179 case PCMDIR_REC_VIRTUAL: 180 c->lock = snd_mtxcreate(c->name, "pcm virtual record 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} 186 187static void 188chn_lockdestroy(struct pcm_channel *c) 189{ 190 snd_mtxfree(c->lock); 191 cv_destroy(&c->cv); 192} 193 194/** 195 * @brief Determine channel is ready for I/O 196 * 197 * @retval 1 = ready for I/O 198 * @retval 0 = not ready for I/O 199 */ 200static int 201chn_polltrigger(struct pcm_channel *c) 202{ 203 struct snd_dbuf *bs = c->bufsoft; 204 unsigned amt, lim; 205 206 CHN_LOCKASSERT(c); 207 if (c->flags & CHN_F_MAPPED) { 208 if (sndbuf_getprevblocks(bs) == 0) 209 return 1; 210 else 211 return (sndbuf_getblocks(bs) > sndbuf_getprevblocks(bs))? 1 : 0; 212 } else { 213 amt = (c->direction == PCMDIR_PLAY)? sndbuf_getfree(bs) : sndbuf_getready(bs); 214#if 0 215 lim = (c->flags & CHN_F_HAS_SIZE)? sndbuf_getblksz(bs) : 1; 216#endif 217 lim = c->lw; 218 return (amt >= lim) ? 1 : 0; 219 } 220 return 0; 221} 222 223static int 224chn_pollreset(struct pcm_channel *c) 225{ 226 struct snd_dbuf *bs = c->bufsoft; 227 228 CHN_LOCKASSERT(c); 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;
| 181 break; 182 case 0: 183 c->lock = snd_mtxcreate(c->name, "pcm fake channel"); 184 break; 185 } 186 187 cv_init(&c->cv, c->name); 188} 189 190static void 191chn_lockdestroy(struct pcm_channel *c) 192{ 193 snd_mtxfree(c->lock); 194 cv_destroy(&c->cv); 195} 196 197/** 198 * @brief Determine channel is ready for I/O 199 * 200 * @retval 1 = ready for I/O 201 * @retval 0 = not ready for I/O 202 */ 203static int 204chn_polltrigger(struct pcm_channel *c) 205{ 206 struct snd_dbuf *bs = c->bufsoft; 207 unsigned amt, lim; 208 209 CHN_LOCKASSERT(c); 210 if (c->flags & CHN_F_MAPPED) { 211 if (sndbuf_getprevblocks(bs) == 0) 212 return 1; 213 else 214 return (sndbuf_getblocks(bs) > sndbuf_getprevblocks(bs))? 1 : 0; 215 } else { 216 amt = (c->direction == PCMDIR_PLAY)? sndbuf_getfree(bs) : sndbuf_getready(bs); 217#if 0 218 lim = (c->flags & CHN_F_HAS_SIZE)? sndbuf_getblksz(bs) : 1; 219#endif 220 lim = c->lw; 221 return (amt >= lim) ? 1 : 0; 222 } 223 return 0; 224} 225 226static int 227chn_pollreset(struct pcm_channel *c) 228{ 229 struct snd_dbuf *bs = c->bufsoft; 230 231 CHN_LOCKASSERT(c); 232 sndbuf_updateprevtotal(bs); 233 return 1; 234} 235 236static void 237chn_wakeup(struct pcm_channel *c) 238{ 239 struct snd_dbuf *bs = c->bufsoft;
|
237 struct pcmchan_children *pce;
| 240 struct pcm_channel *ch;
|
238 239 CHN_LOCKASSERT(c);
| 241 242 CHN_LOCKASSERT(c);
|
240 if (SLIST_EMPTY(&c->children)) {
| 243 if (CHN_EMPTY(c, children)) {
|
241 if (SEL_WAITING(sndbuf_getsel(bs)) && chn_polltrigger(c)) 242 selwakeuppri(sndbuf_getsel(bs), PRIBIO);
| 244 if (SEL_WAITING(sndbuf_getsel(bs)) && chn_polltrigger(c)) 245 selwakeuppri(sndbuf_getsel(bs), PRIBIO);
|
243 wakeup_one(bs);
| 246 } else if (CHN_EMPTY(c, children.busy)) { 247 CHN_FOREACH(ch, c, children) { 248 CHN_LOCK(ch); 249 chn_wakeup(ch); 250 CHN_UNLOCK(ch); 251 }
|
244 } else {
| 252 } else {
|
245 SLIST_FOREACH(pce, &c->children, link) { 246 CHN_LOCK(pce->channel); 247 chn_wakeup(pce->channel); 248 CHN_UNLOCK(pce->channel);
| 253 CHN_FOREACH(ch, c, children.busy) { 254 CHN_LOCK(ch); 255 chn_wakeup(ch); 256 CHN_UNLOCK(ch);
|
249 } 250 }
| 257 } 258 }
|
| 259 if (c->flags & CHN_F_SLEEPING) 260 wakeup_one(bs);
|
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);
| 261} 262 263static int 264chn_sleep(struct pcm_channel *c, char *str, int timeout) 265{ 266 struct snd_dbuf *bs = c->bufsoft; 267 int ret; 268 269 CHN_LOCKASSERT(c);
|
| 270 271 c->flags |= CHN_F_SLEEPING;
|
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
| 272#ifdef USING_MUTEX 273 ret = msleep(bs, c->lock, PRIBIO | PCATCH, str, timeout); 274#else 275 ret = tsleep(bs, PRIBIO | PCATCH, str, timeout); 276#endif
|
| 277 c->flags &= ~CHN_F_SLEEPING;
|
265 266 return ret; 267} 268 269/* 270 * chn_dmaupdate() tracks the status of a dma transfer, 271 * updating pointers. 272 */ 273 274static unsigned int 275chn_dmaupdate(struct pcm_channel *c) 276{ 277 struct snd_dbuf *b = c->bufhard; 278 unsigned int delta, old, hwptr, amt; 279 280 KASSERT(sndbuf_getsize(b) > 0, ("bufsize == 0")); 281 CHN_LOCKASSERT(c); 282 283 old = sndbuf_gethwptr(b); 284 hwptr = chn_getptr(c); 285 delta = (sndbuf_getsize(b) + hwptr - old) % sndbuf_getsize(b); 286 sndbuf_sethwptr(b, hwptr); 287 288 DEB( 289 if (delta >= ((sndbuf_getsize(b) * 15) / 16)) { 290 if (!(c->flags & (CHN_F_CLOSING | CHN_F_ABORTING))) 291 device_printf(c->dev, "hwptr went backwards %d -> %d\n", old, hwptr); 292 } 293 ); 294 295 if (c->direction == PCMDIR_PLAY) { 296 amt = min(delta, sndbuf_getready(b)); 297 amt -= amt % sndbuf_getbps(b); 298 if (amt > 0) 299 sndbuf_dispose(b, NULL, amt); 300 } else { 301 amt = min(delta, sndbuf_getfree(b)); 302 amt -= amt % sndbuf_getbps(b); 303 if (amt > 0) 304 sndbuf_acquire(b, NULL, amt); 305 } 306 if (snd_verbose > 3 && CHN_STARTED(c) && delta == 0) { 307 device_printf(c->dev, "WARNING: %s DMA completion " 308 "too fast/slow ! hwptr=%u, old=%u " 309 "delta=%u amt=%u ready=%u free=%u\n", 310 CHN_DIRSTR(c), hwptr, old, delta, amt, 311 sndbuf_getready(b), sndbuf_getfree(b)); 312 } 313 314 return delta; 315} 316 317void 318chn_wrupdate(struct pcm_channel *c) 319{ 320 int ret; 321 322 CHN_LOCKASSERT(c); 323 KASSERT(c->direction == PCMDIR_PLAY, ("chn_wrupdate on bad channel")); 324 325 if ((c->flags & (CHN_F_MAPPED | CHN_F_VIRTUAL)) || CHN_STOPPED(c)) 326 return; 327 chn_dmaupdate(c); 328 ret = chn_wrfeed(c); 329 /* tell the driver we've updated the primary buffer */ 330 chn_trigger(c, PCMTRIG_EMLDMAWR); 331 DEB(if (ret) 332 printf("chn_wrupdate: chn_wrfeed returned %d\n", ret);) 333 334} 335 336int 337chn_wrfeed(struct pcm_channel *c) 338{ 339 struct snd_dbuf *b = c->bufhard; 340 struct snd_dbuf *bs = c->bufsoft; 341 unsigned int ret, amt; 342 343 CHN_LOCKASSERT(c); 344#if 0 345 DEB( 346 if (c->flags & CHN_F_CLOSING) { 347 sndbuf_dump(b, "b", 0x02); 348 sndbuf_dump(bs, "bs", 0x02); 349 }) 350#endif 351 352 if ((c->flags & CHN_F_MAPPED) && !(c->flags & CHN_F_CLOSING)) 353 sndbuf_acquire(bs, NULL, sndbuf_getfree(bs)); 354 355 amt = sndbuf_getfree(b); 356 DEB(if (amt > sndbuf_getsize(bs) && 357 sndbuf_getbps(bs) >= sndbuf_getbps(b)) { 358 printf("%s(%s): amt %d > source size %d, flags 0x%x", __func__, c->name, 359 amt, sndbuf_getsize(bs), c->flags); 360 }); 361 362 ret = (amt > 0) ? sndbuf_feed(bs, b, c, c->feeder, amt) : ENOSPC; 363 /* 364 * Possible xruns. There should be no empty space left in buffer. 365 */ 366 if (sndbuf_getfree(b) > 0) 367 c->xruns++; 368 369 if (sndbuf_getfree(b) < amt) 370 chn_wakeup(c); 371 372 return ret; 373} 374 375static void 376chn_wrintr(struct pcm_channel *c) 377{ 378 int ret; 379 380 CHN_LOCKASSERT(c); 381 /* update pointers in primary buffer */ 382 chn_dmaupdate(c); 383 /* ...and feed from secondary to primary */ 384 ret = chn_wrfeed(c); 385 /* tell the driver we've updated the primary buffer */ 386 chn_trigger(c, PCMTRIG_EMLDMAWR); 387 DEB(if (ret) 388 printf("chn_wrintr: chn_wrfeed returned %d\n", ret);) 389} 390 391/* 392 * user write routine - uiomove data into secondary buffer, trigger if necessary 393 * if blocking, sleep, rinse and repeat. 394 * 395 * called externally, so must handle locking 396 */ 397 398int 399chn_write(struct pcm_channel *c, struct uio *buf) 400{ 401 struct snd_dbuf *bs = c->bufsoft; 402 void *off; 403 int ret, timeout, sz, t, p; 404 405 CHN_LOCKASSERT(c); 406 407 ret = 0; 408 timeout = chn_timeout * hz; 409 410 while (ret == 0 && buf->uio_resid > 0) { 411 sz = min(buf->uio_resid, sndbuf_getfree(bs)); 412 if (sz > 0) { 413 /* 414 * The following assumes that the free space in 415 * the buffer can never be less around the 416 * unlock-uiomove-lock sequence. 417 */ 418 while (ret == 0 && sz > 0) { 419 p = sndbuf_getfreeptr(bs); 420 t = min(sz, sndbuf_getsize(bs) - p); 421 off = sndbuf_getbufofs(bs, p); 422 CHN_UNLOCK(c); 423 ret = uiomove(off, t, buf); 424 CHN_LOCK(c); 425 sz -= t; 426 sndbuf_acquire(bs, NULL, t); 427 } 428 ret = 0; 429 if (CHN_STOPPED(c)) 430 chn_start(c, 0); 431 } else if (c->flags & (CHN_F_NBIO | CHN_F_NOTRIGGER)) { 432 /** 433 * @todo Evaluate whether EAGAIN is truly desirable. 434 * 4Front drivers behave like this, but I'm 435 * not sure if it at all violates the "write 436 * should be allowed to block" model. 437 * 438 * The idea is that, while set with CHN_F_NOTRIGGER, 439 * a channel isn't playing, *but* without this we 440 * end up with "interrupt timeout / channel dead". 441 */ 442 ret = EAGAIN; 443 } else { 444 ret = chn_sleep(c, "pcmwr", timeout); 445 if (ret == EAGAIN) { 446 ret = EINVAL; 447 c->flags |= CHN_F_DEAD; 448 printf("%s: play interrupt timeout, " 449 "channel dead\n", c->name); 450 } else if (ret == ERESTART || ret == EINTR) 451 c->flags |= CHN_F_ABORTING; 452 } 453 } 454 455 return ret; 456} 457 458#if 0 459static int 460chn_rddump(struct pcm_channel *c, unsigned int cnt) 461{ 462 struct snd_dbuf *b = c->bufhard; 463 464 CHN_LOCKASSERT(c); 465#if 0 466 static u_int32_t kk = 0; 467 printf("%u: dumping %d bytes\n", ++kk, cnt); 468#endif 469 c->xruns++; 470 sndbuf_setxrun(b, sndbuf_getxrun(b) + cnt); 471 return sndbuf_dispose(b, NULL, cnt); 472} 473#endif 474 475/* 476 * Feed new data from the read buffer. Can be called in the bottom half. 477 */ 478int 479chn_rdfeed(struct pcm_channel *c) 480{ 481 struct snd_dbuf *b = c->bufhard; 482 struct snd_dbuf *bs = c->bufsoft; 483 unsigned int ret, amt; 484 485 CHN_LOCKASSERT(c); 486 DEB( 487 if (c->flags & CHN_F_CLOSING) { 488 sndbuf_dump(b, "b", 0x02); 489 sndbuf_dump(bs, "bs", 0x02); 490 }) 491 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);
| 278 279 return ret; 280} 281 282/* 283 * chn_dmaupdate() tracks the status of a dma transfer, 284 * updating pointers. 285 */ 286 287static unsigned int 288chn_dmaupdate(struct pcm_channel *c) 289{ 290 struct snd_dbuf *b = c->bufhard; 291 unsigned int delta, old, hwptr, amt; 292 293 KASSERT(sndbuf_getsize(b) > 0, ("bufsize == 0")); 294 CHN_LOCKASSERT(c); 295 296 old = sndbuf_gethwptr(b); 297 hwptr = chn_getptr(c); 298 delta = (sndbuf_getsize(b) + hwptr - old) % sndbuf_getsize(b); 299 sndbuf_sethwptr(b, hwptr); 300 301 DEB( 302 if (delta >= ((sndbuf_getsize(b) * 15) / 16)) { 303 if (!(c->flags & (CHN_F_CLOSING | CHN_F_ABORTING))) 304 device_printf(c->dev, "hwptr went backwards %d -> %d\n", old, hwptr); 305 } 306 ); 307 308 if (c->direction == PCMDIR_PLAY) { 309 amt = min(delta, sndbuf_getready(b)); 310 amt -= amt % sndbuf_getbps(b); 311 if (amt > 0) 312 sndbuf_dispose(b, NULL, amt); 313 } else { 314 amt = min(delta, sndbuf_getfree(b)); 315 amt -= amt % sndbuf_getbps(b); 316 if (amt > 0) 317 sndbuf_acquire(b, NULL, amt); 318 } 319 if (snd_verbose > 3 && CHN_STARTED(c) && delta == 0) { 320 device_printf(c->dev, "WARNING: %s DMA completion " 321 "too fast/slow ! hwptr=%u, old=%u " 322 "delta=%u amt=%u ready=%u free=%u\n", 323 CHN_DIRSTR(c), hwptr, old, delta, amt, 324 sndbuf_getready(b), sndbuf_getfree(b)); 325 } 326 327 return delta; 328} 329 330void 331chn_wrupdate(struct pcm_channel *c) 332{ 333 int ret; 334 335 CHN_LOCKASSERT(c); 336 KASSERT(c->direction == PCMDIR_PLAY, ("chn_wrupdate on bad channel")); 337 338 if ((c->flags & (CHN_F_MAPPED | CHN_F_VIRTUAL)) || CHN_STOPPED(c)) 339 return; 340 chn_dmaupdate(c); 341 ret = chn_wrfeed(c); 342 /* tell the driver we've updated the primary buffer */ 343 chn_trigger(c, PCMTRIG_EMLDMAWR); 344 DEB(if (ret) 345 printf("chn_wrupdate: chn_wrfeed returned %d\n", ret);) 346 347} 348 349int 350chn_wrfeed(struct pcm_channel *c) 351{ 352 struct snd_dbuf *b = c->bufhard; 353 struct snd_dbuf *bs = c->bufsoft; 354 unsigned int ret, amt; 355 356 CHN_LOCKASSERT(c); 357#if 0 358 DEB( 359 if (c->flags & CHN_F_CLOSING) { 360 sndbuf_dump(b, "b", 0x02); 361 sndbuf_dump(bs, "bs", 0x02); 362 }) 363#endif 364 365 if ((c->flags & CHN_F_MAPPED) && !(c->flags & CHN_F_CLOSING)) 366 sndbuf_acquire(bs, NULL, sndbuf_getfree(bs)); 367 368 amt = sndbuf_getfree(b); 369 DEB(if (amt > sndbuf_getsize(bs) && 370 sndbuf_getbps(bs) >= sndbuf_getbps(b)) { 371 printf("%s(%s): amt %d > source size %d, flags 0x%x", __func__, c->name, 372 amt, sndbuf_getsize(bs), c->flags); 373 }); 374 375 ret = (amt > 0) ? sndbuf_feed(bs, b, c, c->feeder, amt) : ENOSPC; 376 /* 377 * Possible xruns. There should be no empty space left in buffer. 378 */ 379 if (sndbuf_getfree(b) > 0) 380 c->xruns++; 381 382 if (sndbuf_getfree(b) < amt) 383 chn_wakeup(c); 384 385 return ret; 386} 387 388static void 389chn_wrintr(struct pcm_channel *c) 390{ 391 int ret; 392 393 CHN_LOCKASSERT(c); 394 /* update pointers in primary buffer */ 395 chn_dmaupdate(c); 396 /* ...and feed from secondary to primary */ 397 ret = chn_wrfeed(c); 398 /* tell the driver we've updated the primary buffer */ 399 chn_trigger(c, PCMTRIG_EMLDMAWR); 400 DEB(if (ret) 401 printf("chn_wrintr: chn_wrfeed returned %d\n", ret);) 402} 403 404/* 405 * user write routine - uiomove data into secondary buffer, trigger if necessary 406 * if blocking, sleep, rinse and repeat. 407 * 408 * called externally, so must handle locking 409 */ 410 411int 412chn_write(struct pcm_channel *c, struct uio *buf) 413{ 414 struct snd_dbuf *bs = c->bufsoft; 415 void *off; 416 int ret, timeout, sz, t, p; 417 418 CHN_LOCKASSERT(c); 419 420 ret = 0; 421 timeout = chn_timeout * hz; 422 423 while (ret == 0 && buf->uio_resid > 0) { 424 sz = min(buf->uio_resid, sndbuf_getfree(bs)); 425 if (sz > 0) { 426 /* 427 * The following assumes that the free space in 428 * the buffer can never be less around the 429 * unlock-uiomove-lock sequence. 430 */ 431 while (ret == 0 && sz > 0) { 432 p = sndbuf_getfreeptr(bs); 433 t = min(sz, sndbuf_getsize(bs) - p); 434 off = sndbuf_getbufofs(bs, p); 435 CHN_UNLOCK(c); 436 ret = uiomove(off, t, buf); 437 CHN_LOCK(c); 438 sz -= t; 439 sndbuf_acquire(bs, NULL, t); 440 } 441 ret = 0; 442 if (CHN_STOPPED(c)) 443 chn_start(c, 0); 444 } else if (c->flags & (CHN_F_NBIO | CHN_F_NOTRIGGER)) { 445 /** 446 * @todo Evaluate whether EAGAIN is truly desirable. 447 * 4Front drivers behave like this, but I'm 448 * not sure if it at all violates the "write 449 * should be allowed to block" model. 450 * 451 * The idea is that, while set with CHN_F_NOTRIGGER, 452 * a channel isn't playing, *but* without this we 453 * end up with "interrupt timeout / channel dead". 454 */ 455 ret = EAGAIN; 456 } else { 457 ret = chn_sleep(c, "pcmwr", timeout); 458 if (ret == EAGAIN) { 459 ret = EINVAL; 460 c->flags |= CHN_F_DEAD; 461 printf("%s: play interrupt timeout, " 462 "channel dead\n", c->name); 463 } else if (ret == ERESTART || ret == EINTR) 464 c->flags |= CHN_F_ABORTING; 465 } 466 } 467 468 return ret; 469} 470 471#if 0 472static int 473chn_rddump(struct pcm_channel *c, unsigned int cnt) 474{ 475 struct snd_dbuf *b = c->bufhard; 476 477 CHN_LOCKASSERT(c); 478#if 0 479 static u_int32_t kk = 0; 480 printf("%u: dumping %d bytes\n", ++kk, cnt); 481#endif 482 c->xruns++; 483 sndbuf_setxrun(b, sndbuf_getxrun(b) + cnt); 484 return sndbuf_dispose(b, NULL, cnt); 485} 486#endif 487 488/* 489 * Feed new data from the read buffer. Can be called in the bottom half. 490 */ 491int 492chn_rdfeed(struct pcm_channel *c) 493{ 494 struct snd_dbuf *b = c->bufhard; 495 struct snd_dbuf *bs = c->bufsoft; 496 unsigned int ret, amt; 497 498 CHN_LOCKASSERT(c); 499 DEB( 500 if (c->flags & CHN_F_CLOSING) { 501 sndbuf_dump(b, "b", 0x02); 502 sndbuf_dump(bs, "bs", 0x02); 503 }) 504 505#if 0 506 amt = sndbuf_getready(b); 507 if (sndbuf_getfree(bs) < amt) { 508 c->xruns++; 509 amt = sndbuf_getfree(bs); 510 } 511#endif 512 amt = sndbuf_getfree(bs);
|
500 ret = (amt > 0) ? sndbuf_feed(b, bs, c, c->feeder, amt) : 0;
| 513 ret = (amt > 0) ? sndbuf_feed(b, bs, c, c->feeder, amt) : ENOSPC;
|
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) 509 chn_wakeup(c); 510 511 return ret; 512} 513 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
| 514 515 amt = sndbuf_getready(b); 516 if (amt > 0) { 517 c->xruns++; 518 sndbuf_dispose(b, NULL, amt); 519 } 520 521 if (sndbuf_getready(bs) > 0) 522 chn_wakeup(c); 523 524 return ret; 525} 526 527void 528chn_rdupdate(struct pcm_channel *c) 529{ 530 int ret; 531 532 CHN_LOCKASSERT(c); 533 KASSERT(c->direction == PCMDIR_REC, ("chn_rdupdate on bad channel")); 534
|
522 if ((c->flags & CHN_F_MAPPED) || CHN_STOPPED(c))
| 535 if ((c->flags & (CHN_F_MAPPED | CHN_F_VIRTUAL)) || 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} 531 532/* read interrupt routine. Must be called with interrupts blocked. */ 533static void 534chn_rdintr(struct pcm_channel *c) 535{ 536 int ret; 537 538 CHN_LOCKASSERT(c); 539 /* tell the driver to update the primary buffer if non-dma */ 540 chn_trigger(c, PCMTRIG_EMLDMARD); 541 /* update pointers in primary buffer */ 542 chn_dmaupdate(c); 543 /* ...and feed from primary to secondary */ 544 ret = chn_rdfeed(c); 545} 546 547/* 548 * user read routine - trigger if necessary, uiomove data from secondary buffer 549 * if blocking, sleep, rinse and repeat. 550 * 551 * called externally, so must handle locking 552 */ 553 554int 555chn_read(struct pcm_channel *c, struct uio *buf) 556{ 557 struct snd_dbuf *bs = c->bufsoft; 558 void *off; 559 int ret, timeout, sz, t, p; 560 561 CHN_LOCKASSERT(c); 562 563 if (CHN_STOPPED(c)) 564 chn_start(c, 0); 565 566 ret = 0; 567 timeout = chn_timeout * hz; 568 569 while (ret == 0 && buf->uio_resid > 0) { 570 sz = min(buf->uio_resid, sndbuf_getready(bs)); 571 if (sz > 0) { 572 /* 573 * The following assumes that the free space in 574 * the buffer can never be less around the 575 * unlock-uiomove-lock sequence. 576 */ 577 while (ret == 0 && sz > 0) { 578 p = sndbuf_getreadyptr(bs); 579 t = min(sz, sndbuf_getsize(bs) - p); 580 off = sndbuf_getbufofs(bs, p); 581 CHN_UNLOCK(c); 582 ret = uiomove(off, t, buf); 583 CHN_LOCK(c); 584 sz -= t; 585 sndbuf_dispose(bs, NULL, t); 586 } 587 ret = 0; 588 } else if (c->flags & (CHN_F_NBIO | CHN_F_NOTRIGGER)) 589 ret = EAGAIN; 590 else { 591 ret = chn_sleep(c, "pcmrd", timeout); 592 if (ret == EAGAIN) { 593 ret = EINVAL; 594 c->flags |= CHN_F_DEAD; 595 printf("%s: record interrupt timeout, " 596 "channel dead\n", c->name); 597 } else if (ret == ERESTART || ret == EINTR) 598 c->flags |= CHN_F_ABORTING; 599 } 600 } 601 602 return ret; 603} 604 605void 606chn_intr(struct pcm_channel *c) 607{ 608 CHN_LOCK(c); 609 c->interrupts++; 610 if (c->direction == PCMDIR_PLAY) 611 chn_wrintr(c); 612 else 613 chn_rdintr(c); 614 CHN_UNLOCK(c); 615} 616 617u_int32_t 618chn_start(struct pcm_channel *c, int force) 619{ 620 u_int32_t i, j; 621 struct snd_dbuf *b = c->bufhard; 622 struct snd_dbuf *bs = c->bufsoft; 623 624 CHN_LOCKASSERT(c); 625 /* if we're running, or if we're prevented from triggering, bail */ 626 if (CHN_STARTED(c) || ((c->flags & CHN_F_NOTRIGGER) && !force)) 627 return EINVAL; 628 629 if (force) { 630 i = 1; 631 j = 0; 632 } else { 633 if (c->direction == PCMDIR_REC) { 634 i = sndbuf_getfree(bs); 635 j = (i > 0) ? 1 : sndbuf_getready(b); 636 } else { 637 if (sndbuf_getfree(bs) == 0) { 638 i = 1; 639 j = 0; 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 }
| 536 return; 537 chn_trigger(c, PCMTRIG_EMLDMARD); 538 chn_dmaupdate(c); 539 ret = chn_rdfeed(c); 540 DEB(if (ret) 541 printf("chn_rdfeed: %d\n", ret);) 542 543} 544 545/* read interrupt routine. Must be called with interrupts blocked. */ 546static void 547chn_rdintr(struct pcm_channel *c) 548{ 549 int ret; 550 551 CHN_LOCKASSERT(c); 552 /* tell the driver to update the primary buffer if non-dma */ 553 chn_trigger(c, PCMTRIG_EMLDMARD); 554 /* update pointers in primary buffer */ 555 chn_dmaupdate(c); 556 /* ...and feed from primary to secondary */ 557 ret = chn_rdfeed(c); 558} 559 560/* 561 * user read routine - trigger if necessary, uiomove data from secondary buffer 562 * if blocking, sleep, rinse and repeat. 563 * 564 * called externally, so must handle locking 565 */ 566 567int 568chn_read(struct pcm_channel *c, struct uio *buf) 569{ 570 struct snd_dbuf *bs = c->bufsoft; 571 void *off; 572 int ret, timeout, sz, t, p; 573 574 CHN_LOCKASSERT(c); 575 576 if (CHN_STOPPED(c)) 577 chn_start(c, 0); 578 579 ret = 0; 580 timeout = chn_timeout * hz; 581 582 while (ret == 0 && buf->uio_resid > 0) { 583 sz = min(buf->uio_resid, sndbuf_getready(bs)); 584 if (sz > 0) { 585 /* 586 * The following assumes that the free space in 587 * the buffer can never be less around the 588 * unlock-uiomove-lock sequence. 589 */ 590 while (ret == 0 && sz > 0) { 591 p = sndbuf_getreadyptr(bs); 592 t = min(sz, sndbuf_getsize(bs) - p); 593 off = sndbuf_getbufofs(bs, p); 594 CHN_UNLOCK(c); 595 ret = uiomove(off, t, buf); 596 CHN_LOCK(c); 597 sz -= t; 598 sndbuf_dispose(bs, NULL, t); 599 } 600 ret = 0; 601 } else if (c->flags & (CHN_F_NBIO | CHN_F_NOTRIGGER)) 602 ret = EAGAIN; 603 else { 604 ret = chn_sleep(c, "pcmrd", timeout); 605 if (ret == EAGAIN) { 606 ret = EINVAL; 607 c->flags |= CHN_F_DEAD; 608 printf("%s: record interrupt timeout, " 609 "channel dead\n", c->name); 610 } else if (ret == ERESTART || ret == EINTR) 611 c->flags |= CHN_F_ABORTING; 612 } 613 } 614 615 return ret; 616} 617 618void 619chn_intr(struct pcm_channel *c) 620{ 621 CHN_LOCK(c); 622 c->interrupts++; 623 if (c->direction == PCMDIR_PLAY) 624 chn_wrintr(c); 625 else 626 chn_rdintr(c); 627 CHN_UNLOCK(c); 628} 629 630u_int32_t 631chn_start(struct pcm_channel *c, int force) 632{ 633 u_int32_t i, j; 634 struct snd_dbuf *b = c->bufhard; 635 struct snd_dbuf *bs = c->bufsoft; 636 637 CHN_LOCKASSERT(c); 638 /* if we're running, or if we're prevented from triggering, bail */ 639 if (CHN_STARTED(c) || ((c->flags & CHN_F_NOTRIGGER) && !force)) 640 return EINVAL; 641 642 if (force) { 643 i = 1; 644 j = 0; 645 } else { 646 if (c->direction == PCMDIR_REC) { 647 i = sndbuf_getfree(bs); 648 j = (i > 0) ? 1 : sndbuf_getready(b); 649 } else { 650 if (sndbuf_getfree(bs) == 0) { 651 i = 1; 652 j = 0; 653 } else { 654 struct snd_dbuf *pb; 655 656 pb = BUF_PARENT(c, b); 657 i = sndbuf_xbytes(sndbuf_getready(bs), bs, pb); 658 j = sndbuf_getbps(pb); 659 } 660 }
|
648 if (snd_verbose > 3 && SLIST_EMPTY(&c->children))
| 661 if (snd_verbose > 3 && CHN_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; 657 sndbuf_setrun(b, 1); 658 c->feedcount = (c->flags & CHN_F_CLOSING) ? 2 : 0; 659 c->interrupts = 0; 660 c->xruns = 0; 661 if (c->direction == PCMDIR_PLAY && c->parentchannel == NULL) { 662 sndbuf_fillsilence(b); 663 if (snd_verbose > 3) 664 printf("%s: %s starting! (%s) (ready=%d " 665 "force=%d i=%d j=%d intrtimeout=%u " 666 "latency=%dms)\n", 667 __func__, 668 (c->flags & CHN_F_HAS_VCHAN) ? 669 "VCHAN" : "HW", 670 (c->flags & CHN_F_CLOSING) ? "closing" : 671 "running", 672 sndbuf_getready(b), 673 force, i, j, c->timeout, 674 (sndbuf_getsize(b) * 1000) / 675 (sndbuf_getbps(b) * sndbuf_getspd(b))); 676 } 677 chn_trigger(c, PCMTRIG_START); 678 return 0; 679 } 680 681 return 0; 682} 683 684void 685chn_resetbuf(struct pcm_channel *c) 686{ 687 struct snd_dbuf *b = c->bufhard; 688 struct snd_dbuf *bs = c->bufsoft; 689 690 c->blocks = 0; 691 sndbuf_reset(b); 692 sndbuf_reset(bs); 693} 694 695/* 696 * chn_sync waits until the space in the given channel goes above 697 * a threshold. The threshold is checked against fl or rl respectively. 698 * Assume that the condition can become true, do not check here... 699 */ 700int 701chn_sync(struct pcm_channel *c, int threshold) 702{ 703 struct snd_dbuf *b, *bs; 704 int ret, count, hcount, minflush, resid, residp, syncdelay, blksz; 705 u_int32_t cflag; 706 707 CHN_LOCKASSERT(c); 708 709 bs = c->bufsoft; 710 711 if ((c->flags & (CHN_F_DEAD | CHN_F_ABORTING)) || 712 (threshold < 1 && sndbuf_getready(bs) < 1)) 713 return 0; 714 715 if (c->direction != PCMDIR_PLAY) 716 return EINVAL; 717 718 /* if we haven't yet started and nothing is buffered, else start*/ 719 if (CHN_STOPPED(c)) { 720 if (threshold > 0 || sndbuf_getready(bs) > 0) { 721 ret = chn_start(c, 1); 722 if (ret) 723 return ret; 724 } else 725 return 0; 726 } 727 728 b = BUF_PARENT(c, c->bufhard); 729 730 minflush = threshold + sndbuf_xbytes(sndbuf_getready(b), b, bs); 731 732 syncdelay = chn_syncdelay; 733 734 if (syncdelay < 0 && (threshold > 0 || sndbuf_getready(bs) > 0)) 735 minflush += sndbuf_xbytes(sndbuf_getsize(b), b, bs); 736 737 /* 738 * Append (0-1000) millisecond trailing buffer (if needed) 739 * for slower / high latency hardwares (notably USB audio) 740 * to avoid audible truncation. 741 */ 742 if (syncdelay > 0) 743 minflush += (sndbuf_getbps(bs) * sndbuf_getspd(bs) * 744 ((syncdelay > 1000) ? 1000 : syncdelay)) / 1000; 745 746 minflush -= minflush % sndbuf_getbps(bs); 747 748 if (minflush > 0) { 749 threshold = min(minflush, sndbuf_getfree(bs)); 750 sndbuf_clear(bs, threshold); 751 sndbuf_acquire(bs, NULL, threshold); 752 minflush -= threshold; 753 } 754 755 resid = sndbuf_getready(bs); 756 residp = resid; 757 blksz = sndbuf_getblksz(b); 758 if (blksz < 1) { 759 printf("%s: WARNING: blksz < 1 ! maxsize=%d [%d/%d/%d]\n", 760 __func__, sndbuf_getmaxsize(b), sndbuf_getsize(b), 761 sndbuf_getblksz(b), sndbuf_getblkcnt(b)); 762 if (sndbuf_getblkcnt(b) > 0) 763 blksz = sndbuf_getsize(b) / sndbuf_getblkcnt(b); 764 if (blksz < 1) 765 blksz = 1; 766 } 767 count = sndbuf_xbytes(minflush + resid, bs, b) / blksz; 768 hcount = count; 769 ret = 0; 770 771 if (snd_verbose > 3) 772 printf("%s: [begin] timeout=%d count=%d " 773 "minflush=%d resid=%d\n", __func__, c->timeout, count, 774 minflush, resid); 775 776 cflag = c->flags & CHN_F_CLOSING; 777 c->flags |= CHN_F_CLOSING; 778 while (count > 0 && (resid > 0 || minflush > 0)) { 779 ret = chn_sleep(c, "pcmsyn", c->timeout); 780 if (ret == ERESTART || ret == EINTR) { 781 c->flags |= CHN_F_ABORTING; 782 break; 783 } 784 if (ret == 0 || ret == EAGAIN) { 785 resid = sndbuf_getready(bs); 786 if (resid == residp) { 787 --count; 788 if (snd_verbose > 3) 789 printf("%s: [stalled] timeout=%d " 790 "count=%d hcount=%d " 791 "resid=%d minflush=%d\n", 792 __func__, c->timeout, count, 793 hcount, resid, minflush); 794 } else if (resid < residp && count < hcount) { 795 ++count; 796 if (snd_verbose > 3) 797 printf("%s: [resume] timeout=%d " 798 "count=%d hcount=%d " 799 "resid=%d minflush=%d\n", 800 __func__, c->timeout, count, 801 hcount, resid, minflush); 802 } 803 if (minflush > 0 && sndbuf_getfree(bs) > 0) { 804 threshold = min(minflush, 805 sndbuf_getfree(bs)); 806 sndbuf_clear(bs, threshold); 807 sndbuf_acquire(bs, NULL, threshold); 808 resid = sndbuf_getready(bs); 809 minflush -= threshold; 810 } 811 residp = resid; 812 } 813 } 814 c->flags &= ~CHN_F_CLOSING; 815 c->flags |= cflag; 816 817 if (snd_verbose > 3) 818 printf("%s: timeout=%d count=%d hcount=%d resid=%d residp=%d " 819 "minflush=%d ret=%d\n", 820 __func__, c->timeout, count, hcount, resid, residp, 821 minflush, ret); 822 823 return 0; 824} 825 826/* called externally, handle locking */ 827int 828chn_poll(struct pcm_channel *c, int ev, struct thread *td) 829{ 830 struct snd_dbuf *bs = c->bufsoft; 831 int ret; 832 833 CHN_LOCKASSERT(c); 834 if (!(c->flags & (CHN_F_MAPPED | CHN_F_TRIGGERED))) 835 chn_start(c, 1); 836 ret = 0; 837 if (chn_polltrigger(c) && chn_pollreset(c)) 838 ret = ev; 839 else 840 selrecord(td, sndbuf_getsel(bs)); 841 return ret; 842} 843 844/* 845 * chn_abort terminates a running dma transfer. it may sleep up to 200ms. 846 * it returns the number of bytes that have not been transferred. 847 * 848 * called from: dsp_close, dsp_ioctl, with channel locked 849 */ 850int 851chn_abort(struct pcm_channel *c) 852{ 853 int missing = 0; 854 struct snd_dbuf *b = c->bufhard; 855 struct snd_dbuf *bs = c->bufsoft; 856 857 CHN_LOCKASSERT(c); 858 if (CHN_STOPPED(c)) 859 return 0; 860 c->flags |= CHN_F_ABORTING; 861 862 c->flags &= ~CHN_F_TRIGGERED; 863 /* kill the channel */ 864 chn_trigger(c, PCMTRIG_ABORT); 865 sndbuf_setrun(b, 0); 866 if (!(c->flags & CHN_F_VIRTUAL)) 867 chn_dmaupdate(c); 868 missing = sndbuf_getready(bs); 869 870 c->flags &= ~CHN_F_ABORTING; 871 return missing; 872} 873 874/* 875 * this routine tries to flush the dma transfer. It is called 876 * on a close of a playback channel. 877 * first, if there is data in the buffer, but the dma has not yet 878 * begun, we need to start it. 879 * next, we wait for the play buffer to drain 880 * finally, we stop the dma. 881 * 882 * called from: dsp_close, not valid for record channels. 883 */ 884 885int 886chn_flush(struct pcm_channel *c) 887{ 888 struct snd_dbuf *b = c->bufhard; 889 890 CHN_LOCKASSERT(c); 891 KASSERT(c->direction == PCMDIR_PLAY, ("chn_flush on bad channel")); 892 DEB(printf("chn_flush: c->flags 0x%08x\n", c->flags)); 893 894 c->flags |= CHN_F_CLOSING; 895 chn_sync(c, 0); 896 c->flags &= ~CHN_F_TRIGGERED; 897 /* kill the channel */ 898 chn_trigger(c, PCMTRIG_ABORT); 899 sndbuf_setrun(b, 0); 900 901 c->flags &= ~CHN_F_CLOSING; 902 return 0; 903} 904 905int 906fmtvalid(u_int32_t fmt, u_int32_t *fmtlist) 907{ 908 int i; 909 910 for (i = 0; fmtlist[i]; i++) 911 if (fmt == fmtlist[i]) 912 return 1; 913 return 0; 914} 915 916static struct afmtstr_table default_afmtstr_table[] = { 917 { "alaw", AFMT_A_LAW }, { "mulaw", AFMT_MU_LAW }, 918 { "u8", AFMT_U8 }, { "s8", AFMT_S8 }, 919 { "s16le", AFMT_S16_LE }, { "s16be", AFMT_S16_BE }, 920 { "u16le", AFMT_U16_LE }, { "u16be", AFMT_U16_BE }, 921 { "s24le", AFMT_S24_LE }, { "s24be", AFMT_S24_BE }, 922 { "u24le", AFMT_U24_LE }, { "u24be", AFMT_U24_BE }, 923 { "s32le", AFMT_S32_LE }, { "s32be", AFMT_S32_BE }, 924 { "u32le", AFMT_U32_LE }, { "u32be", AFMT_U32_BE }, 925 { NULL, 0 }, 926}; 927 928int 929afmtstr_swap_sign(char *s) 930{ 931 if (s == NULL || strlen(s) < 2) /* full length of "s8" */ 932 return 0; 933 if (*s == 's') 934 *s = 'u'; 935 else if (*s == 'u') 936 *s = 's'; 937 else 938 return 0; 939 return 1; 940} 941 942int 943afmtstr_swap_endian(char *s) 944{ 945 if (s == NULL || strlen(s) < 5) /* full length of "s16le" */ 946 return 0; 947 if (s[3] == 'l') 948 s[3] = 'b'; 949 else if (s[3] == 'b') 950 s[3] = 'l'; 951 else 952 return 0; 953 return 1; 954} 955 956u_int32_t 957afmtstr2afmt(struct afmtstr_table *tbl, const char *s, int stereo) 958{ 959 size_t fsz, sz; 960 961 sz = (s == NULL) ? 0 : strlen(s); 962 963 if (sz > 1) { 964 965 if (tbl == NULL) 966 tbl = default_afmtstr_table; 967 968 for (; tbl->fmtstr != NULL; tbl++) { 969 fsz = strlen(tbl->fmtstr); 970 if (sz < fsz) 971 continue; 972 if (strncmp(s, tbl->fmtstr, fsz) != 0) 973 continue; 974 if (fsz == sz) 975 return tbl->format | 976 ((stereo) ? AFMT_STEREO : 0); 977 if ((sz - fsz) < 2 || s[fsz] != ':') 978 break; 979 /* 980 * For now, just handle mono/stereo. 981 */ 982 if ((s[fsz + 2] == '\0' && (s[fsz + 1] == 'm' || 983 s[fsz + 1] == '1')) || 984 strcmp(s + fsz + 1, "mono") == 0) 985 return tbl->format; 986 if ((s[fsz + 2] == '\0' && (s[fsz + 1] == 's' || 987 s[fsz + 1] == '2')) || 988 strcmp(s + fsz + 1, "stereo") == 0) 989 return tbl->format | AFMT_STEREO; 990 break; 991 } 992 } 993 994 return 0; 995} 996 997u_int32_t 998afmt2afmtstr(struct afmtstr_table *tbl, u_int32_t afmt, char *dst, 999 size_t len, int type, int stereo) 1000{ 1001 u_int32_t fmt = 0; 1002 char *fmtstr = NULL, *tag = ""; 1003 1004 if (tbl == NULL) 1005 tbl = default_afmtstr_table; 1006 1007 for (; tbl->format != 0; tbl++) { 1008 if (tbl->format == 0) 1009 break; 1010 if ((afmt & ~AFMT_STEREO) != tbl->format) 1011 continue; 1012 fmt = afmt; 1013 fmtstr = tbl->fmtstr; 1014 break; 1015 } 1016 1017 if (fmt != 0 && fmtstr != NULL && dst != NULL && len > 0) { 1018 strlcpy(dst, fmtstr, len); 1019 switch (type) { 1020 case AFMTSTR_SIMPLE: 1021 tag = (fmt & AFMT_STEREO) ? ":s" : ":m"; 1022 break; 1023 case AFMTSTR_NUM: 1024 tag = (fmt & AFMT_STEREO) ? ":2" : ":1"; 1025 break; 1026 case AFMTSTR_FULL: 1027 tag = (fmt & AFMT_STEREO) ? ":stereo" : ":mono"; 1028 break; 1029 case AFMTSTR_NONE: 1030 default: 1031 break; 1032 } 1033 if (strlen(tag) > 0 && ((stereo && !(fmt & AFMT_STEREO)) || \ 1034 (!stereo && (fmt & AFMT_STEREO)))) 1035 strlcat(dst, tag, len); 1036 } 1037 1038 return fmt; 1039} 1040 1041int 1042chn_reset(struct pcm_channel *c, u_int32_t fmt) 1043{ 1044 int hwspd, r; 1045 1046 CHN_LOCKASSERT(c); 1047 c->feedcount = 0; 1048 c->flags &= CHN_F_RESET; 1049 c->interrupts = 0; 1050 c->timeout = 1; 1051 c->xruns = 0; 1052 1053 r = CHANNEL_RESET(c->methods, c->devinfo); 1054 if (fmt != 0) { 1055#if 0 1056 hwspd = DSP_DEFAULT_SPEED; 1057 /* only do this on a record channel until feederbuilder works */ 1058 if (c->direction == PCMDIR_REC) 1059 RANGE(hwspd, chn_getcaps(c)->minspeed, chn_getcaps(c)->maxspeed); 1060 c->speed = hwspd; 1061#endif 1062 hwspd = chn_getcaps(c)->minspeed; 1063 c->speed = hwspd; 1064 1065 if (r == 0) 1066 r = chn_setformat(c, fmt); 1067 if (r == 0) 1068 r = chn_setspeed(c, hwspd); 1069#if 0 1070 if (r == 0) 1071 r = chn_setvolume(c, 100, 100); 1072#endif 1073 } 1074 if (r == 0) 1075 r = chn_setlatency(c, chn_latency); 1076 if (r == 0) { 1077 chn_resetbuf(c); 1078 r = CHANNEL_RESETDONE(c->methods, c->devinfo); 1079 } 1080 return r; 1081} 1082 1083int 1084chn_init(struct pcm_channel *c, void *devinfo, int dir, int direction) 1085{ 1086 struct feeder_class *fc; 1087 struct snd_dbuf *b, *bs; 1088 int ret; 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;
| 662 printf("%s: %s (%s) threshold i=%d j=%d\n", 663 __func__, CHN_DIRSTR(c), 664 (c->flags & CHN_F_VIRTUAL) ? "virtual" : "hardware", 665 i, j); 666 } 667 668 if (i >= j) { 669 c->flags |= CHN_F_TRIGGERED; 670 sndbuf_setrun(b, 1); 671 c->feedcount = (c->flags & CHN_F_CLOSING) ? 2 : 0; 672 c->interrupts = 0; 673 c->xruns = 0; 674 if (c->direction == PCMDIR_PLAY && c->parentchannel == NULL) { 675 sndbuf_fillsilence(b); 676 if (snd_verbose > 3) 677 printf("%s: %s starting! (%s) (ready=%d " 678 "force=%d i=%d j=%d intrtimeout=%u " 679 "latency=%dms)\n", 680 __func__, 681 (c->flags & CHN_F_HAS_VCHAN) ? 682 "VCHAN" : "HW", 683 (c->flags & CHN_F_CLOSING) ? "closing" : 684 "running", 685 sndbuf_getready(b), 686 force, i, j, c->timeout, 687 (sndbuf_getsize(b) * 1000) / 688 (sndbuf_getbps(b) * sndbuf_getspd(b))); 689 } 690 chn_trigger(c, PCMTRIG_START); 691 return 0; 692 } 693 694 return 0; 695} 696 697void 698chn_resetbuf(struct pcm_channel *c) 699{ 700 struct snd_dbuf *b = c->bufhard; 701 struct snd_dbuf *bs = c->bufsoft; 702 703 c->blocks = 0; 704 sndbuf_reset(b); 705 sndbuf_reset(bs); 706} 707 708/* 709 * chn_sync waits until the space in the given channel goes above 710 * a threshold. The threshold is checked against fl or rl respectively. 711 * Assume that the condition can become true, do not check here... 712 */ 713int 714chn_sync(struct pcm_channel *c, int threshold) 715{ 716 struct snd_dbuf *b, *bs; 717 int ret, count, hcount, minflush, resid, residp, syncdelay, blksz; 718 u_int32_t cflag; 719 720 CHN_LOCKASSERT(c); 721 722 bs = c->bufsoft; 723 724 if ((c->flags & (CHN_F_DEAD | CHN_F_ABORTING)) || 725 (threshold < 1 && sndbuf_getready(bs) < 1)) 726 return 0; 727 728 if (c->direction != PCMDIR_PLAY) 729 return EINVAL; 730 731 /* if we haven't yet started and nothing is buffered, else start*/ 732 if (CHN_STOPPED(c)) { 733 if (threshold > 0 || sndbuf_getready(bs) > 0) { 734 ret = chn_start(c, 1); 735 if (ret) 736 return ret; 737 } else 738 return 0; 739 } 740 741 b = BUF_PARENT(c, c->bufhard); 742 743 minflush = threshold + sndbuf_xbytes(sndbuf_getready(b), b, bs); 744 745 syncdelay = chn_syncdelay; 746 747 if (syncdelay < 0 && (threshold > 0 || sndbuf_getready(bs) > 0)) 748 minflush += sndbuf_xbytes(sndbuf_getsize(b), b, bs); 749 750 /* 751 * Append (0-1000) millisecond trailing buffer (if needed) 752 * for slower / high latency hardwares (notably USB audio) 753 * to avoid audible truncation. 754 */ 755 if (syncdelay > 0) 756 minflush += (sndbuf_getbps(bs) * sndbuf_getspd(bs) * 757 ((syncdelay > 1000) ? 1000 : syncdelay)) / 1000; 758 759 minflush -= minflush % sndbuf_getbps(bs); 760 761 if (minflush > 0) { 762 threshold = min(minflush, sndbuf_getfree(bs)); 763 sndbuf_clear(bs, threshold); 764 sndbuf_acquire(bs, NULL, threshold); 765 minflush -= threshold; 766 } 767 768 resid = sndbuf_getready(bs); 769 residp = resid; 770 blksz = sndbuf_getblksz(b); 771 if (blksz < 1) { 772 printf("%s: WARNING: blksz < 1 ! maxsize=%d [%d/%d/%d]\n", 773 __func__, sndbuf_getmaxsize(b), sndbuf_getsize(b), 774 sndbuf_getblksz(b), sndbuf_getblkcnt(b)); 775 if (sndbuf_getblkcnt(b) > 0) 776 blksz = sndbuf_getsize(b) / sndbuf_getblkcnt(b); 777 if (blksz < 1) 778 blksz = 1; 779 } 780 count = sndbuf_xbytes(minflush + resid, bs, b) / blksz; 781 hcount = count; 782 ret = 0; 783 784 if (snd_verbose > 3) 785 printf("%s: [begin] timeout=%d count=%d " 786 "minflush=%d resid=%d\n", __func__, c->timeout, count, 787 minflush, resid); 788 789 cflag = c->flags & CHN_F_CLOSING; 790 c->flags |= CHN_F_CLOSING; 791 while (count > 0 && (resid > 0 || minflush > 0)) { 792 ret = chn_sleep(c, "pcmsyn", c->timeout); 793 if (ret == ERESTART || ret == EINTR) { 794 c->flags |= CHN_F_ABORTING; 795 break; 796 } 797 if (ret == 0 || ret == EAGAIN) { 798 resid = sndbuf_getready(bs); 799 if (resid == residp) { 800 --count; 801 if (snd_verbose > 3) 802 printf("%s: [stalled] timeout=%d " 803 "count=%d hcount=%d " 804 "resid=%d minflush=%d\n", 805 __func__, c->timeout, count, 806 hcount, resid, minflush); 807 } else if (resid < residp && count < hcount) { 808 ++count; 809 if (snd_verbose > 3) 810 printf("%s: [resume] timeout=%d " 811 "count=%d hcount=%d " 812 "resid=%d minflush=%d\n", 813 __func__, c->timeout, count, 814 hcount, resid, minflush); 815 } 816 if (minflush > 0 && sndbuf_getfree(bs) > 0) { 817 threshold = min(minflush, 818 sndbuf_getfree(bs)); 819 sndbuf_clear(bs, threshold); 820 sndbuf_acquire(bs, NULL, threshold); 821 resid = sndbuf_getready(bs); 822 minflush -= threshold; 823 } 824 residp = resid; 825 } 826 } 827 c->flags &= ~CHN_F_CLOSING; 828 c->flags |= cflag; 829 830 if (snd_verbose > 3) 831 printf("%s: timeout=%d count=%d hcount=%d resid=%d residp=%d " 832 "minflush=%d ret=%d\n", 833 __func__, c->timeout, count, hcount, resid, residp, 834 minflush, ret); 835 836 return 0; 837} 838 839/* called externally, handle locking */ 840int 841chn_poll(struct pcm_channel *c, int ev, struct thread *td) 842{ 843 struct snd_dbuf *bs = c->bufsoft; 844 int ret; 845 846 CHN_LOCKASSERT(c); 847 if (!(c->flags & (CHN_F_MAPPED | CHN_F_TRIGGERED))) 848 chn_start(c, 1); 849 ret = 0; 850 if (chn_polltrigger(c) && chn_pollreset(c)) 851 ret = ev; 852 else 853 selrecord(td, sndbuf_getsel(bs)); 854 return ret; 855} 856 857/* 858 * chn_abort terminates a running dma transfer. it may sleep up to 200ms. 859 * it returns the number of bytes that have not been transferred. 860 * 861 * called from: dsp_close, dsp_ioctl, with channel locked 862 */ 863int 864chn_abort(struct pcm_channel *c) 865{ 866 int missing = 0; 867 struct snd_dbuf *b = c->bufhard; 868 struct snd_dbuf *bs = c->bufsoft; 869 870 CHN_LOCKASSERT(c); 871 if (CHN_STOPPED(c)) 872 return 0; 873 c->flags |= CHN_F_ABORTING; 874 875 c->flags &= ~CHN_F_TRIGGERED; 876 /* kill the channel */ 877 chn_trigger(c, PCMTRIG_ABORT); 878 sndbuf_setrun(b, 0); 879 if (!(c->flags & CHN_F_VIRTUAL)) 880 chn_dmaupdate(c); 881 missing = sndbuf_getready(bs); 882 883 c->flags &= ~CHN_F_ABORTING; 884 return missing; 885} 886 887/* 888 * this routine tries to flush the dma transfer. It is called 889 * on a close of a playback channel. 890 * first, if there is data in the buffer, but the dma has not yet 891 * begun, we need to start it. 892 * next, we wait for the play buffer to drain 893 * finally, we stop the dma. 894 * 895 * called from: dsp_close, not valid for record channels. 896 */ 897 898int 899chn_flush(struct pcm_channel *c) 900{ 901 struct snd_dbuf *b = c->bufhard; 902 903 CHN_LOCKASSERT(c); 904 KASSERT(c->direction == PCMDIR_PLAY, ("chn_flush on bad channel")); 905 DEB(printf("chn_flush: c->flags 0x%08x\n", c->flags)); 906 907 c->flags |= CHN_F_CLOSING; 908 chn_sync(c, 0); 909 c->flags &= ~CHN_F_TRIGGERED; 910 /* kill the channel */ 911 chn_trigger(c, PCMTRIG_ABORT); 912 sndbuf_setrun(b, 0); 913 914 c->flags &= ~CHN_F_CLOSING; 915 return 0; 916} 917 918int 919fmtvalid(u_int32_t fmt, u_int32_t *fmtlist) 920{ 921 int i; 922 923 for (i = 0; fmtlist[i]; i++) 924 if (fmt == fmtlist[i]) 925 return 1; 926 return 0; 927} 928 929static struct afmtstr_table default_afmtstr_table[] = { 930 { "alaw", AFMT_A_LAW }, { "mulaw", AFMT_MU_LAW }, 931 { "u8", AFMT_U8 }, { "s8", AFMT_S8 }, 932 { "s16le", AFMT_S16_LE }, { "s16be", AFMT_S16_BE }, 933 { "u16le", AFMT_U16_LE }, { "u16be", AFMT_U16_BE }, 934 { "s24le", AFMT_S24_LE }, { "s24be", AFMT_S24_BE }, 935 { "u24le", AFMT_U24_LE }, { "u24be", AFMT_U24_BE }, 936 { "s32le", AFMT_S32_LE }, { "s32be", AFMT_S32_BE }, 937 { "u32le", AFMT_U32_LE }, { "u32be", AFMT_U32_BE }, 938 { NULL, 0 }, 939}; 940 941int 942afmtstr_swap_sign(char *s) 943{ 944 if (s == NULL || strlen(s) < 2) /* full length of "s8" */ 945 return 0; 946 if (*s == 's') 947 *s = 'u'; 948 else if (*s == 'u') 949 *s = 's'; 950 else 951 return 0; 952 return 1; 953} 954 955int 956afmtstr_swap_endian(char *s) 957{ 958 if (s == NULL || strlen(s) < 5) /* full length of "s16le" */ 959 return 0; 960 if (s[3] == 'l') 961 s[3] = 'b'; 962 else if (s[3] == 'b') 963 s[3] = 'l'; 964 else 965 return 0; 966 return 1; 967} 968 969u_int32_t 970afmtstr2afmt(struct afmtstr_table *tbl, const char *s, int stereo) 971{ 972 size_t fsz, sz; 973 974 sz = (s == NULL) ? 0 : strlen(s); 975 976 if (sz > 1) { 977 978 if (tbl == NULL) 979 tbl = default_afmtstr_table; 980 981 for (; tbl->fmtstr != NULL; tbl++) { 982 fsz = strlen(tbl->fmtstr); 983 if (sz < fsz) 984 continue; 985 if (strncmp(s, tbl->fmtstr, fsz) != 0) 986 continue; 987 if (fsz == sz) 988 return tbl->format | 989 ((stereo) ? AFMT_STEREO : 0); 990 if ((sz - fsz) < 2 || s[fsz] != ':') 991 break; 992 /* 993 * For now, just handle mono/stereo. 994 */ 995 if ((s[fsz + 2] == '\0' && (s[fsz + 1] == 'm' || 996 s[fsz + 1] == '1')) || 997 strcmp(s + fsz + 1, "mono") == 0) 998 return tbl->format; 999 if ((s[fsz + 2] == '\0' && (s[fsz + 1] == 's' || 1000 s[fsz + 1] == '2')) || 1001 strcmp(s + fsz + 1, "stereo") == 0) 1002 return tbl->format | AFMT_STEREO; 1003 break; 1004 } 1005 } 1006 1007 return 0; 1008} 1009 1010u_int32_t 1011afmt2afmtstr(struct afmtstr_table *tbl, u_int32_t afmt, char *dst, 1012 size_t len, int type, int stereo) 1013{ 1014 u_int32_t fmt = 0; 1015 char *fmtstr = NULL, *tag = ""; 1016 1017 if (tbl == NULL) 1018 tbl = default_afmtstr_table; 1019 1020 for (; tbl->format != 0; tbl++) { 1021 if (tbl->format == 0) 1022 break; 1023 if ((afmt & ~AFMT_STEREO) != tbl->format) 1024 continue; 1025 fmt = afmt; 1026 fmtstr = tbl->fmtstr; 1027 break; 1028 } 1029 1030 if (fmt != 0 && fmtstr != NULL && dst != NULL && len > 0) { 1031 strlcpy(dst, fmtstr, len); 1032 switch (type) { 1033 case AFMTSTR_SIMPLE: 1034 tag = (fmt & AFMT_STEREO) ? ":s" : ":m"; 1035 break; 1036 case AFMTSTR_NUM: 1037 tag = (fmt & AFMT_STEREO) ? ":2" : ":1"; 1038 break; 1039 case AFMTSTR_FULL: 1040 tag = (fmt & AFMT_STEREO) ? ":stereo" : ":mono"; 1041 break; 1042 case AFMTSTR_NONE: 1043 default: 1044 break; 1045 } 1046 if (strlen(tag) > 0 && ((stereo && !(fmt & AFMT_STEREO)) || \ 1047 (!stereo && (fmt & AFMT_STEREO)))) 1048 strlcat(dst, tag, len); 1049 } 1050 1051 return fmt; 1052} 1053 1054int 1055chn_reset(struct pcm_channel *c, u_int32_t fmt) 1056{ 1057 int hwspd, r; 1058 1059 CHN_LOCKASSERT(c); 1060 c->feedcount = 0; 1061 c->flags &= CHN_F_RESET; 1062 c->interrupts = 0; 1063 c->timeout = 1; 1064 c->xruns = 0; 1065 1066 r = CHANNEL_RESET(c->methods, c->devinfo); 1067 if (fmt != 0) { 1068#if 0 1069 hwspd = DSP_DEFAULT_SPEED; 1070 /* only do this on a record channel until feederbuilder works */ 1071 if (c->direction == PCMDIR_REC) 1072 RANGE(hwspd, chn_getcaps(c)->minspeed, chn_getcaps(c)->maxspeed); 1073 c->speed = hwspd; 1074#endif 1075 hwspd = chn_getcaps(c)->minspeed; 1076 c->speed = hwspd; 1077 1078 if (r == 0) 1079 r = chn_setformat(c, fmt); 1080 if (r == 0) 1081 r = chn_setspeed(c, hwspd); 1082#if 0 1083 if (r == 0) 1084 r = chn_setvolume(c, 100, 100); 1085#endif 1086 } 1087 if (r == 0) 1088 r = chn_setlatency(c, chn_latency); 1089 if (r == 0) { 1090 chn_resetbuf(c); 1091 r = CHANNEL_RESETDONE(c->methods, c->devinfo); 1092 } 1093 return r; 1094} 1095 1096int 1097chn_init(struct pcm_channel *c, void *devinfo, int dir, int direction) 1098{ 1099 struct feeder_class *fc; 1100 struct snd_dbuf *b, *bs; 1101 int ret; 1102 1103 if (chn_timeout < CHN_TIMEOUT_MIN || chn_timeout > CHN_TIMEOUT_MAX) 1104 chn_timeout = CHN_TIMEOUT; 1105 1106 chn_lockinit(c, dir); 1107 1108 b = NULL; 1109 bs = NULL;
|
| 1110 CHN_INIT(c, children); 1111 CHN_INIT(c, children.busy);
|
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) 1105 goto out; 1106 bs = sndbuf_create(c->dev, c->name, "secondary", c); 1107 if (bs == NULL) 1108 goto out; 1109 1110 CHN_LOCK(c); 1111 1112 ret = EINVAL; 1113 fc = feeder_getclass(NULL); 1114 if (fc == NULL) 1115 goto out; 1116 if (chn_addfeeder(c, fc, NULL)) 1117 goto out; 1118 1119 /* 1120 * XXX - sndbuf_setup() & sndbuf_resize() expect to be called 1121 * with the channel unlocked because they are also called 1122 * from driver methods that don't know about locking 1123 */ 1124 CHN_UNLOCK(c); 1125 sndbuf_setup(bs, NULL, 0); 1126 CHN_LOCK(c); 1127 c->bufhard = b; 1128 c->bufsoft = bs; 1129 c->flags = 0; 1130 c->feederflags = 0; 1131 c->sm = NULL; 1132 1133 ret = ENODEV; 1134 CHN_UNLOCK(c); /* XXX - Unlock for CHANNEL_INIT() malloc() call */ 1135 c->devinfo = CHANNEL_INIT(c->methods, devinfo, b, c, direction); 1136 CHN_LOCK(c); 1137 if (c->devinfo == NULL) 1138 goto out; 1139 1140 ret = ENOMEM; 1141 if ((sndbuf_getsize(b) == 0) && ((c->flags & CHN_F_VIRTUAL) == 0)) 1142 goto out; 1143 1144 ret = chn_setdir(c, direction); 1145 if (ret) 1146 goto out; 1147 1148 ret = sndbuf_setfmt(b, AFMT_U8); 1149 if (ret) 1150 goto out; 1151 1152 ret = sndbuf_setfmt(bs, AFMT_U8); 1153 if (ret) 1154 goto out; 1155 1156 /** 1157 * @todo Should this be moved somewhere else? The primary buffer 1158 * is allocated by the driver or via DMA map setup, and tmpbuf 1159 * seems to only come into existence in sndbuf_resize(). 1160 */ 1161 if (c->direction == PCMDIR_PLAY) { 1162 bs->sl = sndbuf_getmaxsize(bs); 1163 bs->shadbuf = malloc(bs->sl, M_DEVBUF, M_NOWAIT); 1164 if (bs->shadbuf == NULL) { 1165 ret = ENOMEM; 1166 goto out; 1167 } 1168 } 1169 1170out: 1171 CHN_UNLOCK(c); 1172 if (ret) { 1173 if (c->devinfo) { 1174 if (CHANNEL_FREE(c->methods, c->devinfo)) 1175 sndbuf_free(b); 1176 } 1177 if (bs) 1178 sndbuf_destroy(bs); 1179 if (b) 1180 sndbuf_destroy(b); 1181 c->flags |= CHN_F_DEAD; 1182 chn_lockdestroy(c); 1183 1184 return ret; 1185 } 1186 1187 return 0; 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
| 1112 c->devinfo = NULL; 1113 c->feeder = NULL; 1114 c->latency = -1; 1115 c->timeout = 1; 1116 1117 ret = ENOMEM; 1118 b = sndbuf_create(c->dev, c->name, "primary", c); 1119 if (b == NULL) 1120 goto out; 1121 bs = sndbuf_create(c->dev, c->name, "secondary", c); 1122 if (bs == NULL) 1123 goto out; 1124 1125 CHN_LOCK(c); 1126 1127 ret = EINVAL; 1128 fc = feeder_getclass(NULL); 1129 if (fc == NULL) 1130 goto out; 1131 if (chn_addfeeder(c, fc, NULL)) 1132 goto out; 1133 1134 /* 1135 * XXX - sndbuf_setup() & sndbuf_resize() expect to be called 1136 * with the channel unlocked because they are also called 1137 * from driver methods that don't know about locking 1138 */ 1139 CHN_UNLOCK(c); 1140 sndbuf_setup(bs, NULL, 0); 1141 CHN_LOCK(c); 1142 c->bufhard = b; 1143 c->bufsoft = bs; 1144 c->flags = 0; 1145 c->feederflags = 0; 1146 c->sm = NULL; 1147 1148 ret = ENODEV; 1149 CHN_UNLOCK(c); /* XXX - Unlock for CHANNEL_INIT() malloc() call */ 1150 c->devinfo = CHANNEL_INIT(c->methods, devinfo, b, c, direction); 1151 CHN_LOCK(c); 1152 if (c->devinfo == NULL) 1153 goto out; 1154 1155 ret = ENOMEM; 1156 if ((sndbuf_getsize(b) == 0) && ((c->flags & CHN_F_VIRTUAL) == 0)) 1157 goto out; 1158 1159 ret = chn_setdir(c, direction); 1160 if (ret) 1161 goto out; 1162 1163 ret = sndbuf_setfmt(b, AFMT_U8); 1164 if (ret) 1165 goto out; 1166 1167 ret = sndbuf_setfmt(bs, AFMT_U8); 1168 if (ret) 1169 goto out; 1170 1171 /** 1172 * @todo Should this be moved somewhere else? The primary buffer 1173 * is allocated by the driver or via DMA map setup, and tmpbuf 1174 * seems to only come into existence in sndbuf_resize(). 1175 */ 1176 if (c->direction == PCMDIR_PLAY) { 1177 bs->sl = sndbuf_getmaxsize(bs); 1178 bs->shadbuf = malloc(bs->sl, M_DEVBUF, M_NOWAIT); 1179 if (bs->shadbuf == NULL) { 1180 ret = ENOMEM; 1181 goto out; 1182 } 1183 } 1184 1185out: 1186 CHN_UNLOCK(c); 1187 if (ret) { 1188 if (c->devinfo) { 1189 if (CHANNEL_FREE(c->methods, c->devinfo)) 1190 sndbuf_free(b); 1191 } 1192 if (bs) 1193 sndbuf_destroy(bs); 1194 if (b) 1195 sndbuf_destroy(b); 1196 c->flags |= CHN_F_DEAD; 1197 chn_lockdestroy(c); 1198 1199 return ret; 1200 } 1201 1202 return 0; 1203} 1204 1205int 1206chn_kill(struct pcm_channel *c) 1207{ 1208 struct snd_dbuf *b = c->bufhard; 1209 struct snd_dbuf *bs = c->bufsoft; 1210
|
1196 if (CHN_STARTED(c))
| 1211 if (CHN_STARTED(c)) { 1212 CHN_LOCK(c);
|
1197 chn_trigger(c, PCMTRIG_ABORT);
| 1213 chn_trigger(c, PCMTRIG_ABORT);
|
1198 while (chn_removefeeder(c) == 0);
| 1214 CHN_UNLOCK(c); 1215 } 1216 while (chn_removefeeder(c) == 0) 1217 ;
|
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} 1207 1208int 1209chn_setdir(struct pcm_channel *c, int dir) 1210{ 1211#ifdef DEV_ISA 1212 struct snd_dbuf *b = c->bufhard; 1213#endif 1214 int r; 1215 1216 CHN_LOCKASSERT(c); 1217 c->direction = dir; 1218 r = CHANNEL_SETDIR(c->methods, c->devinfo, c->direction); 1219#ifdef DEV_ISA 1220 if (!r && SND_DMA(b)) 1221 sndbuf_dmasetdir(b, c->direction); 1222#endif 1223 return r; 1224} 1225 1226int 1227chn_setvolume(struct pcm_channel *c, int left, int right) 1228{ 1229 CHN_LOCKASSERT(c); 1230 /* should add a feeder for volume changing if channel returns -1 */ 1231 if (left > 100) 1232 left = 100; 1233 if (left < 0) 1234 left = 0; 1235 if (right > 100) 1236 right = 100; 1237 if (right < 0) 1238 right = 0; 1239 c->volume = left | (right << 8); 1240 return 0; 1241} 1242 1243static u_int32_t 1244round_pow2(u_int32_t v) 1245{ 1246 u_int32_t ret; 1247 1248 if (v < 2) 1249 v = 2; 1250 ret = 0; 1251 while (v >> ret) 1252 ret++; 1253 ret = 1 << (ret - 1); 1254 while (ret < v) 1255 ret <<= 1; 1256 return ret; 1257} 1258 1259static u_int32_t 1260round_blksz(u_int32_t v, int round) 1261{ 1262 u_int32_t ret, tmp; 1263 1264 if (round < 1) 1265 round = 1; 1266 1267 ret = min(round_pow2(v), CHN_2NDBUFMAXSIZE >> 1); 1268 1269 if (ret > v && (ret >> 1) > 0 && (ret >> 1) >= ((v * 3) >> 2)) 1270 ret >>= 1; 1271 1272 tmp = ret - (ret % round); 1273 while (tmp < 16 || tmp < round) { 1274 ret <<= 1; 1275 tmp = ret - (ret % round); 1276 } 1277 1278 return ret; 1279} 1280 1281/* 1282 * 4Front call it DSP Policy, while we call it "Latency Profile". The idea 1283 * is to keep 2nd buffer short so that it doesn't cause long queue during 1284 * buffer transfer. 1285 * 1286 * Latency reference table for 48khz stereo 16bit: (PLAY) 1287 * 1288 * +---------+------------+-----------+------------+ 1289 * | Latency | Blockcount | Blocksize | Buffersize | 1290 * +---------+------------+-----------+------------+ 1291 * | 0 | 2 | 64 | 128 | 1292 * +---------+------------+-----------+------------+ 1293 * | 1 | 4 | 128 | 512 | 1294 * +---------+------------+-----------+------------+ 1295 * | 2 | 8 | 512 | 4096 | 1296 * +---------+------------+-----------+------------+ 1297 * | 3 | 16 | 512 | 8192 | 1298 * +---------+------------+-----------+------------+ 1299 * | 4 | 32 | 512 | 16384 | 1300 * +---------+------------+-----------+------------+ 1301 * | 5 | 32 | 1024 | 32768 | 1302 * +---------+------------+-----------+------------+ 1303 * | 6 | 16 | 2048 | 32768 | 1304 * +---------+------------+-----------+------------+ 1305 * | 7 | 8 | 4096 | 32768 | 1306 * +---------+------------+-----------+------------+ 1307 * | 8 | 4 | 8192 | 32768 | 1308 * +---------+------------+-----------+------------+ 1309 * | 9 | 2 | 16384 | 32768 | 1310 * +---------+------------+-----------+------------+ 1311 * | 10 | 2 | 32768 | 65536 | 1312 * +---------+------------+-----------+------------+ 1313 * 1314 * Recording need a different reference table. All we care is 1315 * gobbling up everything within reasonable buffering threshold. 1316 * 1317 * Latency reference table for 48khz stereo 16bit: (REC) 1318 * 1319 * +---------+------------+-----------+------------+ 1320 * | Latency | Blockcount | Blocksize | Buffersize | 1321 * +---------+------------+-----------+------------+ 1322 * | 0 | 512 | 32 | 16384 | 1323 * +---------+------------+-----------+------------+ 1324 * | 1 | 256 | 64 | 16384 | 1325 * +---------+------------+-----------+------------+ 1326 * | 2 | 128 | 128 | 16384 | 1327 * +---------+------------+-----------+------------+ 1328 * | 3 | 64 | 256 | 16384 | 1329 * +---------+------------+-----------+------------+ 1330 * | 4 | 32 | 512 | 16384 | 1331 * +---------+------------+-----------+------------+ 1332 * | 5 | 32 | 1024 | 32768 | 1333 * +---------+------------+-----------+------------+ 1334 * | 6 | 16 | 2048 | 32768 | 1335 * +---------+------------+-----------+------------+ 1336 * | 7 | 8 | 4096 | 32768 | 1337 * +---------+------------+-----------+------------+ 1338 * | 8 | 4 | 8192 | 32768 | 1339 * +---------+------------+-----------+------------+ 1340 * | 9 | 2 | 16384 | 32768 | 1341 * +---------+------------+-----------+------------+ 1342 * | 10 | 2 | 32768 | 65536 | 1343 * +---------+------------+-----------+------------+ 1344 * 1345 * Calculations for other data rate are entirely based on these reference 1346 * tables. For normal operation, Latency 5 seems give the best, well 1347 * balanced performance for typical workload. Anything below 5 will 1348 * eat up CPU to keep up with increasing context switches because of 1349 * shorter buffer space and usually require the application to handle it 1350 * aggresively through possibly real time programming technique. 1351 * 1352 */ 1353#define CHN_LATENCY_PBLKCNT_REF \ 1354 {{1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 1}, \ 1355 {1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 1}} 1356#define CHN_LATENCY_PBUFSZ_REF \ 1357 {{7, 9, 12, 13, 14, 15, 15, 15, 15, 15, 16}, \ 1358 {11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 17}} 1359 1360#define CHN_LATENCY_RBLKCNT_REF \ 1361 {{9, 8, 7, 6, 5, 5, 4, 3, 2, 1, 1}, \ 1362 {9, 8, 7, 6, 5, 5, 4, 3, 2, 1, 1}} 1363#define CHN_LATENCY_RBUFSZ_REF \ 1364 {{14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 16}, \ 1365 {15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 17}} 1366 1367#define CHN_LATENCY_DATA_REF 192000 /* 48khz stereo 16bit ~ 48000 x 2 x 2 */ 1368 1369static int 1370chn_calclatency(int dir, int latency, int bps, u_int32_t datarate, 1371 u_int32_t max, int *rblksz, int *rblkcnt) 1372{ 1373 static int pblkcnts[CHN_LATENCY_PROFILE_MAX + 1][CHN_LATENCY_MAX + 1] = 1374 CHN_LATENCY_PBLKCNT_REF; 1375 static int pbufszs[CHN_LATENCY_PROFILE_MAX + 1][CHN_LATENCY_MAX + 1] = 1376 CHN_LATENCY_PBUFSZ_REF; 1377 static int rblkcnts[CHN_LATENCY_PROFILE_MAX + 1][CHN_LATENCY_MAX + 1] = 1378 CHN_LATENCY_RBLKCNT_REF; 1379 static int rbufszs[CHN_LATENCY_PROFILE_MAX + 1][CHN_LATENCY_MAX + 1] = 1380 CHN_LATENCY_RBUFSZ_REF; 1381 u_int32_t bufsz; 1382 int lprofile, blksz, blkcnt; 1383 1384 if (latency < CHN_LATENCY_MIN || latency > CHN_LATENCY_MAX || 1385 bps < 1 || datarate < 1 || 1386 !(dir == PCMDIR_PLAY || dir == PCMDIR_REC)) { 1387 if (rblksz != NULL) 1388 *rblksz = CHN_2NDBUFMAXSIZE >> 1; 1389 if (rblkcnt != NULL) 1390 *rblkcnt = 2; 1391 printf("%s: FAILED dir=%d latency=%d bps=%d " 1392 "datarate=%u max=%u\n", 1393 __func__, dir, latency, bps, datarate, max); 1394 return CHN_2NDBUFMAXSIZE; 1395 } 1396 1397 lprofile = chn_latency_profile; 1398 1399 if (dir == PCMDIR_PLAY) { 1400 blkcnt = pblkcnts[lprofile][latency]; 1401 bufsz = pbufszs[lprofile][latency]; 1402 } else { 1403 blkcnt = rblkcnts[lprofile][latency]; 1404 bufsz = rbufszs[lprofile][latency]; 1405 } 1406 1407 bufsz = round_pow2(snd_xbytes(1 << bufsz, CHN_LATENCY_DATA_REF, 1408 datarate)); 1409 if (bufsz > max) 1410 bufsz = max; 1411 blksz = round_blksz(bufsz >> blkcnt, bps); 1412 1413 if (rblksz != NULL) 1414 *rblksz = blksz; 1415 if (rblkcnt != NULL) 1416 *rblkcnt = 1 << blkcnt; 1417 1418 return blksz << blkcnt; 1419} 1420 1421static int 1422chn_resizebuf(struct pcm_channel *c, int latency, 1423 int blkcnt, int blksz) 1424{ 1425 struct snd_dbuf *b, *bs, *pb; 1426 int sblksz, sblkcnt, hblksz, hblkcnt, limit = 1; 1427 int ret; 1428 1429 CHN_LOCKASSERT(c); 1430 1431 if ((c->flags & (CHN_F_MAPPED | CHN_F_TRIGGERED)) || 1432 !(c->direction == PCMDIR_PLAY || c->direction == PCMDIR_REC)) 1433 return EINVAL; 1434 1435 if (latency == -1) { 1436 c->latency = -1; 1437 latency = chn_latency; 1438 } else if (latency == -2) { 1439 latency = c->latency; 1440 if (latency < CHN_LATENCY_MIN || latency > CHN_LATENCY_MAX) 1441 latency = chn_latency; 1442 } else if (latency < CHN_LATENCY_MIN || latency > CHN_LATENCY_MAX) 1443 return EINVAL; 1444 else { 1445 c->latency = latency; 1446 limit = 0; 1447 } 1448 1449 bs = c->bufsoft; 1450 b = c->bufhard; 1451 1452 if (!(blksz == 0 || blkcnt == -1) && 1453 (blksz < 16 || blksz < sndbuf_getbps(bs) || blkcnt < 2 || 1454 (blksz * blkcnt) > CHN_2NDBUFMAXSIZE)) 1455 return EINVAL; 1456 1457 chn_calclatency(c->direction, latency, sndbuf_getbps(bs), 1458 sndbuf_getbps(bs) * sndbuf_getspd(bs), CHN_2NDBUFMAXSIZE, 1459 &sblksz, &sblkcnt); 1460 1461 if (blksz == 0 || blkcnt == -1) { 1462 if (blkcnt == -1) 1463 c->flags &= ~CHN_F_HAS_SIZE; 1464 if (c->flags & CHN_F_HAS_SIZE) { 1465 blksz = sndbuf_getblksz(bs); 1466 blkcnt = sndbuf_getblkcnt(bs); 1467 } 1468 } else 1469 c->flags |= CHN_F_HAS_SIZE; 1470 1471 if (c->flags & CHN_F_HAS_SIZE) { 1472 /* 1473 * The application has requested their own blksz/blkcnt. 1474 * Just obey with it, and let them toast alone. We can 1475 * clamp it to the nearest latency profile, but that would 1476 * defeat the purpose of having custom control. The least 1477 * we can do is round it to the nearest ^2 and align it. 1478 */ 1479 sblksz = round_blksz(blksz, sndbuf_getbps(bs)); 1480 sblkcnt = round_pow2(blkcnt); 1481 limit = 0; 1482 } 1483 1484 if (c->parentchannel != NULL) { 1485 pb = BUF_PARENT(c, NULL); 1486 CHN_UNLOCK(c); 1487 chn_notify(c->parentchannel, CHN_N_BLOCKSIZE); 1488 CHN_LOCK(c); 1489 limit = (limit != 0 && pb != NULL) ? 1490 sndbuf_xbytes(sndbuf_getsize(pb), pb, bs) : 0; 1491 c->timeout = c->parentchannel->timeout; 1492 } else { 1493 hblkcnt = 2; 1494 if (c->flags & CHN_F_HAS_SIZE) { 1495 hblksz = round_blksz(sndbuf_xbytes(sblksz, bs, b), 1496 sndbuf_getbps(b)); 1497 hblkcnt = round_pow2(sndbuf_getblkcnt(bs)); 1498 } else 1499 chn_calclatency(c->direction, latency, 1500 sndbuf_getbps(b), 1501 sndbuf_getbps(b) * sndbuf_getspd(b), 1502 CHN_2NDBUFMAXSIZE, &hblksz, &hblkcnt); 1503 1504 if ((hblksz << 1) > sndbuf_getmaxsize(b)) 1505 hblksz = round_blksz(sndbuf_getmaxsize(b) >> 1, 1506 sndbuf_getbps(b)); 1507 1508 while ((hblksz * hblkcnt) > sndbuf_getmaxsize(b)) { 1509 if (hblkcnt < 4) 1510 hblksz >>= 1; 1511 else 1512 hblkcnt >>= 1; 1513 } 1514 1515 hblksz -= hblksz % sndbuf_getbps(b); 1516 1517#if 0 1518 hblksz = sndbuf_getmaxsize(b) >> 1; 1519 hblksz -= hblksz % sndbuf_getbps(b); 1520 hblkcnt = 2; 1521#endif 1522 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
| 1218 if (CHANNEL_FREE(c->methods, c->devinfo)) 1219 sndbuf_free(b); 1220 c->flags |= CHN_F_DEAD; 1221 sndbuf_destroy(bs); 1222 sndbuf_destroy(b); 1223 chn_lockdestroy(c); 1224 return 0; 1225} 1226 1227int 1228chn_setdir(struct pcm_channel *c, int dir) 1229{ 1230#ifdef DEV_ISA 1231 struct snd_dbuf *b = c->bufhard; 1232#endif 1233 int r; 1234 1235 CHN_LOCKASSERT(c); 1236 c->direction = dir; 1237 r = CHANNEL_SETDIR(c->methods, c->devinfo, c->direction); 1238#ifdef DEV_ISA 1239 if (!r && SND_DMA(b)) 1240 sndbuf_dmasetdir(b, c->direction); 1241#endif 1242 return r; 1243} 1244 1245int 1246chn_setvolume(struct pcm_channel *c, int left, int right) 1247{ 1248 CHN_LOCKASSERT(c); 1249 /* should add a feeder for volume changing if channel returns -1 */ 1250 if (left > 100) 1251 left = 100; 1252 if (left < 0) 1253 left = 0; 1254 if (right > 100) 1255 right = 100; 1256 if (right < 0) 1257 right = 0; 1258 c->volume = left | (right << 8); 1259 return 0; 1260} 1261 1262static u_int32_t 1263round_pow2(u_int32_t v) 1264{ 1265 u_int32_t ret; 1266 1267 if (v < 2) 1268 v = 2; 1269 ret = 0; 1270 while (v >> ret) 1271 ret++; 1272 ret = 1 << (ret - 1); 1273 while (ret < v) 1274 ret <<= 1; 1275 return ret; 1276} 1277 1278static u_int32_t 1279round_blksz(u_int32_t v, int round) 1280{ 1281 u_int32_t ret, tmp; 1282 1283 if (round < 1) 1284 round = 1; 1285 1286 ret = min(round_pow2(v), CHN_2NDBUFMAXSIZE >> 1); 1287 1288 if (ret > v && (ret >> 1) > 0 && (ret >> 1) >= ((v * 3) >> 2)) 1289 ret >>= 1; 1290 1291 tmp = ret - (ret % round); 1292 while (tmp < 16 || tmp < round) { 1293 ret <<= 1; 1294 tmp = ret - (ret % round); 1295 } 1296 1297 return ret; 1298} 1299 1300/* 1301 * 4Front call it DSP Policy, while we call it "Latency Profile". The idea 1302 * is to keep 2nd buffer short so that it doesn't cause long queue during 1303 * buffer transfer. 1304 * 1305 * Latency reference table for 48khz stereo 16bit: (PLAY) 1306 * 1307 * +---------+------------+-----------+------------+ 1308 * | Latency | Blockcount | Blocksize | Buffersize | 1309 * +---------+------------+-----------+------------+ 1310 * | 0 | 2 | 64 | 128 | 1311 * +---------+------------+-----------+------------+ 1312 * | 1 | 4 | 128 | 512 | 1313 * +---------+------------+-----------+------------+ 1314 * | 2 | 8 | 512 | 4096 | 1315 * +---------+------------+-----------+------------+ 1316 * | 3 | 16 | 512 | 8192 | 1317 * +---------+------------+-----------+------------+ 1318 * | 4 | 32 | 512 | 16384 | 1319 * +---------+------------+-----------+------------+ 1320 * | 5 | 32 | 1024 | 32768 | 1321 * +---------+------------+-----------+------------+ 1322 * | 6 | 16 | 2048 | 32768 | 1323 * +---------+------------+-----------+------------+ 1324 * | 7 | 8 | 4096 | 32768 | 1325 * +---------+------------+-----------+------------+ 1326 * | 8 | 4 | 8192 | 32768 | 1327 * +---------+------------+-----------+------------+ 1328 * | 9 | 2 | 16384 | 32768 | 1329 * +---------+------------+-----------+------------+ 1330 * | 10 | 2 | 32768 | 65536 | 1331 * +---------+------------+-----------+------------+ 1332 * 1333 * Recording need a different reference table. All we care is 1334 * gobbling up everything within reasonable buffering threshold. 1335 * 1336 * Latency reference table for 48khz stereo 16bit: (REC) 1337 * 1338 * +---------+------------+-----------+------------+ 1339 * | Latency | Blockcount | Blocksize | Buffersize | 1340 * +---------+------------+-----------+------------+ 1341 * | 0 | 512 | 32 | 16384 | 1342 * +---------+------------+-----------+------------+ 1343 * | 1 | 256 | 64 | 16384 | 1344 * +---------+------------+-----------+------------+ 1345 * | 2 | 128 | 128 | 16384 | 1346 * +---------+------------+-----------+------------+ 1347 * | 3 | 64 | 256 | 16384 | 1348 * +---------+------------+-----------+------------+ 1349 * | 4 | 32 | 512 | 16384 | 1350 * +---------+------------+-----------+------------+ 1351 * | 5 | 32 | 1024 | 32768 | 1352 * +---------+------------+-----------+------------+ 1353 * | 6 | 16 | 2048 | 32768 | 1354 * +---------+------------+-----------+------------+ 1355 * | 7 | 8 | 4096 | 32768 | 1356 * +---------+------------+-----------+------------+ 1357 * | 8 | 4 | 8192 | 32768 | 1358 * +---------+------------+-----------+------------+ 1359 * | 9 | 2 | 16384 | 32768 | 1360 * +---------+------------+-----------+------------+ 1361 * | 10 | 2 | 32768 | 65536 | 1362 * +---------+------------+-----------+------------+ 1363 * 1364 * Calculations for other data rate are entirely based on these reference 1365 * tables. For normal operation, Latency 5 seems give the best, well 1366 * balanced performance for typical workload. Anything below 5 will 1367 * eat up CPU to keep up with increasing context switches because of 1368 * shorter buffer space and usually require the application to handle it 1369 * aggresively through possibly real time programming technique. 1370 * 1371 */ 1372#define CHN_LATENCY_PBLKCNT_REF \ 1373 {{1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 1}, \ 1374 {1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 1}} 1375#define CHN_LATENCY_PBUFSZ_REF \ 1376 {{7, 9, 12, 13, 14, 15, 15, 15, 15, 15, 16}, \ 1377 {11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 17}} 1378 1379#define CHN_LATENCY_RBLKCNT_REF \ 1380 {{9, 8, 7, 6, 5, 5, 4, 3, 2, 1, 1}, \ 1381 {9, 8, 7, 6, 5, 5, 4, 3, 2, 1, 1}} 1382#define CHN_LATENCY_RBUFSZ_REF \ 1383 {{14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 16}, \ 1384 {15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 17}} 1385 1386#define CHN_LATENCY_DATA_REF 192000 /* 48khz stereo 16bit ~ 48000 x 2 x 2 */ 1387 1388static int 1389chn_calclatency(int dir, int latency, int bps, u_int32_t datarate, 1390 u_int32_t max, int *rblksz, int *rblkcnt) 1391{ 1392 static int pblkcnts[CHN_LATENCY_PROFILE_MAX + 1][CHN_LATENCY_MAX + 1] = 1393 CHN_LATENCY_PBLKCNT_REF; 1394 static int pbufszs[CHN_LATENCY_PROFILE_MAX + 1][CHN_LATENCY_MAX + 1] = 1395 CHN_LATENCY_PBUFSZ_REF; 1396 static int rblkcnts[CHN_LATENCY_PROFILE_MAX + 1][CHN_LATENCY_MAX + 1] = 1397 CHN_LATENCY_RBLKCNT_REF; 1398 static int rbufszs[CHN_LATENCY_PROFILE_MAX + 1][CHN_LATENCY_MAX + 1] = 1399 CHN_LATENCY_RBUFSZ_REF; 1400 u_int32_t bufsz; 1401 int lprofile, blksz, blkcnt; 1402 1403 if (latency < CHN_LATENCY_MIN || latency > CHN_LATENCY_MAX || 1404 bps < 1 || datarate < 1 || 1405 !(dir == PCMDIR_PLAY || dir == PCMDIR_REC)) { 1406 if (rblksz != NULL) 1407 *rblksz = CHN_2NDBUFMAXSIZE >> 1; 1408 if (rblkcnt != NULL) 1409 *rblkcnt = 2; 1410 printf("%s: FAILED dir=%d latency=%d bps=%d " 1411 "datarate=%u max=%u\n", 1412 __func__, dir, latency, bps, datarate, max); 1413 return CHN_2NDBUFMAXSIZE; 1414 } 1415 1416 lprofile = chn_latency_profile; 1417 1418 if (dir == PCMDIR_PLAY) { 1419 blkcnt = pblkcnts[lprofile][latency]; 1420 bufsz = pbufszs[lprofile][latency]; 1421 } else { 1422 blkcnt = rblkcnts[lprofile][latency]; 1423 bufsz = rbufszs[lprofile][latency]; 1424 } 1425 1426 bufsz = round_pow2(snd_xbytes(1 << bufsz, CHN_LATENCY_DATA_REF, 1427 datarate)); 1428 if (bufsz > max) 1429 bufsz = max; 1430 blksz = round_blksz(bufsz >> blkcnt, bps); 1431 1432 if (rblksz != NULL) 1433 *rblksz = blksz; 1434 if (rblkcnt != NULL) 1435 *rblkcnt = 1 << blkcnt; 1436 1437 return blksz << blkcnt; 1438} 1439 1440static int 1441chn_resizebuf(struct pcm_channel *c, int latency, 1442 int blkcnt, int blksz) 1443{ 1444 struct snd_dbuf *b, *bs, *pb; 1445 int sblksz, sblkcnt, hblksz, hblkcnt, limit = 1; 1446 int ret; 1447 1448 CHN_LOCKASSERT(c); 1449 1450 if ((c->flags & (CHN_F_MAPPED | CHN_F_TRIGGERED)) || 1451 !(c->direction == PCMDIR_PLAY || c->direction == PCMDIR_REC)) 1452 return EINVAL; 1453 1454 if (latency == -1) { 1455 c->latency = -1; 1456 latency = chn_latency; 1457 } else if (latency == -2) { 1458 latency = c->latency; 1459 if (latency < CHN_LATENCY_MIN || latency > CHN_LATENCY_MAX) 1460 latency = chn_latency; 1461 } else if (latency < CHN_LATENCY_MIN || latency > CHN_LATENCY_MAX) 1462 return EINVAL; 1463 else { 1464 c->latency = latency; 1465 limit = 0; 1466 } 1467 1468 bs = c->bufsoft; 1469 b = c->bufhard; 1470 1471 if (!(blksz == 0 || blkcnt == -1) && 1472 (blksz < 16 || blksz < sndbuf_getbps(bs) || blkcnt < 2 || 1473 (blksz * blkcnt) > CHN_2NDBUFMAXSIZE)) 1474 return EINVAL; 1475 1476 chn_calclatency(c->direction, latency, sndbuf_getbps(bs), 1477 sndbuf_getbps(bs) * sndbuf_getspd(bs), CHN_2NDBUFMAXSIZE, 1478 &sblksz, &sblkcnt); 1479 1480 if (blksz == 0 || blkcnt == -1) { 1481 if (blkcnt == -1) 1482 c->flags &= ~CHN_F_HAS_SIZE; 1483 if (c->flags & CHN_F_HAS_SIZE) { 1484 blksz = sndbuf_getblksz(bs); 1485 blkcnt = sndbuf_getblkcnt(bs); 1486 } 1487 } else 1488 c->flags |= CHN_F_HAS_SIZE; 1489 1490 if (c->flags & CHN_F_HAS_SIZE) { 1491 /* 1492 * The application has requested their own blksz/blkcnt. 1493 * Just obey with it, and let them toast alone. We can 1494 * clamp it to the nearest latency profile, but that would 1495 * defeat the purpose of having custom control. The least 1496 * we can do is round it to the nearest ^2 and align it. 1497 */ 1498 sblksz = round_blksz(blksz, sndbuf_getbps(bs)); 1499 sblkcnt = round_pow2(blkcnt); 1500 limit = 0; 1501 } 1502 1503 if (c->parentchannel != NULL) { 1504 pb = BUF_PARENT(c, NULL); 1505 CHN_UNLOCK(c); 1506 chn_notify(c->parentchannel, CHN_N_BLOCKSIZE); 1507 CHN_LOCK(c); 1508 limit = (limit != 0 && pb != NULL) ? 1509 sndbuf_xbytes(sndbuf_getsize(pb), pb, bs) : 0; 1510 c->timeout = c->parentchannel->timeout; 1511 } else { 1512 hblkcnt = 2; 1513 if (c->flags & CHN_F_HAS_SIZE) { 1514 hblksz = round_blksz(sndbuf_xbytes(sblksz, bs, b), 1515 sndbuf_getbps(b)); 1516 hblkcnt = round_pow2(sndbuf_getblkcnt(bs)); 1517 } else 1518 chn_calclatency(c->direction, latency, 1519 sndbuf_getbps(b), 1520 sndbuf_getbps(b) * sndbuf_getspd(b), 1521 CHN_2NDBUFMAXSIZE, &hblksz, &hblkcnt); 1522 1523 if ((hblksz << 1) > sndbuf_getmaxsize(b)) 1524 hblksz = round_blksz(sndbuf_getmaxsize(b) >> 1, 1525 sndbuf_getbps(b)); 1526 1527 while ((hblksz * hblkcnt) > sndbuf_getmaxsize(b)) { 1528 if (hblkcnt < 4) 1529 hblksz >>= 1; 1530 else 1531 hblkcnt >>= 1; 1532 } 1533 1534 hblksz -= hblksz % sndbuf_getbps(b); 1535 1536#if 0 1537 hblksz = sndbuf_getmaxsize(b) >> 1; 1538 hblksz -= hblksz % sndbuf_getbps(b); 1539 hblkcnt = 2; 1540#endif 1541 1542 CHN_UNLOCK(c); 1543 if (chn_usefrags == 0 || 1544 CHANNEL_SETFRAGMENTS(c->methods, c->devinfo, 1545 hblksz, hblkcnt) < 1) 1546 sndbuf_setblksz(b, CHANNEL_SETBLOCKSIZE(c->methods, 1547 c->devinfo, hblksz)); 1548 CHN_LOCK(c); 1549
|
1531 if (!SLIST_EMPTY(&c->children)) {
| 1550 if (!CHN_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 1540 /* 1541 * Interrupt timeout 1542 */ 1543 c->timeout = ((u_int64_t)hz * sndbuf_getsize(b)) / 1544 ((u_int64_t)sndbuf_getspd(b) * sndbuf_getbps(b)); 1545 if (c->timeout < 1) 1546 c->timeout = 1; 1547 } 1548 1549 if (limit > CHN_2NDBUFMAXSIZE) 1550 limit = CHN_2NDBUFMAXSIZE; 1551 1552#if 0 1553 while (limit > 0 && (sblksz * sblkcnt) > limit) { 1554 if (sblkcnt < 4) 1555 break; 1556 sblkcnt >>= 1; 1557 } 1558#endif 1559 1560 while ((sblksz * sblkcnt) < limit) 1561 sblkcnt <<= 1; 1562 1563 while ((sblksz * sblkcnt) > CHN_2NDBUFMAXSIZE) { 1564 if (sblkcnt < 4) 1565 sblksz >>= 1; 1566 else 1567 sblkcnt >>= 1; 1568 } 1569 1570 sblksz -= sblksz % sndbuf_getbps(bs); 1571 1572 if (sndbuf_getblkcnt(bs) != sblkcnt || sndbuf_getblksz(bs) != sblksz || 1573 sndbuf_getsize(bs) != (sblkcnt * sblksz)) { 1574 ret = sndbuf_remalloc(bs, sblkcnt, sblksz); 1575 if (ret != 0) { 1576 printf("%s: Failed: %d %d\n", __func__, 1577 sblkcnt, sblksz); 1578 return ret; 1579 } 1580 } 1581 1582 /* 1583 * OSSv4 docs: "By default OSS will set the low water level equal 1584 * to the fragment size which is optimal in most cases." 1585 */ 1586 c->lw = sndbuf_getblksz(bs); 1587 chn_resetbuf(c); 1588 1589 if (snd_verbose > 3) 1590 printf("%s: %s (%s) timeout=%u " 1591 "b[%d/%d/%d] bs[%d/%d/%d] limit=%d\n", 1592 __func__, CHN_DIRSTR(c), 1593 (c->flags & CHN_F_VIRTUAL) ? "virtual" : "hardware", 1594 c->timeout, 1595 sndbuf_getsize(b), sndbuf_getblksz(b), 1596 sndbuf_getblkcnt(b), 1597 sndbuf_getsize(bs), sndbuf_getblksz(bs), 1598 sndbuf_getblkcnt(bs), limit); 1599 1600 return 0; 1601} 1602 1603int 1604chn_setlatency(struct pcm_channel *c, int latency) 1605{ 1606 CHN_LOCKASSERT(c); 1607 /* Destroy blksz/blkcnt, enforce latency profile. */ 1608 return chn_resizebuf(c, latency, -1, 0); 1609} 1610 1611int 1612chn_setblocksize(struct pcm_channel *c, int blkcnt, int blksz) 1613{ 1614 CHN_LOCKASSERT(c); 1615 /* Destroy latency profile, enforce blksz/blkcnt */ 1616 return chn_resizebuf(c, -1, blkcnt, blksz); 1617} 1618 1619static int 1620chn_tryspeed(struct pcm_channel *c, int speed) 1621{ 1622 struct pcm_feeder *f; 1623 struct snd_dbuf *b = c->bufhard; 1624 struct snd_dbuf *bs = c->bufsoft; 1625 struct snd_dbuf *x; 1626 int r, delta; 1627 1628 CHN_LOCKASSERT(c); 1629 DEB(printf("setspeed, channel %s\n", c->name)); 1630 DEB(printf("want speed %d, ", speed)); 1631 if (speed <= 0) 1632 return EINVAL; 1633 if (CHN_STOPPED(c)) { 1634 r = 0; 1635 c->speed = speed; 1636 sndbuf_setspd(bs, speed); 1637 RANGE(speed, chn_getcaps(c)->minspeed, chn_getcaps(c)->maxspeed); 1638 DEB(printf("try speed %d, ", speed)); 1639 sndbuf_setspd(b, CHANNEL_SETSPEED(c->methods, c->devinfo, speed)); 1640 DEB(printf("got speed %d\n", sndbuf_getspd(b))); 1641 1642 delta = sndbuf_getspd(b) - sndbuf_getspd(bs); 1643 if (delta < 0) 1644 delta = -delta; 1645 1646 c->feederflags &= ~(1 << FEEDER_RATE); 1647 /* 1648 * Used to be 500. It was too big! 1649 */ 1650 if (delta > feeder_rate_round) 1651 c->feederflags |= 1 << FEEDER_RATE; 1652 else 1653 sndbuf_setspd(bs, sndbuf_getspd(b)); 1654 1655 r = chn_buildfeeder(c); 1656 DEB(printf("r = %d\n", r)); 1657 if (r) 1658 goto out; 1659 1660 if (!(c->feederflags & (1 << FEEDER_RATE))) 1661 goto out; 1662 1663 r = EINVAL; 1664 f = chn_findfeeder(c, FEEDER_RATE); 1665 DEB(printf("feedrate = %p\n", f)); 1666 if (f == NULL) 1667 goto out; 1668 1669 x = (c->direction == PCMDIR_REC)? b : bs; 1670 r = FEEDER_SET(f, FEEDRATE_SRC, sndbuf_getspd(x)); 1671 DEB(printf("feeder_set(FEEDRATE_SRC, %d) = %d\n", sndbuf_getspd(x), r)); 1672 if (r) 1673 goto out; 1674 1675 x = (c->direction == PCMDIR_REC)? bs : b; 1676 r = FEEDER_SET(f, FEEDRATE_DST, sndbuf_getspd(x)); 1677 DEB(printf("feeder_set(FEEDRATE_DST, %d) = %d\n", sndbuf_getspd(x), r)); 1678out: 1679 if (!r) 1680 r = CHANNEL_SETFORMAT(c->methods, c->devinfo, 1681 sndbuf_getfmt(b)); 1682 if (!r) 1683 sndbuf_setfmt(bs, c->format); 1684 if (!r) 1685 r = chn_resizebuf(c, -2, 0, 0); 1686 DEB(printf("setspeed done, r = %d\n", r)); 1687 return r; 1688 } else 1689 return EINVAL; 1690} 1691 1692int 1693chn_setspeed(struct pcm_channel *c, int speed) 1694{ 1695 int r, oldspeed = c->speed; 1696 1697 r = chn_tryspeed(c, speed); 1698 if (r) { 1699 if (snd_verbose > 3) 1700 printf("Failed to set speed %d falling back to %d\n", 1701 speed, oldspeed); 1702 r = chn_tryspeed(c, oldspeed); 1703 } 1704 return r; 1705} 1706 1707static int 1708chn_tryformat(struct pcm_channel *c, u_int32_t fmt) 1709{ 1710 struct snd_dbuf *b = c->bufhard; 1711 struct snd_dbuf *bs = c->bufsoft; 1712 int r; 1713 1714 CHN_LOCKASSERT(c); 1715 if (CHN_STOPPED(c)) { 1716 DEB(printf("want format %d\n", fmt)); 1717 c->format = fmt; 1718 r = chn_buildfeeder(c); 1719 if (r == 0) { 1720 sndbuf_setfmt(bs, c->format); 1721 chn_resetbuf(c); 1722 r = CHANNEL_SETFORMAT(c->methods, c->devinfo, sndbuf_getfmt(b)); 1723 if (r == 0) 1724 r = chn_tryspeed(c, c->speed); 1725 } 1726 return r; 1727 } else 1728 return EINVAL; 1729} 1730 1731int 1732chn_setformat(struct pcm_channel *c, u_int32_t fmt) 1733{ 1734 u_int32_t oldfmt = c->format; 1735 int r; 1736 1737 r = chn_tryformat(c, fmt); 1738 if (r) { 1739 if (snd_verbose > 3) 1740 printf("Format change 0x%08x failed, reverting to 0x%08x\n", 1741 fmt, oldfmt); 1742 chn_tryformat(c, oldfmt); 1743 } 1744 return r; 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
| 1551 sblksz = round_blksz( 1552 sndbuf_xbytes(sndbuf_getsize(b) >> 1, b, bs), 1553 sndbuf_getbps(bs)); 1554 sblkcnt = 2; 1555 limit = 0; 1556 } else if (limit != 0) 1557 limit = sndbuf_xbytes(sndbuf_getsize(b), b, bs); 1558 1559 /* 1560 * Interrupt timeout 1561 */ 1562 c->timeout = ((u_int64_t)hz * sndbuf_getsize(b)) / 1563 ((u_int64_t)sndbuf_getspd(b) * sndbuf_getbps(b)); 1564 if (c->timeout < 1) 1565 c->timeout = 1; 1566 } 1567 1568 if (limit > CHN_2NDBUFMAXSIZE) 1569 limit = CHN_2NDBUFMAXSIZE; 1570 1571#if 0 1572 while (limit > 0 && (sblksz * sblkcnt) > limit) { 1573 if (sblkcnt < 4) 1574 break; 1575 sblkcnt >>= 1; 1576 } 1577#endif 1578 1579 while ((sblksz * sblkcnt) < limit) 1580 sblkcnt <<= 1; 1581 1582 while ((sblksz * sblkcnt) > CHN_2NDBUFMAXSIZE) { 1583 if (sblkcnt < 4) 1584 sblksz >>= 1; 1585 else 1586 sblkcnt >>= 1; 1587 } 1588 1589 sblksz -= sblksz % sndbuf_getbps(bs); 1590 1591 if (sndbuf_getblkcnt(bs) != sblkcnt || sndbuf_getblksz(bs) != sblksz || 1592 sndbuf_getsize(bs) != (sblkcnt * sblksz)) { 1593 ret = sndbuf_remalloc(bs, sblkcnt, sblksz); 1594 if (ret != 0) { 1595 printf("%s: Failed: %d %d\n", __func__, 1596 sblkcnt, sblksz); 1597 return ret; 1598 } 1599 } 1600 1601 /* 1602 * OSSv4 docs: "By default OSS will set the low water level equal 1603 * to the fragment size which is optimal in most cases." 1604 */ 1605 c->lw = sndbuf_getblksz(bs); 1606 chn_resetbuf(c); 1607 1608 if (snd_verbose > 3) 1609 printf("%s: %s (%s) timeout=%u " 1610 "b[%d/%d/%d] bs[%d/%d/%d] limit=%d\n", 1611 __func__, CHN_DIRSTR(c), 1612 (c->flags & CHN_F_VIRTUAL) ? "virtual" : "hardware", 1613 c->timeout, 1614 sndbuf_getsize(b), sndbuf_getblksz(b), 1615 sndbuf_getblkcnt(b), 1616 sndbuf_getsize(bs), sndbuf_getblksz(bs), 1617 sndbuf_getblkcnt(bs), limit); 1618 1619 return 0; 1620} 1621 1622int 1623chn_setlatency(struct pcm_channel *c, int latency) 1624{ 1625 CHN_LOCKASSERT(c); 1626 /* Destroy blksz/blkcnt, enforce latency profile. */ 1627 return chn_resizebuf(c, latency, -1, 0); 1628} 1629 1630int 1631chn_setblocksize(struct pcm_channel *c, int blkcnt, int blksz) 1632{ 1633 CHN_LOCKASSERT(c); 1634 /* Destroy latency profile, enforce blksz/blkcnt */ 1635 return chn_resizebuf(c, -1, blkcnt, blksz); 1636} 1637 1638static int 1639chn_tryspeed(struct pcm_channel *c, int speed) 1640{ 1641 struct pcm_feeder *f; 1642 struct snd_dbuf *b = c->bufhard; 1643 struct snd_dbuf *bs = c->bufsoft; 1644 struct snd_dbuf *x; 1645 int r, delta; 1646 1647 CHN_LOCKASSERT(c); 1648 DEB(printf("setspeed, channel %s\n", c->name)); 1649 DEB(printf("want speed %d, ", speed)); 1650 if (speed <= 0) 1651 return EINVAL; 1652 if (CHN_STOPPED(c)) { 1653 r = 0; 1654 c->speed = speed; 1655 sndbuf_setspd(bs, speed); 1656 RANGE(speed, chn_getcaps(c)->minspeed, chn_getcaps(c)->maxspeed); 1657 DEB(printf("try speed %d, ", speed)); 1658 sndbuf_setspd(b, CHANNEL_SETSPEED(c->methods, c->devinfo, speed)); 1659 DEB(printf("got speed %d\n", sndbuf_getspd(b))); 1660 1661 delta = sndbuf_getspd(b) - sndbuf_getspd(bs); 1662 if (delta < 0) 1663 delta = -delta; 1664 1665 c->feederflags &= ~(1 << FEEDER_RATE); 1666 /* 1667 * Used to be 500. It was too big! 1668 */ 1669 if (delta > feeder_rate_round) 1670 c->feederflags |= 1 << FEEDER_RATE; 1671 else 1672 sndbuf_setspd(bs, sndbuf_getspd(b)); 1673 1674 r = chn_buildfeeder(c); 1675 DEB(printf("r = %d\n", r)); 1676 if (r) 1677 goto out; 1678 1679 if (!(c->feederflags & (1 << FEEDER_RATE))) 1680 goto out; 1681 1682 r = EINVAL; 1683 f = chn_findfeeder(c, FEEDER_RATE); 1684 DEB(printf("feedrate = %p\n", f)); 1685 if (f == NULL) 1686 goto out; 1687 1688 x = (c->direction == PCMDIR_REC)? b : bs; 1689 r = FEEDER_SET(f, FEEDRATE_SRC, sndbuf_getspd(x)); 1690 DEB(printf("feeder_set(FEEDRATE_SRC, %d) = %d\n", sndbuf_getspd(x), r)); 1691 if (r) 1692 goto out; 1693 1694 x = (c->direction == PCMDIR_REC)? bs : b; 1695 r = FEEDER_SET(f, FEEDRATE_DST, sndbuf_getspd(x)); 1696 DEB(printf("feeder_set(FEEDRATE_DST, %d) = %d\n", sndbuf_getspd(x), r)); 1697out: 1698 if (!r) 1699 r = CHANNEL_SETFORMAT(c->methods, c->devinfo, 1700 sndbuf_getfmt(b)); 1701 if (!r) 1702 sndbuf_setfmt(bs, c->format); 1703 if (!r) 1704 r = chn_resizebuf(c, -2, 0, 0); 1705 DEB(printf("setspeed done, r = %d\n", r)); 1706 return r; 1707 } else 1708 return EINVAL; 1709} 1710 1711int 1712chn_setspeed(struct pcm_channel *c, int speed) 1713{ 1714 int r, oldspeed = c->speed; 1715 1716 r = chn_tryspeed(c, speed); 1717 if (r) { 1718 if (snd_verbose > 3) 1719 printf("Failed to set speed %d falling back to %d\n", 1720 speed, oldspeed); 1721 r = chn_tryspeed(c, oldspeed); 1722 } 1723 return r; 1724} 1725 1726static int 1727chn_tryformat(struct pcm_channel *c, u_int32_t fmt) 1728{ 1729 struct snd_dbuf *b = c->bufhard; 1730 struct snd_dbuf *bs = c->bufsoft; 1731 int r; 1732 1733 CHN_LOCKASSERT(c); 1734 if (CHN_STOPPED(c)) { 1735 DEB(printf("want format %d\n", fmt)); 1736 c->format = fmt; 1737 r = chn_buildfeeder(c); 1738 if (r == 0) { 1739 sndbuf_setfmt(bs, c->format); 1740 chn_resetbuf(c); 1741 r = CHANNEL_SETFORMAT(c->methods, c->devinfo, sndbuf_getfmt(b)); 1742 if (r == 0) 1743 r = chn_tryspeed(c, c->speed); 1744 } 1745 return r; 1746 } else 1747 return EINVAL; 1748} 1749 1750int 1751chn_setformat(struct pcm_channel *c, u_int32_t fmt) 1752{ 1753 u_int32_t oldfmt = c->format; 1754 int r; 1755 1756 r = chn_tryformat(c, fmt); 1757 if (r) { 1758 if (snd_verbose > 3) 1759 printf("Format change 0x%08x failed, reverting to 0x%08x\n", 1760 fmt, oldfmt); 1761 chn_tryformat(c, oldfmt); 1762 } 1763 return r; 1764} 1765 1766int 1767chn_trigger(struct pcm_channel *c, int go) 1768{ 1769#ifdef DEV_ISA 1770 struct snd_dbuf *b = c->bufhard; 1771#endif
|
| 1772 struct snddev_info *d = c->parentsnddev;
|
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
| 1773 int ret; 1774 1775 CHN_LOCKASSERT(c); 1776#ifdef DEV_ISA 1777 if (SND_DMA(b) && (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)) 1778 sndbuf_dmabounce(b); 1779#endif
|
| 1780 if ((go == PCMTRIG_START || go == PCMTRIG_STOP || 1781 go == PCMTRIG_ABORT) && go == c->trigger) 1782 return 0; 1783
|
1760 ret = CHANNEL_TRIGGER(c->methods, c->devinfo, go); 1761
| 1784 ret = CHANNEL_TRIGGER(c->methods, c->devinfo, go); 1785
|
| 1786 if (ret == 0) { 1787 switch (go) { 1788 case PCMTRIG_START: 1789 if (snd_verbose > 3) 1790 device_printf(c->dev, 1791 "%s() %s: calling go=0x%08x , " 1792 "prev=0x%08x\n", __func__, c->name, go, 1793 c->trigger); 1794 if (c->trigger != PCMTRIG_START) { 1795 c->trigger = go; 1796 CHN_UNLOCK(c); 1797 pcm_lock(d); 1798 CHN_INSERT_HEAD(d, c, channels.pcm.busy); 1799 pcm_unlock(d); 1800 CHN_LOCK(c); 1801 } 1802 break; 1803 case PCMTRIG_STOP: 1804 case PCMTRIG_ABORT: 1805 if (snd_verbose > 3) 1806 device_printf(c->dev, 1807 "%s() %s: calling go=0x%08x , " 1808 "prev=0x%08x\n", __func__, c->name, go, 1809 c->trigger); 1810 if (c->trigger == PCMTRIG_START) { 1811 c->trigger = go; 1812 CHN_UNLOCK(c); 1813 pcm_lock(d); 1814 CHN_REMOVE(d, c, channels.pcm.busy); 1815 pcm_unlock(d); 1816 CHN_LOCK(c); 1817 } 1818 break; 1819 default: 1820 break; 1821 } 1822 } 1823
|
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 1770 * running in 16 bit stereo mode would require 4 bytes per sample, so a 1771 * hwptr value ranging from 32-35 would be returned as 32.) 1772 * 1773 * @param c PCM channel context 1774 * @returns sample-aligned hardware buffer pointer index 1775 */ 1776int 1777chn_getptr(struct pcm_channel *c) 1778{ 1779#if 0 1780 int hwptr; 1781 int a = (1 << c->align) - 1; 1782 1783 CHN_LOCKASSERT(c); 1784 hwptr = (c->flags & CHN_F_TRIGGERED)? CHANNEL_GETPTR(c->methods, c->devinfo) : 0; 1785 /* don't allow unaligned values in the hwa ptr */ 1786#if 1 1787 hwptr &= ~a ; /* Apply channel align mask */ 1788#endif 1789 hwptr &= DMA_ALIGN_MASK; /* Apply DMA align mask */ 1790 return hwptr; 1791#endif 1792 int hwptr; 1793 1794 CHN_LOCKASSERT(c); 1795 hwptr = (CHN_STARTED(c)) ? CHANNEL_GETPTR(c->methods, c->devinfo) : 0; 1796 return (hwptr - (hwptr % sndbuf_getbps(c->bufhard))); 1797} 1798 1799struct pcmchan_caps * 1800chn_getcaps(struct pcm_channel *c) 1801{ 1802 CHN_LOCKASSERT(c); 1803 return CHANNEL_GETCAPS(c->methods, c->devinfo); 1804} 1805 1806u_int32_t 1807chn_getformats(struct pcm_channel *c) 1808{ 1809 u_int32_t *fmtlist, fmts; 1810 int i; 1811 1812 fmtlist = chn_getcaps(c)->fmtlist; 1813 fmts = 0; 1814 for (i = 0; fmtlist[i]; i++) 1815 fmts |= fmtlist[i]; 1816 1817 /* report software-supported formats */ 1818 if (report_soft_formats) 1819 fmts |= AFMT_MU_LAW|AFMT_A_LAW|AFMT_U32_LE|AFMT_U32_BE| 1820 AFMT_S32_LE|AFMT_S32_BE|AFMT_U24_LE|AFMT_U24_BE| 1821 AFMT_S24_LE|AFMT_S24_BE|AFMT_U16_LE|AFMT_U16_BE| 1822 AFMT_S16_LE|AFMT_S16_BE|AFMT_U8|AFMT_S8; 1823 1824 return fmts; 1825} 1826 1827static int 1828chn_buildfeeder(struct pcm_channel *c) 1829{ 1830 struct feeder_class *fc; 1831 struct pcm_feederdesc desc; 1832 u_int32_t tmp[2], type, flags, hwfmt, *fmtlist; 1833 int err; 1834 char fmtstr[AFMTSTR_MAXSZ]; 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
| 1824 return ret; 1825} 1826 1827/** 1828 * @brief Queries sound driver for sample-aligned hardware buffer pointer index 1829 * 1830 * This function obtains the hardware pointer location, then aligns it to 1831 * the current bytes-per-sample value before returning. (E.g., a channel 1832 * running in 16 bit stereo mode would require 4 bytes per sample, so a 1833 * hwptr value ranging from 32-35 would be returned as 32.) 1834 * 1835 * @param c PCM channel context 1836 * @returns sample-aligned hardware buffer pointer index 1837 */ 1838int 1839chn_getptr(struct pcm_channel *c) 1840{ 1841#if 0 1842 int hwptr; 1843 int a = (1 << c->align) - 1; 1844 1845 CHN_LOCKASSERT(c); 1846 hwptr = (c->flags & CHN_F_TRIGGERED)? CHANNEL_GETPTR(c->methods, c->devinfo) : 0; 1847 /* don't allow unaligned values in the hwa ptr */ 1848#if 1 1849 hwptr &= ~a ; /* Apply channel align mask */ 1850#endif 1851 hwptr &= DMA_ALIGN_MASK; /* Apply DMA align mask */ 1852 return hwptr; 1853#endif 1854 int hwptr; 1855 1856 CHN_LOCKASSERT(c); 1857 hwptr = (CHN_STARTED(c)) ? CHANNEL_GETPTR(c->methods, c->devinfo) : 0; 1858 return (hwptr - (hwptr % sndbuf_getbps(c->bufhard))); 1859} 1860 1861struct pcmchan_caps * 1862chn_getcaps(struct pcm_channel *c) 1863{ 1864 CHN_LOCKASSERT(c); 1865 return CHANNEL_GETCAPS(c->methods, c->devinfo); 1866} 1867 1868u_int32_t 1869chn_getformats(struct pcm_channel *c) 1870{ 1871 u_int32_t *fmtlist, fmts; 1872 int i; 1873 1874 fmtlist = chn_getcaps(c)->fmtlist; 1875 fmts = 0; 1876 for (i = 0; fmtlist[i]; i++) 1877 fmts |= fmtlist[i]; 1878 1879 /* report software-supported formats */ 1880 if (report_soft_formats) 1881 fmts |= AFMT_MU_LAW|AFMT_A_LAW|AFMT_U32_LE|AFMT_U32_BE| 1882 AFMT_S32_LE|AFMT_S32_BE|AFMT_U24_LE|AFMT_U24_BE| 1883 AFMT_S24_LE|AFMT_S24_BE|AFMT_U16_LE|AFMT_U16_BE| 1884 AFMT_S16_LE|AFMT_S16_BE|AFMT_U8|AFMT_S8; 1885 1886 return fmts; 1887} 1888 1889static int 1890chn_buildfeeder(struct pcm_channel *c) 1891{ 1892 struct feeder_class *fc; 1893 struct pcm_feederdesc desc; 1894 u_int32_t tmp[2], type, flags, hwfmt, *fmtlist; 1895 int err; 1896 char fmtstr[AFMTSTR_MAXSZ]; 1897 1898 CHN_LOCKASSERT(c); 1899 while (chn_removefeeder(c) == 0) 1900 ; 1901 KASSERT((c->feeder == NULL), ("feeder chain not empty")); 1902 1903 c->align = sndbuf_getalign(c->bufsoft); 1904
|
1843 if (SLIST_EMPTY(&c->children)) {
| 1905 if (CHN_EMPTY(c, children) || c->direction == PCMDIR_REC) { 1906 /* 1907 * Virtual rec need this. 1908 */
|
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;
| 1909 fc = feeder_getclass(NULL); 1910 KASSERT(fc != NULL, ("can't find root feeder")); 1911 1912 err = chn_addfeeder(c, fc, NULL); 1913 if (err) { 1914 DEB(printf("can't add root feeder, err %d\n", err)); 1915 1916 return err; 1917 } 1918 c->feeder->desc->out = c->format;
|
1854 } else {
| 1919 } else if (c->direction == PCMDIR_PLAY) {
|
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; 1863 desc.flags = 0; 1864 fc = feeder_getclass(&desc); 1865 if (fc == NULL) { 1866 DEB(printf("can't find vchan feeder\n")); 1867 1868 return EOPNOTSUPP; 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 }
| 1920 if (c->flags & CHN_F_HAS_VCHAN) { 1921 desc.type = FEEDER_MIXER; 1922 desc.in = c->format; 1923 } else { 1924 DEB(printf("can't decide which feeder type to use!\n")); 1925 return EOPNOTSUPP; 1926 } 1927 desc.out = c->format; 1928 desc.flags = 0; 1929 fc = feeder_getclass(&desc); 1930 if (fc == NULL) { 1931 DEB(printf("can't find vchan feeder\n")); 1932 1933 return EOPNOTSUPP; 1934 } 1935 1936 err = chn_addfeeder(c, fc, &desc); 1937 if (err) { 1938 DEB(printf("can't add vchan feeder, err %d\n", err)); 1939 1940 return err; 1941 }
|
1877 }
| 1942 } else 1943 return EOPNOTSUPP; 1944
|
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 && 1886 (c->parentsnddev->flags & SD_F_PSWAPLR)) || 1887 (c->direction == PCMDIR_REC && 1888 (c->parentsnddev->flags & SD_F_RSWAPLR)))) 1889 c->feederflags |= 1 << FEEDER_SWAPLR; 1890 flags = c->feederflags; 1891 fmtlist = chn_getcaps(c)->fmtlist; 1892 1893 DEB(printf("feederflags %x\n", flags)); 1894 1895 for (type = FEEDER_RATE; type < FEEDER_LAST; type++) { 1896 if (flags & (1 << type)) { 1897 desc.type = type; 1898 desc.in = 0; 1899 desc.out = 0; 1900 desc.flags = 0; 1901 DEB(printf("find feeder type %d, ", type)); 1902 if (type == FEEDER_VOLUME || type == FEEDER_RATE) { 1903 if (c->feeder->desc->out & AFMT_32BIT) 1904 strlcpy(fmtstr,"s32le", sizeof(fmtstr)); 1905 else if (c->feeder->desc->out & AFMT_24BIT) 1906 strlcpy(fmtstr, "s24le", sizeof(fmtstr)); 1907 else { 1908 /* 1909 * 8bit doesn't provide enough headroom 1910 * for proper processing without 1911 * creating too much noises. Force to 1912 * 16bit instead. 1913 */ 1914 strlcpy(fmtstr, "s16le", sizeof(fmtstr)); 1915 } 1916 if (!(c->feeder->desc->out & AFMT_8BIT) && 1917 c->feeder->desc->out & AFMT_BIGENDIAN) 1918 afmtstr_swap_endian(fmtstr); 1919 if (!(c->feeder->desc->out & (AFMT_A_LAW | AFMT_MU_LAW)) && 1920 !(c->feeder->desc->out & AFMT_SIGNED)) 1921 afmtstr_swap_sign(fmtstr); 1922 desc.in = afmtstr2afmt(NULL, fmtstr, AFMTSTR_MONO_RETURN); 1923 if (desc.in == 0) 1924 desc.in = AFMT_S16_LE; 1925 /* feeder_volume need stereo processing */ 1926 if (type == FEEDER_VOLUME || 1927 c->feeder->desc->out & AFMT_STEREO) 1928 desc.in |= AFMT_STEREO; 1929 desc.out = desc.in; 1930 } else if (type == FEEDER_SWAPLR) { 1931 desc.in = c->feeder->desc->out; 1932 desc.in |= AFMT_STEREO; 1933 desc.out = desc.in; 1934 } 1935 1936 fc = feeder_getclass(&desc); 1937 DEB(printf("got %p\n", fc)); 1938 if (fc == NULL) { 1939 DEB(printf("can't find required feeder type %d\n", type)); 1940 1941 return EOPNOTSUPP; 1942 } 1943 1944 if (desc.in == 0 || desc.out == 0) 1945 desc = *fc->desc; 1946 1947 DEB(printf("build fmtchain from 0x%08x to 0x%08x: ", c->feeder->desc->out, fc->desc->in)); 1948 tmp[0] = desc.in; 1949 tmp[1] = 0; 1950 if (chn_fmtchain(c, tmp) == 0) { 1951 DEB(printf("failed\n")); 1952 1953 return ENODEV; 1954 } 1955 DEB(printf("ok\n")); 1956 1957 err = chn_addfeeder(c, fc, &desc); 1958 if (err) { 1959 DEB(printf("can't add feeder %p, output 0x%x, err %d\n", fc, fc->desc->out, err)); 1960 1961 return err; 1962 } 1963 DEB(printf("added feeder %p, output 0x%x\n", fc, c->feeder->desc->out)); 1964 } 1965 } 1966 1967 if (c->direction == PCMDIR_REC) { 1968 tmp[0] = c->format; 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;
| 1945 c->feederflags &= ~(1 << FEEDER_VOLUME); 1946 if (c->direction == PCMDIR_PLAY && 1947 !(c->flags & CHN_F_VIRTUAL) && c->parentsnddev && 1948 (c->parentsnddev->flags & SD_F_SOFTPCMVOL) && 1949 c->parentsnddev->mixer_dev) 1950 c->feederflags |= 1 << FEEDER_VOLUME; 1951 if (!(c->flags & CHN_F_VIRTUAL) && c->parentsnddev && 1952 ((c->direction == PCMDIR_PLAY && 1953 (c->parentsnddev->flags & SD_F_PSWAPLR)) || 1954 (c->direction == PCMDIR_REC && 1955 (c->parentsnddev->flags & SD_F_RSWAPLR)))) 1956 c->feederflags |= 1 << FEEDER_SWAPLR; 1957 flags = c->feederflags; 1958 fmtlist = chn_getcaps(c)->fmtlist; 1959 1960 DEB(printf("feederflags %x\n", flags)); 1961 1962 for (type = FEEDER_RATE; type < FEEDER_LAST; type++) { 1963 if (flags & (1 << type)) { 1964 desc.type = type; 1965 desc.in = 0; 1966 desc.out = 0; 1967 desc.flags = 0; 1968 DEB(printf("find feeder type %d, ", type)); 1969 if (type == FEEDER_VOLUME || type == FEEDER_RATE) { 1970 if (c->feeder->desc->out & AFMT_32BIT) 1971 strlcpy(fmtstr,"s32le", sizeof(fmtstr)); 1972 else if (c->feeder->desc->out & AFMT_24BIT) 1973 strlcpy(fmtstr, "s24le", sizeof(fmtstr)); 1974 else { 1975 /* 1976 * 8bit doesn't provide enough headroom 1977 * for proper processing without 1978 * creating too much noises. Force to 1979 * 16bit instead. 1980 */ 1981 strlcpy(fmtstr, "s16le", sizeof(fmtstr)); 1982 } 1983 if (!(c->feeder->desc->out & AFMT_8BIT) && 1984 c->feeder->desc->out & AFMT_BIGENDIAN) 1985 afmtstr_swap_endian(fmtstr); 1986 if (!(c->feeder->desc->out & (AFMT_A_LAW | AFMT_MU_LAW)) && 1987 !(c->feeder->desc->out & AFMT_SIGNED)) 1988 afmtstr_swap_sign(fmtstr); 1989 desc.in = afmtstr2afmt(NULL, fmtstr, AFMTSTR_MONO_RETURN); 1990 if (desc.in == 0) 1991 desc.in = AFMT_S16_LE; 1992 /* feeder_volume need stereo processing */ 1993 if (type == FEEDER_VOLUME || 1994 c->feeder->desc->out & AFMT_STEREO) 1995 desc.in |= AFMT_STEREO; 1996 desc.out = desc.in; 1997 } else if (type == FEEDER_SWAPLR) { 1998 desc.in = c->feeder->desc->out; 1999 desc.in |= AFMT_STEREO; 2000 desc.out = desc.in; 2001 } 2002 2003 fc = feeder_getclass(&desc); 2004 DEB(printf("got %p\n", fc)); 2005 if (fc == NULL) { 2006 DEB(printf("can't find required feeder type %d\n", type)); 2007 2008 return EOPNOTSUPP; 2009 } 2010 2011 if (desc.in == 0 || desc.out == 0) 2012 desc = *fc->desc; 2013 2014 DEB(printf("build fmtchain from 0x%08x to 0x%08x: ", c->feeder->desc->out, fc->desc->in)); 2015 tmp[0] = desc.in; 2016 tmp[1] = 0; 2017 if (chn_fmtchain(c, tmp) == 0) { 2018 DEB(printf("failed\n")); 2019 2020 return ENODEV; 2021 } 2022 DEB(printf("ok\n")); 2023 2024 err = chn_addfeeder(c, fc, &desc); 2025 if (err) { 2026 DEB(printf("can't add feeder %p, output 0x%x, err %d\n", fc, fc->desc->out, err)); 2027 2028 return err; 2029 } 2030 DEB(printf("added feeder %p, output 0x%x\n", fc, c->feeder->desc->out)); 2031 } 2032 } 2033 2034 if (c->direction == PCMDIR_REC) { 2035 tmp[0] = c->format; 2036 tmp[1] = 0; 2037 hwfmt = chn_fmtchain(c, tmp); 2038 } else 2039 hwfmt = chn_fmtchain(c, fmtlist); 2040 2041 if (hwfmt == 0 || !fmtvalid(hwfmt, fmtlist)) { 2042 DEB(printf("Invalid hardware format: 0x%08x\n", hwfmt)); 2043 return ENODEV;
|
| 2044 } else if (c->direction == PCMDIR_REC && !CHN_EMPTY(c, children)) { 2045 /* 2046 * Kind of awkward. This whole "MIXER" concept need a 2047 * rethinking, I guess :) . Recording is the inverse 2048 * of Playback, which is why we push mixer vchan down here. 2049 */ 2050 if (c->flags & CHN_F_HAS_VCHAN) { 2051 desc.type = FEEDER_MIXER; 2052 desc.in = c->format; 2053 } else 2054 return EOPNOTSUPP; 2055 desc.out = c->format; 2056 desc.flags = 0; 2057 fc = feeder_getclass(&desc); 2058 if (fc == NULL) 2059 return EOPNOTSUPP; 2060 2061 err = chn_addfeeder(c, fc, &desc); 2062 if (err != 0) 2063 return err;
|
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 1985 vol = 100 | (100 << 8); 1986 1987 CHN_UNLOCK(c); 1988 /* 1989 * XXX This is ugly! The way mixer subs being so secretive 1990 * about its own internals force us to use this silly 1991 * monkey trick. 1992 */ 1993 if (mixer_ioctl(c->parentsnddev->mixer_dev, 1994 MIXER_READ(SOUND_MIXER_PCM), (caddr_t)&vol, -1, NULL) != 0) 1995 device_printf(c->dev, "Soft PCM Volume: Failed to read default value\n"); 1996 left = vol & 0x7f; 1997 right = (vol >> 8) & 0x7f; 1998 if (c->parentsnddev != NULL && 1999 c->parentsnddev->mixer_dev != NULL && 2000 c->parentsnddev->mixer_dev->si_drv1 != NULL) 2001 parent = mix_getparent( 2002 c->parentsnddev->mixer_dev->si_drv1, 2003 SOUND_MIXER_PCM); 2004 if (parent != SOUND_MIXER_NONE) { 2005 vol = 100 | (100 << 8); 2006 if (mixer_ioctl(c->parentsnddev->mixer_dev, 2007 MIXER_READ(parent), 2008 (caddr_t)&vol, -1, NULL) != 0) 2009 device_printf(c->dev, "Soft Volume: Failed to read parent default value\n"); 2010 left = (left * (vol & 0x7f)) / 100; 2011 right = (right * ((vol >> 8) & 0x7f)) / 100; 2012 } 2013 CHN_LOCK(c); 2014 chn_setvolume(c, left, right); 2015 } 2016 2017 return 0; 2018} 2019 2020int 2021chn_notify(struct pcm_channel *c, u_int32_t flags) 2022{
| 2064 } 2065 2066 sndbuf_setfmt(c->bufhard, hwfmt); 2067 2068 if ((flags & (1 << FEEDER_VOLUME))) { 2069 u_int32_t parent = SOUND_MIXER_NONE; 2070 int vol, left, right; 2071 2072 vol = 100 | (100 << 8); 2073 2074 CHN_UNLOCK(c); 2075 /* 2076 * XXX This is ugly! The way mixer subs being so secretive 2077 * about its own internals force us to use this silly 2078 * monkey trick. 2079 */ 2080 if (mixer_ioctl(c->parentsnddev->mixer_dev, 2081 MIXER_READ(SOUND_MIXER_PCM), (caddr_t)&vol, -1, NULL) != 0) 2082 device_printf(c->dev, "Soft PCM Volume: Failed to read default value\n"); 2083 left = vol & 0x7f; 2084 right = (vol >> 8) & 0x7f; 2085 if (c->parentsnddev != NULL && 2086 c->parentsnddev->mixer_dev != NULL && 2087 c->parentsnddev->mixer_dev->si_drv1 != NULL) 2088 parent = mix_getparent( 2089 c->parentsnddev->mixer_dev->si_drv1, 2090 SOUND_MIXER_PCM); 2091 if (parent != SOUND_MIXER_NONE) { 2092 vol = 100 | (100 << 8); 2093 if (mixer_ioctl(c->parentsnddev->mixer_dev, 2094 MIXER_READ(parent), 2095 (caddr_t)&vol, -1, NULL) != 0) 2096 device_printf(c->dev, "Soft Volume: Failed to read parent default value\n"); 2097 left = (left * (vol & 0x7f)) / 100; 2098 right = (right * ((vol >> 8) & 0x7f)) / 100; 2099 } 2100 CHN_LOCK(c); 2101 chn_setvolume(c, left, right); 2102 } 2103 2104 return 0; 2105} 2106 2107int 2108chn_notify(struct pcm_channel *c, u_int32_t flags) 2109{
|
2023 struct pcmchan_children *pce; 2024 struct pcm_channel *child;
| |
2025 int run; 2026 2027 CHN_LOCK(c); 2028
| 2110 int run; 2111 2112 CHN_LOCK(c); 2113
|
2029 if (SLIST_EMPTY(&c->children)) {
| 2114 if (CHN_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 2038 */ 2039 if (run) 2040 flags &= CHN_N_VOLUME | CHN_N_TRIGGER; 2041 2042 if (flags & CHN_N_RATE) { 2043 /* 2044 * we could do something here, like scan children and decide on 2045 * the most appropriate rate to mix at, but we don't for now 2046 */ 2047 } 2048 if (flags & CHN_N_FORMAT) { 2049 /* 2050 * we could do something here, like scan children and decide on 2051 * the most appropriate mixer feeder to use, but we don't for now 2052 */ 2053 } 2054 if (flags & CHN_N_VOLUME) { 2055 /* 2056 * we could do something here but we don't for now 2057 */ 2058 } 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;
| 2115 CHN_UNLOCK(c); 2116 return ENODEV; 2117 } 2118 2119 run = (CHN_STARTED(c)) ? 1 : 0; 2120 /* 2121 * if the hwchan is running, we can't change its rate, format or 2122 * blocksize 2123 */ 2124 if (run) 2125 flags &= CHN_N_VOLUME | CHN_N_TRIGGER; 2126 2127 if (flags & CHN_N_RATE) { 2128 /* 2129 * we could do something here, like scan children and decide on 2130 * the most appropriate rate to mix at, but we don't for now 2131 */ 2132 } 2133 if (flags & CHN_N_FORMAT) { 2134 /* 2135 * we could do something here, like scan children and decide on 2136 * the most appropriate mixer feeder to use, but we don't for now 2137 */ 2138 } 2139 if (flags & CHN_N_VOLUME) { 2140 /* 2141 * we could do something here but we don't for now 2142 */ 2143 } 2144 if (flags & CHN_N_BLOCKSIZE) { 2145 /* 2146 * Set to default latency profile 2147 */ 2148 chn_setlatency(c, chn_latency); 2149 } 2150 if (flags & CHN_N_TRIGGER) { 2151 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 }
| 2152 2153 nrun = CHN_EMPTY(c, children.busy) ? 0 : 1;
|
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} 2089 2090/** 2091 * @brief Fetch array of supported discrete sample rates 2092 * 2093 * Wrapper for CHANNEL_GETRATES. Please see channel_if.m:getrates() for 2094 * detailed information. 2095 * 2096 * @note If the operation isn't supported, this function will just return 0 2097 * (no rates in the array), and *rates will be set to NULL. Callers 2098 * should examine rates @b only if this function returns non-zero. 2099 * 2100 * @param c pcm channel to examine 2101 * @param rates pointer to array of integers; rate table will be recorded here 2102 * 2103 * @return number of rates in the array pointed to be @c rates 2104 */ 2105int 2106chn_getrates(struct pcm_channel *c, int **rates) 2107{ 2108 KASSERT(rates != NULL, ("rates is null")); 2109 CHN_LOCKASSERT(c); 2110 return CHANNEL_GETRATES(c->methods, c->devinfo, rates); 2111} 2112 2113/** 2114 * @brief Remove channel from a sync group, if there is one. 2115 * 2116 * This function is initially intended for the following conditions: 2117 * - Starting a syncgroup (@c SNDCTL_DSP_SYNCSTART ioctl) 2118 * - Closing a device. (A channel can't be destroyed if it's still in use.) 2119 * 2120 * @note Before calling this function, the syncgroup list mutex must be 2121 * held. (Consider pcm_channel::sm protected by the SG list mutex 2122 * whether @c c is locked or not.) 2123 * 2124 * @param c channel device to be started or closed 2125 * @returns If this channel was the only member of a group, the group ID 2126 * is returned to the caller so that the caller can release it 2127 * via free_unr() after giving up the syncgroup lock. Else it 2128 * returns 0. 2129 */ 2130int 2131chn_syncdestroy(struct pcm_channel *c) 2132{ 2133 struct pcmchan_syncmember *sm; 2134 struct pcmchan_syncgroup *sg; 2135 int sg_id; 2136 2137 sg_id = 0; 2138 2139 PCM_SG_LOCKASSERT(MA_OWNED); 2140 2141 if (c->sm != NULL) { 2142 sm = c->sm; 2143 sg = sm->parent; 2144 c->sm = NULL; 2145 2146 KASSERT(sg != NULL, ("syncmember has null parent")); 2147 2148 SLIST_REMOVE(&sg->members, sm, pcmchan_syncmember, link); 2149 free(sm, M_DEVBUF); 2150 2151 if (SLIST_EMPTY(&sg->members)) { 2152 SLIST_REMOVE(&snd_pcm_syncgroups, sg, pcmchan_syncgroup, link); 2153 sg_id = sg->id; 2154 free(sg, M_DEVBUF); 2155 } 2156 } 2157 2158 return sg_id; 2159} 2160 2161void 2162chn_lock(struct pcm_channel *c) 2163{ 2164 CHN_LOCK(c); 2165} 2166 2167void 2168chn_unlock(struct pcm_channel *c) 2169{ 2170 CHN_UNLOCK(c); 2171} 2172 2173#ifdef OSSV4_EXPERIMENT 2174int 2175chn_getpeaks(struct pcm_channel *c, int *lpeak, int *rpeak) 2176{ 2177 CHN_LOCKASSERT(c); 2178 return CHANNEL_GETPEAKS(c->methods, c->devinfo, lpeak, rpeak); 2179} 2180#endif
| 2154 if (nrun && !run) 2155 chn_start(c, 1); 2156 if (!nrun && run) 2157 chn_abort(c); 2158 } 2159 CHN_UNLOCK(c); 2160 return 0; 2161} 2162 2163/** 2164 * @brief Fetch array of supported discrete sample rates 2165 * 2166 * Wrapper for CHANNEL_GETRATES. Please see channel_if.m:getrates() for 2167 * detailed information. 2168 * 2169 * @note If the operation isn't supported, this function will just return 0 2170 * (no rates in the array), and *rates will be set to NULL. Callers 2171 * should examine rates @b only if this function returns non-zero. 2172 * 2173 * @param c pcm channel to examine 2174 * @param rates pointer to array of integers; rate table will be recorded here 2175 * 2176 * @return number of rates in the array pointed to be @c rates 2177 */ 2178int 2179chn_getrates(struct pcm_channel *c, int **rates) 2180{ 2181 KASSERT(rates != NULL, ("rates is null")); 2182 CHN_LOCKASSERT(c); 2183 return CHANNEL_GETRATES(c->methods, c->devinfo, rates); 2184} 2185 2186/** 2187 * @brief Remove channel from a sync group, if there is one. 2188 * 2189 * This function is initially intended for the following conditions: 2190 * - Starting a syncgroup (@c SNDCTL_DSP_SYNCSTART ioctl) 2191 * - Closing a device. (A channel can't be destroyed if it's still in use.) 2192 * 2193 * @note Before calling this function, the syncgroup list mutex must be 2194 * held. (Consider pcm_channel::sm protected by the SG list mutex 2195 * whether @c c is locked or not.) 2196 * 2197 * @param c channel device to be started or closed 2198 * @returns If this channel was the only member of a group, the group ID 2199 * is returned to the caller so that the caller can release it 2200 * via free_unr() after giving up the syncgroup lock. Else it 2201 * returns 0. 2202 */ 2203int 2204chn_syncdestroy(struct pcm_channel *c) 2205{ 2206 struct pcmchan_syncmember *sm; 2207 struct pcmchan_syncgroup *sg; 2208 int sg_id; 2209 2210 sg_id = 0; 2211 2212 PCM_SG_LOCKASSERT(MA_OWNED); 2213 2214 if (c->sm != NULL) { 2215 sm = c->sm; 2216 sg = sm->parent; 2217 c->sm = NULL; 2218 2219 KASSERT(sg != NULL, ("syncmember has null parent")); 2220 2221 SLIST_REMOVE(&sg->members, sm, pcmchan_syncmember, link); 2222 free(sm, M_DEVBUF); 2223 2224 if (SLIST_EMPTY(&sg->members)) { 2225 SLIST_REMOVE(&snd_pcm_syncgroups, sg, pcmchan_syncgroup, link); 2226 sg_id = sg->id; 2227 free(sg, M_DEVBUF); 2228 } 2229 } 2230 2231 return sg_id; 2232} 2233 2234void 2235chn_lock(struct pcm_channel *c) 2236{ 2237 CHN_LOCK(c); 2238} 2239 2240void 2241chn_unlock(struct pcm_channel *c) 2242{ 2243 CHN_UNLOCK(c); 2244} 2245 2246#ifdef OSSV4_EXPERIMENT 2247int 2248chn_getpeaks(struct pcm_channel *c, int *lpeak, int *rpeak) 2249{ 2250 CHN_LOCKASSERT(c); 2251 return CHANNEL_GETPEAKS(c->methods, c->devinfo, lpeak, rpeak); 2252} 2253#endif
|