Tue Sep 29 15:58:54 2009 UTC ()
Add support for playback- or capture-only devices.

Fixes PR 42050


(sborrill)
diff -r1.69 -r1.70 src/share/man/man4/audio.4
diff -r1.247 -r1.248 src/sys/dev/audio.c
diff -r1.65 -r1.66 src/sys/dev/audio_if.h
diff -r1.15 -r1.16 src/sys/dev/pci/hdaudio/hdaudio_afg.c
diff -r1.32 -r1.33 src/sys/sys/audioio.h

cvs diff -r1.69 -r1.70 src/share/man/man4/audio.4 (expand / switch to unified diff)

--- src/share/man/man4/audio.4 2009/01/03 17:44:20 1.69
+++ src/share/man/man4/audio.4 2009/09/29 15:58:54 1.70
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1.\" $NetBSD: audio.4,v 1.69 2009/01/03 17:44:20 christos Exp $ 1.\" $NetBSD: audio.4,v 1.70 2009/09/29 15:58:54 sborrill Exp $
2.\" 2.\"
3.\" Copyright (c) 1996 The NetBSD Foundation, Inc. 3.\" Copyright (c) 1996 The NetBSD Foundation, Inc.
4.\" All rights reserved. 4.\" All rights reserved.
5.\" 5.\"
6.\" This code is derived from software contributed to The NetBSD Foundation 6.\" This code is derived from software contributed to The NetBSD Foundation
7.\" by John T. Kohl. 7.\" by John T. Kohl.
8.\" 8.\"
9.\" Redistribution and use in source and binary forms, with or without 9.\" Redistribution and use in source and binary forms, with or without
10.\" modification, are permitted provided that the following conditions 10.\" modification, are permitted provided that the following conditions
11.\" are met: 11.\" are met:
12.\" 1. Redistributions of source code must retain the above copyright 12.\" 1. Redistributions of source code must retain the above copyright
13.\" notice, this list of conditions and the following disclaimer. 13.\" notice, this list of conditions and the following disclaimer.
14.\" 2. Redistributions in binary form must reproduce the above copyright 14.\" 2. Redistributions in binary form must reproduce the above copyright
@@ -17,27 +17,27 @@ @@ -17,27 +17,27 @@
17.\" 17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28.\" POSSIBILITY OF SUCH DAMAGE. 28.\" POSSIBILITY OF SUCH DAMAGE.
29.\" 29.\"
30.Dd January 3, 2009 30.Dd September 29, 2009
31.Dt AUDIO 4 31.Dt AUDIO 4
32.Os 32.Os
33.Sh NAME 33.Sh NAME
34.Nm audio 34.Nm audio
35.Nd device-independent audio driver layer 35.Nd device-independent audio driver layer
36.Sh SYNOPSIS 36.Sh SYNOPSIS
37.In sys/audioio.h 37.In sys/audioio.h
38.Sh DESCRIPTION 38.Sh DESCRIPTION
39The 39The
40.Nm 40.Nm
41driver provides support for various audio peripherals. 41driver provides support for various audio peripherals.
42It provides a uniform programming interface layer above different 42It provides a uniform programming interface layer above different
43underlying audio hardware drivers. 43underlying audio hardware drivers.
@@ -233,26 +233,30 @@ This command gets a bit set of hardware  @@ -233,26 +233,30 @@ This command gets a bit set of hardware
233If the hardware 233If the hardware
234has a certain property the corresponding bit is set, otherwise it is not. 234has a certain property the corresponding bit is set, otherwise it is not.
235The properties can have the following values: 235The properties can have the following values:
236.Pp 236.Pp
237.Bl -tag -width AUDIO_PROP_INDEPENDENT -compact 237.Bl -tag -width AUDIO_PROP_INDEPENDENT -compact
238.It Dv AUDIO_PROP_FULLDUPLEX 238.It Dv AUDIO_PROP_FULLDUPLEX
239the device admits full duplex operation. 239the device admits full duplex operation.
240.It Dv AUDIO_PROP_MMAP 240.It Dv AUDIO_PROP_MMAP
241the device can be used with 241the device can be used with
242.Xr mmap 2 . 242.Xr mmap 2 .
243.It Dv AUDIO_PROP_INDEPENDENT 243.It Dv AUDIO_PROP_INDEPENDENT
244the device can set the playing and recording encoding parameters 244the device can set the playing and recording encoding parameters
245independently. 245independently.
 246.It Dv AUDIO_PROP_PLAYBACK
 247the device is capable of audio playback.
 248.It Dv AUDIO_PROP_CAPTURE
 249the device is capable of audio capture.
246.El 250.El
247.It Dv AUDIO_GETIOFFS (audio_offset_t) 251.It Dv AUDIO_GETIOFFS (audio_offset_t)
248.It Dv AUDIO_GETOOFFS (audio_offset_t) 252.It Dv AUDIO_GETOOFFS (audio_offset_t)
249This command fetches the current offset in the input(output) buffer where 253This command fetches the current offset in the input(output) buffer where
250the audio hardware's DMA engine will be putting(getting) data. 254the audio hardware's DMA engine will be putting(getting) data.
251It mostly useful when the device 255It mostly useful when the device
252buffer is available in user space via the 256buffer is available in user space via the
253.Xr mmap 2 257.Xr mmap 2
254call. 258call.
255The information is returned in the audio_offset structure. 259The information is returned in the audio_offset structure.
256.Bd -literal 260.Bd -literal
257typedef struct audio_offset { 261typedef struct audio_offset {
258 u_int samples; /* Total number of bytes transferred */ 262 u_int samples; /* Total number of bytes transferred */

cvs diff -r1.247 -r1.248 src/sys/dev/Attic/audio.c (expand / switch to unified diff)

--- src/sys/dev/Attic/audio.c 2009/09/24 16:03:11 1.247
+++ src/sys/dev/Attic/audio.c 2009/09/29 15:58:54 1.248
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: audio.c,v 1.247 2009/09/24 16:03:11 sborrill Exp $ */ 1/* $NetBSD: audio.c,v 1.248 2009/09/29 15:58:54 sborrill Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1991-1993 Regents of the University of California. 4 * Copyright (c) 1991-1993 Regents of the University of California.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -51,27 +51,27 @@ @@ -51,27 +51,27 @@
51 * generated. 51 * generated.
52 * 52 *
53 * If you try to set both play and record mode on a half-duplex 53 * If you try to set both play and record mode on a half-duplex
54 * device, playing takes precedence. 54 * device, playing takes precedence.
55 */ 55 */
56 56
57/* 57/*
58 * Todo: 58 * Todo:
59 * - Add softaudio() isr processing for wakeup, poll, signals, 59 * - Add softaudio() isr processing for wakeup, poll, signals,
60 * and silence fill. 60 * and silence fill.
61 */ 61 */
62 62
63#include <sys/cdefs.h> 63#include <sys/cdefs.h>
64__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.247 2009/09/24 16:03:11 sborrill Exp $"); 64__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.248 2009/09/29 15:58:54 sborrill Exp $");
65 65
66#include "audio.h" 66#include "audio.h"
67#if NAUDIO > 0 67#if NAUDIO > 0
68 68
69#include <sys/param.h> 69#include <sys/param.h>
70#include <sys/ioctl.h> 70#include <sys/ioctl.h>
71#include <sys/fcntl.h> 71#include <sys/fcntl.h>
72#include <sys/vnode.h> 72#include <sys/vnode.h>
73#include <sys/select.h> 73#include <sys/select.h>
74#include <sys/poll.h> 74#include <sys/poll.h>
75#include <sys/malloc.h> 75#include <sys/malloc.h>
76#include <sys/proc.h> 76#include <sys/proc.h>
77#include <sys/systm.h> 77#include <sys/systm.h>
@@ -182,26 +182,30 @@ int audioactivate(device_t, enum devact) @@ -182,26 +182,30 @@ int audioactivate(device_t, enum devact)
182static void audio_idle(void *); 182static void audio_idle(void *);
183static void audio_activity(device_t, devactive_t); 183static void audio_activity(device_t, devactive_t);
184#endif 184#endif
185 185
186static bool audio_suspend(device_t dv PMF_FN_PROTO); 186static bool audio_suspend(device_t dv PMF_FN_PROTO);
187static bool audio_resume(device_t dv PMF_FN_PROTO); 187static bool audio_resume(device_t dv PMF_FN_PROTO);
188static void audio_volume_down(device_t); 188static void audio_volume_down(device_t);
189static void audio_volume_up(device_t); 189static void audio_volume_up(device_t);
190static void audio_volume_toggle(device_t); 190static void audio_volume_toggle(device_t);
191 191
192static void audio_mixer_capture(struct audio_softc *); 192static void audio_mixer_capture(struct audio_softc *);
193static void audio_mixer_restore(struct audio_softc *); 193static void audio_mixer_restore(struct audio_softc *);
194 194
 195static int audio_get_props(struct audio_softc *);
 196static bool audio_can_playback(struct audio_softc *);
 197static bool audio_can_capture(struct audio_softc *);
 198
195static void audio_softintr_rd(void *); 199static void audio_softintr_rd(void *);
196static void audio_softintr_wr(void *); 200static void audio_softintr_wr(void *);
197 201
198struct portname { 202struct portname {
199 const char *name; 203 const char *name;
200 int mask; 204 int mask;
201}; 205};
202static const struct portname itable[] = { 206static const struct portname itable[] = {
203 { AudioNmicrophone, AUDIO_MICROPHONE }, 207 { AudioNmicrophone, AUDIO_MICROPHONE },
204 { AudioNline, AUDIO_LINE_IN }, 208 { AudioNline, AUDIO_LINE_IN },
205 { AudioNcd, AUDIO_CD }, 209 { AudioNcd, AUDIO_CD },
206 { 0, 0 } 210 { 0, 0 }
207}; 211};
@@ -305,61 +309,71 @@ audioattach(device_t parent, device_t se @@ -305,61 +309,71 @@ audioattach(device_t parent, device_t se
305 hwp->halt_output == 0 || 309 hwp->halt_output == 0 ||
306 hwp->halt_input == 0 || 310 hwp->halt_input == 0 ||
307 hwp->getdev == 0 || 311 hwp->getdev == 0 ||
308 hwp->set_port == 0 || 312 hwp->set_port == 0 ||
309 hwp->get_port == 0 || 313 hwp->get_port == 0 ||
310 hwp->query_devinfo == 0 || 314 hwp->query_devinfo == 0 ||
311 hwp->get_props == 0) { 315 hwp->get_props == 0) {
312 printf(": missing method\n"); 316 printf(": missing method\n");
313 sc->hw_if = 0; 317 sc->hw_if = 0;
314 return; 318 return;
315 } 319 }
316#endif 320#endif
317 321
318 props = hwp->get_props(hdlp); 322 sc->hw_if = hwp;
 323 sc->hw_hdl = hdlp;
 324 sc->sc_dev = parent;
 325 sc->sc_opencnt = 0;
 326 sc->sc_writing = sc->sc_waitcomp = 0;
 327 sc->sc_lastinfovalid = false;
319 328
320 aprint_naive("\n"); 329 props = audio_get_props(sc);
321 330
322 if (props & AUDIO_PROP_FULLDUPLEX) 331 if (props & AUDIO_PROP_FULLDUPLEX)
323 aprint_normal(": full duplex"); 332 aprint_normal(": full duplex");
324 else 333 else
325 aprint_normal(": half duplex"); 334 aprint_normal(": half duplex");
326 335
 336 if (props & AUDIO_PROP_PLAYBACK)
 337 aprint_normal(", playback");
 338 if (props & AUDIO_PROP_CAPTURE)
 339 aprint_normal(", capture");
327 if (props & AUDIO_PROP_MMAP) 340 if (props & AUDIO_PROP_MMAP)
328 aprint_normal(", mmap"); 341 aprint_normal(", mmap");
329 if (props & AUDIO_PROP_INDEPENDENT) 342 if (props & AUDIO_PROP_INDEPENDENT)
330 aprint_normal(", independent"); 343 aprint_normal(", independent");
331 344
 345 aprint_naive("\n");
332 aprint_normal("\n"); 346 aprint_normal("\n");
333 347
334 sc->hw_if = hwp; 348 if (audio_can_playback(sc)) {
335 sc->hw_hdl = hdlp; 349 error = audio_alloc_ring(sc, &sc->sc_pr,
336 sc->sc_dev = parent; 350 AUMODE_PLAY, AU_RING_SIZE);
337 sc->sc_opencnt = 0; 351 if (error) {
338 sc->sc_writing = sc->sc_waitcomp = 0; 352 sc->hw_if = NULL;
339 sc->sc_lastinfovalid = false; 353 aprint_error("audio: could not allocate play buffer\n");
340 354 return;
341 error = audio_alloc_ring(sc, &sc->sc_pr, AUMODE_PLAY, AU_RING_SIZE); 355 }
342 if (error) { 
343 sc->hw_if = NULL; 
344 aprint_error("audio: could not allocate play buffer\n"); 
345 return; 
346 } 356 }
347 error = audio_alloc_ring(sc, &sc->sc_rr, AUMODE_RECORD, AU_RING_SIZE); 357 if (audio_can_capture(sc)) {
348 if (error) { 358 error = audio_alloc_ring(sc, &sc->sc_rr,
349 audio_free_ring(sc, &sc->sc_pr); 359 AUMODE_RECORD, AU_RING_SIZE);
350 sc->hw_if = NULL; 360 if (error) {
351 aprint_error("audio: could not allocate record buffer\n"); 361 if (sc->sc_pr.s.start != 0)
352 return; 362 audio_free_ring(sc, &sc->sc_pr);
 363 sc->hw_if = NULL;
 364 aprint_error("audio: could not allocate record buffer\n");
 365 return;
 366 }
353 } 367 }
354 368
355 sc->sc_lastgain = 128; 369 sc->sc_lastgain = 128;
356 370
357 if ((error = audio_set_defaults(sc, 0))) { 371 if ((error = audio_set_defaults(sc, 0))) {
358 aprint_error("audioattach: audio_set_defaults() failed\n"); 372 aprint_error("audioattach: audio_set_defaults() failed\n");
359 sc->hw_if = NULL; 373 sc->hw_if = NULL;
360 return; 374 return;
361 } 375 }
362 376
363 sc->sc_sih_rd = softint_establish(SOFTINT_SERIAL, 377 sc->sc_sih_rd = softint_establish(SOFTINT_SERIAL,
364 audio_softintr_rd, sc); 378 audio_softintr_rd, sc);
365 sc->sc_sih_wr = softint_establish(SOFTINT_SERIAL, 379 sc->sc_sih_wr = softint_establish(SOFTINT_SERIAL,
@@ -732,26 +746,28 @@ audio_alloc_ring(struct audio_softc *sc, @@ -732,26 +746,28 @@ audio_alloc_ring(struct audio_softc *sc,
732 r->s.start = hw->allocm(hdl, direction, bufsize, 746 r->s.start = hw->allocm(hdl, direction, bufsize,
733 M_DEVBUF, M_WAITOK); 747 M_DEVBUF, M_WAITOK);
734 else 748 else
735 r->s.start = malloc(bufsize, M_DEVBUF, M_WAITOK); 749 r->s.start = malloc(bufsize, M_DEVBUF, M_WAITOK);
736 if (r->s.start == 0) 750 if (r->s.start == 0)
737 return ENOMEM; 751 return ENOMEM;
738 r->s.bufsize = bufsize; 752 r->s.bufsize = bufsize;
739 return 0; 753 return 0;
740} 754}
741 755
742void 756void
743audio_free_ring(struct audio_softc *sc, struct audio_ringbuffer *r) 757audio_free_ring(struct audio_softc *sc, struct audio_ringbuffer *r)
744{ 758{
 759 if (r->s.start == 0)
 760 return;
745 761
746 if (sc->hw_if->freem) 762 if (sc->hw_if->freem)
747 sc->hw_if->freem(sc->hw_hdl, r->s.start, M_DEVBUF); 763 sc->hw_if->freem(sc->hw_hdl, r->s.start, M_DEVBUF);
748 else 764 else
749 free(r->s.start, M_DEVBUF); 765 free(r->s.start, M_DEVBUF);
750 r->s.start = 0; 766 r->s.start = 0;
751} 767}
752 768
753static int 769static int
754audio_setup_pfilters(struct audio_softc *sc, const audio_params_t *pp, 770audio_setup_pfilters(struct audio_softc *sc, const audio_params_t *pp,
755 stream_filter_list_t *pfilters) 771 stream_filter_list_t *pfilters)
756{ 772{
757 stream_filter_t *pf[AUDIO_MAX_FILTERS]; 773 stream_filter_t *pf[AUDIO_MAX_FILTERS];
@@ -1291,84 +1307,98 @@ audio_init_ringbuffer(struct audio_softc @@ -1291,84 +1307,98 @@ audio_init_ringbuffer(struct audio_softc
1291 rp->copying = false; 1307 rp->copying = false;
1292 rp->needfill = false; 1308 rp->needfill = false;
1293 rp->mmapped = false; 1309 rp->mmapped = false;
1294} 1310}
1295 1311
1296int 1312int
1297audio_initbufs(struct audio_softc *sc) 1313audio_initbufs(struct audio_softc *sc)
1298{ 1314{
1299 const struct audio_hw_if *hw; 1315 const struct audio_hw_if *hw;
1300 int error; 1316 int error;
1301 1317
1302 DPRINTF(("audio_initbufs: mode=0x%x\n", sc->sc_mode)); 1318 DPRINTF(("audio_initbufs: mode=0x%x\n", sc->sc_mode));
1303 hw = sc->hw_if; 1319 hw = sc->hw_if;
1304 audio_init_ringbuffer(sc, &sc->sc_rr, AUMODE_RECORD); 1320 if (audio_can_capture(sc)) {
1305 if (hw->init_input && (sc->sc_mode & AUMODE_RECORD)) { 1321 audio_init_ringbuffer(sc, &sc->sc_rr, AUMODE_RECORD);
1306 error = hw->init_input(sc->hw_hdl, sc->sc_rr.s.start, 1322 if (hw->init_input && (sc->sc_mode & AUMODE_RECORD)) {
 1323 error = hw->init_input(sc->hw_hdl, sc->sc_rr.s.start,
1307 sc->sc_rr.s.end - sc->sc_rr.s.start); 1324 sc->sc_rr.s.end - sc->sc_rr.s.start);
1308 if (error) 1325 if (error)
1309 return error; 1326 return error;
 1327 }
1310 } 1328 }
1311 1329
1312 audio_init_ringbuffer(sc, &sc->sc_pr, AUMODE_PLAY); 1330 if (audio_can_playback(sc)) {
1313 sc->sc_sil_count = 0; 1331 audio_init_ringbuffer(sc, &sc->sc_pr, AUMODE_PLAY);
1314 if (hw->init_output && (sc->sc_mode & AUMODE_PLAY)) { 1332 sc->sc_sil_count = 0;
1315 error = hw->init_output(sc->hw_hdl, sc->sc_pr.s.start, 1333 if (hw->init_output && (sc->sc_mode & AUMODE_PLAY)) {
 1334 error = hw->init_output(sc->hw_hdl, sc->sc_pr.s.start,
1316 sc->sc_pr.s.end - sc->sc_pr.s.start); 1335 sc->sc_pr.s.end - sc->sc_pr.s.start);
1317 if (error) 1336 if (error)
1318 return error; 1337 return error;
 1338 }
1319 } 1339 }
1320 1340
1321#ifdef AUDIO_INTR_TIME 1341#ifdef AUDIO_INTR_TIME
1322#define double u_long 1342#define double u_long
1323 sc->sc_pnintr = 0; 1343 if (audio_can_playback(sc)) {
1324 sc->sc_pblktime = (u_long)( 1344 sc->sc_pnintr = 0;
1325 (double)sc->sc_pr.blksize * 100000 / 1345 sc->sc_pblktime = (u_long)(
1326 (double)(sc->sc_pparams.precision / NBBY * 1346 (double)sc->sc_pr.blksize * 100000 /
1327 sc->sc_pparams.channels * 1347 (double)(sc->sc_pparams.precision / NBBY *
1328 sc->sc_pparams.sample_rate)) * 10; 1348 sc->sc_pparams.channels *
1329 DPRINTF(("audio: play blktime = %lu for %d\n", 1349 sc->sc_pparams.sample_rate)) * 10;
1330 sc->sc_pblktime, sc->sc_pr.blksize)); 1350 DPRINTF(("audio: play blktime = %lu for %d\n",
1331 sc->sc_rnintr = 0; 1351 sc->sc_pblktime, sc->sc_pr.blksize));
1332 sc->sc_rblktime = (u_long)( 1352 }
1333 (double)sc->sc_rr.blksize * 100000 / 1353 if (audio_can_capture(sc)) {
1334 (double)(sc->sc_rparams.precision / NBBY * 1354 sc->sc_rnintr = 0;
1335 sc->sc_rparams.channels * 1355 sc->sc_rblktime = (u_long)(
1336 sc->sc_rparams.sample_rate)) * 10; 1356 (double)sc->sc_rr.blksize * 100000 /
1337 DPRINTF(("audio: record blktime = %lu for %d\n", 1357 (double)(sc->sc_rparams.precision / NBBY *
1338 sc->sc_rblktime, sc->sc_rr.blksize)); 1358 sc->sc_rparams.channels *
 1359 sc->sc_rparams.sample_rate)) * 10;
 1360 DPRINTF(("audio: record blktime = %lu for %d\n",
 1361 sc->sc_rblktime, sc->sc_rr.blksize));
 1362 }
1339#undef double 1363#undef double
1340#endif 1364#endif
1341 1365
1342 return 0; 1366 return 0;
1343} 1367}
1344 1368
1345void 1369void
1346audio_calcwater(struct audio_softc *sc) 1370audio_calcwater(struct audio_softc *sc)
1347{ 1371{
1348 1372
1349 /* set high at 100% */ 1373 /* set high at 100% */
1350 sc->sc_pr.usedhigh = sc->sc_pustream->end - sc->sc_pustream->start; 1374 if (audio_can_playback(sc)) {
1351 /* set low at 75% of usedhigh */ 1375 sc->sc_pr.usedhigh =
1352 sc->sc_pr.usedlow = sc->sc_pr.usedhigh * 3 / 4; 1376 sc->sc_pustream->end - sc->sc_pustream->start;
1353 if (sc->sc_pr.usedlow == sc->sc_pr.usedhigh) 1377 /* set low at 75% of usedhigh */
1354 sc->sc_pr.usedlow -= sc->sc_pr.blksize; 1378 sc->sc_pr.usedlow = sc->sc_pr.usedhigh * 3 / 4;
1355 1379 if (sc->sc_pr.usedlow == sc->sc_pr.usedhigh)
1356 sc->sc_rr.usedhigh = sc->sc_rustream->end - sc->sc_rustream->start 1380 sc->sc_pr.usedlow -= sc->sc_pr.blksize;
1357 - sc->sc_rr.blksize; 1381 }
1358 sc->sc_rr.usedlow = 0; 1382
1359 DPRINTF(("%s: plow=%d phigh=%d rlow=%d rhigh=%d\n", __func__, 1383 if (audio_can_capture(sc)) {
1360 sc->sc_pr.usedlow, sc->sc_pr.usedhigh, 1384 sc->sc_rr.usedhigh =
1361 sc->sc_rr.usedlow, sc->sc_rr.usedhigh)); 1385 sc->sc_rustream->end - sc->sc_rustream->start -
 1386 sc->sc_rr.blksize;
 1387 sc->sc_rr.usedlow = 0;
 1388 DPRINTF(("%s: plow=%d phigh=%d rlow=%d rhigh=%d\n", __func__,
 1389 sc->sc_pr.usedlow, sc->sc_pr.usedhigh,
 1390 sc->sc_rr.usedlow, sc->sc_rr.usedhigh));
 1391 }
1362} 1392}
1363 1393
1364static inline int 1394static inline int
1365audio_sleep_timo(int *chan, const char *label, int timo) 1395audio_sleep_timo(int *chan, const char *label, int timo)
1366{ 1396{
1367 int st; 1397 int st;
1368 1398
1369 if (label == NULL) 1399 if (label == NULL)
1370 label = "audio"; 1400 label = "audio";
1371 1401
1372 DPRINTFN(3, ("audio_sleep_timo: chan=%p, label=%s, timo=%d\n", 1402 DPRINTFN(3, ("audio_sleep_timo: chan=%p, label=%s, timo=%d\n",
1373 chan, label, timo)); 1403 chan, label, timo));
1374 *chan = 1; 1404 *chan = 1;
@@ -1426,27 +1456,27 @@ audio_open(dev_t dev, struct audio_softc @@ -1426,27 +1456,27 @@ audio_open(dev_t dev, struct audio_softc
1426 } 1456 }
1427 1457
1428 sc->sc_async_audio = 0; 1458 sc->sc_async_audio = 0;
1429 sc->sc_rchan = 0; 1459 sc->sc_rchan = 0;
1430 sc->sc_wchan = 0; 1460 sc->sc_wchan = 0;
1431 sc->sc_sil_count = 0; 1461 sc->sc_sil_count = 0;
1432 sc->sc_rbus = false; 1462 sc->sc_rbus = false;
1433 sc->sc_pbus = false; 1463 sc->sc_pbus = false;
1434 sc->sc_eof = 0; 1464 sc->sc_eof = 0;
1435 sc->sc_playdrop = 0; 1465 sc->sc_playdrop = 0;
1436 1466
1437 sc->sc_full_duplex =  1467 sc->sc_full_duplex =
1438 (flags & (FWRITE|FREAD)) == (FWRITE|FREAD) && 1468 (flags & (FWRITE|FREAD)) == (FWRITE|FREAD) &&
1439 (hw->get_props(sc->hw_hdl) & AUDIO_PROP_FULLDUPLEX); 1469 (audio_get_props(sc) & AUDIO_PROP_FULLDUPLEX);
1440 1470
1441 mode = 0; 1471 mode = 0;
1442 if (flags & FREAD) { 1472 if (flags & FREAD) {
1443 sc->sc_open |= AUOPEN_READ; 1473 sc->sc_open |= AUOPEN_READ;
1444 mode |= AUMODE_RECORD; 1474 mode |= AUMODE_RECORD;
1445 } 1475 }
1446 if (flags & FWRITE) { 1476 if (flags & FWRITE) {
1447 sc->sc_open |= AUOPEN_WRITE; 1477 sc->sc_open |= AUOPEN_WRITE;
1448 mode |= AUMODE_PLAY | AUMODE_PLAY_ALL; 1478 mode |= AUMODE_PLAY | AUMODE_PLAY_ALL;
1449 } 1479 }
1450 1480
1451 /* 1481 /*
1452 * Multiplex device: /dev/audio (MU-Law) and /dev/sound (linear) 1482 * Multiplex device: /dev/audio (MU-Law) and /dev/sound (linear)
@@ -2241,44 +2271,44 @@ audio_ioctl(struct audio_softc *sc, u_lo @@ -2241,44 +2271,44 @@ audio_ioctl(struct audio_softc *sc, u_lo
2241 DPRINTF(("AUDIO_GETENC\n")); 2271 DPRINTF(("AUDIO_GETENC\n"));
2242 error = hw->query_encoding(sc->hw_hdl, 2272 error = hw->query_encoding(sc->hw_hdl,
2243 (struct audio_encoding *)addr); 2273 (struct audio_encoding *)addr);
2244 break; 2274 break;
2245 2275
2246 case AUDIO_GETFD: 2276 case AUDIO_GETFD:
2247 DPRINTF(("AUDIO_GETFD\n")); 2277 DPRINTF(("AUDIO_GETFD\n"));
2248 *(int *)addr = sc->sc_full_duplex; 2278 *(int *)addr = sc->sc_full_duplex;
2249 break; 2279 break;
2250 2280
2251 case AUDIO_SETFD: 2281 case AUDIO_SETFD:
2252 DPRINTF(("AUDIO_SETFD\n")); 2282 DPRINTF(("AUDIO_SETFD\n"));
2253 fd = *(int *)addr; 2283 fd = *(int *)addr;
2254 if (hw->get_props(sc->hw_hdl) & AUDIO_PROP_FULLDUPLEX) { 2284 if (audio_get_props(sc) & AUDIO_PROP_FULLDUPLEX) {
2255 if (hw->setfd) 2285 if (hw->setfd)
2256 error = hw->setfd(sc->hw_hdl, fd); 2286 error = hw->setfd(sc->hw_hdl, fd);
2257 else 2287 else
2258 error = 0; 2288 error = 0;
2259 if (!error) 2289 if (!error)
2260 sc->sc_full_duplex = fd; 2290 sc->sc_full_duplex = fd;
2261 } else { 2291 } else {
2262 if (fd) 2292 if (fd)
2263 error = ENOTTY; 2293 error = ENOTTY;
2264 else 2294 else
2265 error = 0; 2295 error = 0;
2266 } 2296 }
2267 break; 2297 break;
2268 2298
2269 case AUDIO_GETPROPS: 2299 case AUDIO_GETPROPS:
2270 DPRINTF(("AUDIO_GETPROPS\n")); 2300 DPRINTF(("AUDIO_GETPROPS\n"));
2271 *(int *)addr = hw->get_props(sc->hw_hdl); 2301 *(int *)addr = audio_get_props(sc);
2272 break; 2302 break;
2273 2303
2274 default: 2304 default:
2275 if (hw->dev_ioctl) { 2305 if (hw->dev_ioctl) {
2276 error = hw->dev_ioctl(sc->hw_hdl, cmd, addr, flag, l); 2306 error = hw->dev_ioctl(sc->hw_hdl, cmd, addr, flag, l);
2277 } else { 2307 } else {
2278 DPRINTF(("audio_ioctl: unknown ioctl\n")); 2308 DPRINTF(("audio_ioctl: unknown ioctl\n"));
2279 error = EINVAL; 2309 error = EINVAL;
2280 } 2310 }
2281 break; 2311 break;
2282 } 2312 }
2283 DPRINTF(("audio_ioctl(%lu,'%c',%lu) result %d\n", 2313 DPRINTF(("audio_ioctl(%lu,'%c',%lu) result %d\n",
2284 IOCPARM_LEN(cmd), (char)IOCGROUP(cmd), cmd&0xff, error)); 2314 IOCPARM_LEN(cmd), (char)IOCGROUP(cmd), cmd&0xff, error));
@@ -2429,27 +2459,27 @@ audio_kqfilter(struct audio_softc *sc, s @@ -2429,27 +2459,27 @@ audio_kqfilter(struct audio_softc *sc, s
2429 2459
2430 return 0; 2460 return 0;
2431} 2461}
2432 2462
2433paddr_t 2463paddr_t
2434audio_mmap(struct audio_softc *sc, off_t off, int prot) 2464audio_mmap(struct audio_softc *sc, off_t off, int prot)
2435{ 2465{
2436 const struct audio_hw_if *hw; 2466 const struct audio_hw_if *hw;
2437 struct audio_ringbuffer *cb; 2467 struct audio_ringbuffer *cb;
2438 int s; 2468 int s;
2439 2469
2440 DPRINTF(("audio_mmap: off=%lld, prot=%d\n", (long long)off, prot)); 2470 DPRINTF(("audio_mmap: off=%lld, prot=%d\n", (long long)off, prot));
2441 hw = sc->hw_if; 2471 hw = sc->hw_if;
2442 if (!(hw->get_props(sc->hw_hdl) & AUDIO_PROP_MMAP) || !hw->mappage) 2472 if (!(audio_get_props(sc) & AUDIO_PROP_MMAP) || !hw->mappage)
2443 return -1; 2473 return -1;
2444#if 0 2474#if 0
2445/* XXX 2475/* XXX
2446 * The idea here was to use the protection to determine if 2476 * The idea here was to use the protection to determine if
2447 * we are mapping the read or write buffer, but it fails. 2477 * we are mapping the read or write buffer, but it fails.
2448 * The VM system is broken in (at least) two ways. 2478 * The VM system is broken in (at least) two ways.
2449 * 1) If you map memory VM_PROT_WRITE you SIGSEGV 2479 * 1) If you map memory VM_PROT_WRITE you SIGSEGV
2450 * when writing to it, so VM_PROT_READ|VM_PROT_WRITE 2480 * when writing to it, so VM_PROT_READ|VM_PROT_WRITE
2451 * has to be used for mmapping the play buffer. 2481 * has to be used for mmapping the play buffer.
2452 * 2) Even if calling mmap() with VM_PROT_READ|VM_PROT_WRITE 2482 * 2) Even if calling mmap() with VM_PROT_READ|VM_PROT_WRITE
2453 * audio_mmap will get called at some point with VM_PROT_READ 2483 * audio_mmap will get called at some point with VM_PROT_READ
2454 * only. 2484 * only.
2455 * So, alas, we always map the play buffer for now. 2485 * So, alas, we always map the play buffer for now.
@@ -2488,52 +2518,58 @@ audio_mmap(struct audio_softc *sc, off_t @@ -2488,52 +2518,58 @@ audio_mmap(struct audio_softc *sc, off_t
2488 2518
2489 return hw->mappage(sc->hw_hdl, cb->s.start, off, prot); 2519 return hw->mappage(sc->hw_hdl, cb->s.start, off, prot);
2490} 2520}
2491 2521
2492int 2522int
2493audiostartr(struct audio_softc *sc) 2523audiostartr(struct audio_softc *sc)
2494{ 2524{
2495 int error; 2525 int error;
2496 2526
2497 DPRINTF(("audiostartr: start=%p used=%d(hi=%d) mmapped=%d\n", 2527 DPRINTF(("audiostartr: start=%p used=%d(hi=%d) mmapped=%d\n",
2498 sc->sc_rr.s.start, audio_stream_get_used(&sc->sc_rr.s), 2528 sc->sc_rr.s.start, audio_stream_get_used(&sc->sc_rr.s),
2499 sc->sc_rr.usedhigh, sc->sc_rr.mmapped)); 2529 sc->sc_rr.usedhigh, sc->sc_rr.mmapped));
2500 2530
 2531 if (!audio_can_capture(sc))
 2532 return EINVAL;
 2533
2501 if (sc->hw_if->trigger_input) 2534 if (sc->hw_if->trigger_input)
2502 error = sc->hw_if->trigger_input(sc->hw_hdl, sc->sc_rr.s.start, 2535 error = sc->hw_if->trigger_input(sc->hw_hdl, sc->sc_rr.s.start,
2503 sc->sc_rr.s.end, sc->sc_rr.blksize, 2536 sc->sc_rr.s.end, sc->sc_rr.blksize,
2504 audio_rint, (void *)sc, &sc->sc_rr.s.param); 2537 audio_rint, (void *)sc, &sc->sc_rr.s.param);
2505 else 2538 else
2506 error = sc->hw_if->start_input(sc->hw_hdl, sc->sc_rr.s.start, 2539 error = sc->hw_if->start_input(sc->hw_hdl, sc->sc_rr.s.start,
2507 sc->sc_rr.blksize, audio_rint, (void *)sc); 2540 sc->sc_rr.blksize, audio_rint, (void *)sc);
2508 if (error) { 2541 if (error) {
2509 DPRINTF(("audiostartr failed: %d\n", error)); 2542 DPRINTF(("audiostartr failed: %d\n", error));
2510 return error; 2543 return error;
2511 } 2544 }
2512 sc->sc_rbus = true; 2545 sc->sc_rbus = true;
2513 return 0; 2546 return 0;
2514} 2547}
2515 2548
2516int 2549int
2517audiostartp(struct audio_softc *sc) 2550audiostartp(struct audio_softc *sc)
2518{ 2551{
2519 int error; 2552 int error;
2520 int used; 2553 int used;
2521 2554
2522 used = audio_stream_get_used(&sc->sc_pr.s); 2555 used = audio_stream_get_used(&sc->sc_pr.s);
2523 DPRINTF(("audiostartp: start=%p used=%d(hi=%d blk=%d) mmapped=%d\n", 2556 DPRINTF(("audiostartp: start=%p used=%d(hi=%d blk=%d) mmapped=%d\n",
2524 sc->sc_pr.s.start, used, sc->sc_pr.usedhigh, 2557 sc->sc_pr.s.start, used, sc->sc_pr.usedhigh,
2525 sc->sc_pr.blksize, sc->sc_pr.mmapped)); 2558 sc->sc_pr.blksize, sc->sc_pr.mmapped));
2526 2559
 2560 if (!audio_can_playback(sc))
 2561 return EINVAL;
 2562
2527 if (!sc->sc_pr.mmapped && used < sc->sc_pr.blksize) { 2563 if (!sc->sc_pr.mmapped && used < sc->sc_pr.blksize) {
2528 wakeup(&sc->sc_wchan); 2564 wakeup(&sc->sc_wchan);
2529 DPRINTF(("%s: wakeup and return\n", __func__)); 2565 DPRINTF(("%s: wakeup and return\n", __func__));
2530 return 0; 2566 return 0;
2531 } 2567 }
2532 2568
2533 if (sc->hw_if->trigger_output) { 2569 if (sc->hw_if->trigger_output) {
2534 DPRINTF(("%s: call trigger_output\n", __func__)); 2570 DPRINTF(("%s: call trigger_output\n", __func__));
2535 error = sc->hw_if->trigger_output(sc->hw_hdl, sc->sc_pr.s.start, 2571 error = sc->hw_if->trigger_output(sc->hw_hdl, sc->sc_pr.s.start,
2536 sc->sc_pr.s.end, sc->sc_pr.blksize, 2572 sc->sc_pr.s.end, sc->sc_pr.blksize,
2537 audio_pint, (void *)sc, &sc->sc_pr.s.param); 2573 audio_pint, (void *)sc, &sc->sc_pr.s.param);
2538 } else { 2574 } else {
2539 DPRINTF(("%s: call start_output\n", __func__)); 2575 DPRINTF(("%s: call start_output\n", __func__));
@@ -3321,26 +3357,32 @@ audiosetinfo(struct audio_softc *sc, str @@ -3321,26 +3357,32 @@ audiosetinfo(struct audio_softc *sc, str
3321 rp.precision = r->precision; 3357 rp.precision = r->precision;
3322 /* we don't have API to specify validbits */ 3358 /* we don't have API to specify validbits */
3323 rp.validbits = r->precision; 3359 rp.validbits = r->precision;
3324 nr++; 3360 nr++;
3325 } 3361 }
3326 if (SPECIFIED(p->channels)) { 3362 if (SPECIFIED(p->channels)) {
3327 pp.channels = p->channels; 3363 pp.channels = p->channels;
3328 np++; 3364 np++;
3329 } 3365 }
3330 if (SPECIFIED(r->channels)) { 3366 if (SPECIFIED(r->channels)) {
3331 rp.channels = r->channels; 3367 rp.channels = r->channels;
3332 nr++; 3368 nr++;
3333 } 3369 }
 3370
 3371 if (!audio_can_capture(sc))
 3372 nr = 0;
 3373 if (!audio_can_playback(sc))
 3374 np = 0;
 3375
3334#ifdef AUDIO_DEBUG 3376#ifdef AUDIO_DEBUG
3335 if (audiodebug && nr > 0) 3377 if (audiodebug && nr > 0)
3336 audio_print_params("audiosetinfo() Setting record params:", &rp); 3378 audio_print_params("audiosetinfo() Setting record params:", &rp);
3337 if (audiodebug && np > 0) 3379 if (audiodebug && np > 0)
3338 audio_print_params("audiosetinfo() Setting play params:", &pp); 3380 audio_print_params("audiosetinfo() Setting play params:", &pp);
3339#endif 3381#endif
3340 if (nr > 0 && (error = audio_check_params(&rp))) 3382 if (nr > 0 && (error = audio_check_params(&rp)))
3341 return error; 3383 return error;
3342 if (np > 0 && (error = audio_check_params(&pp))) 3384 if (np > 0 && (error = audio_check_params(&pp)))
3343 return error; 3385 return error;
3344 3386
3345 oldpblksize = sc->sc_pr.blksize; 3387 oldpblksize = sc->sc_pr.blksize;
3346 oldrblksize = sc->sc_rr.blksize; 3388 oldrblksize = sc->sc_rr.blksize;
@@ -3372,27 +3414,27 @@ audiosetinfo(struct audio_softc *sc, str @@ -3372,27 +3414,27 @@ audiosetinfo(struct audio_softc *sc, str
3372 sc->sc_mode = ai->mode; 3414 sc->sc_mode = ai->mode;
3373 if (sc->sc_mode & AUMODE_PLAY_ALL) 3415 if (sc->sc_mode & AUMODE_PLAY_ALL)
3374 sc->sc_mode |= AUMODE_PLAY; 3416 sc->sc_mode |= AUMODE_PLAY;
3375 if ((sc->sc_mode & AUMODE_PLAY) && !sc->sc_full_duplex) 3417 if ((sc->sc_mode & AUMODE_PLAY) && !sc->sc_full_duplex)
3376 /* Play takes precedence */ 3418 /* Play takes precedence */
3377 sc->sc_mode &= ~AUMODE_RECORD; 3419 sc->sc_mode &= ~AUMODE_RECORD;
3378 } 3420 }
3379 3421
3380 oldpus = sc->sc_pustream; 3422 oldpus = sc->sc_pustream;
3381 oldrus = sc->sc_rustream; 3423 oldrus = sc->sc_rustream;
3382 if (modechange) { 3424 if (modechange) {
3383 int indep; 3425 int indep;
3384 3426
3385 indep = hw->get_props(sc->hw_hdl) & AUDIO_PROP_INDEPENDENT; 3427 indep = audio_get_props(sc) & AUDIO_PROP_INDEPENDENT;
3386 if (!indep) { 3428 if (!indep) {
3387 if (setmode == AUMODE_RECORD) 3429 if (setmode == AUMODE_RECORD)
3388 pp = rp; 3430 pp = rp;
3389 else if (setmode == AUMODE_PLAY) 3431 else if (setmode == AUMODE_PLAY)
3390 rp = pp; 3432 rp = pp;
3391 } 3433 }
3392 memset(&pfilters, 0, sizeof(pfilters)); 3434 memset(&pfilters, 0, sizeof(pfilters));
3393 memset(&rfilters, 0, sizeof(rfilters)); 3435 memset(&rfilters, 0, sizeof(rfilters));
3394 pfilters.append = stream_filter_list_append; 3436 pfilters.append = stream_filter_list_append;
3395 pfilters.prepend = stream_filter_list_prepend; 3437 pfilters.prepend = stream_filter_list_prepend;
3396 pfilters.set = stream_filter_list_set; 3438 pfilters.set = stream_filter_list_set;
3397 rfilters.append = stream_filter_list_append; 3439 rfilters.append = stream_filter_list_append;
3398 rfilters.prepend = stream_filter_list_prepend; 3440 rfilters.prepend = stream_filter_list_prepend;
@@ -3706,32 +3748,35 @@ audiogetinfo(struct audio_softc *sc, str @@ -3706,32 +3748,35 @@ audiogetinfo(struct audio_softc *sc, str
3706 r->pause = sc->sc_rr.pause; 3748 r->pause = sc->sc_rr.pause;
3707 3749
3708 p->error = sc->sc_pr.drops != 0; 3750 p->error = sc->sc_pr.drops != 0;
3709 r->error = sc->sc_rr.drops != 0; 3751 r->error = sc->sc_rr.drops != 0;
3710 3752
3711 p->waiting = r->waiting = 0; /* open never hangs */ 3753 p->waiting = r->waiting = 0; /* open never hangs */
3712 3754
3713 p->open = (sc->sc_open & AUOPEN_WRITE) != 0; 3755 p->open = (sc->sc_open & AUOPEN_WRITE) != 0;
3714 r->open = (sc->sc_open & AUOPEN_READ) != 0; 3756 r->open = (sc->sc_open & AUOPEN_READ) != 0;
3715 3757
3716 p->active = sc->sc_pbus; 3758 p->active = sc->sc_pbus;
3717 r->active = sc->sc_rbus; 3759 r->active = sc->sc_rbus;
3718 3760
3719 p->buffer_size = sc->sc_pustream->bufsize; 3761 p->buffer_size = sc->sc_pustream ? sc->sc_pustream->bufsize : 0;
3720 r->buffer_size = sc->sc_rustream->bufsize; 3762 r->buffer_size = sc->sc_rustream ? sc->sc_rustream->bufsize : 0;
3721 3763
3722 ai->blocksize = sc->sc_pr.blksize; 3764 ai->blocksize = sc->sc_pr.blksize;
3723 ai->hiwat = sc->sc_pr.usedhigh / sc->sc_pr.blksize; 3765 if (sc->sc_pr.blksize > 0) {
3724 ai->lowat = sc->sc_pr.usedlow / sc->sc_pr.blksize; 3766 ai->hiwat = sc->sc_pr.usedhigh / sc->sc_pr.blksize;
 3767 ai->lowat = sc->sc_pr.usedlow / sc->sc_pr.blksize;
 3768 } else
 3769 ai->hiwat = ai->lowat = 0;
3725 ai->mode = sc->sc_mode; 3770 ai->mode = sc->sc_mode;
3726 3771
3727 return 0; 3772 return 0;
3728} 3773}
3729 3774
3730/* 3775/*
3731 * Mixer driver 3776 * Mixer driver
3732 */ 3777 */
3733int 3778int
3734mixer_open(dev_t dev, struct audio_softc *sc, int flags, 3779mixer_open(dev_t dev, struct audio_softc *sc, int flags,
3735 int ifmt, struct lwp *l) 3780 int ifmt, struct lwp *l)
3736{ 3781{
3737 if (sc->hw_if == NULL) 3782 if (sc->hw_if == NULL)
@@ -4127,14 +4172,45 @@ audio_volume_toggle(device_t dv) @@ -4127,14 +4172,45 @@ audio_volume_toggle(device_t dv)
4127 int s; 4172 int s;
4128 4173
4129 s = splaudio(); 4174 s = splaudio();
4130 au_get_gain(sc, &sc->sc_outports, &gain, &balance); 4175 au_get_gain(sc, &sc->sc_outports, &gain, &balance);
4131 if (gain != 0) { 4176 if (gain != 0) {
4132 sc->sc_lastgain = gain; 4177 sc->sc_lastgain = gain;
4133 newgain = 0; 4178 newgain = 0;
4134 } else 4179 } else
4135 newgain = sc->sc_lastgain; 4180 newgain = sc->sc_lastgain;
4136 au_set_gain(sc, &sc->sc_outports, newgain, balance); 4181 au_set_gain(sc, &sc->sc_outports, newgain, balance);
4137 splx(s); 4182 splx(s);
4138} 4183}
4139 4184
 4185static int
 4186audio_get_props(struct audio_softc *sc)
 4187{
 4188 const struct audio_hw_if *hw;
 4189 int props;
 4190
 4191 hw = sc->hw_if;
 4192 props = hw->get_props(sc->hw_hdl);
 4193
 4194 /*
 4195 * if neither playback nor capture properties are reported,
 4196 * assume both are supported by the device driver
 4197 */
 4198 if ((props & (AUDIO_PROP_PLAYBACK|AUDIO_PROP_CAPTURE)) == 0)
 4199 props |= (AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE);
 4200
 4201 return props;
 4202}
 4203
 4204static bool
 4205audio_can_playback(struct audio_softc *sc)
 4206{
 4207 return audio_get_props(sc) & AUDIO_PROP_PLAYBACK ? true : false;
 4208}
 4209
 4210static bool
 4211audio_can_capture(struct audio_softc *sc)
 4212{
 4213 return audio_get_props(sc) & AUDIO_PROP_CAPTURE ? true : false;
 4214}
 4215
4140#endif /* NAUDIO > 0 */ 4216#endif /* NAUDIO > 0 */

cvs diff -r1.65 -r1.66 src/sys/dev/Attic/audio_if.h (expand / switch to unified diff)

--- src/sys/dev/Attic/audio_if.h 2008/03/04 18:23:44 1.65
+++ src/sys/dev/Attic/audio_if.h 2009/09/29 15:58:54 1.66
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: audio_if.h,v 1.65 2008/03/04 18:23:44 cube Exp $ */ 1/* $NetBSD: audio_if.h,v 1.66 2009/09/29 15:58:54 sborrill Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1994 Havard Eidnes. 4 * Copyright (c) 1994 Havard Eidnes.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -76,33 +76,35 @@ typedef struct audio_stream { @@ -76,33 +76,35 @@ typedef struct audio_stream {
76 size_t bufsize; /* allocated memory */ 76 size_t bufsize; /* allocated memory */
77 uint8_t *start; /* start of buffer area */ 77 uint8_t *start; /* start of buffer area */
78 uint8_t *end; /* end of valid buffer area */ 78 uint8_t *end; /* end of valid buffer area */
79 uint8_t *inp; /* address to be written next */ 79 uint8_t *inp; /* address to be written next */
80 const uint8_t *outp; /* address to be read next */ 80 const uint8_t *outp; /* address to be read next */
81 int used; /* valid data size in this stream */ 81 int used; /* valid data size in this stream */
82 audio_params_t param; /* represents this stream */ 82 audio_params_t param; /* represents this stream */
83 bool loop; 83 bool loop;
84} audio_stream_t; 84} audio_stream_t;
85 85
86static __inline int 86static __inline int
87audio_stream_get_space(const audio_stream_t *s) 87audio_stream_get_space(const audio_stream_t *s)
88{ 88{
89 return (s->end - s->start) - s->used; 89 if (s)
 90 return (s->end - s->start) - s->used;
 91 return 0;
90} 92}
91 93
92static __inline int 94static __inline int
93audio_stream_get_used(const audio_stream_t *s) 95audio_stream_get_used(const audio_stream_t *s)
94{ 96{
95 return s->used; 97 return s ? s->used : 0;
96} 98}
97 99
98static __inline uint8_t * 100static __inline uint8_t *
99audio_stream_add_inp(audio_stream_t *s, uint8_t *v, int diff) 101audio_stream_add_inp(audio_stream_t *s, uint8_t *v, int diff)
100{ 102{
101 s->used += diff; 103 s->used += diff;
102 v += diff; 104 v += diff;
103 if (v >= s->end) 105 if (v >= s->end)
104 v -= s->end - s->start; 106 v -= s->end - s->start;
105 return v; 107 return v;
106} 108}
107 109
108static __inline const uint8_t * 110static __inline const uint8_t *

cvs diff -r1.15 -r1.16 src/sys/dev/pci/hdaudio/Attic/hdaudio_afg.c (expand / switch to unified diff)

--- src/sys/dev/pci/hdaudio/Attic/hdaudio_afg.c 2009/09/27 02:36:38 1.15
+++ src/sys/dev/pci/hdaudio/Attic/hdaudio_afg.c 2009/09/29 15:58:54 1.16
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: hdaudio_afg.c,v 1.15 2009/09/27 02:36:38 jmcneill Exp $ */ 1/* $NetBSD: hdaudio_afg.c,v 1.16 2009/09/29 15:58:54 sborrill Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2009 Precedence Technologies Ltd <support@precedence.co.uk> 4 * Copyright (c) 2009 Precedence Technologies Ltd <support@precedence.co.uk>
5 * Copyright (c) 2009 Jared D. McNeill <jmcneill@invisible.ca> 5 * Copyright (c) 2009 Jared D. McNeill <jmcneill@invisible.ca>
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * This code is derived from software contributed to The NetBSD Foundation 8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Precedence Technologies Ltd 9 * by Precedence Technologies Ltd
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions 12 * modification, are permitted provided that the following conditions
13 * are met: 13 * are met:
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
@@ -50,27 +50,27 @@ @@ -50,27 +50,27 @@
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 52 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE. 59 * SUCH DAMAGE.
60 */ 60 */
61 61
62#include <sys/cdefs.h> 62#include <sys/cdefs.h>
63__KERNEL_RCSID(0, "$NetBSD: hdaudio_afg.c,v 1.15 2009/09/27 02:36:38 jmcneill Exp $"); 63__KERNEL_RCSID(0, "$NetBSD: hdaudio_afg.c,v 1.16 2009/09/29 15:58:54 sborrill Exp $");
64 64
65#include <sys/types.h> 65#include <sys/types.h>
66#include <sys/param.h> 66#include <sys/param.h>
67#include <sys/systm.h> 67#include <sys/systm.h>
68#include <sys/kernel.h> 68#include <sys/kernel.h>
69#include <sys/device.h> 69#include <sys/device.h>
70#include <sys/conf.h> 70#include <sys/conf.h>
71#include <sys/bus.h> 71#include <sys/bus.h>
72#include <sys/kmem.h> 72#include <sys/kmem.h>
73 73
74#include <sys/audioio.h> 74#include <sys/audioio.h>
75#include <dev/audio_if.h> 75#include <dev/audio_if.h>
76#include <dev/auconv.h> 76#include <dev/auconv.h>
@@ -3313,33 +3313,31 @@ hdaudio_afg_set_params(void *opaque, int @@ -3313,33 +3313,31 @@ hdaudio_afg_set_params(void *opaque, int
3313 } 3313 }
3314 return 0; 3314 return 0;
3315} 3315}
3316 3316
3317static int 3317static int
3318hdaudio_afg_round_blocksize(void *opaque, int blksize, int mode, 3318hdaudio_afg_round_blocksize(void *opaque, int blksize, int mode,
3319 const audio_params_t *param) 3319 const audio_params_t *param)
3320{ 3320{
3321 struct hdaudio_audiodev *ad = opaque; 3321 struct hdaudio_audiodev *ad = opaque;
3322 struct hdaudio_stream *st; 3322 struct hdaudio_stream *st;
3323 int bufsize; 3323 int bufsize;
3324 3324
3325 st = (mode == AUMODE_PLAY) ? ad->ad_playback : ad->ad_capture; 3325 st = (mode == AUMODE_PLAY) ? ad->ad_playback : ad->ad_capture;
3326#ifdef DIAGNOSTIC 
3327 if (st == NULL) { 3326 if (st == NULL) {
3328 hda_error(ad->ad_sc, 3327 hda_trace(ad->ad_sc,
3329 "round_blocksize called for invalid stream\n"); 3328 "round_blocksize called for invalid stream\n");
3330 return 256; 3329 return 128;
3331 } 3330 }
3332#endif 
3333 3331
3334 /* Multiple of 128 */ 3332 /* Multiple of 128 */
3335 blksize &= ~128; 3333 blksize &= ~128;
3336 if (blksize <= 0) 3334 if (blksize <= 0)
3337 blksize = 128; 3335 blksize = 128;
3338 3336
3339 bufsize = st->st_data.dma_size; 3337 bufsize = st->st_data.dma_size;
3340 if (bufsize > HDAUDIO_BDL_MAX * blksize) { 3338 if (bufsize > HDAUDIO_BDL_MAX * blksize) {
3341 blksize = bufsize / HDAUDIO_BDL_MAX; 3339 blksize = bufsize / HDAUDIO_BDL_MAX;
3342 if (blksize & 128) 3340 if (blksize & 128)
3343 blksize = (blksize + 128) & ~128; 3341 blksize = (blksize + 128) & ~128;
3344 } 3342 }
3345 3343
@@ -3573,28 +3571,41 @@ hdaudio_afg_mappage(void *opaque, void * @@ -3573,28 +3571,41 @@ hdaudio_afg_mappage(void *opaque, void *
3573 else 3571 else
3574 return -1; 3572 return -1;
3575 3573
3576 if (st->st_data.dma_valid == false) 3574 if (st->st_data.dma_valid == false)
3577 return -1; 3575 return -1;
3578 3576
3579 return bus_dmamem_mmap(st->st_host->sc_dmat, st->st_data.dma_segs, 3577 return bus_dmamem_mmap(st->st_host->sc_dmat, st->st_data.dma_segs,
3580 st->st_data.dma_nsegs, off, prot, BUS_DMA_WAITOK); 3578 st->st_data.dma_nsegs, off, prot, BUS_DMA_WAITOK);
3581} 3579}
3582 3580
3583static int 3581static int
3584hdaudio_afg_get_props(void *opaque) 3582hdaudio_afg_get_props(void *opaque)
3585{ 3583{
 3584 struct hdaudio_audiodev *ad = opaque;
 3585 int props = 0;
 3586
 3587 if (ad->ad_playback)
 3588 props |= AUDIO_PROP_PLAYBACK;
 3589 if (ad->ad_capture)
 3590 props |= AUDIO_PROP_CAPTURE;
 3591 if (ad->ad_playback && ad->ad_capture) {
 3592 props |= AUDIO_PROP_FULLDUPLEX;
 3593 props |= AUDIO_PROP_INDEPENDENT;
 3594 }
 3595
3586 /* TODO: AUDIO_PROP_MMAP */ 3596 /* TODO: AUDIO_PROP_MMAP */
3587 return AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX; 3597
 3598 return props;
3588} 3599}
3589 3600
3590static int 3601static int
3591hdaudio_afg_trigger_output(void *opaque, void *start, void *end, int blksize, 3602hdaudio_afg_trigger_output(void *opaque, void *start, void *end, int blksize,
3592 void (*intr)(void *), void *intrarg, const audio_params_t *param) 3603 void (*intr)(void *), void *intrarg, const audio_params_t *param)
3593{ 3604{
3594 struct hdaudio_audiodev *ad = opaque; 3605 struct hdaudio_audiodev *ad = opaque;
3595 bus_size_t dmasize; 3606 bus_size_t dmasize;
3596 3607
3597 if (ad->ad_playback == NULL) 3608 if (ad->ad_playback == NULL)
3598 return ENXIO; 3609 return ENXIO;
3599 if (ad->ad_playback->st_data.dma_valid == false) 3610 if (ad->ad_playback->st_data.dma_valid == false)
3600 return ENOMEM; 3611 return ENOMEM;

cvs diff -r1.32 -r1.33 src/sys/sys/audioio.h (expand / switch to unified diff)

--- src/sys/sys/audioio.h 2007/06/11 13:05:47 1.32
+++ src/sys/sys/audioio.h 2009/09/29 15:58:54 1.33
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: audioio.h,v 1.32 2007/06/11 13:05:47 joerg Exp $ */ 1/* $NetBSD: audioio.h,v 1.33 2009/09/29 15:58:54 sborrill Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1991-1993 Regents of the University of California. 4 * Copyright (c) 1991-1993 Regents of the University of California.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -175,26 +175,28 @@ typedef struct audio_encoding { @@ -175,26 +175,28 @@ typedef struct audio_encoding {
175#define AUDIO_WSEEK _IOR('A', 25, u_long) 175#define AUDIO_WSEEK _IOR('A', 25, u_long)
176#define AUDIO_RERROR _IOR('A', 26, int) 176#define AUDIO_RERROR _IOR('A', 26, int)
177#define AUDIO_GETDEV _IOR('A', 27, struct audio_device) 177#define AUDIO_GETDEV _IOR('A', 27, struct audio_device)
178#define AUDIO_GETENC _IOWR('A', 28, struct audio_encoding) 178#define AUDIO_GETENC _IOWR('A', 28, struct audio_encoding)
179#define AUDIO_GETFD _IOR('A', 29, int) 179#define AUDIO_GETFD _IOR('A', 29, int)
180#define AUDIO_SETFD _IOWR('A', 30, int) 180#define AUDIO_SETFD _IOWR('A', 30, int)
181#define AUDIO_PERROR _IOR('A', 31, int) 181#define AUDIO_PERROR _IOR('A', 31, int)
182#define AUDIO_GETIOFFS _IOR('A', 32, struct audio_offset) 182#define AUDIO_GETIOFFS _IOR('A', 32, struct audio_offset)
183#define AUDIO_GETOOFFS _IOR('A', 33, struct audio_offset) 183#define AUDIO_GETOOFFS _IOR('A', 33, struct audio_offset)
184#define AUDIO_GETPROPS _IOR('A', 34, int) 184#define AUDIO_GETPROPS _IOR('A', 34, int)
185#define AUDIO_PROP_FULLDUPLEX 0x01 185#define AUDIO_PROP_FULLDUPLEX 0x01
186#define AUDIO_PROP_MMAP 0x02 186#define AUDIO_PROP_MMAP 0x02
187#define AUDIO_PROP_INDEPENDENT 0x04 187#define AUDIO_PROP_INDEPENDENT 0x04
 188#define AUDIO_PROP_PLAYBACK 0x10
 189#define AUDIO_PROP_CAPTURE 0x20
188#define AUDIO_GETBUFINFO _IOR('A', 35, struct audio_info) 190#define AUDIO_GETBUFINFO _IOR('A', 35, struct audio_info)
189 191
190/* 192/*
191 * Mixer device 193 * Mixer device
192 */ 194 */
193#define AUDIO_MIN_GAIN 0 195#define AUDIO_MIN_GAIN 0
194#define AUDIO_MAX_GAIN 255 196#define AUDIO_MAX_GAIN 255
195 197
196typedef struct mixer_level { 198typedef struct mixer_level {
197 int num_channels; 199 int num_channels;
198 u_char level[8]; /* [num_channels] */ 200 u_char level[8]; /* [num_channels] */
199} mixer_level_t; 201} mixer_level_t;
200#define AUDIO_MIXER_LEVEL_MONO 0 202#define AUDIO_MIXER_LEVEL_MONO 0