summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBinzi Cao - Sun Microsystems - Beijing China <Binzi.Cao@Sun.COM>2009-08-28 10:14:12 +0800
committerBinzi Cao - Sun Microsystems - Beijing China <Binzi.Cao@Sun.COM>2009-08-28 10:14:12 +0800
commite272e4c8df90e762ecb6a6564503bb2cb1e2027d (patch)
tree063487b7cea8764dec3ab3501a813ade7c9c66bf
parent0ff3af34972e8504d3d8bc351d12371be6a60abf (diff)
downloadillumos-joyent-e272e4c8df90e762ecb6a6564503bb2cb1e2027d.tar.gz
6842045 usb audio driver should be updated to OSS framework
6855250 "audioplay" may cause system hang when play audio files to USB headset on snv_117 6852046 MPlayer have problems playing on Sun OSS implementation using OSS driver 6854227 considerable usb audio distortion on build 116 6837267 warlock is not clean for usb audio
-rw-r--r--usr/src/uts/common/Makefile.files2
-rw-r--r--usr/src/uts/common/io/usb/clients/audio/usb_ac/audio_shim.c1948
-rw-r--r--usr/src/uts/common/io/usb/clients/audio/usb_ac/audio_shim.h154
-rw-r--r--usr/src/uts/common/io/usb/clients/audio/usb_ac/usb_ac.c2660
-rw-r--r--usr/src/uts/common/io/usb/clients/audio/usb_ah/usb_ah.c4
-rw-r--r--usr/src/uts/common/io/usb/clients/audio/usb_as/usb_as.c195
-rw-r--r--usr/src/uts/common/io/warlock/usb_ac.wlcmd33
-rw-r--r--usr/src/uts/common/io/warlock/usb_ac_with_sada.wlcmd151
-rw-r--r--usr/src/uts/common/io/warlock/usb_ac_with_usba.wlcmd43
-rw-r--r--usr/src/uts/common/io/warlock/usb_as.wlcmd7
-rw-r--r--usr/src/uts/common/io/warlock/usb_as_with_sada.wlcmd168
-rw-r--r--usr/src/uts/common/io/warlock/usb_as_with_usba.wlcmd13
-rw-r--r--usr/src/uts/common/sys/usb/clients/audio/usb_ac/usb_ac.h162
-rw-r--r--usr/src/uts/common/sys/usb/clients/audio/usb_as/usb_as.h5
-rw-r--r--usr/src/uts/common/sys/usb/clients/audio/usb_audio.h8
-rw-r--r--usr/src/uts/common/sys/usb/clients/audio/usb_mixer.h4
-rw-r--r--usr/src/uts/intel/usb_ac/Makefile20
-rw-r--r--usr/src/uts/intel/usb_as/Makefile15
-rw-r--r--usr/src/uts/sparc/usb_ac/Makefile19
-rw-r--r--usr/src/uts/sparc/usb_as/Makefile13
20 files changed, 1849 insertions, 3775 deletions
diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files
index 11161e87f9..bb8498a58f 100644
--- a/usr/src/uts/common/Makefile.files
+++ b/usr/src/uts/common/Makefile.files
@@ -708,7 +708,7 @@ USBVC_OBJS += usbvc.o usbvc_v4l2.o
HIDPARSER_OBJS += hidparser.o
-USB_AC_OBJS += usb_ac.o audio_shim.o
+USB_AC_OBJS += usb_ac.o
USB_AS_OBJS += usb_as.o
diff --git a/usr/src/uts/common/io/usb/clients/audio/usb_ac/audio_shim.c b/usr/src/uts/common/io/usb/clients/audio/usb_ac/audio_shim.c
deleted file mode 100644
index 123a07e050..0000000000
--- a/usr/src/uts/common/io/usb/clients/audio/usb_ac/audio_shim.c
+++ /dev/null
@@ -1,1948 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <sys/note.h>
-#include <sys/varargs.h>
-#include <sys/stream.h>
-#include <sys/modctl.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/strsun.h>
-#include <sys/strsubr.h>
-#include <sys/taskq.h>
-
-#include <sys/audio.h>
-#include <sys/audio/audio_support.h>
-#include <sys/mixer.h>
-#include <sys/audio/audio_mixer.h>
-
-#include <sys/usb/usba/usbai_version.h>
-#include <sys/usb/usba.h>
-#include <sys/usb/clients/audio/usb_audio.h>
-#include <sys/usb/clients/audio/usb_mixer.h>
-#include <sys/usb/clients/audio/usb_ac/usb_ac.h>
-
-#include "audio_shim.h"
-
-
-
-
-/*
- * The code here is a "shim" connecting legacy SADA USB drivers with the
- * Boomer audio framework, translating interfaces between the two.
- * This is an interim measure until new Boomer-native USB drivers are in place.
- */
-
-extern void audio_dump_bytes(const uint8_t *, int);
-extern void audio_dump_words(const uint16_t *, int);
-extern void audio_dump_dwords(const uint32_t *, int);
-
-
-#define ASHIM_ENG_PLAY 0
-#define ASHIM_ENG_REC 1
-
-#define ASHIM_GET_ENG(statep, which) (&(statep)->engines[(which)])
-#define ASHIM_ENG_DIR(engp) \
- (((engp)->af_eflags & ENGINE_OUTPUT_CAP) ? AUDIO_PLAY : AUDIO_RECORD)
-
-static int ashim_eng_start(ashim_eng_t *);
-static void ashim_eng_stop(ashim_eng_t *);
-
-static int ashim_af_open(void *arg, int flag,
- unsigned *fragszp, unsigned *nfragsp, caddr_t *bufp);
-static void ashim_af_close(void *arg);
-static uint64_t ashim_af_count(void *arg);
-static int ashim_af_start(void *arg);
-static void ashim_af_stop(void *arg);
-static int ashim_af_format(void *arg);
-static int ashim_af_channels(void *arg);
-static int ashim_af_rate(void *arg);
-static void ashim_af_sync(void *arg, unsigned nframes);
-static size_t ashim_af_qlen(void *arg);
-
-audio_engine_ops_t ashim_engine_ops = {
- AUDIO_ENGINE_VERSION,
- ashim_af_open,
- ashim_af_close,
- ashim_af_start,
- ashim_af_stop,
- ashim_af_count,
- ashim_af_format,
- ashim_af_channels,
- ashim_af_rate,
- ashim_af_sync,
- ashim_af_qlen,
-};
-
-
-#define ASHIM_BUFSCALE_MIN 1
-#define ASHIM_BUFSCALE_MAX 2000
-#define ASHIM_BUFSCALE_DEF 10
-
-/* engine buffer size in terms of fragments */
-int ashim_bufscale = ASHIM_BUFSCALE_DEF;
-
-/* use driver specified buffer size instead */
-int ashim_use_drvbuf = 0;
-
-/* format override */
-uint_t ashim_fmt_sr = 0;
-uint_t ashim_fmt_ch = 0;
-uint_t ashim_fmt_prec = 0;
-uint_t ashim_fmt_enc = 0; /* use SADA values e.g. AUDIO_ENCODING_LINEAR = 3 */
-
-/* open without starting engine */
-int ashim_eng_disable = 0;
-
-/* dump audio data */
-uint64_t ashim_dump_audio_start = 0;
-uint64_t ashim_dump_audio_len = 0;
-int ashim_dump_audio_bufsel = 0; /* 0 = shim buf; 1 = drv/dma buf */
-
-/* dump i/o related counters */
-uint64_t ashim_dump_counters_start = 0;
-uint64_t ashim_dump_counters_len = 0;
-
-/* ignore errors when setting control values */
-int ashim_ctrl_ignore_errors = 0;
-
-/*
- * *************************************************************************
- * audio controls
- *
- * Note: we cannot determine if a SADA device truly supports play or record
- * gain adjustment until we actually try the command. Messages showing
- * failed control updates will be printed at the DINFO ashim_debug level.
- */
-
-#define AUDIO_CTRL_STEREO_LEFT(v) ((uint8_t)((v) & 0xff))
-#define AUDIO_CTRL_STEREO_RIGHT(v) ((uint8_t)(((v) >> 8) & 0xff))
-#define AUDIO_CTRL_STEREO_VAL(l, r) (((l) & 0xff) | (((r) & 0xff) << 8))
-
-/*
- * framework gain range
- */
-#define AF_MAX_GAIN 100
-#define AF_MIN_GAIN 0
-
-#define AF_MAX_GAIN_ST AUDIO_CTRL_STEREO_VAL(AF_MAX_GAIN, AF_MAX_GAIN)
-#define AF_MIN_GAIN_ST AUDIO_CTRL_STEREO_VAL(AF_MIN_GAIN, AF_MIN_GAIN)
-
-/*
- * convert between framework and driver gain values
- * must multiply (n) before dividing else D2F_GAIN result will be 0
- */
-#define F2D_GAIN(n) (((n) * AUDIO_MAX_GAIN) / AF_MAX_GAIN)
-#define D2F_GAIN(n) (((n) * AF_MAX_GAIN) / AUDIO_MAX_GAIN)
-
-typedef struct ashim_ctrl_map ashim_ctrl_map_t;
-
-static uint64_t ashim_ctrl_defval(ashim_state_t *statep,
- ashim_ctrl_map_t *mapp);
-static int ashim_ctrl_set_defaults(ashim_state_t *statep);
-static int ashim_ctrl_restore(ashim_state_t *statep);
-
-static int ashim_ctrl_rd(void *, uint64_t *);
-static int ashim_ctrl_wr_st(void *, uint64_t);
-static int ashim_ctrl_wr_mn(void *, uint64_t);
-static int ashim_ctrl_wr_bool(void *, uint64_t);
-static int ashim_ctrl_wr_ports(void *, uint64_t);
-
-static void ashim_rem_controls(ashim_state_t *statep);
-static int ashim_add_controls(ashim_state_t *statep);
-
-
-/*
- * map framework port definitions to SADA ports
- */
-
-typedef struct {
- int dport;
- const char *pname;
-} ashim_port_map_t;
-
-
-static ashim_port_map_t ashim_play_pmap[] = {
- {AUDIO_SPEAKER, AUDIO_PORT_SPEAKER},
- {AUDIO_HEADPHONE, AUDIO_PORT_HEADPHONES},
- {AUDIO_LINE_OUT, AUDIO_PORT_LINEOUT},
- {AUDIO_SPDIF_OUT, AUDIO_PORT_SPDIFOUT},
- {AUDIO_AUX1_OUT, AUDIO_PORT_AUX1OUT},
- {AUDIO_AUX2_OUT, AUDIO_PORT_AUX2OUT}
-};
-static int ashim_play_pmap_len =
- sizeof (ashim_play_pmap) / sizeof (ashim_port_map_t);
-
-
-static ashim_port_map_t ashim_rec_pmap[] = {
- {AUDIO_MICROPHONE, AUDIO_PORT_MIC},
- {AUDIO_LINE_IN, AUDIO_PORT_LINEIN},
- {AUDIO_CD, AUDIO_PORT_CD},
- {AUDIO_SPDIF_IN, AUDIO_PORT_SPDIFIN},
- {AUDIO_AUX1_IN, AUDIO_PORT_AUX1IN},
- {AUDIO_AUX2_IN, AUDIO_PORT_AUX2IN},
- {AUDIO_CODEC_LOOPB_IN, AUDIO_PORT_STEREOMIX}
-};
-static int ashim_rec_pmap_len =
- sizeof (ashim_rec_pmap) / sizeof (ashim_port_map_t);
-
-
-/*
- * map frameowork controls to SADA controls
- */
-struct ashim_ctrl_map {
- int dcmd;
- int dir;
- audio_ctrl_desc_t acd;
- audio_ctrl_wr_t af_wr;
- audio_ctrl_rd_t af_rd;
-};
-
-#define DESC_ST(n, f) { \
- .acd_name = (n), \
- .acd_type = AUDIO_CTRL_TYPE_STEREO, \
- .acd_flags = (f) | \
- AUDIO_CTRL_FLAG_READABLE | AUDIO_CTRL_FLAG_WRITEABLE, \
- .acd_maxvalue = AF_MAX_GAIN, \
- .acd_minvalue = AF_MIN_GAIN, \
-}
-#define FUNC_ST \
- &ashim_ctrl_wr_st, &ashim_ctrl_rd
-
-
-#define DESC_MN(n, f) { \
- .acd_name = (n), \
- .acd_type = AUDIO_CTRL_TYPE_MONO, \
- .acd_flags = (f) | \
- AUDIO_CTRL_FLAG_READABLE | AUDIO_CTRL_FLAG_WRITEABLE, \
- .acd_maxvalue = AF_MAX_GAIN, \
- .acd_minvalue = AF_MIN_GAIN, \
-}
-#define FUNC_MN \
- &ashim_ctrl_wr_mn, &ashim_ctrl_rd
-
-
-#define DESC_BOOL(n, f) { \
- .acd_name = (n), \
- .acd_type = AUDIO_CTRL_TYPE_BOOLEAN, \
- .acd_flags = (f) | \
- AUDIO_CTRL_FLAG_READABLE | AUDIO_CTRL_FLAG_WRITEABLE, \
- .acd_maxvalue = 1, \
- .acd_minvalue = 0, \
-}
-#define FUNC_BOOL \
- &ashim_ctrl_wr_bool, &ashim_ctrl_rd
-
-
-#define DESC_OUTS(n, f) { \
- .acd_name = AUDIO_CTRL_ID_OUTPUTS, \
- .acd_type = AUDIO_CTRL_TYPE_ENUM, \
- .acd_flags = (f) | \
- AUDIO_CTRL_FLAG_READABLE | AUDIO_CTRL_FLAG_WRITEABLE | \
- AUDIO_CTRL_FLAG_MULTI, \
- .acd_maxvalue = (n), \
- .acd_minvalue = (n), \
-}
-
-#define DESC_INS(n, f) { \
- .acd_name = AUDIO_CTRL_ID_INPUTS, \
- .acd_type = AUDIO_CTRL_TYPE_ENUM, \
- .acd_flags = (f) | \
- AUDIO_CTRL_FLAG_READABLE | AUDIO_CTRL_FLAG_WRITEABLE, \
- .acd_maxvalue = (n), \
- .acd_minvalue = (n), \
-}
-#define FUNC_PORTS \
- &ashim_ctrl_wr_ports, &ashim_ctrl_rd
-
-
-/*
- * sada <-> framework translation table
- * a DESC_NULL() for audio_ctrl_desc_t is used to indicate a
- * non-registered sada control that needs some initialization or be used
- * internally by the shim
- *
- * Note: currently, usb_ac only notifies the framework of play volume changes
- * from HID so the volume control the only one using AUDIO_CTRL_FLAG_POLL
- */
-static ashim_ctrl_map_t ashim_ctrl_map[] = {
- {AM_SET_GAIN, AUDIO_PLAY,
- DESC_ST(AUDIO_CTRL_ID_VOLUME, AUDIO_CTRL_FLAG_MAINVOL |
- AUDIO_CTRL_FLAG_PLAY | AUDIO_CTRL_FLAG_POLL),
- FUNC_ST},
-
- {AM_SET_GAIN, AUDIO_PLAY,
- DESC_MN(AUDIO_CTRL_ID_VOLUME, AUDIO_CTRL_FLAG_MAINVOL |
- AUDIO_CTRL_FLAG_PLAY | AUDIO_CTRL_FLAG_POLL),
- FUNC_MN},
-
- {AM_SET_GAIN, AUDIO_RECORD,
- DESC_ST(AUDIO_CTRL_ID_RECGAIN, AUDIO_CTRL_FLAG_RECVOL |
- AUDIO_CTRL_FLAG_REC),
- FUNC_ST},
-
- {AM_SET_GAIN, AUDIO_RECORD,
- DESC_MN(AUDIO_CTRL_ID_RECGAIN, AUDIO_CTRL_FLAG_RECVOL |
- AUDIO_CTRL_FLAG_REC),
- FUNC_MN},
-
- {AM_SET_MONITOR_GAIN, AUDIO_RECORD,
- DESC_MN(AUDIO_CTRL_ID_MONGAIN, AUDIO_CTRL_FLAG_MONVOL |
- AUDIO_CTRL_FLAG_MONITOR),
- FUNC_MN},
-
- {AM_MIC_BOOST, AUDIO_RECORD,
- DESC_BOOL(AUDIO_CTRL_ID_MICBOOST, 0),
- FUNC_BOOL},
-
- {AM_SET_PORT, AUDIO_PLAY,
- DESC_OUTS(0, 0),
- FUNC_PORTS},
-
- {AM_SET_PORT, AUDIO_RECORD,
- DESC_INS(0, 0),
- FUNC_PORTS},
-};
-static int ashim_ctrl_map_len =
- sizeof (ashim_ctrl_map) / sizeof (ashim_ctrl_map_t);
-
-
-/*
- * *************************************************************************
- * shim support routines
- */
-
-int ashim_debug = DBG_WARN;
-
-static void
-vdprint(debug_level_t lvl, const char *fmt, va_list adx)
-{
- if (ashim_debug < lvl)
- return;
-
- vcmn_err(CE_CONT, fmt, adx);
-}
-
-static void
-dwarn(const char *fmt, ...)
-{
- va_list adx;
-
- va_start(adx, fmt);
- vdprint(DBG_WARN, fmt, adx);
- va_end(adx);
-}
-
-static void
-dinfo(const char *fmt, ...)
-{
- va_list adx;
-
- va_start(adx, fmt);
- vdprint(DBG_INFO, fmt, adx);
- va_end(adx);
-}
-
-static void
-ddtl(const char *fmt, ...)
-{
- va_list adx;
-
- va_start(adx, fmt);
- vdprint(DBG_DETAIL, fmt, adx);
- va_end(adx);
-}
-
-
-/*
- * get the maximum format specification the device supports
- */
-static void
-ashim_max_fmt(ashim_state_t *statep, int dir, ashim_fmt_t *fmtp)
-{
- am_ad_ch_cap_t *capp = &statep->ad_infop->ad_play;
- am_ad_cap_comb_t *combp = statep->ad_infop->ad_play_comb;
-
- uint_t *srs, *chs;
- uint_t sr, ch, prec, enc, val;
- int i;
-
- if (dir == AUDIO_RECORD) {
- capp = &statep->ad_infop->ad_record;
- combp = statep->ad_infop->ad_rec_comb;
- }
- srs = capp->ad_mixer_srs.ad_srs;
- chs = capp->ad_chs;
-
- for (i = 0, sr = 0; srs[i]; i++) {
- val = srs[i];
- if (val > sr)
- sr = val;
- }
-
- for (i = 0, ch = 0; chs[i]; i++) {
- val = chs[i];
- if (val > ch)
- ch = val;
- }
-
- for (i = 0, prec = 0, enc = 0; combp[i].ad_prec; i++) {
- val = combp[i].ad_prec;
- if (val > prec)
- prec = val;
-
- val = combp[i].ad_enc;
- if (val > enc)
- enc = val;
- }
-
- fmtp->sr = ashim_fmt_sr ? ashim_fmt_sr : sr;
- fmtp->ch = ashim_fmt_ch ? ashim_fmt_ch : ch;
- fmtp->prec = ashim_fmt_prec ? ashim_fmt_prec : prec;
- fmtp->enc = ashim_fmt_enc ? ashim_fmt_enc : enc;
-}
-
-
-/*
- * calls the driver's setup routine if present
- * For USB audio, this opens a pipe to the endpoint usb_as
- * returns AUDIO_SUCCESS or AUDIO_FAILURE
- */
-static int
-ashim_ad_setup(ashim_state_t *statep, int dir)
-{
- am_ad_entry_t *ad_entry = statep->ad_infop->ad_entry;
-
- if (ad_entry->ad_setup == NULL)
- return (AUDIO_SUCCESS);
-
- return (ad_entry->ad_setup(AUDIO_SHIMST2HDL(statep), dir));
-}
-
-
-/*
- * calls the driver's teardown routine if present.
- * Note that the amount of teardowns must match the amount of setups used
- * in each direction.
- * returns AUDIO_SUCCESS or AUDIO_FAILURE
- */
-static void
-ashim_ad_teardown(ashim_state_t *statep, int dir)
-{
- am_ad_entry_t *ad_entry = statep->ad_infop->ad_entry;
-
- if (ad_entry->ad_teardown != NULL)
- ad_entry->ad_teardown(AUDIO_SHIMST2HDL(statep), dir);
-}
-
-
-/*
- * sets the audio format (sample rate, channels, precision, encoding)
- * returns AUDIO_SUCCESS or AUDIO_FAILURE
- */
-static int
-ashim_set_fmt(ashim_state_t *statep, int dir, ashim_fmt_t *fmtp)
-{
- am_ad_entry_t *ad_entry = statep->ad_infop->ad_entry;
-
- return (ad_entry->ad_set_format(AUDIO_SHIMST2HDL(statep), dir,
- fmtp->sr, fmtp->ch, fmtp->prec, fmtp->enc));
-}
-
-
-static int
-ashim_af_fmt(ashim_fmt_t *fmtp)
-{
- switch (fmtp->enc) {
- case AUDIO_ENCODING_ULAW:
- return (AUDIO_FORMAT_ULAW);
- case AUDIO_ENCODING_ALAW:
- return (AUDIO_FORMAT_ALAW);
- case AUDIO_ENCODING_DVI:
- return (AUDIO_FORMAT_NONE);
- case AUDIO_ENCODING_LINEAR8:
- return (AUDIO_FORMAT_U8);
- case AUDIO_ENCODING_LINEAR:
- break;
- default:
- return (AUDIO_FORMAT_NONE);
- }
-
- switch (fmtp->prec) {
- case 8:
- return (AUDIO_FORMAT_S8);
- case 16:
- return (AUDIO_FORMAT_S16_NE);
- case 24:
- return (AUDIO_FORMAT_S24_NE);
- case 32:
- return (AUDIO_FORMAT_S32_NE);
- default:
- break;
- }
- return (AUDIO_FORMAT_NONE);
-}
-
-
-static void
-ashim_rem_eng(ashim_state_t *statep, ashim_eng_t *engp)
-{
- if (statep->af_devp == NULL || engp->af_engp == NULL)
- return;
-
- audio_dev_remove_engine(statep->af_devp, engp->af_engp);
- audio_engine_free(engp->af_engp);
- engp->af_engp = NULL;
-
-}
-
-
-static int
-ashim_add_eng(ashim_state_t *statep, int dir)
-{
- audio_dev_t *af_devp = statep->af_devp;
- ashim_eng_t *engp;
- audio_engine_t *af_engp;
- int rv = AUDIO_FAILURE;
- int which;
-
- if (dir == AUDIO_PLAY) {
- which = ASHIM_ENG_PLAY;
- engp = ASHIM_GET_ENG(statep, which);
- engp->af_eflags = ENGINE_OUTPUT_CAP;
- engp->prinfop = &statep->ad_infop->ad_defaults->play;
- engp->name = "PLAY";
- } else {
- which = ASHIM_ENG_REC;
- engp = ASHIM_GET_ENG(statep, which);
- engp->af_eflags = ENGINE_INPUT_CAP;
- engp->prinfop = &statep->ad_infop->ad_defaults->record;
- engp->name = "RECORD";
- }
-
- mutex_init(&engp->lock, NULL, MUTEX_DRIVER, NULL);
-
- engp->statep = statep;
-
- ashim_max_fmt(statep, dir, &engp->fmt);
- engp->af_fmt = ashim_af_fmt(&engp->fmt);
-
- af_engp = audio_engine_alloc(&ashim_engine_ops, engp->af_eflags);
- if (af_engp == NULL) {
- audio_dev_warn(af_devp, "audio_engine_alloc failed");
- goto OUT;
- }
-
- engp->af_engp = af_engp;
- audio_engine_set_private(af_engp, engp);
- audio_dev_add_engine(af_devp, af_engp);
-
- engp->flags = ENG_ENABLED;
-
- /*
- * Set the format for this engine
- */
- if (ashim_set_fmt(statep, dir, &engp->fmt) != AUDIO_SUCCESS) {
- audio_dev_warn(af_devp, "set format failed, dir = %d\n", dir);
- goto OUT;
- }
- rv = AUDIO_SUCCESS;
-
-OUT:
- if (rv != AUDIO_SUCCESS)
- ashim_rem_eng(statep, engp);
-
- return (rv);
-}
-
-
-static int
-ashim_set_config(ashim_state_t *statep, ashim_ctrl_t *ctrlp, int cmd, int dir,
- int arg1, int arg2)
-{
- int (*fn)(audiohdl_t, int, int, int, int) =
- statep->ad_infop->ad_entry->ad_set_config;
-
- ddtl("%s - ashim_set_config: cmd 0x%x, dir %d, arg1 0x%x, arg2 0x%x\n",
- statep->dstr, cmd, dir, arg1, arg2);
-
- if (fn(AUDIO_SHIMST2HDL(statep), cmd, dir, arg1, arg2) !=
- AUDIO_SUCCESS) {
- dinfo("%s: failed update control %s "
- "with cmd 0x%x, dir %d, arg1 0x%x, arg2 0x%x",
- statep->dstr, ctrlp->acd.acd_name, cmd, dir, arg1, arg2);
- return (EIO);
- }
-
- return (0);
-}
-
-
-static int
-ashim_ctrl_set_defaults(ashim_state_t *statep)
-{
- ashim_ctrl_t *ctrlp;
- int rv = AUDIO_SUCCESS;
-
- for (ctrlp = statep->controls; ctrlp; ctrlp = ctrlp->nextp) {
- if (audio_control_write(ctrlp->af_ctrlp, ctrlp->defval)) {
- dinfo("%s: setting control %s to default value "
- "0x%llx failed\n",
- statep->dstr, ctrlp->acd.acd_name,
- (long long unsigned)ctrlp->defval);
- rv = AUDIO_FAILURE;
- }
- }
- return (rv);
-}
-
-
-static int
-ashim_ctrl_restore(ashim_state_t *statep)
-{
- ashim_ctrl_t *ctrlp;
- int rv = AUDIO_SUCCESS;
-
- for (ctrlp = statep->controls; ctrlp; ctrlp = ctrlp->nextp) {
- if (ctrlp->af_wr((void *)ctrlp, ctrlp->cval) != 0) {
- dinfo("%s: restoring "
- "control %s to value 0x%llx failed",
- statep->dstr, ctrlp->acd.acd_name,
- (long long unsigned)ctrlp->cval);
- rv = AUDIO_FAILURE;
- }
- }
- return (rv);
-}
-
-
-static inline void
-ashim_dump_audio(ashim_eng_t *engp, void *buf, int sz)
-{
- if (engp->io_count >= ashim_dump_audio_start &&
- engp->io_count - ashim_dump_audio_start < ashim_dump_audio_len) {
- int samples = sz >> engp->smszshift;
- int frames = samples >> engp->frsmshift;
-
- cmn_err(CE_NOTE, "\n\n======= %s - %s: REQUEST #%llu, "
- "BUF I/O #%llu, SAMPLES %d (%d frames, %d bytes), "
- "BUF ADDR 0x%p =======\n",
- engp->statep->dstr, engp->name,
- (unsigned long long)engp->io_count,
- (unsigned long long)engp->bufio_count,
- samples, frames, sz, buf);
-
- if (sz <= 0)
- return;
-
- switch (engp->fmt.prec) {
- case 8:
- case 24:
- audio_dump_bytes((uint8_t *)buf, sz);
- break;
- case 16:
- audio_dump_words((uint16_t *)buf, sz >> 1);
- break;
- case 32:
- audio_dump_dwords((uint32_t *)buf, sz >> 2);
- break;
- }
- }
-}
-
-
-static inline void
-ashim_dump_counters(ashim_eng_t *engp, unsigned frames, int bufcnt)
-{
- if (engp->io_count >= ashim_dump_counters_start &&
- engp->io_count - ashim_dump_counters_start <
- ashim_dump_counters_len) {
- int samples = frames << engp->frsmshift;
- int sz = samples << engp->smszshift;
-
- if (bufcnt >= 0) {
- cmn_err(CE_CONT, "======= %s - %s: buf i/o %d of "
- "REQUEST #%llu, SAMPLES %d "
- "(%d frames, %d bytes)\n",
- engp->statep->dstr, engp->name, bufcnt,
- (unsigned long long)engp->io_count, samples,
- frames, sz);
- } else {
- cmn_err(CE_CONT, "======= %s - %s: REQUEST #%llu, "
- "SAMPLES %d (%d frames, %d bytes)\n",
- engp->statep->dstr, engp->name,
- (unsigned long long)engp->io_count,
- samples, frames, sz);
- }
- }
-}
-
-
-/*
- * moves data between driver buffer and framework/shim buffer
- */
-static void
-ashim_eng_bufio(ashim_eng_t *engp, void *buf, size_t sz)
-{
- size_t cpsz = sz;
- caddr_t *src, *dst, *dp;
-
- if (engp->af_eflags & ENGINE_OUTPUT_CAP) {
- src = &engp->bufpos;
- dst = (caddr_t *)&buf;
- } else {
- src = (caddr_t *)&buf;
- dst = &engp->bufpos;
- }
- dp = ashim_dump_audio_bufsel ? (caddr_t *)&buf : &engp->bufpos;
-
- /*
- * Wrap. If sz is exactly the remainder of the buffer
- * (bufpos + sz == bufendp) then the second cpsz should be 0 and so
- * the second memcpy() should have no effect, with bufpos updated
- * to the head of the buffer.
- */
- if (engp->bufpos + sz >= engp->bufendp) {
- cpsz = (size_t)engp->bufendp - (size_t)engp->bufpos;
- (void) memcpy(*dst, *src, cpsz);
-
- if (ashim_dump_audio_len)
- ashim_dump_audio(engp, *dp, cpsz);
-
- buf = (caddr_t)buf + cpsz;
- engp->bufpos = engp->bufp;
- cpsz = sz - cpsz;
- }
-
- if (cpsz) {
- (void) memcpy(*dst, *src, cpsz);
-
- if (ashim_dump_audio_len)
- ashim_dump_audio(engp, *dp, cpsz);
-
- engp->bufpos += cpsz;
- }
- engp->bufio_count++;
-}
-
-
-static void
-ashim_prtstats(ashim_eng_t *engp)
-{
- ashim_state_t *statep = engp->statep;
-
- dinfo("%s - %s: driver i/o: %llu, framework i/o: %llu, "
- "frames: %llu\n", statep->dstr, engp->name,
- (long long unsigned)engp->io_count,
- (long long unsigned)engp->bufio_count,
- (long long unsigned)engp->frames);
-}
-
-
-/*
- * *************************************************************************
- * audio control routines
- */
-
-static uint64_t
-ashim_ctrl_defval(ashim_state_t *statep, ashim_ctrl_map_t *mapp)
-{
- audio_prinfo_t *play_prp = &statep->ad_infop->ad_defaults->play;
- audio_prinfo_t *rec_prp = &statep->ad_infop->ad_defaults->record;
- const char *cname = mapp->acd.acd_name;
- uint64_t cval = 0;
- uint64_t gain;
- ashim_fmt_t fmt;
-
- if (strcmp(cname, AUDIO_CTRL_ID_VOLUME) == 0) {
- ashim_max_fmt(statep, AUDIO_PLAY, &fmt);
- if (fmt.ch == 0)
- return (0);
-
- gain = D2F_GAIN(play_prp->gain);
- if (fmt.ch == 1)
- cval = gain;
- else
- cval = AUDIO_CTRL_STEREO_VAL(gain, gain);
-
- } else if (strcmp(cname, AUDIO_CTRL_ID_RECGAIN) == 0) {
- ashim_max_fmt(statep, AUDIO_RECORD, &fmt);
- if (fmt.ch == 0)
- return (0);
-
- gain = D2F_GAIN(rec_prp->gain);
- if (fmt.ch == 1)
- cval = gain;
- else
- cval = AUDIO_CTRL_STEREO_VAL(gain, gain);
-
- } else if (strcmp(cname, AUDIO_CTRL_ID_MONGAIN) == 0) {
- cval = D2F_GAIN(statep->ad_infop->ad_defaults->monitor_gain);
-
- } else if (strcmp(cname, AUDIO_CTRL_ID_MICBOOST) == 0) {
- cval = 0;
-
- } else if (strcmp(cname, AUDIO_CTRL_ID_OUTPUTS) == 0) {
- cval = play_prp->port;
-
- } else if (strcmp(cname, AUDIO_CTRL_ID_INPUTS) == 0) {
- cval = rec_prp->port;
- }
-
- return (cval);
-}
-
-
-static ashim_ctrl_t *
-ashim_find_ctrl_dcmd(ashim_state_t *statep, int dcmd, int dir)
-{
- ashim_ctrl_t *ctrlp;
-
- for (ctrlp = statep->controls; ctrlp != NULL; ctrlp = ctrlp->nextp) {
- if (ctrlp->dcmd == dcmd && ctrlp->dir == dir)
- break;
- }
- return (ctrlp);
-}
-
-
-/*
- * control callback and related routines
- */
-
-static int
-ashim_ctrl_gain_mutable(ashim_ctrl_t *ctrlp, int left, int right)
-{
- ashim_state_t *statep = ctrlp->statep;
- int gain;
-
- if (left == 0 && right == 0)
- gain = 0;
- else if (left != 0)
- gain = left;
- else
- gain = right;
-
- if (ctrlp->dcmd == AM_SET_GAIN && ctrlp->dir == AUDIO_PLAY) {
- /*
- * mute when gain = 0, and on the transition when gain != 0
- * but do not set unmute cmds during non-zero changes
- */
- if (gain == 0) {
- ctrlp->flags |= CTRL_MUTED;
-
- if (ashim_set_config(statep, ctrlp, AM_OUTPUT_MUTE,
- AUDIO_PLAY, 1, 0) != AUDIO_SUCCESS)
- return (EIO);
-
- } else if (ctrlp->flags & CTRL_MUTED) {
- ctrlp->flags &= ~CTRL_MUTED;
-
- if (ashim_set_config(statep, ctrlp, AM_OUTPUT_MUTE,
- AUDIO_PLAY, 0, 0) != AUDIO_SUCCESS)
- return (EIO);
- }
- }
-
- return (0);
-}
-
-
-/*
- * control read callback
- */
-static int
-ashim_ctrl_rd(void *arg, uint64_t *cvalp)
-{
- ashim_ctrl_t *ctrlp = arg;
-
- mutex_enter(&ctrlp->lock);
- *cvalp = ctrlp->cval;
- mutex_exit(&ctrlp->lock);
-
- return (0);
-}
-
-
-/*
- * stereo level control callback
- */
-static int
-ashim_ctrl_wr_st(void *arg, uint64_t cval)
-{
- ashim_ctrl_t *ctrlp = arg;
- ashim_state_t *statep = ctrlp->statep;
- int rv = EIO;
- int left, right;
-
- ddtl("%s - control %s WRITE: 0x%llx\n", statep->dstr,
- ctrlp->acd.acd_name, (long long unsigned)cval);
-
- left = AUDIO_CTRL_STEREO_LEFT(cval);
- right = AUDIO_CTRL_STEREO_RIGHT(cval);
-
- if (left < AF_MIN_GAIN || left > AF_MAX_GAIN ||
- right < AF_MIN_GAIN || right > AF_MAX_GAIN) {
- dinfo("%s - control %s invalid value: 0x%llx\n", statep->dstr,
- ctrlp->acd.acd_name, (long long unsigned)cval);
- return (EINVAL);
- }
-
- mutex_enter(&ctrlp->lock);
- ctrlp->cval = cval;
-
- left = F2D_GAIN(left);
- right = F2D_GAIN(right);
-
- if (ashim_set_config(statep, ctrlp, ctrlp->dcmd, ctrlp->dir, left,
- 0) != AUDIO_SUCCESS)
- goto OUT;
-
- if (ashim_set_config(statep, ctrlp, ctrlp->dcmd, ctrlp->dir, right,
- 1) != AUDIO_SUCCESS) {
- /* restore previous left gain value */
- (void) ashim_set_config(statep, ctrlp, ctrlp->dcmd, ctrlp->dir,
- left, 0);
- goto OUT;
- }
-
- rv = ashim_ctrl_gain_mutable(ctrlp, left, right);
-
-OUT:
- mutex_exit(&ctrlp->lock);
- return (ashim_ctrl_ignore_errors ? 0 : rv);
-}
-
-
-/*
- * mono level control callback
- */
-static int
-ashim_ctrl_wr_mn(void *arg, uint64_t cval)
-{
- ashim_ctrl_t *ctrlp = arg;
- ashim_state_t *statep = ctrlp->statep;
- int rv = EIO;
- int gain;
-
- ddtl("%s - control %s WRITE: 0x%llx\n", statep->dstr,
- ctrlp->acd.acd_name, (long long unsigned)cval);
-
- if (cval < (uint64_t)AF_MIN_GAIN || cval > (uint64_t)AF_MAX_GAIN) {
- dinfo("%s - control %s invalid value: 0x%llx\n", statep->dstr,
- ctrlp->acd.acd_name, (long long unsigned)cval);
- return (EINVAL);
- }
-
- mutex_enter(&ctrlp->lock);
- ctrlp->cval = cval;
-
- gain = (int)F2D_GAIN(cval);
-
- if (ashim_set_config(statep, ctrlp, ctrlp->dcmd, ctrlp->dir,
- gain, 0) != AUDIO_SUCCESS)
- goto OUT;
-
- rv = ashim_ctrl_gain_mutable(ctrlp, gain, 0);
-
-OUT:
- mutex_exit(&ctrlp->lock);
- return (ashim_ctrl_ignore_errors ? 0 : rv);
-}
-
-
-/*
- * boolean control callback
- */
-/*ARGSUSED*/
-static int
-ashim_ctrl_wr_bool(void *arg, uint64_t cval)
-{
- ashim_ctrl_t *ctrlp = arg;
- ashim_state_t *statep = ctrlp->statep;
- int rv = EIO;
-
- ddtl("%s - control %s WRITE: 0x%llx\n", statep->dstr,
- ctrlp->acd.acd_name, (long long unsigned)cval);
-
- mutex_enter(&ctrlp->lock);
- ctrlp->cval = cval;
-
- if (ashim_set_config(statep, ctrlp, ctrlp->dcmd, ctrlp->dir,
- (int)cval, 0) != AUDIO_SUCCESS)
- goto OUT;
-
- rv = 0;
-
-OUT:
- mutex_exit(&ctrlp->lock);
- return (ashim_ctrl_ignore_errors ? 0 : rv);
-}
-
-
-/*
- * port selection control callback
- */
-static int
-ashim_ctrl_wr_ports(void *arg, uint64_t cval)
-{
- ashim_ctrl_t *ctrlp = arg;
- ashim_state_t *statep = ctrlp->statep;
- int rv = EIO;
- int dports = cval & 0xff;
-
- ddtl("%s - control %s WRITE: 0x%llx\n", statep->dstr,
- ctrlp->acd.acd_name, (long long unsigned)cval);
-
- if ((cval & ~ctrlp->acd.acd_minvalue) !=
- (ctrlp->acd.acd_maxvalue & ~ctrlp->acd.acd_minvalue)) {
- dinfo("%s - control %s invalid value: 0x%llx\n", statep->dstr,
- ctrlp->acd.acd_name, (long long unsigned)cval);
- return (EINVAL);
- }
-
- mutex_enter(&ctrlp->lock);
- ctrlp->cval = cval;
-
- if (ashim_set_config(statep, ctrlp, ctrlp->dcmd, ctrlp->dir, dports,
- 0) != AUDIO_SUCCESS)
- goto OUT;
-
- rv = 0;
-
-OUT:
- mutex_exit(&ctrlp->lock);
- return (ashim_ctrl_ignore_errors ? 0 : rv);
-}
-
-
-/*
- * audio control registration related routines
- */
-
-static ashim_ctrl_t *
-ashim_ctrl_alloc(void)
-{
- return (kmem_zalloc(sizeof (ashim_ctrl_t), KM_SLEEP));
-}
-
-
-static void
-ashim_ctrl_free(ashim_ctrl_t *ctrlp)
-{
- kmem_free(ctrlp, sizeof (ashim_ctrl_t));
-}
-
-
-static void
-ashim_ctrl_insert(ashim_state_t *statep, ashim_ctrl_t *ctrlp)
-{
- ctrlp->nextp = statep->controls;
- statep->controls = ctrlp;
-}
-
-
-/*
- * returns the amount of modifiable ports
- */
-static int
-ashim_ctrl_init_ports(ashim_state_t *statep, ashim_ctrl_t *ctrlp)
-{
- audio_prinfo_t *prp;
- ashim_port_map_t *pmap;
- int pmaplen;
- int i;
- int count = 0;
-
- if (ctrlp->dir == AUDIO_PLAY) {
- prp = &statep->ad_infop->ad_defaults->play;
- pmap = ashim_play_pmap;
- pmaplen = ashim_play_pmap_len;
- } else {
- prp = &statep->ad_infop->ad_defaults->record;
- pmap = ashim_rec_pmap;
- pmaplen = ashim_rec_pmap_len;
- }
-
- /*
- * look at all SADA supported ports then set the corresponding
- * framework defined bits in the control description if the driver
- * informs us that it is present (avail_ports) and if it can be
- * toggled on/off (mod_ports)
- */
- for (i = 0; i < pmaplen; i++) {
- ctrlp->acd.acd_enum[i] = pmap[i].pname;
-
- if (pmap[i].dport & prp->avail_ports) {
- ctrlp->acd.acd_maxvalue |= pmap[i].dport;
-
- dinfo("%s: available port: "
- "driver 0x%x, framework 0x%s\n",
- statep->dstr, pmap[i].dport, pmap[i].pname);
- }
- if (pmap[i].dport & prp->mod_ports) {
- ctrlp->acd.acd_minvalue |= pmap[i].dport;
-
- dinfo("%s: modifiable port: "
- "(driver 0x%x, framework %s)\n",
- statep->dstr, pmap[i].dport, pmap[i].pname);
-
- count++;
- }
- }
-
- return (count);
-}
-
-
-static void
-ashim_ctrl_fini(ashim_ctrl_t *ctrlp)
-{
- mutex_destroy(&ctrlp->lock);
-}
-
-
-/*
- * returns 0 if initialization is successful; failure to initialize is
- * not fatal so caller should deallocate and continue on to the next control
- */
-static int
-ashim_ctrl_init(ashim_state_t *statep, ashim_ctrl_t *ctrlp,
- ashim_ctrl_map_t *mapp)
-{
- ctrlp->dcmd = mapp->dcmd;
- ctrlp->dir = mapp->dir;
- ctrlp->acd = mapp->acd;
- ctrlp->af_ctrlp = NULL;
- ctrlp->defval = ashim_ctrl_defval(statep, mapp);
- ctrlp->cval = ctrlp->defval;
- ctrlp->af_wr = mapp->af_wr;
- ctrlp->statep = statep;
-
- if (mapp->acd.acd_type == AUDIO_CTRL_TYPE_ENUM &&
- ashim_ctrl_init_ports(statep, ctrlp) <= 1) {
- dinfo("%s: no more than one modifiable port detected for "
- "control %s, enabling and skipping\n",
- statep->dstr, ctrlp->acd.acd_name);
-
- (void) ctrlp->af_wr((void *)ctrlp, ctrlp->defval);
- return (1);
- }
-
- mutex_init(&ctrlp->lock, NULL, MUTEX_DRIVER, NULL);
- return (0);
-}
-
-
-/*
- * heuristic to determine if a control is actually present by writing the
- * default value and checking if the operation succeeds
- */
-/*ARGSUSED*/
-static int
-ashim_ctrl_test(ashim_state_t *statep, ashim_ctrl_t *ctrlp)
-{
- return (ctrlp->af_wr((void *)ctrlp, ctrlp->defval));
-}
-
-
-static void
-ashim_rem_controls(ashim_state_t *statep)
-{
- ashim_ctrl_t *ctrlp = statep->controls;
- ashim_ctrl_t *nextp;
-
- while (ctrlp != NULL) {
- if (ctrlp->af_ctrlp != NULL)
- audio_dev_del_control(ctrlp->af_ctrlp);
-
- nextp = ctrlp->nextp;
- ashim_ctrl_fini(ctrlp);
- ashim_ctrl_free(ctrlp);
- ctrlp = nextp;
- }
-
- /* required */
- statep->controls = NULL;
-}
-
-
-static int
-ashim_add_controls(ashim_state_t *statep)
-{
- int rv = AUDIO_FAILURE;
- int i;
- ashim_ctrl_map_t *mapp;
- ashim_ctrl_t *ctrlp;
- audio_ctrl_t *af_ctrlp;
- ashim_fmt_t playfmt = {0};
- ashim_fmt_t recfmt = {0};
- ashim_fmt_t *fmtp;
- int ad_feat = statep->ad_infop->ad_defaults->hw_features;
-
- if (ad_feat & AUDIO_HWFEATURE_PLAY)
- ashim_max_fmt(statep, AUDIO_PLAY, &playfmt);
-
- if (ad_feat & AUDIO_HWFEATURE_RECORD)
- ashim_max_fmt(statep, AUDIO_RECORD, &recfmt);
-
- for (i = 0; i < ashim_ctrl_map_len; i++) {
- mapp = &ashim_ctrl_map[i];
- fmtp = NULL;
-
- if (mapp->dir == AUDIO_PLAY) {
- if (!(ad_feat & AUDIO_HWFEATURE_PLAY))
- continue;
-
- fmtp = &playfmt;
- }
- if (mapp->dir == AUDIO_RECORD) {
- if (!(ad_feat & AUDIO_HWFEATURE_RECORD))
- continue;
-
- fmtp = &recfmt;
- }
-
- if (mapp->dcmd == AM_SET_GAIN) {
- if (fmtp->ch == 0)
- continue;
-
- if (mapp->acd.acd_type == AUDIO_CTRL_TYPE_MONO &&
- fmtp->ch != 1)
- continue;
-
- if (mapp->acd.acd_type == AUDIO_CTRL_TYPE_STEREO &&
- fmtp->ch != 2)
- continue;
- }
-
- ctrlp = ashim_ctrl_alloc();
-
- if (ashim_ctrl_init(statep, ctrlp, mapp)) {
- ashim_ctrl_free(ctrlp);
- continue;
- }
-
- if (ashim_ctrl_test(statep, ctrlp)) {
- dwarn("%s: i= %d, control %s tested invalid\n",
- statep->dstr, i, ctrlp->acd.acd_name);
-
- ashim_ctrl_fini(ctrlp);
- ashim_ctrl_free(ctrlp);
- continue;
- }
-
- af_ctrlp = audio_dev_add_control(statep->af_devp, &ctrlp->acd,
- mapp->af_rd, mapp->af_wr, (void *)ctrlp);
-
- if (af_ctrlp == NULL) {
- audio_dev_warn(statep->af_devp, "failed to add "
- "control %s", ctrlp->acd.acd_name);
- ashim_ctrl_fini(ctrlp);
- ashim_ctrl_free(ctrlp);
- goto OUT;
- }
-
- dinfo("%s: added control %s, type: %d, "
- "flags: 0x%x, min: 0x%llx, max: 0x%llx, default: 0x%llx\n",
- statep->dstr, ctrlp->acd.acd_name, ctrlp->acd.acd_type,
- ctrlp->acd.acd_flags,
- ctrlp->acd.acd_minvalue, ctrlp->acd.acd_maxvalue,
- ctrlp->defval);
-
- ctrlp->af_ctrlp = af_ctrlp;
- ashim_ctrl_insert(statep, ctrlp);
- }
-
- rv = AUDIO_SUCCESS;
-
-OUT:
- if (rv != AUDIO_SUCCESS)
- ashim_rem_controls(statep);
- return (rv);
-}
-
-
-/*
- * **************************************************************************
- * replacements for SADA framework interfaces
- */
-
-void *
-audio_sup_get_private(audiohdl_t handle)
-{
- return (AUDIO_HDL2SHIMST(handle)->private);
-}
-
-
-void
-audio_sup_set_private(audiohdl_t handle, void *private)
-{
- AUDIO_HDL2SHIMST(handle)->private = private;
-}
-
-
-int
-audio_sup_unregister(audiohdl_t handle)
-{
- ashim_state_t *statep;
-
- if (handle == NULL)
- return (AUDIO_SUCCESS);
-
- statep = AUDIO_HDL2SHIMST(handle);
-
- kmem_free(statep, sizeof (*statep));
- return (AUDIO_SUCCESS);
-}
-
-
-audiohdl_t
-audio_sup_register(dev_info_t *dip)
-{
- ashim_state_t *statep = NULL;
- int inst;
- const char *nm;
-
- statep = kmem_zalloc(sizeof (*statep), KM_SLEEP);
- statep->dip = dip;
-
- inst = ddi_get_instance(dip);
- nm = ddi_driver_name(dip);
-
- (void) snprintf(statep->dstr, sizeof (statep->dstr),
- "%s#%d", nm, inst);
-
- return (AUDIO_SHIMST2HDL(statep));
-}
-
-
-int
-am_unregister(audiohdl_t handle)
-{
- ashim_state_t *statep = AUDIO_HDL2SHIMST(handle);
-
- if (statep->af_devp == NULL)
- return (AUDIO_SUCCESS);
-
- if (statep->flags & AF_REGISTERED) {
- if (audio_dev_unregister(statep->af_devp) != DDI_SUCCESS) {
- dwarn("%s: am_unregister: audio_dev_unregister() "
- "failed\n", statep->dstr);
-
- return (AUDIO_FAILURE);
- }
- statep->flags &= ~AF_REGISTERED;
- }
-
- return (AUDIO_SUCCESS);
-}
-
-
-/*ARGSUSED*/
-int
-am_detach(audiohdl_t handle, ddi_detach_cmd_t cmd)
-{
- ashim_state_t *statep = AUDIO_HDL2SHIMST(handle);
- int i;
-
- if (statep == NULL)
- return (AUDIO_SUCCESS);
-
- if (statep->af_devp == NULL)
- return (AUDIO_SUCCESS);
-
- if ((statep->flags & AF_REGISTERED) &&
- audio_dev_unregister(statep->af_devp) != DDI_SUCCESS) {
- dwarn("%s: am_detach: audio_dev_unregister() failed\n",
- statep->dstr);
- return (AUDIO_FAILURE);
- }
- statep->flags &= ~AF_REGISTERED;
-
- for (i = 0; i < ASHIM_ENG_MAX; i++)
- ashim_rem_eng(statep, &statep->engines[i]);
-
- if (statep->controls != NULL)
- ashim_rem_controls(statep);
-
- audio_dev_free(statep->af_devp);
- statep->af_devp = NULL;
-
- return (AUDIO_SUCCESS);
-}
-
-
-int
-am_attach(audiohdl_t handle, ddi_attach_cmd_t cmd,
- am_ad_info_t *ad_infop)
-{
- ashim_state_t *statep = AUDIO_HDL2SHIMST(handle);
- audio_dev_t *af_devp;
- int ad_feat = ad_infop->ad_defaults->hw_features;
- int rv = AUDIO_FAILURE;
-
- if (cmd != DDI_ATTACH)
- return (AUDIO_FAILURE);
-
- af_devp = audio_dev_alloc(statep->dip, 0);
- audio_dev_set_description(af_devp, ad_infop->ad_dev_info->name);
- audio_dev_set_version(af_devp, ad_infop->ad_dev_info->version);
-
- statep->af_devp = af_devp;
- statep->ad_infop = ad_infop;
-
-
- /*
- * If the device supports both play and record we require duplex
- * functionality. However, there are no known simplex SADA devices.
- * In this case we limit the device to play only.
- */
- if ((ad_feat & AUDIO_HWFEATURE_PLAY) &&
- (ad_feat & AUDIO_HWFEATURE_RECORD) &&
- !(ad_feat & AUDIO_HWFEATURE_DUPLEX)) {
- audio_dev_warn(af_devp, "missing duplex feature "
- "required for record");
-
- ad_feat &= ~AUDIO_HWFEATURE_RECORD;
- ad_infop->ad_defaults->hw_features = ad_feat;
- }
-
- if (ad_feat & AUDIO_HWFEATURE_PLAY) {
- if (ashim_add_eng(statep, AUDIO_PLAY) != AUDIO_SUCCESS)
- goto OUT;
- }
- if (ad_feat & AUDIO_HWFEATURE_RECORD) {
- if (ashim_add_eng(statep, AUDIO_RECORD) != AUDIO_SUCCESS)
- goto OUT;
- }
-
- if (ashim_add_controls(statep) != AUDIO_SUCCESS)
- goto OUT;
-
- if (ashim_ctrl_set_defaults(statep) != AUDIO_SUCCESS)
- goto OUT;
-
- if (audio_dev_register(af_devp) != DDI_SUCCESS) {
- audio_dev_warn(af_devp, "audio_dev_register() failed");
- goto OUT;
- }
- statep->flags |= AF_REGISTERED;
-
- rv = AUDIO_SUCCESS;
-
-OUT:
- if (rv != AUDIO_SUCCESS)
- (void) am_detach(handle, DDI_DETACH);
- return (rv);
-}
-
-
-int
-am_get_audio(audiohdl_t handle, void *buf, int samples)
-{
- ashim_state_t *statep = AUDIO_HDL2SHIMST(handle);
- ashim_eng_t *engp = ASHIM_GET_ENG(statep, ASHIM_ENG_PLAY);
- unsigned reqframes = samples >> engp->frsmshift;
- unsigned frames;
- unsigned i;
- size_t sz;
- int bufcnt = 0;
- caddr_t bp = buf;
-
- mutex_enter(&engp->lock);
- if (ashim_dump_counters_len)
- ashim_dump_counters(engp, reqframes, -1);
-
- if (!(engp->flags & ENG_STARTED)) {
- ddtl("%s - am_get_audio: stop in progress, ignoring\n",
- statep->dstr);
- mutex_exit(&engp->lock);
- return (0);
- }
- mutex_exit(&engp->lock);
-
- /* break requests from the driver into fragment sized chunks */
- for (i = 0; i < reqframes; i += frames) {
- mutex_enter(&engp->lock);
-
- frames = reqframes - i;
- if (frames > engp->fragfr)
- frames = engp->fragfr;
-
- sz = (frames << engp->frsmshift) << engp->smszshift;
-
- if (ashim_dump_counters_len) {
- ashim_dump_counters(engp, frames, bufcnt);
- }
- bufcnt++;
-
- /* must move data before updating framework */
- ashim_eng_bufio(engp, bp, sz);
- engp->frames += frames;
- bp += sz;
-
- mutex_exit(&engp->lock);
- audio_engine_consume(engp->af_engp);
- }
-
- mutex_enter(&engp->lock);
- engp->io_count++;
- mutex_exit(&engp->lock);
-
- return (samples);
-}
-
-
-void
-am_play_shutdown(audiohdl_t handle)
-{
-
- ashim_state_t *statep = AUDIO_HDL2SHIMST(handle);
- am_ad_entry_t *ad_entry = statep->ad_infop->ad_entry;
-
- ad_entry->ad_stop_play(handle);
-
- /*
- * XXX
- * used to notify framework that device's engine has stopped
- */
-}
-
-
-void
-am_send_audio(audiohdl_t handle, void *buf, int samples)
-{
- ashim_state_t *statep = AUDIO_HDL2SHIMST(handle);
- ashim_eng_t *engp = ASHIM_GET_ENG(statep, ASHIM_ENG_REC);
- unsigned reqframes = samples >> engp->frsmshift;
- unsigned frames;
- unsigned i;
- size_t sz;
- int bufcnt = 0;
- caddr_t bp = buf;
-
- mutex_enter(&engp->lock);
- if (ashim_dump_counters_len)
- ashim_dump_counters(engp, reqframes, -1);
-
- if (!(engp->flags & ENG_STARTED)) {
- ddtl("%s - am_send_audio: stop in progress, ignoring\n",
- statep->dstr);
-
- mutex_exit(&engp->lock);
- return;
- }
- mutex_exit(&engp->lock);
-
- /* break requests from the driver into fragment sized chunks */
- for (i = 0; i < reqframes; i += frames) {
- mutex_enter(&engp->lock);
-
- frames = reqframes - i;
- if (frames > engp->fragfr)
- frames = engp->fragfr;
-
- sz = (frames << engp->frsmshift) << engp->smszshift;
-
- if (ashim_dump_counters_len)
- ashim_dump_counters(engp, frames, bufcnt);
- bufcnt++;
-
- /* must move data before updating framework */
- ashim_eng_bufio(engp, bp, sz);
- engp->frames += frames;
- bp += sz;
-
- mutex_exit(&engp->lock);
- audio_engine_produce(engp->af_engp);
- }
-
- mutex_enter(&engp->lock);
- engp->io_count++;
- mutex_exit(&engp->lock);
-}
-
-void
-audio_sup_restore_state(audiohdl_t handle)
-{
- ashim_state_t *statep = AUDIO_HDL2SHIMST(handle);
- ashim_eng_t *engp;
- int i;
- int start = 0;
-
- (void) ashim_ctrl_restore(statep);
-
- for (i = 0; i < ASHIM_ENG_MAX; i++) {
- engp = &statep->engines[i];
- if (engp->af_engp == NULL)
- continue;
- start = (engp->flags & ENG_STARTED);
-
- if (start)
- (void) ashim_eng_start(engp);
- }
-}
-
-
-/*
- * **************************************************************************
- * audio framework engine callbacks
- */
-
-/*ARGSUSED*/
-static int
-ashim_af_open(void *arg, int flag,
- unsigned *fragfrp, unsigned *nfragsp, caddr_t *bufp)
-{
- ashim_eng_t *engp = (ashim_eng_t *)arg;
- ashim_state_t *statep = engp->statep;
- int rv = EIO;
- int dir = ASHIM_ENG_DIR(engp);
-
-
- if (usb_ac_open(statep->dip) != AUDIO_SUCCESS) {
- audio_dev_warn(statep->af_devp, "usb_ac_open failed");
- return (EIO);
- }
-
- mutex_enter(&engp->lock);
-
-
- engp->intrate = (engp->af_eflags & ENGINE_OUTPUT_CAP) ?
- statep->ad_infop->ad_play.ad_int_rate :
- statep->ad_infop->ad_record.ad_int_rate;
-
- engp->sampsz = engp->fmt.prec / 8;
- engp->framesz = engp->sampsz * engp->fmt.ch;
-
- if (engp->fmt.ch > 2) {
- audio_dev_warn(statep->af_devp, "unsupported ",
- "channel count: %u", engp->fmt.ch);
- goto OUT;
- }
- if (engp->fmt.prec > 16) {
- audio_dev_warn(statep->af_devp, "unsupported ",
- "precision: %u", engp->fmt.prec);
- goto OUT;
- }
-
- engp->frsmshift = engp->fmt.ch / 2;
- engp->smszshift = engp->sampsz / 2;
-
- /*
- * In order to match the requested number of samples per interrupt
- * from SADA drivers when computing the fragment size,
- * we need to first truncate the floating point result from
- * sample rate * channels / intr rate
- * then adjust up to an even number, before multiplying it
- * with the sample size
- */
- engp->fragsz = engp->fmt.sr * engp->fmt.ch / engp->intrate;
- if (engp->fragsz & 1)
- engp->fragsz++;
- engp->fragsz *= engp->sampsz;
- engp->fragfr = engp->fragsz / engp->framesz;
-
- if (ashim_use_drvbuf) {
- engp->bufsz = ((engp)->af_eflags & ENGINE_OUTPUT_CAP) ?
- statep->ad_infop->ad_play.ad_bsize :
- statep->ad_infop->ad_record.ad_bsize;
-
- engp->nfrags = engp->bufsz / engp->fragsz;
-
- /* adjust buf size to frag boundary */
- if (engp->nfrags * engp->fragsz < engp->bufsz)
- engp->nfrags++;
-
- engp->bufsz = engp->nfrags * engp->fragsz;
- } else {
- if (ashim_bufscale < ASHIM_BUFSCALE_MIN ||
- ashim_bufscale > ASHIM_BUFSCALE_MAX)
- engp->nfrags = ASHIM_BUFSCALE_DEF;
- else
- engp->nfrags = ashim_bufscale;
- engp->bufsz = engp->fragsz * engp->nfrags;
- }
-
- engp->bufp = kmem_zalloc(engp->bufsz, KM_SLEEP);
- engp->bufpos = engp->bufp;
- engp->bufendp = engp->bufp + engp->bufsz;
- engp->frames = 0;
- engp->io_count = 0;
- engp->bufio_count = 0;
-
- *fragfrp = engp->fragfr;
- *nfragsp = engp->nfrags;
- *bufp = engp->bufp;
-
- if (ashim_ad_setup(statep, dir) != AUDIO_SUCCESS) {
- audio_dev_warn(statep->af_devp, "device setup failed");
- goto OUT;
- }
- statep->flags |= AD_SETUP;
-
- rv = 0;
-
- dinfo("%s - %s: "
- "frames per frag: %u, frags in buffer: %u, frag size: %u, "
- "intr rate: %u, buffer size: %u, buffer: 0x%p - 0x%p\n",
- statep->dstr, engp->name,
- *fragfrp, *nfragsp, engp->fragsz,
- engp->intrate, engp->bufsz, *bufp, engp->bufendp);
-
-OUT:
- mutex_exit(&engp->lock);
- if (rv != 0)
- ashim_af_close(arg);
-
- return (rv);
-}
-
-
-static void
-ashim_af_close(void *arg)
-{
- ashim_eng_t *engp = (ashim_eng_t *)arg;
- ashim_state_t *statep = engp->statep;
-
- mutex_enter(&engp->lock);
-
- if (statep->flags & AD_SETUP) {
- ashim_ad_teardown(statep, ASHIM_ENG_DIR(engp));
- statep->flags &= ~AD_SETUP;
- }
-
- if (engp->bufp != NULL) {
- kmem_free(engp->bufp, engp->bufsz);
- engp->bufp = NULL;
- engp->bufpos = NULL;
- engp->bufendp = NULL;
- }
-
- ashim_prtstats(engp);
- mutex_exit(&engp->lock);
-
- usb_ac_close(statep->dip);
-}
-
-
-static int
-ashim_eng_start(ashim_eng_t *engp)
-{
- ashim_state_t *statep = engp->statep;
- am_ad_entry_t *ad_entry = statep->ad_infop->ad_entry;
- int (*start)(audiohdl_t);
- int rv = 0;
-
- start = ((engp)->af_eflags & ENGINE_OUTPUT_CAP) ?
- ad_entry->ad_start_play : ad_entry->ad_start_record;
-
- dinfo("%s: starting device %s engine\n", statep->dstr, engp->name);
-
- if ((*start)(AUDIO_SHIMST2HDL(statep)) != AUDIO_SUCCESS) {
- audio_dev_warn(statep->af_devp, "failed to start %s engine",
- engp->name);
- rv = EIO;
- }
-
- return (rv);
-}
-
-
-static void
-ashim_eng_stop(ashim_eng_t *engp)
-{
- ashim_state_t *statep = engp->statep;
- am_ad_entry_t *ad_entry = statep->ad_infop->ad_entry;
- void (*stop)(audiohdl_t);
-
- stop = ((engp)->af_eflags & ENGINE_OUTPUT_CAP) ?
- ad_entry->ad_stop_play : ad_entry->ad_stop_record;
-
- dinfo("%s: stopping device %s engine\n", statep->dstr, engp->name);
-
- (*stop)(AUDIO_SHIMST2HDL(statep));
-}
-
-
-static int
-ashim_af_start(void *arg)
-{
- ashim_eng_t *engp = (ashim_eng_t *)arg;
- int rv = EIO;
-
- if (ashim_eng_disable)
- return (rv);
-
- mutex_enter(&engp->lock);
- engp->flags |= ENG_STARTED;
- mutex_exit(&engp->lock);
-
- rv = ashim_eng_start(engp);
-
- return (rv);
-}
-
-
-static void
-ashim_af_stop(void *arg)
-{
- ashim_eng_t *engp = (ashim_eng_t *)arg;
-
- mutex_enter(&engp->lock);
- engp->flags &= ~ENG_STARTED;
- mutex_exit(&engp->lock);
-
- ashim_eng_stop(engp);
-}
-
-
-static uint64_t
-ashim_af_count(void *arg)
-{
- ashim_eng_t *engp = arg;
- uint64_t val;
-
- mutex_enter(&engp->lock);
- val = engp->frames;
- mutex_exit(&engp->lock);
-
- return (val);
-}
-
-
-static int
-ashim_af_format(void *arg)
-{
- ashim_eng_t *engp = arg;
-
- return (engp->af_fmt);
-}
-
-static int
-ashim_af_channels(void *arg)
-{
- ashim_eng_t *engp = arg;
-
- return (engp->fmt.ch);
-}
-
-
-static int
-ashim_af_rate(void *arg)
-{
- ashim_eng_t *engp = arg;
-
- return (engp->fmt.sr);
-}
-
-
-/*ARGSUSED*/
-static void
-ashim_af_sync(void *arg, unsigned nframes)
-{
- /*
- * drivers will call ddi_dma_sync() themselves after requesting data
- * on playback and before sending data on record through the shim
- */
-}
-
-
-static size_t
-ashim_af_qlen(void *arg)
-{
- ashim_eng_t *engp = (ashim_eng_t *)arg;
-
- return (engp->fragfr);
-}
-
-
-/*
- * **************************************************************************
- * interfaces used by USB audio
- */
-
-/*ARGSUSED*/
-int
-am_hw_state_change(audiohdl_t handle, int cmd, int dir, int value,
- int sleep)
-{
- ashim_state_t *statep = AUDIO_HDL2SHIMST(handle);
- ashim_ctrl_t *ctrlp;
- uint64_t cval = 0;
- int64_t left, right, delta = 0;
- int dcmd = AM_SET_GAIN;
-
- /* only known HWSC command used */
- if (cmd != AM_HWSC_SET_GAIN_DELTA) {
- audio_dev_warn(statep->af_devp, "invalid HW state change "
- "command recieved");
- return (AUDIO_FAILURE);
- }
-
- ctrlp = ashim_find_ctrl_dcmd(statep, dcmd, dir);
- if (ctrlp == NULL) {
- audio_dev_warn(statep->af_devp, "driver control command %d "
- "not found for HW state change command %d", dcmd, cmd);
- return (AUDIO_FAILURE);
- }
- ASSERT(value != 0);
-
- mutex_enter(&ctrlp->lock);
-
- delta = D2F_GAIN(value);
-
- /*
- * Value got from device can be scaled to 0,
- * set the delta to -1 or 1.
- */
- if (delta == 0) {
- delta = (value < 0)?-1:1;
- }
- left = AUDIO_CTRL_STEREO_LEFT(ctrlp->cval) + delta;
- right = AUDIO_CTRL_STEREO_RIGHT(ctrlp->cval) + delta;
-
- if (left > AF_MAX_GAIN)
- left = AF_MAX_GAIN;
- if (right > AF_MAX_GAIN)
- right = AF_MAX_GAIN;
-
- if (left < AF_MIN_GAIN)
- left = AF_MIN_GAIN;
- if (right < AF_MIN_GAIN)
- right = AF_MIN_GAIN;
-
- cval = AUDIO_CTRL_STEREO_VAL(left, right);
- mutex_exit(&ctrlp->lock);
-
- if (audio_control_write(ctrlp->af_ctrlp, cval)) {
- audio_dev_warn(statep->af_devp, "updating "
- "control %s to value 0x%llx by driver failed",
- ctrlp->acd.acd_name, (long long unsigned)cval);
- return (AUDIO_FAILURE);
- }
- return (AUDIO_SUCCESS);
-}
diff --git a/usr/src/uts/common/io/usb/clients/audio/usb_ac/audio_shim.h b/usr/src/uts/common/io/usb/clients/audio/usb_ac/audio_shim.h
deleted file mode 100644
index 6f73d61091..0000000000
--- a/usr/src/uts/common/io/usb/clients/audio/usb_ac/audio_shim.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-
-#ifndef _AUDIO_SHIM_H
-#define _AUDIO_SHIM_H
-
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/audio.h>
-#include <sys/audio/audio_support.h>
-#include <sys/mixer.h>
-#include <sys/audio/audio_mixer.h>
-
-#include <sys/audio/audio_driver.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-typedef enum {DBG_WARN = 1, DBG_INFO, DBG_DETAIL} debug_level_t;
-
-int am_unregister(audiohdl_t handle);
-
-#define CTRL_MUTED 0x1 /* muted output gain */
-
-#define TQ_NM_MAX 64
-#define DSTR_MAX 64
-
-typedef struct ashim_config_arg ashim_config_arg_t;
-typedef struct ashim_ctrl ashim_ctrl_t;
-typedef struct ashim_fmt ashim_fmt_t;
-typedef struct ashim_eng ashim_eng_t;
-typedef struct ashim_state ashim_state_t;
-
-struct ashim_config_arg {
- int cmd;
- int dir;
- int arg1;
- int arg2;
-};
-
-struct ashim_ctrl {
- int dcmd; /* SADA command */
- int dir; /* play or record */
- audio_ctrl_desc_t acd; /* description */
- audio_ctrl_t *af_ctrlp; /* framework handle */
- uint64_t cval; /* current control value */
- uint64_t defval; /* default control value */
- audio_ctrl_wr_t af_wr; /* write callback */
-
- int flags; /* CTRL_XXX flags */
- kmutex_t lock;
-
- ashim_state_t *statep;
- ashim_ctrl_t *nextp;
-};
-
-struct ashim_fmt {
- int sr; /* sample rate */
- uint_t ch; /* channels */
- uint_t prec; /* precision */
- uint_t enc; /* encoding */
-};
-
-struct ashim_eng {
- ashim_state_t *statep;
- audio_engine_t *af_engp;
- int af_eflags; /* ENGINE_* flags */
- int af_fmt; /* AUDIO_FORMAT_* flags */
- ashim_fmt_t fmt;
-
- unsigned intrate; /* interrupt rate */
- unsigned sampsz; /* sample size */
- unsigned framesz; /* frame size */
- unsigned fragsz; /* fragment size */
- unsigned nfrags; /* number of fragments in buffer */
- unsigned fragfr; /* number of frames per fragment */
- unsigned frsmshift; /* right shift: frames in sample cnt */
- unsigned smszshift; /* left shift: sample cnt * sampsz */
-
- caddr_t bufp; /* I/O buf; framework to/from drv */
- unsigned bufsz; /* buffer size */
- caddr_t bufpos; /* buffer position */
- caddr_t bufendp; /* end of buffer */
-
- audio_prinfo_t *prinfop; /* SADA ad_defaults play/record */
-
- uint64_t frames; /* total frames processed since open */
- uint64_t io_count; /* i/o requests from the driver */
- uint64_t bufio_count; /* i/o requests to the framework */
- char *name;
-
-#define ENG_STARTED 0x1
-#define ENG_ENABLED 0x10
- int flags;
-
- kmutex_t lock;
-};
-
-struct ashim_state {
- dev_info_t *dip;
- void *private; /* private audio driver data */
- audio_dev_t *af_devp;
- am_ad_info_t *ad_infop;
-
-#define ASHIM_ENG_MAX 2
- ashim_eng_t engines[ASHIM_ENG_MAX];
-
- ashim_ctrl_t *controls;
-
- char *devnm;
- char dstr[DSTR_MAX];
-
-#define AF_REGISTERED 0x1
-#define AD_SETUP 0x10
- int flags;
-};
-
-/*
- * Macros used to convert between audio handles and the shim state structure.
- */
-#define AUDIO_HDL2SHIMST(hdl) ((ashim_state_t *)(hdl))
-#define AUDIO_SHIMST2HDL(statep) ((audiohdl_t)(statep))
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _AUDIO_SHIM_H */
diff --git a/usr/src/uts/common/io/usb/clients/audio/usb_ac/usb_ac.c b/usr/src/uts/common/io/usb/clients/audio/usb_ac/usb_ac.c
index 05b29cffb9..be6d8d1b28 100644
--- a/usr/src/uts/common/io/usb/clients/audio/usb_ac/usb_ac.c
+++ b/usr/src/uts/common/io/usb/clients/audio/usb_ac/usb_ac.c
@@ -25,12 +25,6 @@
/*
* AUDIO CONTROL Driver:
- * This driver is derived from the legacy SADA streams-based usb_ac driver
- * and serves as an intermediate measure before the full conversion to the
- * to the Boomer framework in a follow-on phase of the Boomer project, which
- * will utilize more comprehensive USB audio features as well. Multiplexor
- * plumbing functionality that used to be in the usb_ac_dacf DACF module is
- * now located here.
*
* usb_ac is a multiplexor that sits on top of usb_as and hid and is
* responsible for (1) providing the entry points to audio mixer framework,
@@ -65,19 +59,14 @@
*/
#include <sys/usb/usba/usbai_version.h>
#include <sys/usb/usba.h>
-#include <sys/stropts.h>
#include <sys/sunndi.h>
-#include <sys/ndi_impldefs.h>
#include <sys/strsubr.h>
#include <sys/strsun.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/sunldi.h>
-#include <sys/audio.h>
-#include <sys/audio/audio_support.h>
-#include <sys/mixer.h>
-#include <sys/audio/audio_mixer.h>
+#include <sys/audio/audio_driver.h>
#include <sys/usb/clients/audio/usb_audio.h>
#include <sys/usb/clients/audio/usb_mixer.h>
@@ -87,7 +76,6 @@
#include <sys/usb/clients/hid/hidminor.h>
#include <sys/usb/clients/audio/usb_as/usb_as.h>
-#include "audio_shim.h"
/* debug support */
uint_t usb_ac_errlevel = USB_LOG_L4;
@@ -102,46 +90,68 @@ uint_t usb_ac_wait_hid = 1;
/*
* table for converting term types of input and output terminals
- * to SADA port types (pretty rough mapping)
+ * to OSS port types (pretty rough mapping)
*/
+static const char *usb_audio_dtypes[] = {
+ AUDIO_PORT_LINEIN,
+ AUDIO_PORT_LINEOUT,
+ AUDIO_PORT_SPEAKER,
+ AUDIO_PORT_HEADPHONES,
+ AUDIO_PORT_HANDSET,
+ AUDIO_PORT_CD,
+ AUDIO_PORT_MIC,
+ AUDIO_PORT_PHONE,
+ AUDIO_PORT_SPDIFIN,
+ AUDIO_PORT_OTHER,
+ NULL,
+};
+enum {
+ USB_PORT_LINEIN = 0,
+ USB_PORT_LINEOUT,
+ USB_PORT_SPEAKER,
+ USB_PORT_HEADPHONES,
+ USB_PORT_HANDSET,
+ USB_PORT_CD,
+ USB_PORT_MIC,
+ USB_PORT_PHONE,
+ USB_PORT_SPDIFIN,
+ USB_PORT_UNKNOWN
+};
+
static struct {
ushort_t term_type;
- ushort_t port_type;
+ uint_t port_type;
} usb_ac_term_type_map[] = {
-{ USB_AUDIO_TERM_TYPE_STREAMING, AUDIO_LINE_IN|AUDIO_LINE_OUT },
-{ USB_AUDIO_TERM_TYPE_MICROPHONE, AUDIO_MICROPHONE },
-{ USB_AUDIO_TERM_TYPE_DT_MICROPHONE, AUDIO_MICROPHONE },
-{ USB_AUDIO_TERM_TYPE_PERS_MICROPHONE, AUDIO_MICROPHONE },
-{ USB_AUDIO_TERM_TYPE_OMNI_DIR_MICROPHONE, AUDIO_MICROPHONE },
-{ USB_AUDIO_TERM_TYPE_MICROPHONE_ARRAY, AUDIO_MICROPHONE },
-{ USB_AUDIO_TERM_TYPE_PROCESSING_MIC_ARRAY, AUDIO_MICROPHONE },
-{ USB_AUDIO_TERM_TYPE_SPEAKER, AUDIO_SPEAKER },
-{ USB_AUDIO_TERM_TYPE_HEADPHONES, AUDIO_HEADPHONE },
-{ USB_AUDIO_TERM_TYPE_DISPLAY_AUDIO, AUDIO_LINE_OUT },
-{ USB_AUDIO_TERM_TYPE_DT_SPEAKER, AUDIO_SPEAKER },
-{ USB_AUDIO_TERM_TYPE_ROOM_SPEAKER, AUDIO_SPEAKER },
-{ USB_AUDIO_TERM_TYPE_COMM_SPEAKER, AUDIO_SPEAKER },
-{ USB_AUDIO_TERM_TYPE_LF_EFFECTS_SPEAKER, AUDIO_SPEAKER },
-{ USB_AUDIO_TERM_TYPE_HANDSET, AUDIO_LINE_IN|AUDIO_LINE_OUT },
-{ USB_AUDIO_TERM_TYPE_HEADSET, AUDIO_LINE_IN|AUDIO_LINE_OUT },
-{ USB_AUDIO_TERM_TYPE_SPEAKERPHONE, AUDIO_LINE_IN|AUDIO_LINE_OUT },
-{ USB_AUDIO_TERM_TYPE_ECHO_SUPP_SPEAKERPHONE,
- AUDIO_LINE_IN|AUDIO_LINE_OUT },
-{ USB_AUDIO_TERM_TYPE_ECHO_CANCEL_SPEAKERPHONE,
- AUDIO_LINE_IN|AUDIO_LINE_OUT },
-{ USB_AUDIO_TERM_TYPE_PHONE_LINE, AUDIO_LINE_IN|AUDIO_LINE_OUT },
-{ USB_AUDIO_TERM_TYPE_TELEPHONE, AUDIO_LINE_IN|AUDIO_LINE_OUT },
-{ USB_AUDIO_TERM_TYPE_DOWN_LINE_PHONE, AUDIO_LINE_IN|AUDIO_LINE_OUT },
-{ USB_AUDIO_TERM_TYPE_ANALOG_CONNECTOR, AUDIO_LINE_IN|AUDIO_LINE_OUT },
-{ USB_AUDIO_TERM_TYPE_DIGITAL_AUDIO_IF, AUDIO_LINE_IN|AUDIO_LINE_OUT },
-{ USB_AUDIO_TERM_TYPE_LINE_CONNECTOR, AUDIO_LINE_IN|AUDIO_LINE_OUT },
-{ USB_AUDIO_TERM_TYPE_LEGACY_AUDIO_CONNECTOR,
- AUDIO_LINE_IN|AUDIO_LINE_OUT },
-{ USB_AUDIO_TERM_TYPE_SPDIF_IF, AUDIO_SPDIF_IN },
-{ USB_AUDIO_TERM_TYPE_1394_DA_STREAM,
- AUDIO_LINE_IN|AUDIO_LINE_OUT },
-{ USB_AUDIO_TERM_TYPE_1394_DV_STREAM_SNDTRCK,
- AUDIO_LINE_IN|AUDIO_LINE_OUT },
+
+ /* Input Terminal Types */
+{ USB_AUDIO_TERM_TYPE_MICROPHONE, USB_PORT_MIC },
+{ USB_AUDIO_TERM_TYPE_DT_MICROPHONE, USB_PORT_MIC },
+{ USB_AUDIO_TERM_TYPE_PERS_MICROPHONE, USB_PORT_MIC },
+{ USB_AUDIO_TERM_TYPE_OMNI_DIR_MICROPHONE, USB_PORT_MIC },
+{ USB_AUDIO_TERM_TYPE_MICROPHONE_ARRAY, USB_PORT_MIC },
+{ USB_AUDIO_TERM_TYPE_PROCESSING_MIC_ARRAY, USB_PORT_MIC },
+
+ /* Output Terminal Types */
+{ USB_AUDIO_TERM_TYPE_SPEAKER, USB_PORT_SPEAKER },
+{ USB_AUDIO_TERM_TYPE_HEADPHONES, USB_PORT_HEADPHONES },
+{ USB_AUDIO_TERM_TYPE_DISPLAY_AUDIO, USB_PORT_LINEOUT },
+{ USB_AUDIO_TERM_TYPE_DT_SPEAKER, USB_PORT_SPEAKER },
+{ USB_AUDIO_TERM_TYPE_ROOM_SPEAKER, USB_PORT_SPEAKER },
+{ USB_AUDIO_TERM_TYPE_COMM_SPEAKER, USB_PORT_SPEAKER },
+{ USB_AUDIO_TERM_TYPE_LF_EFFECTS_SPEAKER, USB_PORT_SPEAKER },
+
+ /* Bi-directional Terminal Types */
+{ USB_AUDIO_TERM_TYPE_HANDSET, USB_PORT_HANDSET },
+
+ /* Telephony Terminal Types */
+{ USB_AUDIO_TERM_TYPE_PHONE_LINE, USB_PORT_PHONE},
+{ USB_AUDIO_TERM_TYPE_TELEPHONE, USB_PORT_PHONE},
+{ USB_AUDIO_TERM_TYPE_DOWN_LINE_PHONE, USB_PORT_PHONE },
+
+ /* External Terminal Types */
+{ USB_AUDIO_TERM_TYPE_SPDIF_IF, USB_PORT_SPDIFIN },
+ /* Embedded Function Terminal Types */
+{ USB_AUDIO_TERM_TYPE_CD_PLAYER, USB_PORT_CD },
{ 0, 0 }
};
@@ -153,9 +163,6 @@ static int usb_ac_attach(dev_info_t *, ddi_attach_cmd_t);
static int usb_ac_detach(dev_info_t *, ddi_detach_cmd_t);
static int usb_ac_power(dev_info_t *, int, int);
-/* plumbing */
-static usb_ac_plumbed_t *usb_ac_get_plumb_info(usb_ac_state_t *, char *,
- uchar_t);
static uint_t usb_ac_get_featureID(usb_ac_state_t *, uchar_t, uint_t,
uint_t);
@@ -163,10 +170,6 @@ static uint_t usb_ac_get_featureID(usb_ac_state_t *, uchar_t, uint_t,
int usb_ac_open(dev_info_t *);
void usb_ac_close(dev_info_t *);
-/* registration */
-static int usb_ac_get_curr_n_channels(usb_ac_state_t *, int);
-static usb_audio_formats_t *usb_ac_get_curr_format(usb_ac_state_t *, int);
-
/* descriptor handling */
static int usb_ac_handle_descriptors(usb_ac_state_t *);
static void usb_ac_add_unit_descriptor(usb_ac_state_t *, uchar_t *, size_t);
@@ -238,31 +241,24 @@ static int usb_ac_set_gain(usb_ac_state_t *, uint_t,
uint_t, uint_t, uint_t, uint_t, uint_t *);
static int usb_ac_set_monitor_gain(usb_ac_state_t *, uint_t,
uint_t, uint_t, uint_t, uint_t, uint_t *);
-static int usb_ac_set_mute(usb_ac_state_t *, uint_t, uint_t,
- uint_t, uint_t, uint_t, uint_t *);
static int usb_ac_set_volume(usb_ac_state_t *, uint_t, short, int dir,
int);
static int usb_ac_get_maxmin_volume(usb_ac_state_t *, uint_t, int, int,
int, short *);
-static int usb_ac_send_as_cmd(usb_ac_state_t *, usb_ac_plumbed_t *,
+static int usb_ac_send_as_cmd(usb_ac_state_t *, usb_audio_eng_t *,
int, void *);
-static int usb_ac_send_format_cmd(audiohdl_t, int, int, int, int, int);
-static int usb_ac_do_setup(audiohdl_t, int);
-static void usb_ac_do_teardown(audiohdl_t, int);
-static void usb_ac_do_stop_play(audiohdl_t);
-static void usb_ac_do_stop_record(audiohdl_t);
-
-/* Mixer entry points */
-static int usb_ac_setup(audiohdl_t, int);
-static void usb_ac_teardown(audiohdl_t, int);
-static int usb_ac_set_config(audiohdl_t, int, int, int, int);
-static int usb_ac_set_format(audiohdl_t, int, int, int, int, int);
-static int usb_ac_start_play(audiohdl_t);
-static void usb_ac_stop_play(audiohdl_t);
-static int usb_ac_start_record(audiohdl_t);
-static void usb_ac_stop_record(audiohdl_t);
+static int usb_ac_set_format(usb_ac_state_t *, usb_audio_eng_t *);
+static int usb_ac_do_setup(usb_ac_state_t *, usb_audio_eng_t *);
+
+/* usb audio basic function entries */
+static int usb_ac_setup(usb_ac_state_t *, usb_audio_eng_t *);
+static void usb_ac_teardown(usb_ac_state_t *, usb_audio_eng_t *);
+static int usb_ac_start_play(usb_ac_state_t *, usb_audio_eng_t *);
+static int usb_ac_start_record(usb_ac_state_t *, usb_audio_eng_t *);
+static void usb_ac_stop_record(usb_ac_state_t *, usb_audio_eng_t *);
static int usb_ac_restore_audio_state(usb_ac_state_t *, int);
+static int usb_ac_ctrl_restore(usb_ac_state_t *);
/*
* Mux
*/
@@ -270,7 +266,7 @@ static int usb_ac_mux_walk_siblings(usb_ac_state_t *);
static void usb_ac_print_reg_data(usb_ac_state_t *,
usb_as_registration_t *);
static int usb_ac_get_reg_data(usb_ac_state_t *, ldi_handle_t, int);
-static int usb_ac_setup_plumbed(usb_ac_state_t *, int, int, int);
+static int usb_ac_setup_plumbed(usb_ac_state_t *, int, int);
static int usb_ac_mixer_registration(usb_ac_state_t *);
static void usb_ac_hold_siblings(usb_ac_state_t *);
static int usb_ac_online_siblings(usb_ac_state_t *);
@@ -286,29 +282,13 @@ static int usb_ac_read_msg(usb_ac_plumbed_t *, mblk_t *);
static int usb_ac_do_plumbing(usb_ac_state_t *);
static int usb_ac_do_unplumbing(usb_ac_state_t *);
-/* just generic, USB Audio, 1.0 spec-compliant */
-static audio_device_t usb_dev_info =
- { {"USB Audio"}, {"1.0"}, {"external"} };
-
-/*
- * mixer registration data
- */
-static am_ad_entry_t usb_ac_entry = {
- usb_ac_setup, /* ad_setup() */
- usb_ac_teardown, /* ad_teardown() */
- usb_ac_set_config, /* ad_set_config() */
- usb_ac_set_format, /* ad_set_format() */
- usb_ac_start_play, /* ad_start_play() */
- usb_ac_stop_play, /* ad_stop_play() */
- usb_ac_start_record, /* ad_start_record() */
- usb_ac_stop_record, /* ad_stop_record() */
-};
+static int usb_change_phy_vol(usb_ac_state_t *, int);
+static void usb_restore_engine(usb_ac_state_t *);
/* anchor for soft state structures */
void *usb_ac_statep;
-
/*
* DDI Structures
*/
@@ -343,6 +323,39 @@ static struct modlinkage usb_ac_modlinkage = {
NULL /* NULL terminates the list */
};
+static int usb_audio_register(usb_ac_state_t *);
+static int usb_audio_unregister(usb_ac_state_t *);
+
+static int usb_engine_open(void *, int, unsigned *, unsigned *, caddr_t *);
+static void usb_engine_close(void *);
+static uint64_t usb_engine_count(void *);
+static int usb_engine_start(void *);
+static void usb_engine_stop(void *);
+static int usb_engine_format(void *);
+static int usb_engine_channels(void *);
+static int usb_engine_rate(void *);
+static void usb_engine_sync(void *, unsigned);
+static size_t usb_engine_qlen(void *);
+
+/* engine buffer size in terms of fragments */
+
+audio_engine_ops_t usb_engine_ops = {
+ AUDIO_ENGINE_VERSION,
+ usb_engine_open,
+ usb_engine_close,
+ usb_engine_start,
+ usb_engine_stop,
+ usb_engine_count,
+ usb_engine_format,
+ usb_engine_channels,
+ usb_engine_rate,
+ usb_engine_sync,
+ usb_engine_qlen,
+};
+
+
+
+_NOTE(SCHEME_PROTECTS_DATA("unique per call", mblk_t))
/* standard entry points */
int
@@ -366,7 +379,6 @@ _init(void)
return (rval);
}
-
int
_fini(void)
{
@@ -381,14 +393,12 @@ _fini(void)
return (rval);
}
-
int
_info(struct modinfo *modinfop)
{
return (mod_info(&usb_ac_modlinkage, modinfop));
}
-
extern uint_t nproc;
#define INIT_PROCESS_CNT 3
@@ -442,7 +452,6 @@ usb_ac_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
goto fail;
}
-
/* get log handle */
uacp->usb_ac_log_handle = usb_alloc_log_hdl(dip, "ac",
&usb_ac_errlevel,
@@ -483,18 +492,6 @@ usb_ac_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
uacp->usb_ac_default_ph = uacp->usb_ac_dev_data->dev_default_ph;
- uacp->usb_ac_audiohdl = audio_sup_register(dip);
-
- if (uacp->usb_ac_audiohdl == NULL) {
- USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
- "audio_sup_register failed");
-
- goto fail;
- }
-
- /* save softstate pointer in audio handle */
- audio_sup_set_private(uacp->usb_ac_audiohdl, (void *)uacp);
-
/* parse all class specific descriptors */
if (usb_ac_handle_descriptors(uacp) != USB_SUCCESS) {
@@ -590,27 +587,11 @@ usb_ac_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
mutex_exit(&uacp->usb_ac_mutex);
return (USB_FAILURE);
}
+ mutex_exit(&uacp->usb_ac_mutex);
- /*
- * call am_unregister() to stop calls into our driver from
- * the framework; can fail if the framework is still busy
- */
- if (uacp->usb_ac_audiohdl != NULL) {
- mutex_exit(&uacp->usb_ac_mutex);
+ (void) usb_audio_unregister(uacp);
- if (am_unregister(uacp->usb_ac_audiohdl) !=
- AUDIO_SUCCESS) {
- USB_DPRINTF_L2(PRINT_MASK_ATTA,
- uacp->usb_ac_log_handle,
- "usb_ac_detach: am_unregister failed, "
- "framework still busy");
- return (USB_FAILURE);
- }
- mutex_enter(&uacp->usb_ac_mutex);
- }
-
- mutex_exit(&uacp->usb_ac_mutex);
/*
* unplumb to stop activity from other modules, then
@@ -650,7 +631,6 @@ usb_ac_cleanup(dev_info_t *dip, usb_ac_state_t *uacp)
usb_ac_power_t *uacpm;
int rval = USB_FAILURE;
- ASSERT(uacp);
mutex_enter(&uacp->usb_ac_mutex);
uacpm = uacp->usb_ac_pm;
@@ -662,29 +642,7 @@ usb_ac_cleanup(dev_info_t *dip, usb_ac_state_t *uacp)
ASSERT(uacp->usb_ac_plumbing_state == USB_AC_STATE_UNPLUMBED);
- /*
- * deregister with audio framework, if it fails we are hosed
- * and we probably don't want to plumb again
- */
- if (uacp->usb_ac_audiohdl) {
- if (uacp->usb_ac_registered_with_mixer) {
- mutex_exit(&uacp->usb_ac_mutex);
- if (am_detach(uacp->usb_ac_audiohdl, DDI_DETACH) !=
- AUDIO_SUCCESS) {
-
- return (rval);
- }
- } else {
- mutex_exit(&uacp->usb_ac_mutex);
- }
- if (audio_sup_unregister(uacp->usb_ac_audiohdl) !=
- AUDIO_SUCCESS) {
-
- return (rval);
- }
- } else {
- mutex_exit(&uacp->usb_ac_mutex);
- }
+ mutex_exit(&uacp->usb_ac_mutex);
/*
* Disable the event callbacks, after this point, event
@@ -803,11 +761,7 @@ usb_ac_read_msg(usb_ac_plumbed_t *plumb_infop, mblk_t *mp)
char val1;
struct iocblk *iocp;
- USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_read_msg: mp=0x%p, instance=%d", (void *)mp,
- ddi_get_instance(uacp->usb_ac_dip));
- ASSERT(mp != NULL);
ASSERT(mutex_owned(&uacp->usb_ac_mutex));
/*
@@ -846,11 +800,8 @@ usb_ac_read_msg(usb_ac_plumbed_t *plumb_infop, mblk_t *mp)
if (uacp->usb_ac_plumbing_state ==
USB_AC_STATE_PLUMBED) {
mutex_exit(&uacp->usb_ac_mutex);
- (void) am_hw_state_change(
- uacp->usb_ac_audiohdl,
- AM_HWSC_SET_GAIN_DELTA,
- AUDIO_PLAY, val,
- AUDIO_NO_SLEEP);
+ (void) usb_change_phy_vol(
+ uacp, val);
mutex_enter(&uacp->
usb_ac_mutex);
}
@@ -880,8 +831,6 @@ usb_ac_read_msg(usb_ac_plumbed_t *plumb_infop, mblk_t *mp)
freemsg(mp);
}
- USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_read_msg: done");
return (error);
}
@@ -895,6 +844,7 @@ usb_ac_read_msg(usb_ac_plumbed_t *plumb_infop, mblk_t *mp)
static int
usb_ac_power(dev_info_t *dip, int comp, int level)
{
+ _NOTE(ARGUNUSED(comp));
int instance = ddi_get_instance(dip);
usb_ac_state_t *uacp;
usb_ac_power_t *uacpm;
@@ -902,9 +852,6 @@ usb_ac_power(dev_info_t *dip, int comp, int level)
uacp = ddi_get_soft_state(usb_ac_statep, instance);
- USB_DPRINTF_L4(PRINT_MASK_PM, uacp->usb_ac_log_handle,
- "usb_ac_power: comp=%d level=%d", comp, level);
-
mutex_enter(&uacp->usb_ac_mutex);
uacpm = uacp->usb_ac_pm;
@@ -1079,53 +1026,8 @@ usb_ac_create_pm_components(dev_info_t *dip, usb_ac_state_t *uacp)
"pm not enabled");
}
- USB_DPRINTF_L4(PRINT_MASK_PM, uacp->usb_ac_log_handle,
- "usb_ac_create_pm_components: end");
-}
-
-
-/*
- * usb_ac_get_plumb_info:
- * Get plumb_info pointer that matches module "name"
- * If name = "usb_as", match the direction also (record or play)
- */
-static usb_ac_plumbed_t *
-usb_ac_get_plumb_info(usb_ac_state_t *uacp, char *name, uchar_t reg_play_type)
-{
- int n;
- usb_ac_plumbed_t *plumb_infop = NULL;
- usb_as_registration_t *asreg;
- usb_ac_streams_info_t *asinfo;
-
- for (n = 0; n < USB_AC_MAX_PLUMBED; n++) {
- if (uacp->usb_ac_plumbed[n].acp_dip == NULL) {
- continue;
- }
- if (strcmp(ddi_driver_name(uacp->
- usb_ac_plumbed[n].acp_dip), name) != 0) {
- continue;
- }
- if (uacp->usb_ac_plumbed[n].acp_driver == USB_AS_PLUMBED) {
- asinfo = uacp->usb_ac_plumbed[n].acp_data;
- asreg = asinfo->acs_streams_reg;
- /* Match direction */
- if (asreg->reg_mode & reg_play_type) {
- break;
- }
- } else if (uacp->usb_ac_plumbed[n].acp_driver ==
- USB_AH_PLUMBED) {
- break;
- }
- }
-
- if (n < USB_AC_MAX_PLUMBED) {
- plumb_infop = &uacp->usb_ac_plumbed[n];
- }
-
- return (plumb_infop);
}
-
/*
* usb_ac_get_featureID:
* find out if there is at least one feature unit that supports
@@ -1158,9 +1060,6 @@ usb_ac_feature_unit_check(usb_ac_state_t *uacp, uint_t featureID,
usb_audio_feature_unit_descr1_t *feature_descrp;
int n_channel_controls;
- USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_feature_unit_check: ID=%d ch=%d cntrl=%d",
- featureID, channel, control);
ASSERT(featureID < uacp->usb_ac_max_unit);
@@ -1235,10 +1134,6 @@ usb_ac_handle_descriptors(usb_ac_state_t *uacp)
usb_alt_if_data_t *altif_data;
usb_cvs_data_t *cvs;
- USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
- "config=%ld, interface=%d",
- (long)(dev_data->dev_curr_cfg - &dev_data->dev_cfg[0]),
- dev_data->dev_curr_if);
altif_data = &dev_data->dev_curr_cfg->
cfg_if[dev_data->dev_curr_if].if_alt[0];
@@ -1259,7 +1154,8 @@ usb_ac_handle_descriptors(usb_ac_state_t *uacp)
if (index == altif_data->altif_n_cvs) {
USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
- "cannot find descriptor type %d", USB_AUDIO_CS_INTERFACE);
+ "usb_ac_handle_descriptors:cannot find descriptor type %d",
+ USB_AUDIO_CS_INTERFACE);
return (rval);
}
@@ -1280,8 +1176,9 @@ usb_ac_handle_descriptors(usb_ac_state_t *uacp)
}
USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
- "header: type=0x%x subtype=0x%x bcdADC=0x%x\n\t"
+ "index %d, header: type=0x%x subtype=0x%x bcdADC=0x%x\n\t"
"total=0x%x InCol=0x%x",
+ index,
descr.bDescriptorType,
descr.bDescriptorSubType,
descr.bcdADC,
@@ -1310,12 +1207,8 @@ usb_ac_handle_descriptors(usb_ac_state_t *uacp)
usb_ac_setup_connections(uacp);
/* determine port types */
- usb_ac_map_termtype_to_port(uacp, AUDIO_PLAY);
- usb_ac_map_termtype_to_port(uacp, AUDIO_RECORD);
-
- USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
- "input port types=0x%x output port types =0x%x",
- uacp->usb_ac_input_ports, uacp->usb_ac_output_ports);
+ usb_ac_map_termtype_to_port(uacp, USB_AUDIO_PLAY);
+ usb_ac_map_termtype_to_port(uacp, USB_AUDIO_RECORD);
return (rval);
@@ -1360,7 +1253,7 @@ usb_ac_setup_connections(usb_ac_state_t *uacp)
for (unit = 0; unit < uacp->usb_ac_max_unit; unit++) {
USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
- "traversing unit=0x%x type=0x%x",
+ "--------traversing unit=0x%x type=0x%x--------",
unit, units[unit].acu_type);
/* store type in the first unused column */
@@ -1374,8 +1267,8 @@ usb_ac_setup_connections(usb_ac_state_t *uacp)
units[unit].acu_descriptor;
USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
- "sourceID=0x%x type=0x%x", d->bSourceID,
- units[d->bSourceID].acu_type);
+ "USB_AUDIO_FEATURE_UNIT:sourceID=0x%x type=0x%x",
+ d->bSourceID, units[d->bSourceID].acu_type);
if (d->bSourceID != 0) {
ASSERT(p[unit][d->bSourceID] == B_FALSE);
@@ -1390,8 +1283,8 @@ usb_ac_setup_connections(usb_ac_state_t *uacp)
units[unit].acu_descriptor;
USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
- "sourceID=0x%x type=0x%x", d->bSourceID,
- units[d->bSourceID].acu_type);
+ "USB_AUDIO_OUTPUT_TERMINAL:sourceID=0x%x type=0x%x",
+ d->bSourceID, units[d->bSourceID].acu_type);
if (d->bSourceID != 0) {
ASSERT(p[unit][d->bSourceID] == B_FALSE);
@@ -1410,7 +1303,8 @@ usb_ac_setup_connections(usb_ac_state_t *uacp)
for (id = 0; id < n_sourceID; id++) {
USB_DPRINTF_L3(PRINT_MASK_ATTA,
uacp->usb_ac_log_handle,
- "sourceID=0x%x type=0x%x c=%d",
+ "USB_AUDIO_MIXER_UNIT:sourceID=0x%x"
+ "type=0x%x c=%d",
d->baSourceID[id],
units[d->baSourceID[id]].acu_type,
p[unit][d->baSourceID[id]]);
@@ -1434,8 +1328,8 @@ usb_ac_setup_connections(usb_ac_state_t *uacp)
for (id = 0; id < n_sourceID; id++) {
USB_DPRINTF_L3(PRINT_MASK_ATTA,
uacp->usb_ac_log_handle,
- "sourceID=0x%x type=0x%x",
- d->baSourceID[id],
+ "USB_AUDIO_SELECTOR_UNIT:sourceID=0x%x"
+ " type=0x%x", d->baSourceID[id],
units[d->baSourceID[id]].acu_type);
if (d->baSourceID[id] != 0) {
@@ -1457,8 +1351,8 @@ usb_ac_setup_connections(usb_ac_state_t *uacp)
for (id = 0; id < n_sourceID; id++) {
USB_DPRINTF_L3(PRINT_MASK_ATTA,
uacp->usb_ac_log_handle,
- "sourceID=0x%x type=0x%x",
- d->baSourceID[id],
+ "USB_AUDIO_PROCESSING_UNIT:sourceID=0x%x"
+ " type=0x%x", d->baSourceID[id],
units[d->baSourceID[id]].acu_type);
if (d->baSourceID[id] != 0) {
@@ -1480,8 +1374,8 @@ usb_ac_setup_connections(usb_ac_state_t *uacp)
for (id = 0; id < n_sourceID; id++) {
USB_DPRINTF_L3(PRINT_MASK_ATTA,
uacp->usb_ac_log_handle,
- "sourceID=0x%x type=0x%x",
- d->baSourceID[id],
+ "USB_AUDIO_EXTENSION_UNIT:sourceID=0x%x"
+ "type=0x%x", d->baSourceID[id],
units[d->baSourceID[id]].acu_type);
if (d->baSourceID[id] != 0) {
@@ -1579,9 +1473,6 @@ usb_ac_add_unit_descriptor(usb_ac_state_t *uacp, uchar_t *buffer,
char *format;
size_t size;
- USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
- "usb_ac_add_unit_descriptor: 0x%x 0x%x 0x%x",
- buffer[0], buffer[1], buffer[2]);
/* doubling the length should allow for padding */
len = 2 * buffer[0];
@@ -1649,9 +1540,11 @@ usb_ac_add_unit_descriptor(usb_ac_state_t *uacp, uchar_t *buffer,
USB_DPRINTF_L3(PRINT_MASK_ATTA,
uacp->usb_ac_log_handle,
- "input term: type=0x%x sub=0x%x termid=0x%x\n\t"
+ "usb_ac_units[%d] ---input term: type=0x%x sub=0x%x"
+ "termid=0x%x\n\t"
"termtype=0x%x assoc=0x%x #ch=%d "
"chconf=0x%x ich=0x%x iterm=0x%x",
+ d->bTerminalID,
d->bDescriptorType, d->bDescriptorSubType,
d->bTerminalID, d->wTerminalType,
d->bAssocTerminal, d->bNrChannels,
@@ -1672,8 +1565,10 @@ usb_ac_add_unit_descriptor(usb_ac_state_t *uacp, uchar_t *buffer,
USB_DPRINTF_L3(PRINT_MASK_ATTA,
uacp->usb_ac_log_handle,
- "output term: type=0x%x sub=0x%x termid=0x%x\n\t"
+ "usb_ac_units[%d] ---output term: type=0x%x sub=0x%x"
+ " termid=0x%x\n\t"
"termtype=0x%x assoc=0x%x sourceID=0x%x iterm=0x%x",
+ d->bTerminalID,
d->bDescriptorType, d->bDescriptorSubType,
d->bTerminalID, d->wTerminalType,
d->bAssocTerminal, d->bSourceID,
@@ -1693,8 +1588,10 @@ usb_ac_add_unit_descriptor(usb_ac_state_t *uacp, uchar_t *buffer,
USB_DPRINTF_L3(PRINT_MASK_ATTA,
uacp->usb_ac_log_handle,
- "mixer unit: type=0x%x sub=0x%x unitid=0x%x\n\t"
+ "usb_ac_units[%d] ---mixer unit: type=0x%x sub=0x%x"
+ " unitid=0x%x\n\t"
"#pins=0x%x sourceid[0]=0x%x",
+ d->bUnitID,
d->bDescriptorType, d->bDescriptorSubType,
d->bUnitID, d->bNrInPins, d->baSourceID[0]);
usb_ac_alloc_unit(uacp, d->bUnitID);
@@ -1711,8 +1608,10 @@ usb_ac_add_unit_descriptor(usb_ac_state_t *uacp, uchar_t *buffer,
USB_DPRINTF_L3(PRINT_MASK_ATTA,
uacp->usb_ac_log_handle,
- "selector unit: type=0x%x sub=0x%x unitid=0x%x\n\t"
+ "usb_ac_units[%d] ---selector unit: type=0x%x sub=0x%x"
+ " unitid=0x%x\n\t"
"#pins=0x%x sourceid[0]=0x%x",
+ d->bUnitID,
d->bDescriptorType, d->bDescriptorSubType,
d->bUnitID, d->bNrInPins, d->baSourceID[0]);
usb_ac_alloc_unit(uacp, d->bUnitID);
@@ -1729,8 +1628,10 @@ usb_ac_add_unit_descriptor(usb_ac_state_t *uacp, uchar_t *buffer,
USB_DPRINTF_L3(PRINT_MASK_ATTA,
uacp->usb_ac_log_handle,
- "feature unit: type=0x%x sub=0x%x unitid=0x%x\n\t"
+ "usb_ac_units[%d] ---feature unit: type=0x%x sub=0x%x"
+ " unitid=0x%x\n\t"
"sourceid=0x%x size=0x%x",
+ d->bUnitID,
d->bDescriptorType, d->bDescriptorSubType,
d->bUnitID, d->bSourceID, d->bControlSize);
@@ -1748,8 +1649,10 @@ usb_ac_add_unit_descriptor(usb_ac_state_t *uacp, uchar_t *buffer,
USB_DPRINTF_L3(PRINT_MASK_ATTA,
uacp->usb_ac_log_handle,
- "processing unit: type=0x%x sub=0x%x unitid=0x%x\n\t"
+ "usb_ac_units[%d] ---processing unit: type=0x%x sub=0x%x"
+ " unitid=0x%x\n\t"
"#pins=0x%x sourceid[0]=0x%x",
+ d->bUnitID,
d->bDescriptorType, d->bDescriptorSubType,
d->bUnitID, d->bNrInPins, d->baSourceID[0]);
usb_ac_alloc_unit(uacp, d->bUnitID);
@@ -1766,8 +1669,10 @@ usb_ac_add_unit_descriptor(usb_ac_state_t *uacp, uchar_t *buffer,
USB_DPRINTF_L3(PRINT_MASK_ATTA,
uacp->usb_ac_log_handle,
- "mixer unit: type=0x%x sub=0x%x unitid=0x%x\n\t"
+ "usb_ac_units[%d] ---mixer unit: type=0x%x sub=0x%x"
+ " unitid=0x%x\n\t"
"#pins=0x%x sourceid[0]=0x%x",
+ d->bUnitID,
d->bDescriptorType, d->bDescriptorSubType,
d->bUnitID, d->bNrInPins, d->baSourceID[0]);
usb_ac_alloc_unit(uacp, d->bUnitID);
@@ -1795,8 +1700,6 @@ usb_ac_alloc_unit(usb_ac_state_t *uacp, uint_t unit)
usb_ac_unit_list_t *old = NULL;
uint_t max_unit;
- USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
- "usb_ac_alloc_unit: unit=%d", unit);
if (uacp->usb_ac_units) {
if (unit < uacp->usb_ac_max_unit) {
@@ -1838,8 +1741,6 @@ usb_ac_free_all_units(usb_ac_state_t *uacp)
return;
}
- USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
- "usb_ac_alloc_unit: max_unit=%d", uacp->usb_ac_max_unit);
for (unit = 0; unit < uacp->usb_ac_max_unit; unit++) {
unitp = &uacp->usb_ac_units[unit];
@@ -1866,6 +1767,12 @@ usb_ac_lookup_port_type(ushort_t termtype)
{
uint_t i;
+ /*
+ * Looking for a input/ouput terminal type to match the port
+ * type, it should not be common streaming type
+ */
+ ASSERT(termtype != USB_AUDIO_TERM_TYPE_STREAMING);
+
for (i = 0; ; i++) {
if (usb_ac_term_type_map[i].term_type == 0) {
@@ -1878,7 +1785,7 @@ usb_ac_lookup_port_type(ushort_t termtype)
}
}
- return (AUDIO_LINE_IN|AUDIO_LINE_OUT);
+ return (USB_PORT_UNKNOWN);
}
@@ -1891,7 +1798,7 @@ static int
usb_ac_update_port(usb_ac_state_t *uacp, uint_t id,
uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth)
{
- if (dir & AUDIO_PLAY) {
+ if (dir & USB_AUDIO_PLAY) {
usb_audio_output_term_descr_t *d =
(usb_audio_output_term_descr_t *)
uacp->usb_ac_units[id].acu_descriptor;
@@ -1899,25 +1806,23 @@ usb_ac_update_port(usb_ac_state_t *uacp, uint_t id,
usb_ac_lookup_port_type(d->wTerminalType);
USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_update_port: dir=%d type=0x%x port type=%d",
- dir, d->wTerminalType, port_type);
+ "usb_ac_update_port: dir=%d wTerminalType=0x%x, name=%s",
+ dir, d->wTerminalType, usb_audio_dtypes[port_type]);
- uacp->usb_ac_output_ports |= port_type;
- uacp->usb_ac_output_ports &= ~AUDIO_LINE_IN;
+ uacp->usb_ac_output_ports |= (1U << port_type);
} else {
- usb_audio_output_term_descr_t *d =
- (usb_audio_output_term_descr_t *)
+ usb_audio_input_term_descr_t *d =
+ (usb_audio_input_term_descr_t *)
uacp->usb_ac_units[id].acu_descriptor;
uint_t port_type =
usb_ac_lookup_port_type(d->wTerminalType);
USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_update_port: dir=%d type=0x%x port type=%d",
- dir, d->wTerminalType, port_type);
+ "usb_ac_update_port: dir=%d wTerminalType=0x%x, name=%s",
+ dir, d->wTerminalType, usb_audio_dtypes[port_type]);
+
+ uacp->usb_ac_input_ports |= (1U << port_type);
- uacp->usb_ac_input_ports |=
- usb_ac_lookup_port_type(d->wTerminalType);
- uacp->usb_ac_input_ports &= ~AUDIO_LINE_OUT;
}
return (USB_SUCCESS);
@@ -1935,11 +1840,9 @@ usb_ac_map_termtype_to_port(usb_ac_state_t *uacp, uint_t dir)
{
uint_t count = 0;
uint_t depth = 0;
- uint_t search_type = (dir & AUDIO_PLAY) ?
+ uint_t search_type = (dir & USB_AUDIO_PLAY) ?
USB_AUDIO_OUTPUT_TERMINAL : USB_AUDIO_INPUT_TERMINAL;
- USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_map_term_to_port: dir=%d", dir);
(void) usb_ac_traverse_all_units(uacp, dir, search_type, 0,
0, USB_AC_FIND_ALL, &count, 0, &depth, usb_ac_update_port);
@@ -1960,11 +1863,9 @@ usb_ac_set_port(usb_ac_state_t *uacp, uint_t dir, uint_t port)
uint_t id;
uint_t depth = 0;
- USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_set_port: dir=%d port=%d", dir, port);
/* we only support the selector for the record side */
- if (dir & AUDIO_RECORD) {
+ if (dir & USB_AUDIO_RECORD) {
id = usb_ac_traverse_all_units(uacp, dir,
USB_AUDIO_SELECTOR_UNIT, 0,
0, USB_AC_FIND_ONE, &count, port, &depth,
@@ -1993,11 +1894,8 @@ usb_ac_match_port(usb_ac_state_t *uacp, uint_t id,
{
uint_t port_type;
- USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_match_port: id=%d dir=%d port=%d",
- id, dir, arg1);
- if (dir & AUDIO_PLAY) {
+ if (dir & USB_AUDIO_PLAY) {
usb_audio_output_term_descr_t *d =
(usb_audio_output_term_descr_t *)
uacp->usb_ac_units[id].acu_descriptor;
@@ -2019,7 +1917,7 @@ usb_ac_match_port(usb_ac_state_t *uacp, uint_t id,
dir, d->wTerminalType, port_type, arg1);
}
- return ((port_type & arg1) ? USB_SUCCESS : USB_FAILURE);
+ return (((1U << port_type) & arg1) ? USB_SUCCESS : USB_FAILURE);
}
@@ -2037,7 +1935,7 @@ usb_ac_set_selector(usb_ac_state_t *uacp, uint_t id,
uint_t unit = USB_AC_ID_NONE;
uint_t pin;
uint_t search_target =
- (dir & AUDIO_PLAY) ? USB_AUDIO_OUTPUT_TERMINAL :
+ (dir & USB_AUDIO_PLAY) ? USB_AUDIO_OUTPUT_TERMINAL :
USB_AUDIO_INPUT_TERMINAL;
usb_audio_selector_unit_descr1_t *d =
(usb_audio_selector_unit_descr1_t *)
@@ -2045,9 +1943,6 @@ usb_ac_set_selector(usb_ac_state_t *uacp, uint_t id,
int n_sourceID = d->bNrInPins;
int rval = USB_FAILURE;
- USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_set_selector: id=%d dir=%d port=%d",
- id, dir, arg1);
/*
* for each pin, find a term type that matches the
@@ -2098,7 +1993,14 @@ usb_ac_set_selector(usb_ac_state_t *uacp, uint_t id,
mutex_exit(&uacp->usb_ac_mutex);
- data = allocb_wait(1, BPRI_HI, STR_NOSIG, NULL);
+ data = allocb(1, BPRI_HI);
+ if (!data) {
+ USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
+ "usb_ac_set_selector: allocate data failed");
+ mutex_enter(&uacp->usb_ac_mutex);
+
+ return (USB_FAILURE);
+ }
/* pins are 1-based */
*(data->b_rptr) = (char)++pin;
@@ -2155,11 +2057,6 @@ usb_ac_set_control(usb_ac_state_t *uacp, uint_t dir, uint_t search_target,
uint_t id;
uint_t depth = 0;
- USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_set_control: dir=%d type=%d ch=%d cntl=%d",
- dir, search_target, channel, control);
-
-
id = usb_ac_traverse_all_units(uacp, dir, search_target, channel,
control, all_or_one, count, arg1, &depth, func);
@@ -2195,12 +2092,7 @@ usb_ac_traverse_all_units(usb_ac_state_t *uacp, uint_t dir,
{
uint_t unit, start_type, id;
- USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_traverse_all_units: "
- "dir=%d type=%d ch=%d cntl=%d all=%d depth=%d",
- dir, search_target, channel, control, all_or_one, *depth);
-
- start_type = (dir & AUDIO_PLAY) ? USB_AUDIO_INPUT_TERMINAL :
+ start_type = (dir & USB_AUDIO_PLAY) ? USB_AUDIO_INPUT_TERMINAL :
USB_AUDIO_OUTPUT_TERMINAL;
/* keep track of recursion */
@@ -2219,7 +2111,7 @@ usb_ac_traverse_all_units(usb_ac_state_t *uacp, uint_t dir,
}
/* start at streaming term types */
- if (dir & AUDIO_PLAY) {
+ if (dir & USB_AUDIO_PLAY) {
usb_audio_input_term_descr_t *d =
uacp->usb_ac_units[unit].acu_descriptor;
if (d->wTerminalType !=
@@ -2273,9 +2165,6 @@ usb_ac_set_monitor_gain_control(usb_ac_state_t *uacp, uint_t dir,
uint_t unit, id;
uint_t depth = 0;
- USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_set_monitor_gain_control: dir=%d type=%d ch=%d cntl=%d",
- dir, search_target, channel, control);
for (unit = 1; unit < uacp->usb_ac_max_unit; unit++) {
usb_audio_output_term_descr_t *d =
@@ -2312,23 +2201,16 @@ usb_ac_set_monitor_gain_control(usb_ac_state_t *uacp, uint_t dir,
static void
usb_ac_push_unit_id(usb_ac_state_t *uacp, uint_t unit)
{
- USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_push_unit_id: pushing %d at %d", unit,
- uacp->usb_ac_traverse_path_index);
-
uacp->usb_ac_traverse_path[uacp->usb_ac_traverse_path_index++] =
(uchar_t)unit;
ASSERT(uacp->usb_ac_traverse_path_index < uacp->usb_ac_max_unit);
}
+/* ARGSUSED */
static void
usb_ac_pop_unit_id(usb_ac_state_t *uacp, uint_t unit)
{
- USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_push_unit_id: popping %d at %d", unit,
- uacp->usb_ac_traverse_path_index);
-
uacp->usb_ac_traverse_path[uacp->usb_ac_traverse_path_index--] = 0;
}
@@ -2391,14 +2273,9 @@ usb_ac_traverse_connections(usb_ac_state_t *uacp, uint_t start_unit, uint_t dir,
uint_t channel, uint_t control, uint_t arg1, uint_t *depth))
{
uint_t unit, id;
- uint_t done = (dir & AUDIO_PLAY) ? USB_AUDIO_OUTPUT_TERMINAL :
+ uint_t done = (dir & USB_AUDIO_PLAY) ? USB_AUDIO_OUTPUT_TERMINAL :
USB_AUDIO_INPUT_TERMINAL;
- USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_traverse_connections: "
- "start=%d dir=%d type=%d ch=%d cntl=%d all=%d depth=%d",
- start_unit, dir, search_target, channel, control,
- all_or_one, *depth);
/* keep track of recursion depth */
if ((*depth)++ > USB_AC_MAX_DEPTH) {
@@ -2411,7 +2288,7 @@ usb_ac_traverse_connections(usb_ac_state_t *uacp, uint_t start_unit, uint_t dir,
usb_ac_push_unit_id(uacp, start_unit);
for (unit = 1; unit < uacp->usb_ac_max_unit; unit++) {
- uint_t entry = (dir & AUDIO_PLAY) ?
+ uint_t entry = (dir & USB_AUDIO_PLAY) ?
uacp->usb_ac_connections[unit][start_unit] :
uacp->usb_ac_connections[start_unit][unit];
@@ -2490,9 +2367,9 @@ usb_ac_disconnect_event_cb(dev_info_t *dip)
"usb_ac_disconnect_event_cb:start");
usb_ac_serialize_access(uacp);
+ mutex_enter(&uacp->usb_ac_mutex);
/* setting to disconnect state will prevent replumbing */
- mutex_enter(&uacp->usb_ac_mutex);
uacp->usb_ac_dev_state = USB_DEV_DISCONNECTED;
if (uacp->usb_ac_busy_count) {
@@ -2692,7 +2569,7 @@ usb_ac_am_restore_state(void *arg)
*/
delay(USB_AC_RESTORE_DELAY);
- audio_sup_restore_state(uacp->usb_ac_audiohdl);
+ usb_restore_engine(uacp);
mutex_enter(&uacp->usb_ac_mutex);
uacp->usb_ac_plumbing_state = USB_AC_STATE_PLUMBED;
@@ -2717,8 +2594,6 @@ usb_ac_restore_audio_state(usb_ac_state_t *uacp, int flag)
{
ASSERT(mutex_owned(&uacp->usb_ac_mutex));
- USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_restore_audio_state: flag=%d", flag);
switch (uacp->usb_ac_plumbing_state) {
case USB_AC_STATE_PLUMBED:
@@ -2775,35 +2650,28 @@ usb_ac_restore_audio_state(usb_ac_state_t *uacp, int flag)
* Check power is done in usb_ac_send_as_cmd()
*/
static int
-usb_ac_setup(audiohdl_t ahdl, int flag)
+usb_ac_setup(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
{
- int rval = AUDIO_SUCCESS;
- usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
+ int rval = USB_SUCCESS;
- ASSERT(uacp != NULL);
mutex_enter(&uacp->usb_ac_mutex);
if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
mutex_exit(&uacp->usb_ac_mutex);
- return (AUDIO_FAILURE);
+ return (USB_FAILURE);
}
mutex_exit(&uacp->usb_ac_mutex);
usb_ac_serialize_access(uacp);
- if (flag & AUDIO_PLAY) {
- rval = usb_ac_do_setup(ahdl, AUDIO_PLAY);
- }
- if ((rval == USB_SUCCESS) && (flag & AUDIO_RECORD)) {
- rval = usb_ac_do_setup(ahdl, AUDIO_RECORD);
- }
+ rval = usb_ac_do_setup(uacp, engine);
usb_ac_release_access(uacp);
- return ((rval == USB_SUCCESS) ? AUDIO_SUCCESS : AUDIO_FAILURE);
+ return (rval);
}
@@ -2813,23 +2681,15 @@ usb_ac_setup(audiohdl_t ahdl, int flag)
* either from audio framework for usb_ac_set_format
*/
static int
-usb_ac_do_setup(audiohdl_t ahdl, int flag)
+usb_ac_do_setup(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
{
- usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
- usb_ac_plumbed_t *plumb_infop = NULL;
usb_ac_streams_info_t *streams_infop = NULL;
- int dir;
- ASSERT(uacp != NULL);
mutex_enter(&uacp->usb_ac_mutex);
- dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD;
- plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", dir);
- ASSERT(plumb_infop != NULL);
- streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
- ASSERT(streams_infop != NULL);
+ streams_infop = (usb_ac_streams_info_t *)engine->streams;
/*
* Handle multiple setup calls. Pass the setup call to usb_as only
@@ -2846,7 +2706,7 @@ usb_ac_do_setup(audiohdl_t ahdl, int flag)
}
/* Send setup command to usb_as */
- if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_SETUP, 0) !=
+ if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_SETUP, 0) !=
USB_SUCCESS) {
USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
"usb_ac_do_setup: failure");
@@ -2871,48 +2731,20 @@ usb_ac_do_setup(audiohdl_t ahdl, int flag)
* NOTE: allow teardown when disconnected
*/
static void
-usb_ac_teardown(audiohdl_t ahdl, int flag)
+usb_ac_teardown(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
{
- usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
- ASSERT(uacp != NULL);
+ usb_ac_streams_info_t *streams_infop = NULL;
usb_ac_serialize_access(uacp);
- if (flag & AUDIO_PLAY) {
- usb_ac_do_teardown(ahdl, AUDIO_PLAY);
- }
-
- if (flag & AUDIO_RECORD) {
- usb_ac_do_teardown(ahdl, AUDIO_RECORD);
- }
- usb_ac_release_access(uacp);
-}
+ streams_infop = engine->streams;
-/*
- * usb_ac_do_teardown()
- * Check power is done in usb_ac_send_as_cmd()
- */
-static void
-usb_ac_do_teardown(audiohdl_t ahdl, int flag)
-{
- usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
- usb_ac_plumbed_t *plumb_infop = NULL;
- usb_ac_streams_info_t *streams_infop = NULL;
- int dir;
-
- ASSERT(uacp != NULL);
-
mutex_enter(&uacp->usb_ac_mutex);
- dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD;
- plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", dir);
- ASSERT(plumb_infop != NULL);
- streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
- ASSERT(streams_infop != NULL);
/* There should be at least one matching setup call */
ASSERT(streams_infop->acs_setup_teardown_count);
@@ -2924,210 +2756,32 @@ usb_ac_do_teardown(audiohdl_t ahdl, int flag)
*/
if (--(streams_infop->acs_setup_teardown_count)) {
USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_do_teardown: more than one setup/teardown, "
+ "usb_ac_teardown: more than one setup/teardown, "
"cnt=%d",
streams_infop->acs_setup_teardown_count);
- mutex_exit(&uacp->usb_ac_mutex);
-
- return;
+ goto done;
}
/* Send teardown command to usb_as */
- if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_TEARDOWN,
+ if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_TEARDOWN,
(void *)NULL) != USB_SUCCESS) {
USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_do_teardown: failure");
+ "usb_ac_teardown: failure");
streams_infop->acs_setup_teardown_count++;
- mutex_exit(&uacp->usb_ac_mutex);
- return;
+ goto done;
}
+done:
mutex_exit(&uacp->usb_ac_mutex);
USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_do_teardown: End");
-}
-
-
-/*
- * usb_ac_set_config:
- * This routine will send control commands to get the max
- * and min gain balance, calculate the gain to be set from the
- * arguments and send another control command to set it.
- * Check power is done here since we will access the default pipe
- */
-static int
-usb_ac_set_config(audiohdl_t ahdl, int command, int flag, int arg1, int arg2)
-{
- usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
- char *what;
- int rval = AUDIO_FAILURE;
- uint_t channel;
- uchar_t n_channels = 0;
- uint_t dir, count;
- short muteval;
-
- ASSERT(uacp != NULL);
-
- mutex_enter(&uacp->usb_ac_mutex);
-
- if (uacp->usb_ac_plumbing_state < USB_AC_STATE_PLUMBED) {
- mutex_exit(&uacp->usb_ac_mutex);
-
- return (AUDIO_FAILURE);
- }
-
- if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
- mutex_exit(&uacp->usb_ac_mutex);
-
- return (AUDIO_FAILURE);
- }
- mutex_exit(&uacp->usb_ac_mutex);
- usb_ac_serialize_access(uacp);
- mutex_enter(&uacp->usb_ac_mutex);
-
- switch (command) {
- case AM_SET_GAIN:
- /*
- * Set the gain for a channel. The audio mixer calculates the
- * impact, if any, on the channel's gain.
- *
- * 0 <= gain <= AUDIO_MAX_GAIN
- *
- * arg1 --> gain
- * arg2 --> channel #, 0 == left, 1 == right
- */
- what = "gain";
- channel = ++arg2;
- ASSERT(flag != AUDIO_BOTH);
- dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD;
-
- /*
- * We service the set_config command when the device is
- * plumbed and opened.
- */
- n_channels = usb_ac_get_curr_n_channels(uacp, dir);
-
- if (channel > n_channels) {
- USB_DPRINTF_L2(PRINT_MASK_ALL,
- uacp->usb_ac_log_handle,
- "usb_ac_set_config: channel(%d) passed is "
- " > n_channels(%d)", channel, n_channels);
-
- goto done;
- }
- count = 0;
- (void) usb_ac_set_control(uacp, dir,
- USB_AUDIO_FEATURE_UNIT, channel,
- USB_AUDIO_VOLUME_CONTROL,
- USB_AC_FIND_ALL, &count, arg1, usb_ac_set_gain);
-
- /*
- * If feature unit id could not be found, it probably means
- * volume/gain control is not available for this device.
- * and we just return success if we haven't completed
- * the registration with the mixer yet
- */
- if (count == 0) {
- USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "mixer=%d, no featureID, arg1=%d",
- uacp->usb_ac_registered_with_mixer, arg1);
- rval = (uacp->usb_ac_registered_with_mixer == 0) ?
- AUDIO_SUCCESS : AUDIO_FAILURE;
- } else {
- rval = AUDIO_SUCCESS;
- }
-
- break;
- case AM_SET_PORT:
- what = "port";
- ASSERT(flag != AUDIO_BOTH);
- dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD;
-
- rval = usb_ac_set_port(uacp, dir, arg1);
- rval = (rval == USB_SUCCESS) ? AUDIO_SUCCESS : AUDIO_FAILURE;
-
- break;
- case AM_SET_MONITOR_GAIN:
- what = "monitor gain";
- channel = ++arg2;
- dir = AUDIO_RECORD;
-
- /*
- * We service the set_config command when the device is
- * plumbed and opened.
- */
- n_channels = usb_ac_get_curr_n_channels(uacp, dir);
-
- if (channel > n_channels) {
- USB_DPRINTF_L2(PRINT_MASK_ALL,
- uacp->usb_ac_log_handle,
- "usb_ac_set_config: channel(%d) passed is "
- " > n_channels(%d)", channel, n_channels);
-
- goto done;
- }
- count = 0;
- (void) usb_ac_set_monitor_gain_control(uacp, dir,
- USB_AUDIO_INPUT_TERMINAL, channel,
- USB_AUDIO_VOLUME_CONTROL,
- USB_AC_FIND_ALL, &count, arg1,
- usb_ac_set_monitor_gain);
-
- /*
- * always return success since we told the mixer
- * we always support this and sdtaudiocontrol displays
- * monitor gain regardless.
- */
- rval = AUDIO_SUCCESS;
-
- break;
- case AM_OUTPUT_MUTE:
- what = "mute";
- ASSERT(flag != AUDIO_BOTH);
- dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD;
-
- /*
- * arg1 != 0 --> mute
- * arg1 == 0 --> unmute
- * arg2 --> not used
- */
- muteval = (arg1 == 0) ? USB_AUDIO_MUTE_OFF :
- USB_AUDIO_MUTE_ON;
- count = 0;
- (void) usb_ac_set_control(uacp, dir,
- USB_AUDIO_FEATURE_UNIT, 0,
- USB_AUDIO_MUTE_CONTROL,
- USB_AC_FIND_ALL, &count, muteval,
- usb_ac_set_mute);
-
- rval = (count == 0) ? AUDIO_FAILURE : AUDIO_SUCCESS;
-
- break;
- case AM_MIC_BOOST:
- what = "mic boost";
- rval = AUDIO_SUCCESS;
- break;
- default:
- what = "unknown";
- rval = AUDIO_FAILURE;
- }
-
-done:
- mutex_exit(&uacp->usb_ac_mutex);
-
- /* Now it's safe to release access to other routines */
+ "usb_ac_teardown: End");
usb_ac_release_access(uacp);
-
- USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_set_config: %s done, rval=%d", what, rval);
-
- return (rval);
}
@@ -3145,10 +2799,6 @@ usb_ac_set_monitor_gain(usb_ac_state_t *uacp, uint_t unit,
USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
"usb_ac_set_monitor_gain: ");
- USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "id=%d dir=%d ch=%d cntl=%d gain=%d type=%d term type=0x%x",
- unit, dir, channel, control, gain,
- uacp->usb_ac_unit_type[unit], d->wTerminalType);
/* log how we got here */
usb_ac_push_unit_id(uacp, unit);
@@ -3285,7 +2935,7 @@ usb_ac_set_gain(usb_ac_state_t *uacp, uint_t featureID,
if (gain == 0) {
gain = USB_AUDIO_VOLUME_SILENCE;
} else {
- gain = max - ((max - min) * (0x100 - gain))/0x100;
+ gain = max - ((max - min) * (AF_MAX_GAIN - gain))/AF_MAX_GAIN;
}
USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
@@ -3329,251 +2979,97 @@ usb_ac_set_gain(usb_ac_state_t *uacp, uint_t featureID,
* after a set_format command. (2) Check power is done in
* usb_ac_send_as_cmd().
*/
-static int
-usb_ac_set_format(audiohdl_t ahdl, int flag,
- int sample, int channels, int precision, int encoding)
+int
+usb_ac_set_format(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
{
- usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
- usb_audio_formats_t *format;
- usb_audio_formats_t old_format;
- usb_ac_plumbed_t *plumb_infop;
usb_ac_streams_info_t *streams_infop = NULL;
- int old_setup_teardown_count;
- int dir;
- int rval;
-
- ASSERT(uacp != NULL);
+ usb_audio_formats_t format;
+ int old_setup_teardown_count = 0;
mutex_enter(&uacp->usb_ac_mutex);
+ streams_infop = (usb_ac_streams_info_t *)engine->streams;
+
if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
mutex_exit(&uacp->usb_ac_mutex);
- return (AUDIO_FAILURE);
+ return (USB_FAILURE);
}
mutex_exit(&uacp->usb_ac_mutex);
usb_ac_serialize_access(uacp);
-
- ASSERT(flag != AUDIO_BOTH);
-
mutex_enter(&uacp->usb_ac_mutex);
- dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD;
- plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", dir);
- if (plumb_infop == NULL) {
- USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_set_format: no plumb info");
- mutex_exit(&uacp->usb_ac_mutex);
- usb_ac_release_access(uacp);
+ bzero(&format, sizeof (usb_audio_formats_t));
- return (AUDIO_FAILURE);
- }
+ /* save format info */
+ format.fmt_sr = (uint_t)engine->fmt.sr;
+ format.fmt_chns = (uchar_t)engine->fmt.ch;
+ format.fmt_precision = (uchar_t)engine->fmt.prec;
+ format.fmt_encoding = (uchar_t)engine->fmt.enc;
- streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
- ASSERT(streams_infop != NULL);
+ old_setup_teardown_count = streams_infop->acs_setup_teardown_count;
/* isoc pipe not open and playing is not in progress */
- if (streams_infop->acs_setup_teardown_count == 0) {
+ if (old_setup_teardown_count) {
+ streams_infop->acs_setup_teardown_count = 1;
mutex_exit(&uacp->usb_ac_mutex);
-
- rval = usb_ac_send_format_cmd(ahdl, dir, sample,
- channels, precision, encoding);
-
usb_ac_release_access(uacp);
- return ((rval == USB_SUCCESS) ?
- AUDIO_SUCCESS : AUDIO_FAILURE);
- }
-
- /* isoc pipe is open and playing might be in progress */
- format = &streams_infop->acs_ac_to_as_req.acr_curr_format;
-
- /* Keep a copy of the old format */
- bcopy((void *)format, (void *)&old_format,
- sizeof (usb_audio_formats_t));
-
- ASSERT(streams_infop->acs_setup_teardown_count != 0);
-
- old_setup_teardown_count = streams_infop->acs_setup_teardown_count;
- streams_infop->acs_setup_teardown_count = 1;
-
- mutex_exit(&uacp->usb_ac_mutex);
-
- if (dir == AUDIO_PLAY) {
- usb_ac_do_stop_play(ahdl);
- } else if (dir == AUDIO_RECORD) {
- usb_ac_do_stop_record(ahdl);
- }
-
- /* This blocks until the current isoc xfer is over */
- usb_ac_do_teardown(ahdl, dir);
-
- if (usb_ac_send_format_cmd(ahdl, dir, sample,
- channels, precision, encoding) != USB_SUCCESS) {
- /*
- * Setting new alternate has failed, try restoring
- * old one.
- * If there is a bandwidth failure, hang around
- * till bandwidth is available. Also we know that
- * there is a matching alternate, so that can't fail.
- */
- if (usb_ac_send_format_cmd(ahdl, dir,
- old_format.fmt_sr, old_format.fmt_chns,
- old_format.fmt_precision, old_format.fmt_encoding) ==
- USB_FAILURE) {
-
- /* We closed the pipe; reopen it */
- (void) usb_ac_do_setup(ahdl, dir);
-
- mutex_enter(&uacp->usb_ac_mutex);
- streams_infop->acs_setup_teardown_count =
- old_setup_teardown_count;
- mutex_exit(&uacp->usb_ac_mutex);
-
- usb_ac_release_access(uacp);
-
- return (AUDIO_FAILURE);
- }
- }
-
- /* This should block until successful */
- (void) usb_ac_do_setup(ahdl, dir);
-
- mutex_enter(&uacp->usb_ac_mutex);
- streams_infop->acs_setup_teardown_count = old_setup_teardown_count;
- mutex_exit(&uacp->usb_ac_mutex);
-
- usb_ac_release_access(uacp);
+ usb_ac_stop_play(uacp, engine);
+ usb_ac_teardown(uacp, engine);
- return (AUDIO_SUCCESS);
-}
-
-
-/*
- * usb_ac_get_curr_n_channels:
- * Return no. of channels from the current format table
- */
-static int
-usb_ac_get_curr_n_channels(usb_ac_state_t *uacp, int dir)
-{
- usb_audio_formats_t *cur_fmt = usb_ac_get_curr_format(uacp, dir);
-
- return (cur_fmt->fmt_chns);
-}
-
-
-/*
- * usb_ac_get_cur_format:
- * Get format for the current alternate
- */
-static usb_audio_formats_t *
-usb_ac_get_curr_format(usb_ac_state_t *uacp, int dir)
-{
- usb_ac_plumbed_t *plumb_infop;
- usb_ac_streams_info_t *streams_infop = NULL;
-
- ASSERT(mutex_owned(&uacp->usb_ac_mutex));
-
- plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", dir);
- if (plumb_infop == NULL) {
- USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_get_curr_format: no plumb info");
-
- return (NULL);
- }
-
- streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
- ASSERT(streams_infop != NULL);
-
- return (&streams_infop->acs_cur_fmt);
-}
-
-
-/*
- * usb_ac_send_format_cmd
- * Sets format and get alternate setting that matches with
- * the format from the usb_as playing or recording interface
- * Send the set sample freq command down to usb_as.
- */
-static int
-usb_ac_send_format_cmd(audiohdl_t ahdl, int dir,
- int sample, int channels, int precision, int encoding)
-{
- usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
- usb_audio_formats_t *format;
- usb_ac_plumbed_t *plumb_infop = NULL;
- usb_ac_streams_info_t *streams_infop = NULL;
-
- ASSERT(uacp != NULL);
-
- mutex_enter(&uacp->usb_ac_mutex);
- if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
- mutex_exit(&uacp->usb_ac_mutex);
-
- return (USB_FAILURE);
+ usb_ac_serialize_access(uacp);
+ mutex_enter(&uacp->usb_ac_mutex);
}
- plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", dir);
- ASSERT(plumb_infop);
-
- streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
- ASSERT(streams_infop != NULL);
-
- ASSERT(dir == AUDIO_PLAY || dir == AUDIO_RECORD);
- streams_infop->acs_ac_to_as_req.acr_curr_dir = dir;
-
- USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_send_format_cmd: plumb_infop=0x%p, streams_infop=0x%p",
- (void *)plumb_infop, (void *)streams_infop);
-
- format = &(streams_infop->acs_ac_to_as_req.acr_curr_format);
- bzero(format, sizeof (usb_audio_formats_t));
-
- /* save format info */
- format->fmt_sr = (uint_t)sample;
- format->fmt_chns = (uchar_t)channels;
- format->fmt_precision = (uchar_t)precision;
- format->fmt_encoding = (uchar_t)encoding;
-
- streams_infop->acs_cur_fmt = *format;
-
/*
* Set format for the streaming interface with lower write queue
* This boils down to set_alternate interface command in
* usb_as and the reply mp contains the currently active
* alternate number that is stored in the as_req structure
*/
- if (usb_ac_send_as_cmd(uacp, plumb_infop,
- USB_AUDIO_SET_FORMAT, format) != USB_SUCCESS) {
+ if (usb_ac_send_as_cmd(uacp, engine,
+ USB_AUDIO_SET_FORMAT, &format) != USB_SUCCESS) {
USB_DPRINTF_L2(PRINT_MASK_ALL,
uacp->usb_ac_log_handle,
- "usb_ac_send_format_cmd: failed");
- mutex_exit(&uacp->usb_ac_mutex);
+ "usb_ac_set_format: failed");
+ goto fail;
- return (USB_FAILURE);
- } else {
- /* store matching alternate number */
- streams_infop->acs_ac_to_as_req.acr_curr_format.fmt_alt =
- format->fmt_alt;
}
+ int sample = engine->fmt.sr;
/* Set the sample rate */
- if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_SET_SAMPLE_FREQ,
+ if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_SET_SAMPLE_FREQ,
&sample) != USB_SUCCESS) {
USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_send_format_cmd: setting format failed");
+ "usb_ac_set_format: setting format failed");
+ goto fail;
- mutex_exit(&uacp->usb_ac_mutex);
+ }
- return (USB_FAILURE);
+ mutex_exit(&uacp->usb_ac_mutex);
+
+ usb_ac_release_access(uacp);
+
+ /* This should block until successful */
+ if (old_setup_teardown_count) {
+ (void) usb_ac_setup(uacp, engine);
}
+ mutex_enter(&uacp->usb_ac_mutex);
+ streams_infop->acs_setup_teardown_count = old_setup_teardown_count;
mutex_exit(&uacp->usb_ac_mutex);
return (USB_SUCCESS);
-}
+fail:
+ streams_infop->acs_setup_teardown_count = old_setup_teardown_count;
+ mutex_exit(&uacp->usb_ac_mutex);
+ usb_ac_release_access(uacp);
+ return (USB_FAILURE);
+
+}
/*
* usb_ac_start_play
@@ -3581,22 +3077,17 @@ usb_ac_send_format_cmd(audiohdl_t ahdl, int dir,
* Check power is done in usb_ac_send_as_cmd()
*/
static int
-usb_ac_start_play(audiohdl_t ahdl)
+usb_ac_start_play(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
{
- usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
- usb_audio_formats_t *cur_fmt;
- usb_ac_plumbed_t *plumb_infop = NULL;
- int dir, samples;
+ int samples;
usb_audio_play_req_t play_req;
- usb_ac_streams_info_t *streams_infop = NULL;
- ASSERT(uacp != NULL);
mutex_enter(&uacp->usb_ac_mutex);
if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
mutex_exit(&uacp->usb_ac_mutex);
- return (AUDIO_FAILURE);
+ return (USB_FAILURE);
}
mutex_exit(&uacp->usb_ac_mutex);
@@ -3604,33 +3095,19 @@ usb_ac_start_play(audiohdl_t ahdl)
mutex_enter(&uacp->usb_ac_mutex);
- plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", AUDIO_PLAY);
- ASSERT(plumb_infop);
-
- streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
- ASSERT(streams_infop != NULL);
-
- USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_start_play: plumb_infop=0x%p, streams_infop=0x%p",
- (void *)plumb_infop, (void *)streams_infop);
-
- dir = streams_infop->acs_ac_to_as_req.acr_curr_dir;
- ASSERT(dir == AUDIO_PLAY);
- cur_fmt = &streams_infop->acs_ac_to_as_req.acr_curr_format;
/* Check for continuous sample rate done in usb_as */
- samples = cur_fmt->fmt_sr * cur_fmt->fmt_chns /
- uacp->usb_ac_am_ad_info.ad_play.ad_int_rate;
- if (samples & cur_fmt->fmt_chns) {
+ samples = engine->fmt.sr * engine->fmt.ch / engine->intrate;
+ if (samples & engine->fmt.ch) {
samples++;
}
play_req.up_samples = samples;
- play_req.up_handle = ahdl;
+ play_req.up_handle = uacp;
/* Send setup command to usb_as */
- if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_START_PLAY,
+ if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_START_PLAY,
(void *)&play_req) != USB_SUCCESS) {
USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
@@ -3640,29 +3117,29 @@ usb_ac_start_play(audiohdl_t ahdl)
usb_ac_release_access(uacp);
- return (AUDIO_FAILURE);
+ return (USB_FAILURE);
}
mutex_exit(&uacp->usb_ac_mutex);
usb_ac_release_access(uacp);
- return (AUDIO_SUCCESS);
+ return (USB_SUCCESS);
}
/*
* usb_ac_stop_play:
- * Wrapper function for usb_ac_do_stop_play and gets
+ * Stop the play engine
* called from mixer framework.
*/
-static void
-usb_ac_stop_play(audiohdl_t ahdl)
+void
+usb_ac_stop_play(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
{
- usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
-
- ASSERT(uacp != NULL);
+ if (engine == NULL) {
+ engine = &(uacp->engines[0]);
+ }
mutex_enter(&uacp->usb_ac_mutex);
if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
mutex_exit(&uacp->usb_ac_mutex);
@@ -3672,34 +3149,10 @@ usb_ac_stop_play(audiohdl_t ahdl)
mutex_exit(&uacp->usb_ac_mutex);
usb_ac_serialize_access(uacp);
- usb_ac_do_stop_play(ahdl);
- usb_ac_release_access(uacp);
-}
-
-/*
- * usb_ac_do_pause_play:
- * Send a pause_play command to usb_as.
- * Check power is done in usb_ac_send_as_cmd()
- */
-static void
-usb_ac_do_stop_play(audiohdl_t ahdl)
-{
- usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
- usb_ac_plumbed_t *plumb_infop = NULL;
- usb_ac_streams_info_t *streams_infop = NULL;
-
- ASSERT(uacp != NULL);
-
mutex_enter(&uacp->usb_ac_mutex);
- plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", AUDIO_PLAY);
- ASSERT(plumb_infop);
-
- streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
- ASSERT(streams_infop != NULL);
-
/* Send setup command to usb_as */
- if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_PAUSE_PLAY,
+ if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_PAUSE_PLAY,
(void *)NULL) != USB_SUCCESS) {
USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
@@ -3707,6 +3160,7 @@ usb_ac_do_stop_play(audiohdl_t ahdl)
}
mutex_exit(&uacp->usb_ac_mutex);
+ usb_ac_release_access(uacp);
}
@@ -3716,34 +3170,25 @@ usb_ac_do_stop_play(audiohdl_t ahdl)
* Check power is done in usb_ac_send_as_cmd()
*/
static int
-usb_ac_start_record(audiohdl_t ahdl)
+usb_ac_start_record(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
{
- usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
- usb_ac_plumbed_t *plumb_infop = NULL;
- usb_ac_streams_info_t *streams_infop = NULL;
- ASSERT(uacp != NULL);
mutex_enter(&uacp->usb_ac_mutex);
if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
mutex_exit(&uacp->usb_ac_mutex);
- return (AUDIO_FAILURE);
+ return (USB_FAILURE);
}
mutex_exit(&uacp->usb_ac_mutex);
usb_ac_serialize_access(uacp);
-
mutex_enter(&uacp->usb_ac_mutex);
- plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", AUDIO_RECORD);
- ASSERT(plumb_infop);
- streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
- ASSERT(streams_infop != NULL);
/* Send setup command to usb_as */
- if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_START_RECORD,
- (void *)&ahdl) != USB_SUCCESS) {
+ if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_START_RECORD,
+ (void *)uacp) != USB_SUCCESS) {
USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
"usb_ac_start_record: failure");
@@ -3752,14 +3197,13 @@ usb_ac_start_record(audiohdl_t ahdl)
usb_ac_release_access(uacp);
- return (AUDIO_FAILURE);
+ return (USB_FAILURE);
}
mutex_exit(&uacp->usb_ac_mutex);
-
usb_ac_release_access(uacp);
- return (AUDIO_SUCCESS);
+ return (USB_SUCCESS);
}
@@ -3769,42 +3213,14 @@ usb_ac_start_record(audiohdl_t ahdl)
* called form mixer framework.
*/
static void
-usb_ac_stop_record(audiohdl_t ahdl)
+usb_ac_stop_record(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
{
- usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
-
- ASSERT(uacp != NULL);
usb_ac_serialize_access(uacp);
- usb_ac_do_stop_record(ahdl);
- usb_ac_release_access(uacp);
-}
-
-
-/*
- * usb_ac_do_stop_record:
- * Sends a stop_record command down.
- * Check power is done in usb_ac_send_as_cmd()
- */
-static void
-usb_ac_do_stop_record(audiohdl_t ahdl)
-{
- usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
- usb_ac_plumbed_t *plumb_infop = NULL;
- usb_ac_streams_info_t *streams_infop = NULL;
-
- ASSERT(uacp != NULL);
-
mutex_enter(&uacp->usb_ac_mutex);
- plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", AUDIO_RECORD);
- ASSERT(plumb_infop != NULL);
-
- streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
- ASSERT(streams_infop != NULL);
-
/* Send setup command to usb_as */
- if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_STOP_RECORD,
+ if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_STOP_RECORD,
NULL) != USB_SUCCESS) {
USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
@@ -3812,6 +3228,7 @@ usb_ac_do_stop_record(audiohdl_t ahdl)
}
mutex_exit(&uacp->usb_ac_mutex);
+ usb_ac_release_access(uacp);
}
@@ -3823,6 +3240,7 @@ usb_ac_do_stop_record(audiohdl_t ahdl)
* Calculate min or max gain balance and return that. Return
* USB_FAILURE for failure cases
*/
+/* ARGSUSED */
static int
usb_ac_get_maxmin_volume(usb_ac_state_t *uacp, uint_t channel, int cmd,
int dir, int feature_unitID, short *max_or_minp)
@@ -3831,9 +3249,6 @@ usb_ac_get_maxmin_volume(usb_ac_state_t *uacp, uint_t channel, int cmd,
usb_cr_t cr;
usb_cb_flags_t cb_flags;
- USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_get_maxmin_volume: channel=%d, cmd=%d dir=%d",
- channel, cmd, dir);
mutex_exit(&uacp->usb_ac_mutex);
@@ -3881,6 +3296,7 @@ usb_ac_get_maxmin_volume(usb_ac_state_t *uacp, uint_t channel, int cmd,
* usb_ac_set_volume:
* Send USBA command down to set the gain balance
*/
+/* ARGSUSED */
static int
usb_ac_set_volume(usb_ac_state_t *uacp, uint_t channel, short gain, int dir,
int feature_unitID)
@@ -3890,14 +3306,20 @@ usb_ac_set_volume(usb_ac_state_t *uacp, uint_t channel, short gain, int dir,
usb_cb_flags_t cb_flags;
int rval = USB_FAILURE;
- USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_set_volume: channel=%d gain=%d dir=%d FU=%d",
- channel, gain, dir, feature_unitID);
mutex_exit(&uacp->usb_ac_mutex);
/* Construct the mblk_t from gain for sending to USBA */
- data = allocb_wait(4, BPRI_HI, STR_NOSIG, NULL);
+ data = allocb(4, BPRI_HI);
+ if (!data) {
+ USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
+ "usb_ac_set_volume: allocate data failed");
+ mutex_enter(&uacp->usb_ac_mutex);
+
+ return (USB_FAILURE);
+ }
+
+
*(data->b_wptr++) = (char)gain;
*(data->b_wptr++) = (char)(gain >> 8);
@@ -3931,7 +3353,7 @@ usb_ac_set_volume(usb_ac_state_t *uacp, uint_t channel, short gain, int dir,
* usb_ac_set_mute is called for each unit that supports the
* requested control from usb_ac_traverse_connections
*/
-static int
+int
usb_ac_set_mute(usb_ac_state_t *uacp, uint_t featureID, uint_t dir,
uint_t channel, uint_t control, uint_t muteval, uint_t *depth)
{
@@ -3940,19 +3362,26 @@ usb_ac_set_mute(usb_ac_state_t *uacp, uint_t featureID, uint_t dir,
usb_cb_flags_t cb_flags;
int rval = USB_FAILURE;
- USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_set_mute: muteval=0x%x, dir=%d", muteval, dir);
if (usb_ac_feature_unit_check(uacp, featureID,
dir, channel, control, 0, depth) != USB_SUCCESS) {
return (USB_FAILURE);
}
-
mutex_exit(&uacp->usb_ac_mutex);
/* Construct the mblk_t for sending to USBA */
- data = allocb_wait(1, BPRI_HI, STR_NOSIG, NULL);
+ data = allocb(1, BPRI_HI);
+
+ if (!data) {
+ USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
+ "usb_ac_set_mute: allocate data failed");
+ mutex_enter(&uacp->usb_ac_mutex);
+
+ return (USB_FAILURE);
+ }
+
+
*(data->b_wptr++) = (char)muteval;
if ((rval = usb_pipe_sync_ctrl_xfer(
@@ -3973,8 +3402,8 @@ usb_ac_set_mute(usb_ac_state_t *uacp, uint_t featureID, uint_t dir,
USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
"usb_ac_set_mute: failed, cr=%d cb=0x%x", cr, cb_flags);
}
-
freemsg(data);
+
mutex_enter(&uacp->usb_ac_mutex);
return (rval);
@@ -3990,22 +3419,19 @@ usb_ac_set_mute(usb_ac_state_t *uacp, uint_t featureID, uint_t dir,
* it seems better to ensure that both interfaces are at full power
*/
static int
-usb_ac_send_as_cmd(usb_ac_state_t *uacp, usb_ac_plumbed_t *plumb_infop,
+usb_ac_send_as_cmd(usb_ac_state_t *uacp, usb_audio_eng_t *engine,
int cmd, void *arg)
{
usb_ac_streams_info_t *streams_infop;
+ usb_ac_plumbed_t *plumb_infop;
int rv;
int rval;
ldi_handle_t lh;
ASSERT(mutex_owned(&uacp->usb_ac_mutex));
- ASSERT(plumb_infop != NULL);
-
- streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
- ASSERT(streams_infop != NULL);
+ streams_infop = engine->streams;
+ plumb_infop = streams_infop->acs_plumbed;
- USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_send_as_cmd: cmd=0x%x, arg=0x%p", cmd, arg);
lh = plumb_infop->acp_lh;
@@ -4124,15 +3550,10 @@ usb_ac_reader(void *argp)
break;
}
+
if ((acp->acp_flags & ACP_ENABLED) && mp != NULL && rv == 0)
rv = usb_ac_read_msg(acp, mp);
- USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "%s%d read from %s%d, rv=%d",
- ddi_driver_name(uacp->usb_ac_dip),
- ddi_get_instance(uacp->usb_ac_dip),
- ddi_driver_name(acp->acp_dip),
- ddi_get_instance(acp->acp_dip), rv);
}
mutex_exit(&uacp->usb_ac_mutex);
}
@@ -4446,8 +3867,6 @@ usb_ac_mux_unplumbing(usb_ac_state_t *uacp)
mutex_enter(&uacp->usb_ac_mutex);
- USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_mux_unplumbing: state=%d", uacp->usb_ac_plumbing_state);
if (uacp->usb_ac_plumbing_state == USB_AC_STATE_UNPLUMBED) {
USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
@@ -4510,10 +3929,11 @@ usb_ac_mux_unplumbing(usb_ac_state_t *uacp)
ddi_driver_name(acp_dip), inst, minor);
if (lh != NULL) {
- mutex_exit(&uacp->usb_ac_mutex);
acp->acp_flags &= ~ACP_ENABLED;
+ mutex_exit(&uacp->usb_ac_mutex);
+
USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
"usb_ac_mux_unplumbing:[%d] - closing", i);
@@ -4573,10 +3993,6 @@ usb_ac_mux_walk_siblings(usb_ac_state_t *uacp)
pdip = ddi_get_parent(uacp->usb_ac_dip);
child_dip = ddi_get_child(pdip);
- USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_mux_walk_siblings: parent=%s%d",
- ddi_driver_name(pdip), ddi_get_instance(pdip));
-
while ((child_dip != NULL) && (count < USB_AC_MAX_PLUMBED)) {
drv_instance = ddi_get_instance(child_dip);
drv_name = (char *)ddi_driver_name(child_dip);
@@ -4634,7 +4050,9 @@ usb_ac_mux_walk_siblings(usb_ac_state_t *uacp)
error = ldi_ident_from_dip(uacp->usb_ac_dip, &li);
if (error == 0) {
+ mutex_enter(&uacp->usb_ac_mutex);
uacp->usb_ac_plumbed[count].acp_flags |= ACP_ENABLED;
+ mutex_exit(&uacp->usb_ac_mutex);
error = ldi_open_by_dev(&drv_devt, OTYP_CHR,
FREAD|FWRITE, kcred, &drv_lh, li);
@@ -4743,49 +4161,17 @@ usb_ac_mux_walk_siblings(usb_ac_state_t *uacp)
/*
- * usb_ac_find_default_port:
- */
-static int
-usb_ac_find_default_port(uint_t port)
-{
- int i;
-
- for (i = 0; i < 32; i++) {
- if (port & (1 << i)) {
-
- return (1 << i);
- }
- }
-
- return (0);
-}
-
-
-/*
* Register with mixer only after first plumbing.
* Also do not register if earlier reg data
* couldn't be received from at least one
* streaming interface
*/
-_NOTE(SCHEME_PROTECTS_DATA("private", am_ad_info))
static int
usb_ac_mixer_registration(usb_ac_state_t *uacp)
{
- am_ad_info_t *info = &uacp->usb_ac_am_ad_info;
- audio_info_t *dflts = &uacp->usb_ac_am_ad_defaults;
usb_as_registration_t *asreg;
- int n, nplay, nrec;
-
- ASSERT(uacp != NULL);
-
- USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_mixer_registration:infp=0x%p, dflts=0x%p,"
- "already registered=%d", (void *)info, (void *)dflts,
- uacp->usb_ac_registered_with_mixer);
-
- ASSERT(dflts != NULL);
- ASSERT(info != NULL);
+ int n;
if (uacp->usb_ac_registered_with_mixer) {
return (USB_SUCCESS);
@@ -4805,45 +4191,23 @@ usb_ac_mixer_registration(usb_ac_state_t *uacp)
return (USB_FAILURE);
}
- info->ad_defaults = dflts;
-
- dflts->monitor_gain = 0;
- dflts->output_muted = B_FALSE;
- dflts->hw_features = 0;
- dflts->sw_features = AUDIO_SWFEATURE_MIXER;
-
/*
* Fill out streaming interface specific stuff
* Note that we handle only one playing and one recording
* streaming interface at the most
*/
- nplay = nrec = 0;
for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) {
- int ch, chs, default_gain, id;
+ int ch, chs, id;
if (uacp->usb_ac_streams[n].acs_rcvd_reg_data == 0) {
continue;
}
- asreg = uacp->usb_ac_streams[n].acs_streams_reg;
+ asreg = &(uacp->usb_ac_streams[n].acs_streams_reg);
if (asreg->reg_valid == 0) {
continue;
}
- mutex_exit(&uacp->usb_ac_mutex);
-
- USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_mixer_registration: setting format n=%d", n);
-
- /* set first format so get_featureID can be succeed */
- (void) usb_ac_set_format(uacp->usb_ac_audiohdl,
- asreg->reg_mode,
- asreg->reg_srs[0],
- asreg->reg_formats[0].fmt_chns,
- asreg->reg_formats[0].fmt_precision,
- asreg->reg_formats[0].fmt_encoding);
-
- mutex_enter(&uacp->usb_ac_mutex);
chs = asreg->reg_formats[0].fmt_chns;
@@ -4861,88 +4225,28 @@ usb_ac_mixer_registration(usb_ac_state_t *uacp)
break;
}
}
- default_gain = (id == USB_AC_ID_NONE) ?
- AUDIO_MAX_GAIN : (AUDIO_MAX_GAIN/2);
+
+ uacp->usb_ac_streams[n].acs_default_gain =
+ (id == USB_AC_ID_NONE) ? (AF_MAX_GAIN): (AF_MAX_GAIN*3/4);
USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
"usb_ac_mixer_registration:n= [%d] - mode=%d chs=%d"
"default_gain=%d id=%d",
- n, asreg->reg_mode, chs, default_gain, id);
-
- if (asreg->reg_mode == AUDIO_PLAY) {
- nplay++;
- ASSERT(nplay == 1);
-
- dflts->play.sample_rate =
- asreg->reg_srs[0];
- dflts->play.channels =
- asreg->reg_formats[0].fmt_chns;
- dflts->play.precision =
- asreg->reg_formats[0].fmt_precision;
- dflts->play.encoding =
- asreg->reg_formats[0].fmt_encoding;
- dflts->play.gain = default_gain;
- dflts->play.port = usb_ac_find_default_port(
- uacp->usb_ac_output_ports);
- dflts->play.avail_ports = uacp->usb_ac_output_ports;
- dflts->play.mod_ports = 0;
- /* no support for mixer unit */
- dflts->play.buffer_size = 8*1024;
- dflts->hw_features |= AUDIO_HWFEATURE_PLAY;
-
- info->ad_play.ad_mixer_srs.ad_srs = asreg->reg_srs;
-
- info->ad_play.ad_chs = asreg->reg_channels;
- info->ad_play.ad_int_rate = 1000; /* every 1 ms */
- info->ad_play.ad_bsize = 8 * 1024;
- info->ad_play_comb = asreg->reg_combinations;
- } else {
- nrec++;
- ASSERT(nrec == 1);
-
- dflts->record.sample_rate =
- asreg->reg_srs[0];
- dflts->record.channels =
- asreg->reg_formats[0].fmt_chns;
- dflts->record.precision =
- asreg->reg_formats[0].fmt_precision;
- dflts->record.encoding =
- asreg->reg_formats[0].fmt_encoding;
- dflts->record.gain = default_gain;
- dflts->record.port = usb_ac_find_default_port(
- uacp->usb_ac_input_ports);
- dflts->record.avail_ports = uacp->usb_ac_input_ports;
- dflts->record.mod_ports = uacp->usb_ac_input_ports;
- dflts->record.buffer_size = 8*1024;
- dflts->hw_features |= AUDIO_HWFEATURE_RECORD;
-
- info->ad_record.ad_mixer_srs.ad_srs = asreg->reg_srs;
-
- info->ad_record.ad_chs = asreg->reg_channels;
- info->ad_record.ad_int_rate = 1000; /* every 1 ms */
- info->ad_record.ad_bsize = 8 * 1024;
- info->ad_num_mics = 1;
- info->ad_rec_comb = asreg->reg_combinations;
- }
- }
+ n, asreg->reg_mode, chs,
+ uacp->usb_ac_streams[n].acs_default_gain, id);
- if (nplay && nrec) {
- dflts->hw_features |= AUDIO_HWFEATURE_DUPLEX;
}
/* the rest */
- info->ad_entry = &usb_ac_entry;
- info->ad_dev_info = &usb_dev_info;
USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_mixer_registration: calling am_attach");
+ "usb_ac_mixer_registration: calling usb_audio_register");
mutex_exit(&uacp->usb_ac_mutex);
- if (am_attach(uacp->usb_ac_audiohdl, DDI_ATTACH, info) ==
- AUDIO_FAILURE) {
+ if (usb_audio_register(uacp) != USB_SUCCESS) {
USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_mixer_registration: am_attach failed");
+ "usb_ac_mixer_registration: usb_audio_register failed");
mutex_enter(&uacp->usb_ac_mutex);
@@ -4953,16 +4257,12 @@ usb_ac_mixer_registration(usb_ac_state_t *uacp)
uacp->usb_ac_registered_with_mixer = 1;
- USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_mixer_registration:- am_attach succeeded");
-
return (USB_SUCCESS);
}
/*
- * get registration data from usb_as driver unless we already
- * have 2 registrations
+ * Get registriations data when driver attach
*/
static int
usb_ac_get_reg_data(usb_ac_state_t *uacp, ldi_handle_t drv_lh, int index)
@@ -4970,17 +4270,10 @@ usb_ac_get_reg_data(usb_ac_state_t *uacp, ldi_handle_t drv_lh, int index)
int n, error, rval;
usb_as_registration_t *streams_reg;
- USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_get_reg_data: index=%d, mixer registered=%d", index,
- uacp->usb_ac_registered_with_mixer);
- /* if already registered, just setup data structures again */
- if (uacp->usb_ac_registered_with_mixer) {
-
- return (usb_ac_setup_plumbed(uacp, index, -1, -1));
- }
+ ASSERT(uacp->usb_ac_registered_with_mixer == 0);
- for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n ++) {
+ for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) {
/*
* We haven't received registration data
* from n-th streaming interface in the array
@@ -4999,7 +4292,7 @@ usb_ac_get_reg_data(usb_ac_state_t *uacp, ldi_handle_t drv_lh, int index)
}
/* take the stream reg struct with the same index */
- streams_reg = &uacp->usb_ac_streams_reg[n];
+ streams_reg = &uacp->usb_ac_streams[n].acs_streams_reg;
USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
"usb_ac_get_reg_data:regdata from usb_as: streams_reg=0x%p, n=%d",
@@ -5019,13 +4312,13 @@ usb_ac_get_reg_data(usb_ac_state_t *uacp, ldi_handle_t drv_lh, int index)
} else {
mutex_enter(&uacp->usb_ac_mutex);
- rval = usb_ac_setup_plumbed(uacp, index, n, n);
+ rval = usb_ac_setup_plumbed(uacp, index, n);
USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
"usb_ac_get_reg_data:usb_ac_streams[%d]: "
"received_reg_data=%d type=%s", index,
uacp->usb_ac_streams[n].acs_rcvd_reg_data,
- ((streams_reg->reg_mode == AUDIO_PLAY) ?
+ ((streams_reg->reg_mode == USB_AUDIO_PLAY) ?
"play" : "record"));
usb_ac_print_reg_data(uacp, streams_reg);
@@ -5036,64 +4329,21 @@ usb_ac_get_reg_data(usb_ac_state_t *uacp, ldi_handle_t drv_lh, int index)
/*
- * setup plumbed and stream info structure, either initially or
- * after replumbing
- * On replumbing, str_idx and reg_idx are -1
+ * setup plumbed and stream info structure
*/
static int
-usb_ac_setup_plumbed(usb_ac_state_t *uacp, int plb_idx, int str_idx,
- int reg_idx)
+usb_ac_setup_plumbed(usb_ac_state_t *uacp, int plb_idx, int str_idx)
{
- int i;
-
- USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_setup_plumbed: plb_idx=%d str_idx=%d",
- plb_idx, str_idx);
-
- if (str_idx == -1) {
- /* find a free streams info structure */
- for (i = 0; i < USB_AC_MAX_AS_PLUMBED; i++) {
- if (uacp->usb_ac_streams[i].acs_plumbed == NULL) {
- break;
- }
- }
- ASSERT(i < USB_AC_MAX_AS_PLUMBED);
- str_idx = i;
- }
-
uacp->usb_ac_plumbed[plb_idx].acp_data =
&uacp->usb_ac_streams[str_idx];
uacp->usb_ac_streams[str_idx].acs_plumbed =
&uacp->usb_ac_plumbed[plb_idx];
uacp->usb_ac_streams[str_idx].acs_rcvd_reg_data = 1;
- if (reg_idx == -1) {
- /*
- * find the corresponding registration structure, match
- * on interface number and not on dip since dip may have
- * changed
- */
- for (i = 0; i < USB_AC_MAX_AS_PLUMBED; i++) {
- if (uacp->usb_ac_streams_reg[i].reg_ifno ==
- uacp->usb_ac_plumbed[plb_idx].acp_ifno) {
- break;
- }
- }
- if (i == USB_AC_MAX_AS_PLUMBED) {
- USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_setup_plumbed:no corresponding registration "
- "structure");
-
- return (USB_FAILURE);
- }
- reg_idx = i;
- }
- uacp-> usb_ac_streams[str_idx].acs_streams_reg =
- &uacp->usb_ac_streams_reg[reg_idx];
USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_setup_plumbed: done - plb_idx=%d str_idx=%d reg_idx=%d",
- plb_idx, str_idx, reg_idx);
+ "usb_ac_setup_plumbed: done - plb_idx=%d str_idx=%d ",
+ plb_idx, str_idx);
return (USB_SUCCESS);
}
@@ -5108,12 +4358,6 @@ usb_ac_print_reg_data(usb_ac_state_t *uacp,
{
int n;
- USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "usb_ac_print_reg_data: Begin valid=%d, play=%d, "
- "n_formats=%d, compat srs ptr=0x%p",
- reg->reg_valid, reg->reg_mode, reg->reg_n_formats,
- (void *)&reg->reg_srs);
-
for (n = 0; n < reg->reg_n_formats; n++) {
USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
"format%d: alt=%d chns=%d prec=%d enc=%d", n,
@@ -5123,14 +4367,6 @@ usb_ac_print_reg_data(usb_ac_state_t *uacp,
reg->reg_formats[n].fmt_encoding);
}
- USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "combinations: %d %d %d %d %d %d %d %d",
- reg->reg_combinations[0].ad_prec, reg->reg_combinations[0].ad_enc,
- reg->reg_combinations[1].ad_prec, reg->reg_combinations[1].ad_enc,
- reg->reg_combinations[2].ad_prec, reg->reg_combinations[2].ad_enc,
- reg->reg_combinations[3].ad_prec, reg->reg_combinations[3].ad_enc);
-
-
for (n = 0; n < USB_AS_N_FORMATS; n++) {
USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
"reg_formats[%d] ptr=0x%p", n,
@@ -5142,13 +4378,7 @@ usb_ac_print_reg_data(usb_ac_state_t *uacp,
"reg_channels[%d]=%d", n, reg->reg_channels[n]);
}
- for (n = 0; n < USB_AS_N_COMBINATIONS; n++) {
- USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
- "reg_combinations[%d] ptr=0x%p", n,
- (void *)&reg->reg_combinations[n]);
- }
-
- USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
+ USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
"usb_ac_print_reg_data: End");
}
@@ -5266,3 +4496,1223 @@ usb_ac_rele_siblings(usb_ac_state_t *uacp)
}
ndi_devi_exit(pdip, circ);
}
+static void
+usb_restore_engine(usb_ac_state_t *statep)
+{
+ usb_audio_eng_t *engp;
+ int i;
+
+ for (i = 0; i < USB_AC_ENG_MAX; i++) {
+
+ mutex_enter(&statep->usb_ac_mutex);
+ engp = &statep->engines[i];
+ mutex_exit(&statep->usb_ac_mutex);
+
+ if (engp->af_engp == NULL)
+ continue;
+ if (usb_ac_set_format(statep, engp) != USB_SUCCESS) {
+ USB_DPRINTF_L2(PRINT_MASK_ATTA,
+ statep->usb_ac_log_handle,
+ "usb_restore_engine:set format fail, i=%d", i);
+ return;
+ }
+ if (engp->started) {
+ (void) usb_engine_start(engp);
+ }
+
+ }
+
+ (void) usb_ac_ctrl_restore(statep);
+}
+
+
+/*
+ * get the maximum format specification the device supports
+ */
+static void
+usb_ac_max_fmt(usb_as_registration_t *reg_data,
+ usb_audio_format_t *fmtp)
+{
+
+ uint_t *srs, *chs;
+ uint_t sr, ch, prec, enc, val;
+ int i;
+
+ usb_audio_formats_t *reg_formats = reg_data->reg_formats;
+ srs = reg_data->reg_srs;
+ chs = reg_data->reg_channels;
+
+ for (i = 0, sr = 0; srs[i]; i++) {
+ val = srs[i];
+ if (val > sr)
+ sr = val;
+ }
+
+ for (i = 0, ch = 0; chs[i]; i++) {
+ val = chs[i];
+ if (val > ch)
+ ch = val;
+ }
+
+ for (i = 0, prec = 0, enc = 0; i < reg_data->reg_n_formats; i++) {
+ val = reg_formats[i].fmt_precision;
+ if (val > prec)
+ prec = val;
+
+ val = reg_formats[i].fmt_encoding;
+ if (val > enc)
+ enc = val;
+ }
+
+ fmtp->sr = sr;
+ fmtp->ch = ch;
+ fmtp->prec = prec;
+ fmtp->enc = enc;
+}
+
+
+static void
+usb_ac_rem_eng(usb_ac_state_t *statep, usb_audio_eng_t *engp)
+{
+ if (statep->usb_ac_audio_dev == NULL || engp->af_engp == NULL)
+ return;
+
+ audio_dev_remove_engine(statep->usb_ac_audio_dev, engp->af_engp);
+ audio_engine_free(engp->af_engp);
+
+ mutex_enter(&engp->lock);
+ engp->af_engp = NULL;
+ engp->streams = NULL;
+ mutex_exit(&engp->lock);
+}
+
+
+static int
+usb_ac_add_eng(usb_ac_state_t *uacp, usb_ac_streams_info_t *asinfo)
+{
+ audio_dev_t *af_devp = uacp->usb_ac_audio_dev;
+ usb_audio_eng_t *engp;
+ audio_engine_t *af_engp;
+ int rv = USB_FAILURE;
+ int dir = asinfo->acs_streams_reg.reg_mode;
+ uint_t defgain;
+
+ if (asinfo->acs_rcvd_reg_data == 0) {
+
+ return (USB_SUCCESS);
+ }
+ if (dir == USB_AUDIO_PLAY) {
+ engp = &(uacp->engines[0]);
+ } else {
+ engp = &(uacp->engines[1]);
+ }
+
+ mutex_init(&engp->lock, NULL, MUTEX_DRIVER, NULL);
+
+ mutex_enter(&engp->lock);
+
+ engp->af_eflags =
+ (dir == USB_AUDIO_PLAY)?ENGINE_OUTPUT_CAP:ENGINE_INPUT_CAP;
+ engp->statep = uacp;
+
+ /* Set the format for the engine */
+ usb_ac_max_fmt(&(asinfo->acs_streams_reg), &engp->fmt);
+
+ /* init the default gain */
+ defgain = asinfo->acs_default_gain;
+ if (engp->fmt.ch == 2) {
+ engp->af_defgain = AUDIO_CTRL_STEREO_VAL(defgain, defgain);
+ } else {
+ engp->af_defgain = defgain;
+ }
+ engp->streams = asinfo;
+
+ mutex_exit(&engp->lock);
+
+ af_engp = audio_engine_alloc(&usb_engine_ops, engp->af_eflags);
+ if (af_engp == NULL) {
+
+ USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
+ "audio_engine_alloc failed");
+ goto OUT;
+ }
+ ASSERT(engp->af_engp == 0);
+
+ mutex_enter(&engp->lock);
+ engp->af_engp = af_engp;
+ mutex_exit(&engp->lock);
+
+ audio_engine_set_private(af_engp, engp);
+ audio_dev_add_engine(af_devp, af_engp);
+
+ /*
+ * Set the format for this engine
+ */
+ if (usb_ac_set_format(uacp, engp) != USB_SUCCESS) {
+ USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
+ "set format failed, dir = %d", dir);
+ goto OUT;
+ }
+ rv = USB_SUCCESS;
+
+OUT:
+ if (rv != USB_SUCCESS)
+ usb_ac_rem_eng(uacp, engp);
+
+ return (rv);
+}
+
+
+static int
+usb_ac_ctrl_set_defaults(usb_ac_state_t *statep)
+{
+ usb_audio_ctrl_t *ctrlp;
+ int rv = USB_SUCCESS;
+ USB_DPRINTF_L4(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
+ "usb_ac_ctrl_set_defaults:begin");
+
+ for (int i = 0; i < CTL_NUM; i++) {
+ ctrlp = statep->controls[i];
+ if (!ctrlp) {
+ continue;
+ }
+ if (audio_control_write(ctrlp->af_ctrlp, ctrlp->cval)) {
+ USB_DPRINTF_L2(PRINT_MASK_ATTA,
+ statep->usb_ac_log_handle,
+ "usb_ac_ctrl_set_defaults:control write failed");
+ rv = USB_FAILURE;
+ }
+
+ }
+ USB_DPRINTF_L4(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
+ "usb_ac_ctrl_set_defaults:end");
+ return (rv);
+}
+
+
+static int
+usb_ac_ctrl_restore(usb_ac_state_t *statep)
+{
+ usb_audio_ctrl_t *ctrlp;
+ int rv = USB_SUCCESS;
+
+ for (int i = 0; i < CTL_NUM; i++) {
+ ctrlp = statep->controls[i];
+ if (ctrlp) {
+ USB_DPRINTF_L3(PRINT_MASK_ATTA,
+ statep->usb_ac_log_handle,
+ "usb_ac_ctrl_restore:i = %d", i);
+ if (audio_control_write(ctrlp->af_ctrlp, ctrlp->cval)) {
+ rv = USB_FAILURE;
+ }
+ }
+ }
+ return (rv);
+}
+
+
+
+
+/*
+ * moves data between driver buffer and framework/shim buffer
+ */
+static void
+usb_eng_bufio(usb_audio_eng_t *engp, void *buf, size_t sz)
+{
+ size_t cpsz = sz;
+ caddr_t *src, *dst;
+
+ if (engp->af_eflags & ENGINE_OUTPUT_CAP) {
+ src = &engp->bufpos;
+ dst = (caddr_t *)&buf;
+ } else {
+ src = (caddr_t *)&buf;
+ dst = &engp->bufpos;
+ }
+
+ /*
+ * Wrap. If sz is exactly the remainder of the buffer
+ * (bufpos + sz == bufendp) then the second cpsz should be 0 and so
+ * the second memcpy() should have no effect, with bufpos updated
+ * to the head of the buffer.
+ */
+ if (engp->bufpos + sz >= engp->bufendp) {
+ cpsz = (size_t)engp->bufendp - (size_t)engp->bufpos;
+ (void) memcpy(*dst, *src, cpsz);
+
+
+ buf = (caddr_t)buf + cpsz;
+ engp->bufpos = engp->bufp;
+ cpsz = sz - cpsz;
+ }
+
+ if (cpsz) {
+ (void) memcpy(*dst, *src, cpsz);
+
+
+ engp->bufpos += cpsz;
+ }
+ engp->bufio_count++;
+}
+
+
+/*
+ * control read callback
+ */
+static int
+usb_audio_ctrl_read(void *arg, uint64_t *cvalp)
+{
+ usb_audio_ctrl_t *ctrlp = arg;
+
+ mutex_enter(&ctrlp->ctrl_mutex);
+ *cvalp = ctrlp->cval;
+ mutex_exit(&ctrlp->ctrl_mutex);
+
+ return (0);
+}
+
+
+/*
+ * stereo level control callback
+ */
+static int
+usb_audio_write_stero_rec(void *arg, uint64_t cval)
+{
+ usb_audio_ctrl_t *ctrlp = arg;
+ usb_ac_state_t *statep = ctrlp->statep;
+ int rv = EIO;
+ int left, right;
+ uint_t count = 0;
+
+
+ left = AUDIO_CTRL_STEREO_LEFT(cval);
+ right = AUDIO_CTRL_STEREO_RIGHT(cval);
+
+ if (left < AF_MIN_GAIN || left > AF_MAX_GAIN ||
+ right < AF_MIN_GAIN || right > AF_MAX_GAIN) {
+
+ return (EINVAL);
+ }
+
+ mutex_enter(&ctrlp->ctrl_mutex);
+ ctrlp->cval = cval;
+ mutex_exit(&ctrlp->ctrl_mutex);
+
+ mutex_enter(&statep->usb_ac_mutex);
+ (void) usb_ac_set_control(statep, USB_AUDIO_RECORD,
+ USB_AUDIO_FEATURE_UNIT, 1,
+ USB_AUDIO_VOLUME_CONTROL,
+ USB_AC_FIND_ALL, &count, left, usb_ac_set_gain);
+
+ (void) usb_ac_set_control(statep, USB_AUDIO_RECORD,
+ USB_AUDIO_FEATURE_UNIT, 2,
+ USB_AUDIO_VOLUME_CONTROL,
+ USB_AC_FIND_ALL, &count, right, usb_ac_set_gain);
+ rv = 0;
+
+done:
+ mutex_exit(&statep->usb_ac_mutex);
+ return (rv);
+}
+
+static int
+usb_audio_write_ster_vol(void *arg, uint64_t cval)
+{
+ usb_audio_ctrl_t *ctrlp = arg;
+ usb_ac_state_t *statep = ctrlp->statep;
+ int rv = EIO;
+ int left, right;
+ uint_t count = 0;
+
+ left = AUDIO_CTRL_STEREO_LEFT(cval);
+ right = AUDIO_CTRL_STEREO_RIGHT(cval);
+
+ if (left < AF_MIN_GAIN || left > AF_MAX_GAIN ||
+ right < AF_MIN_GAIN || right > AF_MAX_GAIN) {
+ return (EINVAL);
+ }
+
+ mutex_enter(&ctrlp->ctrl_mutex);
+ ctrlp->cval = cval;
+ mutex_exit(&ctrlp->ctrl_mutex);
+
+
+ mutex_enter(&statep->usb_ac_mutex);
+ (void) usb_ac_set_control(statep, USB_AUDIO_PLAY,
+ USB_AUDIO_FEATURE_UNIT, 1,
+ USB_AUDIO_VOLUME_CONTROL,
+ USB_AC_FIND_ALL, &count, left, usb_ac_set_gain);
+
+ (void) usb_ac_set_control(statep, USB_AUDIO_PLAY,
+ USB_AUDIO_FEATURE_UNIT, 2,
+ USB_AUDIO_VOLUME_CONTROL,
+ USB_AC_FIND_ALL, &count, right, usb_ac_set_gain);
+ rv = 0;
+
+OUT:
+ mutex_exit(&statep->usb_ac_mutex);
+ return (rv);
+}
+
+
+/*
+ * mono level control callback
+ */
+static int
+usb_audio_write_mono_vol(void *arg, uint64_t cval)
+{
+ usb_audio_ctrl_t *ctrlp = arg;
+ usb_ac_state_t *statep = ctrlp->statep;
+ int rv = EIO;
+ int gain;
+
+ uint_t count = 0;
+
+ if (cval < (uint64_t)AF_MIN_GAIN || cval > (uint64_t)AF_MAX_GAIN) {
+ return (EINVAL);
+ }
+
+ mutex_enter(&ctrlp->ctrl_mutex);
+ ctrlp->cval = cval;
+ mutex_exit(&ctrlp->ctrl_mutex);
+
+ gain = (int)(cval);
+
+ mutex_enter(&statep->usb_ac_mutex);
+ (void) usb_ac_set_control(statep, USB_AUDIO_PLAY,
+ USB_AUDIO_FEATURE_UNIT, 1,
+ USB_AUDIO_VOLUME_CONTROL,
+ USB_AC_FIND_ALL, &count, gain, usb_ac_set_gain);
+
+ rv = 0;
+OUT:
+ mutex_exit(&statep->usb_ac_mutex);
+
+ return (rv);
+}
+
+
+/*
+ * mono level control callback
+ */
+static int
+usb_audio_write_monitor_gain(void *arg, uint64_t cval)
+{
+ usb_audio_ctrl_t *ctrlp = arg;
+ usb_ac_state_t *statep = ctrlp->statep;
+ int rv = EIO;
+ int gain;
+ uint_t count = 0;
+
+ if (cval < (uint64_t)AF_MIN_GAIN || cval > (uint64_t)AF_MAX_GAIN) {
+
+ return (EINVAL);
+ }
+
+ mutex_enter(&ctrlp->ctrl_mutex);
+ ctrlp->cval = cval;
+ mutex_exit(&ctrlp->ctrl_mutex);
+
+ gain = (int)(cval);
+
+ mutex_enter(&statep->usb_ac_mutex);
+ (void) usb_ac_set_monitor_gain_control(statep, USB_AUDIO_RECORD,
+ USB_AUDIO_INPUT_TERMINAL, 1,
+ USB_AUDIO_VOLUME_CONTROL,
+ USB_AC_FIND_ALL, &count, gain,
+ usb_ac_set_monitor_gain);
+
+ rv = 0;
+OUT:
+ mutex_exit(&statep->usb_ac_mutex);
+ return (rv);
+}
+
+static int
+usb_audio_write_mono_rec(void *arg, uint64_t cval)
+{
+ usb_audio_ctrl_t *ctrlp = arg;
+ usb_ac_state_t *statep = ctrlp->statep;
+ int rv = EIO;
+ int gain;
+
+ uint_t count = 0;
+
+ if (cval < (uint64_t)AF_MIN_GAIN || cval > (uint64_t)AF_MAX_GAIN) {
+
+ return (EINVAL);
+ }
+
+ mutex_enter(&ctrlp->ctrl_mutex);
+ ctrlp->cval = cval;
+ mutex_exit(&ctrlp->ctrl_mutex);
+
+ gain = (int)(cval);
+
+ mutex_enter(&statep->usb_ac_mutex);
+ (void) usb_ac_set_control(statep, USB_AUDIO_RECORD,
+ USB_AUDIO_FEATURE_UNIT, 1,
+ USB_AUDIO_VOLUME_CONTROL,
+ USB_AC_FIND_ALL, &count, gain, usb_ac_set_gain);
+
+ rv = 0;
+
+ mutex_exit(&statep->usb_ac_mutex);
+ return (rv);
+}
+
+static int
+usb_audio_write_mic_boost(void *arg, uint64_t cval)
+{
+ usb_audio_ctrl_t *ctrlp = arg;
+
+ mutex_enter(&ctrlp->ctrl_mutex);
+ ctrlp->cval = cval;
+ mutex_exit(&ctrlp->ctrl_mutex);
+ /* do nothing here */
+ return (0);
+}
+
+static int
+usb_audio_write_rec_src(void *arg, uint64_t cval)
+{
+ usb_audio_ctrl_t *ctrlp = arg;
+ usb_ac_state_t *statep = ctrlp->statep;
+ int rv = 0;
+
+ if (cval & ~(statep->usb_ac_input_ports))
+ return (EINVAL);
+
+ mutex_enter(&ctrlp->ctrl_mutex);
+ ctrlp->cval = cval;
+ mutex_exit(&ctrlp->ctrl_mutex);
+
+ mutex_enter(&statep->usb_ac_mutex);
+ if (usb_ac_set_port(statep, USB_AUDIO_RECORD, cval) != USB_SUCCESS) {
+
+ USB_DPRINTF_L2(PRINT_MASK_ALL, statep->usb_ac_log_handle,
+ "usb_audio_write_rec_src: failed");
+ rv = EINVAL;
+ }
+ mutex_exit(&statep->usb_ac_mutex);
+ rv = 0;
+
+OUT:
+ return (rv);
+
+}
+
+
+int
+usb_audio_set_mute(usb_ac_state_t *statep, uint64_t cval)
+{
+ short muteval;
+ int rval;
+
+ uint_t count;
+ muteval = (cval == 0) ? USB_AUDIO_MUTE_ON : USB_AUDIO_MUTE_OFF;
+ count = 0;
+ /* only support AUDIO_PLAY */
+
+ mutex_enter(&statep->usb_ac_mutex);
+ (void) usb_ac_set_control(statep, USB_AUDIO_PLAY,
+ USB_AUDIO_FEATURE_UNIT, 0,
+ USB_AUDIO_MUTE_CONTROL,
+ USB_AC_FIND_ALL, &count, muteval,
+ usb_ac_set_mute);
+ mutex_exit(&statep->usb_ac_mutex);
+
+ rval = (count == 0) ? USB_SUCCESS : USB_FAILURE;
+
+ return (rval);
+}
+
+
+/*
+ * port selection control callback
+ */
+/*
+ * audio control registration related routines
+ */
+
+static usb_audio_ctrl_t *
+usb_audio_ctrl_alloc(usb_ac_state_t *statep, uint32_t num, uint64_t val)
+{
+ audio_ctrl_desc_t desc;
+ audio_ctrl_wr_t fn;
+ usb_audio_ctrl_t *pc;
+
+ pc = kmem_zalloc(sizeof (usb_audio_ctrl_t), KM_SLEEP);
+
+ mutex_init(&pc->ctrl_mutex, NULL, MUTEX_DRIVER, NULL);
+
+ bzero(&desc, sizeof (desc));
+
+ switch (num) {
+ case CTL_VOLUME_MONO:
+ desc.acd_name = AUDIO_CTRL_ID_VOLUME;
+ desc.acd_type = AUDIO_CTRL_TYPE_MONO;
+ desc.acd_minvalue = 0;
+ desc.acd_maxvalue = AF_MAX_GAIN;
+ desc.acd_flags = AUDIO_CTRL_FLAG_MAINVOL | AUDIO_CTRL_FLAG_RW
+ | AUDIO_CTRL_FLAG_PLAY | AUDIO_CTRL_FLAG_POLL;
+ fn = usb_audio_write_mono_vol;
+ break;
+
+ case CTL_VOLUME_STERO:
+ desc.acd_name = AUDIO_CTRL_ID_VOLUME;
+ desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
+ desc.acd_minvalue = 0;
+ desc.acd_maxvalue = AF_MAX_GAIN;
+ desc.acd_flags = AUDIO_CTRL_FLAG_MAINVOL | AUDIO_CTRL_FLAG_RW
+ | AUDIO_CTRL_FLAG_PLAY | AUDIO_CTRL_FLAG_POLL;
+ fn = usb_audio_write_ster_vol;
+
+ break;
+
+ case CTL_REC_MONO:
+ desc.acd_name = AUDIO_CTRL_ID_RECGAIN;
+ desc.acd_type = AUDIO_CTRL_TYPE_MONO;
+ desc.acd_minvalue = 0;
+ desc.acd_maxvalue = AF_MAX_GAIN;
+ desc.acd_flags = AUDIO_CTRL_FLAG_RECVOL|AUDIO_CTRL_FLAG_REC
+ | AUDIO_CTRL_FLAG_RW;
+ fn = usb_audio_write_mono_rec;
+ break;
+ case CTL_REC_STERO:
+
+ desc.acd_name = AUDIO_CTRL_ID_RECGAIN;
+ desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
+ desc.acd_minvalue = 0;
+ desc.acd_maxvalue = AF_MAX_GAIN;
+ desc.acd_flags = AUDIO_CTRL_FLAG_RECVOL|AUDIO_CTRL_FLAG_REC
+ | AUDIO_CTRL_FLAG_RW;
+ fn = usb_audio_write_stero_rec;
+ break;
+
+ case CTL_MONITOR_GAIN:
+
+ desc.acd_name = AUDIO_CTRL_ID_MONGAIN;
+ desc.acd_type = AUDIO_CTRL_TYPE_MONO;
+ desc.acd_minvalue = 0;
+ desc.acd_maxvalue = AF_MAX_GAIN;
+ desc.acd_flags = AUDIO_CTRL_FLAG_MONVOL |AUDIO_CTRL_FLAG_MONITOR
+ |AUDIO_CTRL_FLAG_RW;
+ fn = usb_audio_write_monitor_gain;
+ break;
+
+ case CTL_MIC_BOOST:
+
+ desc.acd_name = AUDIO_CTRL_ID_MICBOOST;
+ desc.acd_type = AUDIO_CTRL_TYPE_BOOLEAN;
+ desc.acd_minvalue = 0;
+ desc.acd_maxvalue = 1;
+ desc.acd_flags = AUDIO_CTRL_FLAG_RW;
+ fn = usb_audio_write_mic_boost;
+ break;
+ case CTL_REC_SRC:
+
+ desc.acd_name = AUDIO_CTRL_ID_RECSRC;
+ desc.acd_type = AUDIO_CTRL_TYPE_ENUM;
+ desc.acd_minvalue = statep->usb_ac_input_ports;
+ desc.acd_maxvalue = statep->usb_ac_input_ports;
+ desc.acd_flags = AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_REC;
+ for (int i = 0; usb_audio_dtypes[i]; i++) {
+ desc.acd_enum[i] = usb_audio_dtypes[i];
+ }
+
+ fn = usb_audio_write_rec_src;
+ break;
+
+
+
+ default:
+
+ break;
+ }
+
+ mutex_enter(&pc->ctrl_mutex);
+
+ pc->statep = statep;
+ pc->cval = val;
+ pc->af_ctrlp = audio_dev_add_control(statep->usb_ac_audio_dev, &desc,
+ usb_audio_ctrl_read, fn, pc);
+
+ mutex_exit(&pc->ctrl_mutex);
+
+ mutex_enter(&statep->usb_ac_mutex);
+ statep->controls[num] = pc;
+ mutex_exit(&statep->usb_ac_mutex);
+
+
+ return (pc);
+}
+
+
+static void
+usb_audio_ctrl_free(usb_audio_ctrl_t *ctrlp)
+{
+ kmem_free(ctrlp, sizeof (usb_audio_ctrl_t));
+}
+
+static void
+usb_ac_rem_controls(usb_ac_state_t *statep)
+{
+ usb_audio_ctrl_t *ctrlp;
+
+ for (int i = 0; i < CTL_NUM; i++) {
+ ctrlp = statep->controls[i];
+ if (ctrlp) {
+ if (ctrlp->af_ctrlp != NULL)
+ audio_dev_del_control(ctrlp->af_ctrlp);
+
+ usb_audio_ctrl_free(ctrlp);
+ mutex_enter(&statep->usb_ac_mutex);
+ statep->controls[i] = NULL;
+ mutex_exit(&statep->usb_ac_mutex);
+ }
+ }
+
+}
+
+
+static int
+usb_ac_add_controls(usb_ac_state_t *statep)
+{
+ int rv = USB_FAILURE;
+ usb_audio_format_t *format;
+
+
+ if (statep->engines[0].af_engp) {
+ /* Init controls for play format */
+ format = &(statep->engines[0].fmt);
+ if (format->ch == 2) {
+ (void) usb_audio_ctrl_alloc(statep, CTL_VOLUME_STERO,
+ statep->engines[0].af_defgain);
+ } else {
+ (void) usb_audio_ctrl_alloc(statep, CTL_VOLUME_MONO,
+ statep->engines[0].af_defgain);
+ }
+
+ }
+
+ /* Init controls for rec format */
+ if (statep->engines[1].af_engp) {
+ format = &(statep->engines[1].fmt);
+ if (format->ch == 2) {
+ (void) usb_audio_ctrl_alloc(statep, CTL_REC_STERO,
+ statep->engines[1].af_defgain);
+ } else {
+ (void) usb_audio_ctrl_alloc(statep, CTL_REC_MONO,
+ statep->engines[1].af_defgain);
+ }
+
+ /* Add monitor control */
+ {
+ (void) usb_audio_ctrl_alloc(statep,
+ CTL_MONITOR_GAIN, 0);
+ }
+
+ /* Add ports control */
+ {
+ (void) usb_audio_ctrl_alloc(statep, CTL_REC_SRC,
+ statep->usb_ac_input_ports);
+ }
+
+ }
+
+
+ rv = USB_SUCCESS;
+
+OUT:
+ if (rv != USB_SUCCESS)
+ usb_ac_rem_controls(statep);
+ return (rv);
+}
+
+
+
+
+
+/*ARGSUSED*/
+static int
+usb_audio_unregister(usb_ac_state_t *statep)
+{
+ int i;
+
+ if (statep == NULL)
+ return (USB_SUCCESS);
+
+ if (statep->usb_ac_audio_dev == NULL)
+ return (USB_SUCCESS);
+
+ if ((statep->flags & AF_REGISTERED) &&
+ audio_dev_unregister(statep->usb_ac_audio_dev) != DDI_SUCCESS) {
+ return (USB_FAILURE);
+ }
+ mutex_enter(&statep->usb_ac_mutex);
+ statep->flags &= ~AF_REGISTERED;
+ mutex_exit(&statep->usb_ac_mutex);
+
+ for (i = 0; i < USB_AC_ENG_MAX; i++)
+ usb_ac_rem_eng(statep, &statep->engines[i]);
+
+ usb_ac_rem_controls(statep);
+
+ audio_dev_free(statep->usb_ac_audio_dev);
+
+ mutex_enter(&statep->usb_ac_mutex);
+ statep->usb_ac_audio_dev = NULL;
+ mutex_exit(&statep->usb_ac_mutex);
+
+ return (USB_SUCCESS);
+}
+
+
+static int
+usb_audio_register(usb_ac_state_t *statep) {
+ audio_dev_t *af_devp;
+ int rv = USB_FAILURE;
+ int n;
+
+ af_devp = audio_dev_alloc(statep->usb_ac_dip, 0);
+ audio_dev_set_description(af_devp, "USB Audio");
+ audio_dev_set_version(af_devp, "1.0");
+
+ mutex_enter(&statep->usb_ac_mutex);
+ statep->usb_ac_audio_dev = af_devp;
+ mutex_exit(&statep->usb_ac_mutex);
+
+
+ for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) {
+ if (usb_ac_add_eng(statep, &(statep->usb_ac_streams[n]))
+ != USB_SUCCESS) {
+ USB_DPRINTF_L2(PRINT_MASK_ATTA,
+ statep->usb_ac_log_handle,
+ "usb_audio_register: add engine n =%d failed", n);
+ goto OUT;
+ }
+ }
+
+
+ if (usb_ac_add_controls(statep) != USB_SUCCESS) {
+ USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
+ "usb_audio_register: add controls failed");
+ goto OUT;
+ }
+
+ if (usb_ac_ctrl_set_defaults(statep) != USB_SUCCESS) {
+ USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
+ "usb_audio_register: set defaults failed");
+ goto OUT;
+ }
+
+ if (audio_dev_register(af_devp) != DDI_SUCCESS) {
+ USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
+ "audio_dev_register() failed");
+ goto OUT;
+ }
+ mutex_enter(&statep->usb_ac_mutex);
+ statep->flags |= AF_REGISTERED;
+ mutex_exit(&statep->usb_ac_mutex);
+
+ rv = USB_SUCCESS;
+
+OUT:
+ if (rv != USB_SUCCESS) {
+ (void) usb_audio_unregister(statep);
+ }
+ return (rv);
+}
+
+
+int
+usb_ac_get_audio(void *handle, void *buf, int samples)
+{
+ usb_ac_state_t *statep = (usb_ac_state_t *)(handle);
+ usb_audio_eng_t *engp = &(statep->engines[0]);
+ unsigned reqframes = samples >> engp->frsmshift;
+ unsigned frames;
+ unsigned i;
+ size_t sz;
+ int bufcnt = 0;
+ caddr_t bp = buf;
+
+ if (!engp->started) {
+ return (0);
+ }
+
+ /* break requests from the driver into fragment sized chunks */
+ for (i = 0; i < reqframes; i += frames) {
+
+ mutex_enter(&engp->lock);
+ frames = reqframes - i;
+ if (frames > engp->fragfr)
+ frames = engp->fragfr;
+
+ sz = (frames << engp->frsmshift) << engp->smszshift;
+
+ bufcnt++;
+
+ /* must move data before updating framework */
+ usb_eng_bufio(engp, bp, sz);
+ engp->frames += frames;
+ bp += sz;
+
+ mutex_exit(&engp->lock);
+ audio_engine_consume(engp->af_engp);
+ }
+
+ mutex_enter(&engp->lock);
+ engp->io_count++;
+ mutex_exit(&engp->lock);
+
+ return (samples);
+}
+
+
+
+void
+usb_ac_send_audio(void *handle, void *buf, int samples)
+{
+ usb_ac_state_t *statep = (usb_ac_state_t *)(handle);
+ usb_audio_eng_t *engp = &(statep->engines[1]);
+ unsigned reqframes = samples >> engp->frsmshift;
+ unsigned frames;
+ unsigned i;
+ size_t sz;
+ int bufcnt = 0;
+ caddr_t bp = buf;
+
+ mutex_enter(&engp->lock);
+
+ if (!engp->started) {
+
+ mutex_exit(&engp->lock);
+ return;
+ }
+ mutex_exit(&engp->lock);
+
+ /* break requests from the driver into fragment sized chunks */
+ for (i = 0; i < reqframes; i += frames) {
+ mutex_enter(&engp->lock);
+
+ frames = reqframes - i;
+ if (frames > engp->fragfr)
+ frames = engp->fragfr;
+
+ sz = (frames << engp->frsmshift) << engp->smszshift;
+
+ bufcnt++;
+
+ /* must move data before updating framework */
+ usb_eng_bufio(engp, bp, sz);
+ engp->frames += frames;
+ bp += sz;
+
+ mutex_exit(&engp->lock);
+ audio_engine_produce(engp->af_engp);
+ }
+
+ mutex_enter(&engp->lock);
+ engp->io_count++;
+ mutex_exit(&engp->lock);
+}
+
+
+/*
+ * **************************************************************************
+ * audio framework engine callbacks
+ */
+/*ARGSUSED*/
+static int
+usb_engine_open(void *arg, int flag,
+ unsigned *fragfrp, unsigned *nfragsp, caddr_t *bufp)
+{
+ usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
+ usb_ac_state_t *statep = engp->statep;
+ int rv = EIO;
+
+
+ if (usb_ac_open(statep->usb_ac_dip) != USB_SUCCESS) {
+
+ USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
+ "usb_ac_open() failed");
+ return (EIO);
+ }
+
+ mutex_enter(&engp->lock);
+
+ engp->intrate = 150;
+ engp->sampsz = engp->fmt.prec / 8;
+ engp->framesz = engp->sampsz * engp->fmt.ch;
+
+ if (engp->fmt.ch > 2) {
+ USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
+ "unsupported channel count: %u", engp->fmt.ch);
+ mutex_exit(&engp->lock);
+ goto OUT;
+ }
+ if (engp->fmt.prec > 16) {
+ USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
+ "unsupported precision: %u", engp->fmt.prec);
+ mutex_exit(&engp->lock);
+ goto OUT;
+ }
+
+ engp->frsmshift = engp->fmt.ch / 2;
+ engp->smszshift = engp->sampsz / 2;
+
+ /*
+ * In order to match the requested number of samples per interrupt
+ * from SADA drivers when computing the fragment size,
+ * we need to first truncate the floating point result from
+ * sample rate * channels / intr rate
+ * then adjust up to an even number, before multiplying it
+ * with the sample size
+ */
+ engp->fragsz = engp->fmt.sr * engp->fmt.ch / engp->intrate;
+ if (engp->fragsz & 1)
+ engp->fragsz++;
+ engp->fragsz *= engp->sampsz;
+ engp->fragfr = engp->fragsz / engp->framesz;
+
+ engp->nfrags = 10;
+ engp->bufsz = engp->fragsz * engp->nfrags;
+
+ engp->bufp = kmem_zalloc(engp->bufsz, KM_SLEEP);
+ engp->bufpos = engp->bufp;
+ engp->bufendp = engp->bufp + engp->bufsz;
+ engp->frames = 0;
+ engp->io_count = 0;
+ engp->bufio_count = 0;
+
+ *fragfrp = engp->fragfr;
+ *nfragsp = engp->nfrags;
+ *bufp = engp->bufp;
+
+ mutex_exit(&engp->lock);
+
+ if (usb_ac_setup(statep, engp) != USB_SUCCESS) {
+ USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
+ "device setup failed");
+ goto OUT;
+ }
+
+
+
+ mutex_enter(&statep->usb_ac_mutex);
+ statep->flags |= AD_SETUP;
+ mutex_exit(&statep->usb_ac_mutex);
+
+ rv = 0;
+
+
+OUT:
+ if (rv != 0)
+ usb_engine_close(arg);
+
+ return (rv);
+}
+
+
+static void
+usb_engine_close(void *arg)
+{
+ usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
+ usb_ac_state_t *statep = engp->statep;
+
+ if (statep->flags & AD_SETUP) {
+ usb_ac_teardown(statep, engp);
+ mutex_enter(&statep->usb_ac_mutex);
+ statep->flags &= ~AD_SETUP;
+ mutex_exit(&statep->usb_ac_mutex);
+ }
+ mutex_enter(&engp->lock);
+
+ if (engp->bufp != NULL) {
+ kmem_free(engp->bufp, engp->bufsz);
+ engp->bufp = NULL;
+ engp->bufpos = NULL;
+ engp->bufendp = NULL;
+ }
+
+ mutex_exit(&engp->lock);
+
+ usb_ac_close(statep->usb_ac_dip);
+}
+
+
+
+static int
+usb_engine_start(void *arg)
+{
+ usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
+ int rv = 0;
+ int (*start)(usb_ac_state_t *, usb_audio_eng_t *);
+
+ mutex_enter(&engp->lock);
+ engp->started = B_TRUE;
+ mutex_exit(&engp->lock);
+
+ usb_ac_state_t *statep = engp->statep;
+
+ start = ((engp)->af_eflags & ENGINE_OUTPUT_CAP) ?
+ usb_ac_start_play : usb_ac_start_record;
+
+ if ((*start)(statep, engp) != USB_SUCCESS) {
+ USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
+ "failed to start %d engine", engp->af_eflags);
+ rv = EIO;
+ }
+
+
+ return (rv);
+}
+
+
+static void
+usb_engine_stop(void *arg)
+{
+ usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
+
+ mutex_enter(&engp->lock);
+ engp->started = B_FALSE;
+ mutex_exit(&engp->lock);
+
+ usb_ac_state_t *statep = engp->statep;
+ void (*stop)(usb_ac_state_t *, usb_audio_eng_t *);
+
+ stop = ((engp)->af_eflags & ENGINE_OUTPUT_CAP) ?
+ usb_ac_stop_play : usb_ac_stop_record;
+
+ (*stop)(statep, engp);
+}
+
+
+static uint64_t
+usb_engine_count(void *arg)
+{
+ usb_audio_eng_t *engp = arg;
+ uint64_t val;
+
+ mutex_enter(&engp->lock);
+ val = engp->frames;
+ mutex_exit(&engp->lock);
+
+ return (val);
+}
+
+
+static int
+usb_engine_format(void *arg)
+{
+ usb_audio_eng_t *engp = arg;
+
+ switch (engp->fmt.enc) {
+ case USB_AUDIO_FORMAT_TYPE1_MULAW:
+ return (AUDIO_FORMAT_ULAW);
+ case USB_AUDIO_FORMAT_TYPE1_ALAW:
+ return (AUDIO_FORMAT_ALAW);
+ case USB_AUDIO_FORMAT_TYPE1_PCM8:
+ return (AUDIO_FORMAT_U8);
+
+ case USB_AUDIO_FORMAT_TYPE1_PCM:
+ break;
+ default:
+ return (AUDIO_FORMAT_NONE);
+ }
+
+ switch (engp->fmt.prec) {
+ case 8:
+ return (AUDIO_FORMAT_S8);
+ case 16:
+ return (AUDIO_FORMAT_S16_LE);
+ case 24:
+ return (AUDIO_FORMAT_S24_LE);
+ case 32:
+ return (AUDIO_FORMAT_S32_LE);
+ default:
+ break;
+ }
+ return (AUDIO_FORMAT_NONE);
+
+
+}
+
+static int
+usb_engine_channels(void *arg)
+{
+ usb_audio_eng_t *engp = arg;
+
+ return (engp->fmt.ch);
+}
+
+
+static int
+usb_engine_rate(void *arg)
+{
+ usb_audio_eng_t *engp = arg;
+
+ return (engp->fmt.sr);
+}
+
+
+/*ARGSUSED*/
+static void
+usb_engine_sync(void *arg, unsigned nframes)
+{
+ /* Do nothing */
+}
+
+
+static size_t
+usb_engine_qlen(void *arg)
+{
+ usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
+
+ return (engp->fragfr);
+}
+
+/*
+ * **************************************************************************
+ * interfaces used by USB audio
+ */
+
+/*ARGSUSED*/
+static int
+usb_change_phy_vol(usb_ac_state_t *statep, int value)
+{
+ usb_audio_ctrl_t *ctrlp;
+ uint64_t cval = 0;
+ int64_t left, right, delta = 0;
+
+ ctrlp = statep->controls[CTL_VOLUME_STERO];
+
+ ASSERT(value != 0);
+
+ delta = (value < 0)?-1:1;
+
+ left = AUDIO_CTRL_STEREO_LEFT(ctrlp->cval) + delta;
+ right = AUDIO_CTRL_STEREO_RIGHT(ctrlp->cval) + delta;
+
+ if (left > AF_MAX_GAIN)
+ left = AF_MAX_GAIN;
+ if (right > AF_MAX_GAIN)
+ right = AF_MAX_GAIN;
+
+ if (left < AF_MIN_GAIN)
+ left = AF_MIN_GAIN;
+ if (right < AF_MIN_GAIN)
+ right = AF_MIN_GAIN;
+
+ cval = AUDIO_CTRL_STEREO_VAL(left, right);
+
+ if (audio_control_write(ctrlp->af_ctrlp, cval)) {
+ USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
+ "updateing control to value 0x%llx by driver failed",
+ (long long unsigned)cval);
+ return (USB_FAILURE);
+ }
+ return (USB_SUCCESS);
+}
diff --git a/usr/src/uts/common/io/usb/clients/audio/usb_ah/usb_ah.c b/usr/src/uts/common/io/usb/clients/audio/usb_ah/usb_ah.c
index 5d4d6fe05a..3b84d3069f 100644
--- a/usr/src/uts/common/io/usb/clients/audio/usb_ah/usb_ah.c
+++ b/usr/src/uts/common/io/usb/clients/audio/usb_ah/usb_ah.c
@@ -48,10 +48,6 @@
#include <sys/stropts.h>
#include <sys/strsun.h>
-#include <sys/audio.h>
-#include <sys/audio/audio_support.h>
-#include <sys/mixer.h>
-#include <sys/audio/audio_mixer.h>
#include <sys/usb/clients/audio/usb_audio.h>
#include <sys/usb/clients/audio/usb_mixer.h>
diff --git a/usr/src/uts/common/io/usb/clients/audio/usb_as/usb_as.c b/usr/src/uts/common/io/usb/clients/audio/usb_as/usb_as.c
index baa991d736..8777be9ed0 100644
--- a/usr/src/uts/common/io/usb/clients/audio/usb_as/usb_as.c
+++ b/usr/src/uts/common/io/usb/clients/audio/usb_as/usb_as.c
@@ -25,10 +25,6 @@
/*
* Audio Streams Interface Driver:
- * This driver is derived from the legacy SADA streams-based usb_as driver
- * and serves as an intermediate measure before the full conversion to the
- * to the Boomer framework in a follow-on phase of the Boomer project, which
- * will utilize more comprehensive USB audio features as well.
*
* usb_as is responsible for (1) Processing audio data messages during
* play and record and management of isoc pipe, (2) Selecting correct
@@ -58,16 +54,13 @@
#include <sys/ddi.h>
#include <sys/sunddi.h>
-#include <sys/audio.h>
-#include <sys/audio/audio_support.h>
-#include <sys/mixer.h>
-#include <sys/audio/audio_mixer.h>
+#include <sys/audio/audio_driver.h>
#include <sys/usb/clients/audio/usb_audio.h>
#include <sys/usb/clients/audio/usb_mixer.h>
#include <sys/usb/clients/audio/usb_as/usb_as.h>
+#include <sys/usb/clients/audio/usb_ac/usb_ac.h>
-#include "../usb_ac/audio_shim.h"
/* debug support */
uint_t usb_as_errlevel = USB_LOG_L4;
@@ -94,7 +87,6 @@ static void usb_as_prepare_registration_data(usb_as_state_t *);
static int usb_as_valid_format(usb_as_state_t *, uint_t,
uint_t *, uint_t);
static void usb_as_free_alts(usb_as_state_t *);
-static int usb_audio_fmt_convert(int);
static void usb_as_create_pm_components(dev_info_t *, usb_as_state_t *);
static int usb_as_disconnect_event_cb(dev_info_t *);
@@ -123,7 +115,7 @@ static int usb_as_set_sample_freq(usb_as_state_t *, int);
static int usb_as_send_ctrl_cmd(usb_as_state_t *, uchar_t, uchar_t,
ushort_t, ushort_t, ushort_t, mblk_t *, boolean_t);
-static int usb_as_start_record(usb_as_state_t *, audiohdl_t);
+static int usb_as_start_record(usb_as_state_t *, void *);
static int usb_as_stop_record(usb_as_state_t *);
static void usb_as_play_cb(usb_pipe_handle_t, usb_isoc_req_t *);
static void usb_as_record_cb(usb_pipe_handle_t, usb_isoc_req_t *);
@@ -213,6 +205,9 @@ static uint_t usb_as_default_srs[] = {
32000, 33075, 37800, 44100, 48000, 0
};
+_NOTE(SCHEME_PROTECTS_DATA("unique per call", mblk_t))
+_NOTE(SCHEME_PROTECTS_DATA("unique per call", usb_isoc_req_t))
+_NOTE(SCHEME_PROTECTS_DATA("unique per call", usb_isoc_pkt_descr))
int
_init(void)
@@ -360,6 +355,9 @@ usb_as_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
/* initialize mutex */
mutex_init(&uasp->usb_as_mutex, NULL, MUTEX_DRIVER,
uasp->usb_as_dev_data->dev_iblock_cookie);
+
+ cv_init(&uasp->usb_as_pipe_cv, NULL, CV_DRIVER, NULL);
+
uasp->usb_as_ser_acc = usb_init_serialization(dip,
USB_INIT_SER_CHECK_SAME_THREAD);
@@ -676,7 +674,7 @@ usb_as_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
usb_as_pause_play(uasp);
break;
case USB_AUDIO_START_RECORD:
- rv = usb_as_start_record(uasp, *(audiohdl_t *)arg);
+ rv = usb_as_start_record(uasp, (void *)arg);
break;
case USB_AUDIO_STOP_RECORD:
rv = usb_as_stop_record(uasp);
@@ -776,8 +774,6 @@ usb_as_set_format(usb_as_state_t *uasp, usb_audio_formats_t *format)
return (USB_FAILURE);
}
- ASSERT(uasp->usb_as_isoc_ph == NULL);
-
reg = &uasp->usb_as_reg;
interface = uasp->usb_as_ifno;
@@ -808,7 +804,6 @@ usb_as_set_format(usb_as_state_t *uasp, usb_audio_formats_t *format)
return (USB_FAILURE);
}
- ASSERT(uasp->usb_as_isoc_ph == NULL);
USB_DPRINTF_L3(PRINT_MASK_ALL, uasp->usb_as_log_handle,
"usb_as_set_format: interface=%d alternate=%d",
@@ -850,21 +845,37 @@ usb_as_setup(usb_as_state_t *uasp)
usb_ep_descr_t *ep = (usb_ep_descr_t *)uasp->usb_as_alts[alt].alt_ep;
int rval;
+
ASSERT(mutex_owned(&uasp->usb_as_mutex));
USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
"usb_as_setup: Begin usb_as_setup, inst=%d",
ddi_get_instance(uasp->usb_as_dip));
- ASSERT(uasp->usb_as_request_count == 0);
/* Set record packet size to max packet size */
- if (uasp->usb_as_alts[alt].alt_mode == AUDIO_RECORD) {
+ if (uasp->usb_as_alts[alt].alt_mode == USB_AUDIO_RECORD) {
uasp->usb_as_record_pkt_size = ep->wMaxPacketSize;
} else {
uasp->usb_as_record_pkt_size = 0;
}
+ if (uasp->usb_as_isoc_ph != NULL) {
+ while (uasp->usb_as_request_count) {
+ cv_wait(&uasp->usb_as_pipe_cv,
+ &uasp->usb_as_mutex);
+ }
+
+ /* close the isoc pipe which is opened before */
+ mutex_exit(&uasp->usb_as_mutex);
+ usb_pipe_close(uasp->usb_as_dip, uasp->usb_as_isoc_ph,
+ USB_FLAGS_SLEEP, NULL, (usb_opaque_t)NULL);
+
+ mutex_enter(&uasp->usb_as_mutex);
+ uasp->usb_as_isoc_ph = NULL;
+ }
+
+ ASSERT(uasp->usb_as_request_count == 0);
mutex_exit(&uasp->usb_as_mutex);
/* open isoc pipe, may fail if there is no bandwidth */
@@ -922,27 +933,10 @@ usb_as_teardown(usb_as_state_t *uasp)
uasp->usb_as_audio_state = USB_AS_IDLE;
- if (uasp->usb_as_isoc_ph) {
- USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
- "usb_as_teardown: closing isoc pipe, ph=0x%p",
- (void *)uasp->usb_as_isoc_ph);
-
- mutex_exit(&uasp->usb_as_mutex);
-
- /* reply mp will be sent up in isoc close callback */
- usb_pipe_close(uasp->usb_as_dip, uasp->usb_as_isoc_ph,
- USB_FLAGS_SLEEP, NULL, (usb_opaque_t)NULL);
-
- mutex_enter(&uasp->usb_as_mutex);
- uasp->usb_as_isoc_ph = NULL;
+ ASSERT(uasp->usb_as_isoc_ph);
+ /* reset setup flag */
+ uasp->usb_as_setup_cnt--;
- /* reset setup flag */
- uasp->usb_as_setup_cnt--;
-
- } else {
- USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
- "usb_as_teardown: Pipe already closed");
- }
ASSERT(uasp->usb_as_setup_cnt == 0);
@@ -1050,7 +1044,7 @@ usb_as_continue_play(usb_as_state_t *uasp)
static void
usb_as_handle_shutdown(usb_as_state_t *uasp)
{
- audiohdl_t ahdl;
+ void *ahdl;
USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
"usb_as_handle_shutdown, inst=%d",
@@ -1064,7 +1058,7 @@ usb_as_handle_shutdown(usb_as_state_t *uasp)
ahdl = uasp->usb_as_ahdl;
mutex_exit(&uasp->usb_as_mutex);
- am_play_shutdown(ahdl);
+ usb_ac_stop_play(ahdl, NULL);
mutex_enter(&uasp->usb_as_mutex);
}
@@ -1077,7 +1071,7 @@ usb_as_play_isoc_data(usb_as_state_t *uasp, usb_audio_play_req_t *play_req)
usb_isoc_req_t *isoc_req = NULL;
usb_audio_formats_t *format = &uasp->usb_as_curr_format;
mblk_t *data = NULL;
- audiohdl_t ahdl = uasp->usb_as_ahdl;
+ void * ahdl = uasp->usb_as_ahdl;
int precision;
int pkt, frame, n, n_pkts, count;
size_t bufsize;
@@ -1086,15 +1080,15 @@ usb_as_play_isoc_data(usb_as_state_t *uasp, usb_audio_play_req_t *play_req)
ASSERT(mutex_owned(&uasp->usb_as_mutex));
/* we only support two precisions */
- if ((format->fmt_precision != AUDIO_PRECISION_8) &&
- (format->fmt_precision != AUDIO_PRECISION_16)) {
+ if ((format->fmt_precision != USB_AUDIO_PRECISION_8) &&
+ (format->fmt_precision != USB_AUDIO_PRECISION_16)) {
rval = USB_FAILURE;
goto done;
}
- precision = (format->fmt_precision == AUDIO_PRECISION_8) ? 1 : 2;
+ precision = (format->fmt_precision == USB_AUDIO_PRECISION_8) ? 1 : 2;
frame = uasp->usb_as_pkt_count;
@@ -1122,14 +1116,14 @@ usb_as_play_isoc_data(usb_as_state_t *uasp, usb_audio_play_req_t *play_req)
}
/*
- * restriction of Boomer: cannot call am_get_audio() in the context
+ * restriction of Boomer: cannot call usb_ac_get_audio() in the context
* of start so we play a fragment of silence at first
*/
if (play_req != NULL) {
bzero(data->b_wptr, bufsize);
count = bufsize / precision;
- } else if ((count = am_get_audio(ahdl, (void *)data->b_wptr,
+ } else if ((count = usb_ac_get_audio(ahdl, (void *)data->b_wptr,
bufsize / precision)) == 0) {
mutex_enter(&uasp->usb_as_mutex);
if (uasp->usb_as_request_count == 0) {
@@ -1183,20 +1177,6 @@ usb_as_play_isoc_data(usb_as_state_t *uasp, usb_audio_play_req_t *play_req)
}
-#if defined(_BIG_ENDIAN)
- /* byte swap if necessary */
- if (format->fmt_precision == AUDIO_PRECISION_16) {
- int i;
- uchar_t tmp;
- uchar_t *p = data->b_rptr;
-
- for (i = 0; i < bufsize; i += 2, p += 2) {
- tmp = *p;
- *p = *(p + 1);
- *(p + 1) = tmp;
- }
- }
-#endif
/* initialize the packet descriptor */
for (pkt = 0; pkt < n_pkts; pkt++) {
@@ -1231,6 +1211,7 @@ usb_as_play_isoc_data(usb_as_state_t *uasp, usb_audio_play_req_t *play_req)
mutex_enter(&uasp->usb_as_mutex);
uasp->usb_as_request_count--;
+ cv_signal(&uasp->usb_as_pipe_cv);
uasp->usb_as_send_debug_count--;
uasp->usb_as_pkt_count -= n_pkts;
@@ -1307,6 +1288,7 @@ usb_as_play_cb(usb_pipe_handle_t ph, usb_isoc_req_t *isoc_req)
usb_free_isoc_req(isoc_req);
uasp->usb_as_request_count--;
+ cv_signal(&uasp->usb_as_pipe_cv);
uasp->usb_as_rcv_debug_count++;
usb_as_continue_play(uasp);
@@ -1355,6 +1337,7 @@ usb_as_play_exc_cb(usb_pipe_handle_t ph, usb_isoc_req_t *isoc_req)
mutex_enter(&uasp->usb_as_mutex);
uasp->usb_as_rcv_debug_count++;
uasp->usb_as_request_count--;
+ cv_signal(&uasp->usb_as_pipe_cv);
usb_as_handle_shutdown(uasp);
USB_DPRINTF_L2(PRINT_MASK_ALL, uasp->usb_as_log_handle,
@@ -1373,7 +1356,7 @@ usb_as_play_exc_cb(usb_pipe_handle_t ph, usb_isoc_req_t *isoc_req)
* usb_as_start_record
*/
static int
-usb_as_start_record(usb_as_state_t *uasp, audiohdl_t ahdl)
+usb_as_start_record(usb_as_state_t *uasp, void * ahdl)
{
int rval = USB_FAILURE;
usb_isoc_req_t *isoc_req;
@@ -1552,7 +1535,7 @@ usb_as_record_cb(usb_pipe_handle_t ph, usb_isoc_req_t *isoc_req)
{
usb_as_state_t *uasp = (usb_as_state_t *)isoc_req->isoc_client_private;
int i, offset, sz;
- audiohdl_t ahdl;
+ void * ahdl;
usb_audio_formats_t *format = &uasp->usb_as_curr_format;
int precision;
@@ -1572,26 +1555,10 @@ usb_as_record_cb(usb_pipe_handle_t ph, usb_isoc_req_t *isoc_req)
mutex_enter(&uasp->usb_as_mutex);
ahdl = uasp->usb_as_ahdl;
sz = uasp->usb_as_record_pkt_size;
- precision = (format->fmt_precision == AUDIO_PRECISION_8) ? 1 : 2;
+ precision = (format->fmt_precision == USB_AUDIO_PRECISION_8) ? 1 : 2;
if (uasp->usb_as_audio_state != USB_AS_IDLE) {
-#if defined(_BIG_ENDIAN)
- unsigned char *ptr = isoc_req->isoc_data->b_rptr;
-#endif
for (offset = i = 0; i < isoc_req->isoc_pkts_count; i++) {
-#if defined(_BIG_ENDIAN)
- int len = isoc_req->isoc_pkt_descr[i].
- isoc_pkt_actual_length;
- /* do byte swap for precision 16 */
- if (format->fmt_precision == AUDIO_PRECISION_16) {
- int j;
- for (j = 0; j < len; j += 2, ptr += 2) {
- char t = *ptr;
- *ptr = *(ptr + 1);
- *(ptr + 1) = t;
- }
- }
-#endif
USB_DPRINTF_L3(PRINT_MASK_CB, uasp->usb_as_log_handle,
"\tpkt%d: "
"offset=%d pktsize=%d len=%d status=%d resid=%d",
@@ -1610,7 +1577,7 @@ usb_as_record_cb(usb_pipe_handle_t ph, usb_isoc_req_t *isoc_req)
}
mutex_exit(&uasp->usb_as_mutex);
- am_send_audio(ahdl,
+ usb_ac_send_audio(ahdl,
isoc_req->isoc_data->b_rptr + offset,
isoc_req->isoc_pkt_descr[i].isoc_pkt_actual_length /
precision);
@@ -1693,7 +1660,7 @@ usb_as_get_pktsize(usb_as_state_t *uasp, usb_audio_formats_t *format,
pkt_size = (((frameno + 1) % cycle) ?
pkt : (pkt + extra));
pkt_size *= ((format->fmt_precision ==
- AUDIO_PRECISION_16) ? 2 : 1)
+ USB_AUDIO_PRECISION_16) ? 2 : 1)
* format->fmt_chns;
break;
}
@@ -2167,7 +2134,7 @@ usb_as_handle_descriptors(usb_as_state_t *uasp)
uasp->usb_as_alts[alternate].alt_mode =
(ep->bEndpointAddress & USB_EP_DIR_IN) ?
- AUDIO_RECORD : AUDIO_PLAY;
+ USB_AUDIO_RECORD : USB_AUDIO_PLAY;
if (ep_data->ep_n_cvs == 0) {
USB_DPRINTF_L2(PRINT_MASK_ATTA,
@@ -2273,7 +2240,7 @@ usb_as_prepare_registration_data(usb_as_state_t *uasp)
usb_audio_type1_format_descr_t *format;
uchar_t n_alternates = uasp->usb_as_n_alternates;
uchar_t channels[3];
- int alt, n, i, t;
+ int alt, n;
USB_DPRINTF_L4(PRINT_MASK_ATTA, uasp->usb_as_log_handle,
"usb_as_prepare_registration_data:");
@@ -2334,7 +2301,7 @@ usb_as_prepare_registration_data(usb_as_state_t *uasp)
reg->reg_formats[n].fmt_precision =
format->bBitResolution;
reg->reg_formats[n++].fmt_encoding =
- usb_audio_fmt_convert(format->bFormatType);
+ format->bFormatType;
/* count how many mono and stereo we have */
channels[format->bNrChannels]++;
}
@@ -2353,7 +2320,9 @@ usb_as_prepare_registration_data(usb_as_state_t *uasp)
/* dump what we have so far */
for (n = 0; n < reg->reg_n_formats; n++) {
USB_DPRINTF_L3(PRINT_MASK_ATTA, uasp->usb_as_log_handle,
- "format%d: alt=%d chns=%d prec=%d enc=%d", n,
+ "regformats[%d]: termlink = %d, alt=%d chns=%d"
+ " prec=%d enc=%d", n,
+ reg->reg_formats[n].fmt_termlink,
reg->reg_formats[n].fmt_alt,
reg->reg_formats[n].fmt_chns,
reg->reg_formats[n].fmt_precision,
@@ -2367,44 +2336,16 @@ usb_as_prepare_registration_data(usb_as_state_t *uasp)
*/
n = 0;
if (channels[1]) {
- reg->reg_channels[n++] = AUDIO_CHANNELS_MONO;
+ reg->reg_channels[n++] = 1;
}
if (channels[2]) {
- reg->reg_channels[n] = AUDIO_CHANNELS_STEREO;
+ reg->reg_channels[n] = 2;
}
USB_DPRINTF_L3(PRINT_MASK_ATTA, uasp->usb_as_log_handle,
"channels %d %d", reg->reg_channels[0], reg->reg_channels[1]);
- /* fill out combinations */
- for (i = n = 0; n < reg->reg_n_formats; n++) {
- uchar_t prec = reg->reg_formats[n].fmt_precision;
- uchar_t enc = reg->reg_formats[n].fmt_encoding;
-
- /* check if already there */
- for (t = 0; t < n; t++) {
- uchar_t ad_prec = reg->reg_combinations[t].ad_prec;
- uchar_t ad_enc = reg->reg_combinations[t].ad_enc;
- if ((prec == ad_prec) && (enc == ad_enc)) {
- break;
- }
- }
-
- /* if not, add this combination */
- if (t == n) {
- reg->reg_combinations[i].ad_prec = prec;
- reg->reg_combinations[i++].ad_enc = enc;
- }
- }
-
-
- USB_DPRINTF_L3(PRINT_MASK_ATTA, uasp->usb_as_log_handle,
- "combinations: %d %d %d %d %d %d %d %d",
- reg->reg_combinations[0].ad_prec, reg->reg_combinations[0].ad_enc,
- reg->reg_combinations[1].ad_prec, reg->reg_combinations[1].ad_enc,
- reg->reg_combinations[2].ad_prec, reg->reg_combinations[2].ad_enc,
- reg->reg_combinations[3].ad_prec, reg->reg_combinations[3].ad_enc);
reg->reg_valid++;
}
@@ -2489,7 +2430,7 @@ usb_as_valid_format(usb_as_state_t *uasp, uint_t alternate,
break;
}
- USB_DPRINTF_L4(PRINT_MASK_PM, uasp->usb_as_log_handle,
+ USB_DPRINTF_L3(PRINT_MASK_PM, uasp->usb_as_log_handle,
"checking sr=%d", sr);
for (i = 0; i < alt_descr->alt_n_sample_rates; i++) {
if (sr == alt_descr->alt_sample_rates[i]) {
@@ -2544,30 +2485,6 @@ usb_as_valid_format(usb_as_state_t *uasp, uint_t alternate,
}
-/*
- * convert usb audio format type to SADA type
- */
-static int
-usb_audio_fmt_convert(int type)
-{
- switch (type) {
- case USB_AUDIO_FORMAT_TYPE1_PCM:
- return (AUDIO_ENCODING_LINEAR);
-
- case USB_AUDIO_FORMAT_TYPE1_PCM8:
- return (AUDIO_ENCODING_LINEAR8);
-
- case USB_AUDIO_FORMAT_TYPE1_ALAW:
- return (AUDIO_ENCODING_ALAW);
-
- case USB_AUDIO_FORMAT_TYPE1_MULAW:
- return (AUDIO_ENCODING_ULAW);
-
- case USB_AUDIO_FORMAT_TYPE1_IEEE_FLOAT:
- default:
- return (0);
- }
-}
/*
diff --git a/usr/src/uts/common/io/warlock/usb_ac.wlcmd b/usr/src/uts/common/io/warlock/usb_ac.wlcmd
index 6a68d90059..8436bdcf91 100644
--- a/usr/src/uts/common/io/warlock/usb_ac.wlcmd
+++ b/usr/src/uts/common/io/warlock/usb_ac.wlcmd
@@ -28,15 +28,11 @@ one usb_ac_state
### specify the root functions
root usb_ac_open
root usb_ac_close
-root usb_ac_lrput
-root usb_ac_uwput
root usb_ac_disconnect_event_cb
root usb_ac_reconnect_event_cb
root usb_ac_power
-root usb_ac_pause_play
-root usb_ac_set_config
root usb_ac_set_format
root usb_ac_setup
root usb_ac_start_play
@@ -45,6 +41,35 @@ root usb_ac_stop_play
root usb_ac_stop_record
root usb_ac_teardown
+root usb_ac_get_audio
+root usb_ac_send_audio
+root usb_ac_ctrl_restore
+root usb_audio_set_mute
+
+root usb_engine_start
+root usb_engine_stop
+root usb_engine_sync
+root usb_engine_rate
+root usb_engine_format
+root usb_engine_count
+root usb_engine_close
+root usb_engine_channels
+root usb_engine_open
+root usb_engine_qlen
+
+root usb_ac_mux_plumbing_tq
+root usb_ac_mux_unplumbing_tq
+root usb_ac_reader
+
+root usb_audio_write_monitor_gain
+root usb_audio_write_mono_rec
+root usb_audio_write_mono_vol
+root usb_audio_write_ster_vol
+root usb_audio_write_stero_rec
+root usb_audio_write_rec_src
+root usb_audio_write_mic_boost
+root usb_audio_ctrl_read
+
add bus_ops::bus_add_eventcall targets warlock_dummy
add bus_ops::bus_get_eventcookie targets warlock_dummy
add bus_ops::bus_post_event targets warlock_dummy
diff --git a/usr/src/uts/common/io/warlock/usb_ac_with_sada.wlcmd b/usr/src/uts/common/io/warlock/usb_ac_with_sada.wlcmd
deleted file mode 100644
index 9442430d7f..0000000000
--- a/usr/src/uts/common/io/warlock/usb_ac_with_sada.wlcmd
+++ /dev/null
@@ -1,151 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-# warlock command file
-
-one usb_ac_state
-one audio_ch
-one audio_apm_info
-one audio_state
-one am_apm_private
-
-
-# unused functions
-
-root am_hw_state_change
-
-root audio_sup_devt_to_ch_type
-root audio_sup_get_qptr_data
-root audio_sup_open
-root audio_sup_close
-root audio_sup_rput
-root audio_sup_rsvc
-root audio_sup_wput
-root audio_sup_wsvc
-root audio_sup_ch_to_minor
-root audio_sup_construct_minor
-root audio_sup_devt_to_instance
-root audio_sup_free_qptr
-root audio_sup_get_channel_number
-root audio_sup_get_dip
-root audio_sup_get_info
-root audio_sup_get_max_chs
-root audio_sup_get_qptr_instance
-root audio_sup_set_qptr
-root audio_sup_save_audio_data
-root audio_sup_save_state
-root audio_sup_attach
-root audio_sup_detach
-root audio_sup_update_persist_key
-root audio_sup_getinfo
-
-root am_get_src_data
-root am_set_src_data
-root am_hw_state_change
-root am_get_audio
-root am_play_shutdown
-root am_send_audio
-
-# threads
-root am_diag_loopback_task
-root am_get_chinfo_task
-root am_get_mode_task
-root am_getinfo_task
-root am_mixer_task_acknack
-root am_mixerctl_getinfo_task
-root am_mixerctl_setinfo_task
-root am_multiple_open_task
-root am_sample_rate_task
-root am_set_chinfo_task
-root am_set_mode_task
-root am_setinfo_task
-root am_single_open_task
-root am_hw_task
-
-### specify the usb_ac root functions
-root usb_ac_open
-root usb_ac_close
-root usb_ac_disconnect_event_cb
-root usb_ac_reconnect_event_cb
-root usb_ac_power
-root usb_ac_lrput
-root usb_ac_uwput
-
-root usb_ac_print_reg_data
-root usb_ac_am_restore_state
-
-
-# function pointers
-add audio_ch::ch_rput targets am_rput
-add audio_ch::ch_rsvc targets am_rsvc
-add audio_ch::ch_wput targets am_wput
-add audio_ch::ch_wsvc targets am_wsvc
-add audio_apm_info::apm_open targets am_open_audio
-add audio_apm_info::apm_close targets am_close_audio
-add audio_apm_info::apm_open targets am_open_audioctl
-add audio_apm_info::apm_close targets am_close_audioctl
-add audio_apm_info::apm_restore_state targets am_restore_state
-add audio_apm_info::apm_save_state targets am_save_state
-
-
-add am_ad_entry::ad_setup targets usb_ac_setup
-add am_ad_entry::ad_teardown targets usb_ac_teardown
-add am_ad_entry::ad_set_config targets usb_ac_set_config
-add am_ad_entry::ad_set_format targets usb_ac_set_format
-add am_ad_entry::ad_start_play targets usb_ac_start_play
-add am_ad_entry::ad_pause_play targets usb_ac_pause_play
-add am_ad_entry::ad_stop_play targets usb_ac_stop_play
-add am_ad_entry::ad_start_record targets usb_ac_start_record
-add am_ad_entry::ad_stop_record targets usb_ac_stop_record
-add am_ad_entry::ad_ioctl targets warlock_dummy
-add am_ad_entry::ad_iocdata targets warlock_dummy
-
-add bus_ops::bus_add_eventcall targets warlock_dummy
-add bus_ops::bus_get_eventcookie targets warlock_dummy
-add bus_ops::bus_intr_ctl targets warlock_dummy
-add bus_ops::bus_post_event targets warlock_dummy
-add bus_ops::bus_remove_eventcall targets warlock_dummy
-add bus_ops::bus_config targets warlock_dummy
-add bus_ops::bus_unconfig targets warlock_dummy
-
-add am_ad_src_entry::ad_src_adjust targets am_src2_adjust
-add am_ad_src_entry::ad_src_convert targets am_src2_convert
-add am_ad_src_entry::ad_src_exit targets am_src2_exit
-add am_ad_src_entry::ad_src_init targets am_src2_init
-add am_ad_src_entry::ad_src_size targets am_src2_size
-add am_ad_src_entry::ad_src_update targets am_src2_update
-
-add usb_ac_state_space::restore_func targets usb_ac_restore_audio_state
-
-
-# we should never hold as_lock while jumping into another module
-# and with this rule we *sometimes* get these
-assert order audio_state::as_lock audio_ch::ch_lock usb_ac_state::usb_ac_mutex
-
-# this locking order catches problems when the framework holds locks
-# over calling into the driver
-#assert order usb_ac_state::usb_ac_mutex audio_state::as_lock audio_ch::ch_lock
-
-
diff --git a/usr/src/uts/common/io/warlock/usb_ac_with_usba.wlcmd b/usr/src/uts/common/io/warlock/usb_ac_with_usba.wlcmd
index dd4c0a0f46..b557303fe5 100644
--- a/usr/src/uts/common/io/warlock/usb_ac_with_usba.wlcmd
+++ b/usr/src/uts/common/io/warlock/usb_ac_with_usba.wlcmd
@@ -90,6 +90,9 @@ root usb_register_hotplug_cbs
root usb_get_current_cfgidx
root usb_register_client
root usb_reset_device
+root usb_register_dev_driver
+root usb_unregister_dev_driver
+
root hcdi_autoclearing
root hcdi_cb_thread
@@ -156,11 +159,6 @@ root usb_ac_close
root usb_ac_disconnect_event_cb
root usb_ac_reconnect_event_cb
root usb_ac_power
-root usb_ac_lrput
-root usb_ac_uwput
-root usb_ac_power
-root usb_ac_pause_play
-root usb_ac_set_config
root usb_ac_set_format
root usb_ac_setup
root usb_ac_start_play
@@ -169,6 +167,36 @@ root usb_ac_stop_play
root usb_ac_stop_record
root usb_ac_teardown
+root usb_ac_get_audio
+root usb_ac_send_audio
+root usb_ac_ctrl_restore
+root usb_audio_set_mute
+
+root usb_engine_start
+root usb_engine_stop
+root usb_engine_sync
+root usb_engine_rate
+root usb_engine_format
+root usb_engine_count
+root usb_engine_close
+root usb_engine_channels
+root usb_engine_open
+root usb_engine_qlen
+
+root usb_ac_mux_plumbing_tq
+root usb_ac_mux_unplumbing_tq
+root usb_ac_reader
+
+root usb_audio_write_monitor_gain
+root usb_audio_write_mono_rec
+root usb_audio_write_mono_vol
+root usb_audio_write_ster_vol
+root usb_audio_write_stero_rec
+root usb_audio_write_rec_src
+root usb_audio_write_mic_boost
+root usb_audio_ctrl_read
+
+
add hubd::h_cleanup_child targets warlock_dummy
add usba_pipe_async_req::sync_func targets usba_pipe_sync_close
add usba_pipe_async_req::sync_func targets usba_pipe_sync_reset
@@ -191,8 +219,3 @@ add ehci_trans_wrapper::tw_handle_qtd targets ehci_handle_ctrl_qtd
add ehci_trans_wrapper::tw_handle_qtd targets ehci_handle_bulk_qtd
add ehci_trans_wrapper::tw_handle_qtd targets ehci_handle_intr_qtd
-add usb_ac_state_space::restore_func targets usb_ac_restore_audio_state
-add usb_ac_state_space::get_featureID_func targets usb_ac_get_featureID
-add usb_ac_state_space::pm_busy_component targets usb_ac_pm_busy_component
-add usb_ac_state_space::pm_idle_component targets usb_ac_pm_idle_component
-
diff --git a/usr/src/uts/common/io/warlock/usb_as.wlcmd b/usr/src/uts/common/io/warlock/usb_as.wlcmd
index e87d20ecff..4016abb9de 100644
--- a/usr/src/uts/common/io/warlock/usb_as.wlcmd
+++ b/usr/src/uts/common/io/warlock/usb_as.wlcmd
@@ -1,5 +1,5 @@
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# CDDL HEADER START
@@ -22,23 +22,18 @@
# CDDL HEADER END
#
-#ident "%Z%%M% %I% %E% SMI"
one usb_as_state
### specify the root functions
-root usb_as_default_xfer_cb
-root usb_as_default_xfer_exc_cb
root usb_as_disconnect_event_cb
root usb_as_reconnect_event_cb
root usb_as_open
root usb_as_close
-root usb_as_wsrv
root usb_as_power
-root usb_as_isoc_close_cb
root usb_as_play_cb
root usb_as_play_exc_cb
root usb_as_record_cb
diff --git a/usr/src/uts/common/io/warlock/usb_as_with_sada.wlcmd b/usr/src/uts/common/io/warlock/usb_as_with_sada.wlcmd
deleted file mode 100644
index f765176771..0000000000
--- a/usr/src/uts/common/io/warlock/usb_as_with_sada.wlcmd
+++ /dev/null
@@ -1,168 +0,0 @@
-#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#ident "%Z%%M% %I% %E% SMI"
-
-# warlock command file
-
-one usb_as_state
-one audio_ch
-one audio_apm_info
-one audio_state
-one am_apm_private
-
-
-# unused functions
-
-root am_hw_state_change
-
-root audio_sup_attach
-root audio_sup_devt_to_ch_type
-root audio_sup_detach
-root audio_sup_get_qptr_data
-root audio_sup_open
-root audio_sup_close
-root audio_sup_rput
-root audio_sup_rsvc
-root audio_sup_wput
-root audio_sup_wsvc
-root audio_sup_ch_to_minor
-root audio_sup_construct_minor
-root audio_sup_devt_to_instance
-root audio_sup_free_persist_state
-root audio_sup_free_qptr
-root audio_sup_get_channel_number
-root audio_sup_get_dip
-root audio_sup_get_info
-root audio_sup_get_max_chs
-root audio_sup_get_persist_state
-root audio_sup_get_qptr_instance
-root audio_sup_set_persist_state
-root audio_sup_set_qptr
-root audio_sup_save_audio_data
-root audio_sup_save_state
-root audio_sup_update_persist_key
-root audio_sup_getinfo
-
-root am_get_src_data
-root am_set_src_data
-root am_hw_state_change
-root am_get_audio
-root am_play_shutdown
-root am_send_audio
-root am_save_state
-root am_attach
-root am_detach
-root am_restore_state
-
-root audio_sup_attach
-root audio_sup_detach
-root audio_sup_get_private
-root audio_sup_getinfo
-root audio_sup_set_private
-root audio_sup_restore_state
-
-
-# threads
-root am_diag_loopback_task
-root am_get_chinfo_task
-root am_get_mode_task
-root am_getinfo_task
-root am_mixer_task_acknack
-root am_mixerctl_getinfo_task
-root am_mixerctl_setinfo_task
-root am_multiple_open_task
-root am_sample_rate_task
-root am_set_chinfo_task
-root am_set_mode_task
-root am_setinfo_task
-root am_single_open_task
-root am_hw_task
-
-### specify the usb_as root functions
-root usb_as_open
-root usb_as_close
-root usb_as_disconnect_event_cb
-root usb_as_reconnect_event_cb
-root usb_as_power
-root usb_as_wsrv
-root usb_as_isoc_close_cb
-root usb_as_play_cb
-root usb_as_play_exc_cb
-root usb_as_record_cb
-root usb_as_record_exc_cb
-root usb_as_default_xfer_cb
-root usb_as_default_xfer_exc_cb
-
-
-# function pointers
-add audio_ch::ch_rput targets am_rput
-add audio_ch::ch_rsvc targets am_rsvc
-add audio_ch::ch_wput targets am_wput
-add audio_ch::ch_wsvc targets am_wsvc
-add audio_apm_info::apm_open targets am_open_audio
-add audio_apm_info::apm_close targets am_close_audio
-add audio_apm_info::apm_open targets am_open_audioctl
-add audio_apm_info::apm_close targets am_close_audioctl
-add audio_apm_info::apm_restore_state targets am_restore_state
-add audio_apm_info::apm_save_state targets am_save_state
-
-
-add bus_ops::bus_add_eventcall targets warlock_dummy
-add bus_ops::bus_get_eventcookie targets warlock_dummy
-add bus_ops::bus_intr_ctl targets warlock_dummy
-add bus_ops::bus_post_event targets warlock_dummy
-add bus_ops::bus_remove_eventcall targets warlock_dummy
-add bus_ops::bus_config targets warlock_dummy
-add bus_ops::bus_unconfig targets warlock_dummy
-
-add am_ad_src_entry::ad_src_adjust targets am_src2_adjust
-add am_ad_src_entry::ad_src_convert targets am_src2_convert
-add am_ad_src_entry::ad_src_exit targets am_src2_exit
-add am_ad_src_entry::ad_src_init targets am_src2_init
-add am_ad_src_entry::ad_src_size targets am_src2_size
-add am_ad_src_entry::ad_src_update targets am_src2_update
-
-add am_ad_entry::ad_setup targets warlock_dummy
-add am_ad_entry::ad_teardown targets warlock_dummy
-add am_ad_entry::ad_set_config targets warlock_dummy
-add am_ad_entry::ad_set_format targets warlock_dummy
-add am_ad_entry::ad_start_play targets warlock_dummy
-add am_ad_entry::ad_pause_play targets warlock_dummy
-add am_ad_entry::ad_stop_play targets warlock_dummy
-add am_ad_entry::ad_start_record targets warlock_dummy
-add am_ad_entry::ad_stop_record targets warlock_dummy
-add am_ad_entry::ad_ioctl targets warlock_dummy
-add am_ad_entry::ad_iocdata targets warlock_dummy
-
-
-# we should never hold cs_lock while jumping into another module
-# and with this rule we *sometimes* get these
-assert order audio_state::as_lock audio_ch::ch_lock usb_as_state::usb_as_mutex
-
-# this locking order catches problems when the framework holds locks
-# over calling into the driver
-#assert order usb_as_state::usb_as_mutex audio_state::as_lock audio_ch::ch_lock
-
diff --git a/usr/src/uts/common/io/warlock/usb_as_with_usba.wlcmd b/usr/src/uts/common/io/warlock/usb_as_with_usba.wlcmd
index 264bd51ec1..e2a932c3c3 100644
--- a/usr/src/uts/common/io/warlock/usb_as_with_usba.wlcmd
+++ b/usr/src/uts/common/io/warlock/usb_as_with_usba.wlcmd
@@ -1,5 +1,5 @@
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# CDDL HEADER START
@@ -21,7 +21,6 @@
#
# CDDL HEADER END
#
-#ident "%Z%%M% %I% %E% SMI"
one ohci_state
one ehci_state
@@ -45,6 +44,7 @@ root usb_get_if_number
root usb_parse_CV_cfg_descr
root usb_parse_CV_ep_descr
root usb_parse_CV_if_descr
+root usb_parse_comp_ep_descr
root usb_pipe_get_private
root usb_get_current_frame_number
root usb_get_max_isoc_pkts
@@ -90,6 +90,12 @@ root usb_register_hotplug_cbs
root usb_get_current_cfgidx
root usb_register_client
root usb_reset_device
+root usb_register_dev_driver
+root usb_unregister_dev_driver
+
+root ohci_quiesce
+root uhci_quiesce
+root ehci_quiesce
root usb_ugen_attach
root usb_ugen_close
@@ -106,12 +112,10 @@ root usb_ugen_write
### specify the usb_as root functions
root usb_as_open
root usb_as_close
-root usb_as_wsrv
root usb_as_disconnect_event_cb
root usb_as_reconnect_event_cb
root usb_as_power
-root usb_as_isoc_close_cb
root usb_as_play_cb
root usb_as_play_exc_cb
root usb_as_record_cb
@@ -152,6 +156,7 @@ root hubd_reset_thread
root hubd_cpr_post_user_callb
root hubd_bus_power
+add hubd::h_cleanup_child targets warlock_dummy
add usba_pipe_async_req::sync_func targets usba_pipe_sync_close
add usba_pipe_async_req::sync_func targets usba_pipe_sync_reset
diff --git a/usr/src/uts/common/sys/usb/clients/audio/usb_ac/usb_ac.h b/usr/src/uts/common/sys/usb/clients/audio/usb_ac/usb_ac.h
index 55e3d72d06..7cf81f2112 100644
--- a/usr/src/uts/common/sys/usb/clients/audio/usb_ac/usb_ac.h
+++ b/usr/src/uts/common/sys/usb/clients/audio/usb_ac/usb_ac.h
@@ -35,6 +35,7 @@ extern "C" {
#include <sys/sunldi.h>
#include <sys/usb/usba/usbai_private.h>
+
int usb_ac_open(dev_info_t *);
void usb_ac_close(dev_info_t *);
@@ -77,7 +78,6 @@ typedef struct usb_ac_plumbed {
*/
typedef struct usb_ac_to_as_req {
usb_audio_formats_t acr_curr_format; /* format data from mixer */
- int acr_curr_dir;
} usb_ac_to_as_req_t;
@@ -88,15 +88,13 @@ typedef struct usb_ac_streams_info {
/* valid registration data rcvd */
uint_t acs_rcvd_reg_data;
/* pointer to registration data */
- usb_as_registration_t *acs_streams_reg;
+ usb_as_registration_t acs_streams_reg;
- /* request structure to usb_as; one active at a time */
- usb_ac_to_as_req_t acs_ac_to_as_req;
/* Multiple command management */
int acs_setup_teardown_count;
- usb_audio_formats_t acs_cur_fmt; /* format data from mixer */
+ uint8_t acs_default_gain;
} usb_ac_streams_info_t;
@@ -121,12 +119,77 @@ _NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ac_power_t::acpm_wakeup_enabled))
_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ac_power_t::acpm_pwr_states))
_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ac_power_t::acpm_capabilities))
+typedef struct usb_audio_format {
+ int sr; /* sample rate */
+ uint_t ch; /* channels */
+ uint_t prec; /* precision */
+ uint_t enc; /* encoding */
+} usb_audio_format_t;
+
+
+typedef struct usb_audio_eng {
+ void *statep;
+ usb_ac_streams_info_t *streams;
+ audio_engine_t *af_engp;
+
+ int af_eflags; /* ENGINE_* flags */
+ usb_audio_format_t fmt;
+ uint64_t af_defgain;
+
+ unsigned intrate; /* interrupt rate */
+ unsigned sampsz; /* sample size */
+ unsigned framesz; /* frame size */
+ unsigned fragsz; /* fragment size */
+ unsigned nfrags; /* number of fragments in buffer */
+ unsigned fragfr; /* number of frames per fragment */
+ unsigned frsmshift; /* right shift: frames in sample cnt */
+ unsigned smszshift; /* left shift: sample cnt * sampsz */
+
+
+ caddr_t bufp; /* I/O buf; framework to/from drv */
+ unsigned bufsz; /* buffer size */
+ caddr_t bufpos; /* buffer position */
+ caddr_t bufendp; /* end of buffer */
+
+
+ uint64_t frames;
+ uint64_t io_count; /* i/o requests from the driver */
+ uint64_t bufio_count; /* i/o requests to the framework */
+
+ boolean_t started;
+
+ kmutex_t lock;
+} usb_audio_eng_t;
+
+
/* limits */
#define USB_AC_MAX_PLUMBED 3 /* play, record, hid */
#define USB_AC_MAX_AS_PLUMBED 2 /* play, record */
+typedef struct usb_ac_state usb_ac_state_t;
+typedef struct usb_audio_ctrl {
+ audio_ctrl_t *af_ctrlp; /* framework handle */
+ usb_ac_state_t *statep;
+
+ kmutex_t ctrl_mutex;
+ uint64_t cval; /* current control value */
+} usb_audio_ctrl_t;
+
+enum {
+ CTL_VOLUME_MONO = 0,
+ CTL_VOLUME_STERO,
+ CTL_REC_MONO,
+ CTL_REC_STERO,
+ CTL_REC_SRC,
+ CTL_MONITOR_GAIN,
+ CTL_MIC_BOOST,
+ CTL_NUM
+};
+
+#define USB_AC_ENG_MAX 2
/* usb_ac soft state */
-typedef struct usb_ac_state {
+struct usb_ac_state {
+
dev_info_t *usb_ac_dip;
uint_t usb_ac_instance;
usb_log_handle_t usb_ac_log_handle;
@@ -136,11 +199,17 @@ typedef struct usb_ac_state {
kmutex_t usb_ac_mutex;
usb_client_dev_data_t *usb_ac_dev_data; /* registration data */
+ audio_dev_t *usb_ac_audio_dev;
+
+
+
+
+ usb_audio_eng_t engines[USB_AC_ENG_MAX];
+
+
- /* audio framework */
- audiohdl_t usb_ac_audiohdl;
- am_ad_info_t usb_ac_am_ad_info;
- audio_info_t usb_ac_am_ad_defaults;
+ int flags;
+ usb_audio_ctrl_t *controls[CTL_NUM];
/* descriptors */
usb_if_descr_t usb_ac_if_descr;
@@ -159,8 +228,8 @@ typedef struct usb_ac_state {
uchar_t usb_ac_traverse_path_index;
/* port types, eg LINE IN, Micr, Speakers */
- uint_t usb_ac_input_ports;
- uint_t usb_ac_output_ports;
+ uint64_t usb_ac_input_ports;
+ uint64_t usb_ac_output_ports;
/* pipe handle */
usb_pipe_handle_t usb_ac_default_ph;
@@ -185,20 +254,21 @@ typedef struct usb_ac_state {
/* per streams interface info */
usb_ac_streams_info_t usb_ac_streams[USB_AC_MAX_AS_PLUMBED];
- /*
- * preserve streams registration because the mixer does not
- * copy registration data
- */
- usb_as_registration_t usb_ac_streams_reg[USB_AC_MAX_AS_PLUMBED];
ddi_taskq_t *tqp;
char dstr[64];
-} usb_ac_state_t;
+};
/* warlock directives, stable data */
_NOTE(MUTEX_PROTECTS_DATA(usb_ac_state_t::usb_ac_mutex, usb_ac_state_t))
_NOTE(MUTEX_PROTECTS_DATA(usb_ac_state_t::usb_ac_mutex, usb_ac_power_t))
+_NOTE(MUTEX_PROTECTS_DATA(usb_ac_state_t::usb_ac_mutex, usb_ac_plumbed_t))
+_NOTE(MUTEX_PROTECTS_DATA(usb_audio_eng_t::lock, usb_audio_eng_t))
+_NOTE(MUTEX_PROTECTS_DATA(usb_audio_eng_t::lock, usb_audio_format_t))
+_NOTE(MUTEX_PROTECTS_DATA(usb_audio_ctrl_t::ctrl_mutex, usb_audio_ctrl_t))
+
+
_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ac_state_t::usb_ac_dip))
_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ac_state_t::usb_ac_ser_acc))
_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ac_state_t::usb_ac_pm))
@@ -206,9 +276,33 @@ _NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ac_state_t::usb_ac_instance))
_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ac_state_t::usb_ac_default_ph))
_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ac_state_t::usb_ac_log_handle))
_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ac_state_t::usb_ac_if_descr))
-_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ac_state_t::usb_ac_audiohdl))
_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ac_state_t::usb_ac_dev_data))
_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ac_state_t::usb_ac_ifno))
+_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ac_state_t::flags))
+_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ac_state_t::usb_ac_input_ports))
+_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ac_state_t::engines))
+_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ac_state_t::usb_ac_audio_dev))
+_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ac_state_t::controls))
+
+_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_audio_eng_t::af_eflags))
+_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_audio_eng_t::streams))
+_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_audio_eng_t::statep))
+_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_audio_eng_t::fmt))
+_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_audio_eng_t::fragfr))
+_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_audio_eng_t::frsmshift))
+_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_audio_eng_t::started))
+_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_audio_eng_t::af_engp))
+_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_audio_eng_t::io_count))
+_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_audio_eng_t::intrate))
+
+_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_audio_ctrl_t::statep))
+_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_audio_ctrl_t::af_ctrlp))
+_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_audio_ctrl_t::cval))
+
+_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ac_plumbed_t::acp_tqp))
+_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ac_plumbed_t::acp_uacp))
+
+_NOTE(DATA_READABLE_WITHOUT_LOCK(usb_audio_format_t::ch))
/* usb_ac driver only care about two states: plumbed or unplumbed */
#define USB_AC_STATE_UNPLUMBED 0
@@ -235,6 +329,36 @@ _NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ac_state_t::usb_ac_ifno))
/* other useful macros */
#define offsetof(s, m) ((size_t)(&(((s *)0)->m)))
+
+
+
+
+
+#define AF_REGISTERED 0x1
+#define AD_SETUP 0x10
+
+
+int usb_audio_attach(usb_ac_state_t *);
+/*
+ * framework gain range
+ */
+#define AUDIO_CTRL_STEREO_VAL(l, r) (((l) & 0xff) | (((r) & 0xff) << 8))
+#define AUDIO_CTRL_STEREO_LEFT(v) ((uint8_t)((v) & 0xff))
+#define AUDIO_CTRL_STEREO_RIGHT(v) ((uint8_t)(((v) >> 8) & 0xff))
+
+
+#define AF_MAX_GAIN 100
+#define AF_MIN_GAIN 0
+
+
+
+int usb_ac_get_audio(void *, void *, int);
+
+void usb_ac_send_audio(void *, void *, int);
+
+void usb_ac_stop_play(usb_ac_state_t *, usb_audio_eng_t *);
+
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/uts/common/sys/usb/clients/audio/usb_as/usb_as.h b/usr/src/uts/common/sys/usb/clients/audio/usb_as/usb_as.h
index e88168b391..047dfff218 100644
--- a/usr/src/uts/common/sys/usb/clients/audio/usb_as/usb_as.h
+++ b/usr/src/uts/common/sys/usb/clients/audio/usb_as/usb_as.h
@@ -86,6 +86,9 @@ typedef struct usb_as_state {
uint_t usb_as_dev_state;
uint_t usb_as_ifno;
kmutex_t usb_as_mutex;
+ kcondvar_t usb_as_pipe_cv;
+
+
uint_t usb_as_flag; /* status */
/* mblk containing the current control command */
@@ -111,7 +114,7 @@ typedef struct usb_as_state {
/* Isoc pipe stuff */
usb_pipe_handle_t usb_as_isoc_ph;
usb_pipe_policy_t usb_as_isoc_pp;
- audiohdl_t usb_as_ahdl;
+ void * usb_as_ahdl;
uint_t usb_as_request_count;
uint_t usb_as_request_samples;
diff --git a/usr/src/uts/common/sys/usb/clients/audio/usb_audio.h b/usr/src/uts/common/sys/usb/clients/audio/usb_audio.h
index c8e0c0344e..807d5aa435 100644
--- a/usr/src/uts/common/sys/usb/clients/audio/usb_audio.h
+++ b/usr/src/uts/common/sys/usb/clients/audio/usb_audio.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -470,6 +470,12 @@ typedef struct usb_audio_type1_format_descr {
#define USB_AUDIO_MUTE_ON 1
#define USB_AUDIO_MUTE_OFF 0
+#define USB_AUDIO_PRECISION_8 8
+#define USB_AUDIO_PRECISION_16 16
+
+#define USB_AUDIO_PLAY 0x0001
+#define USB_AUDIO_RECORD 0x0002
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/uts/common/sys/usb/clients/audio/usb_mixer.h b/usr/src/uts/common/sys/usb/clients/audio/usb_mixer.h
index 87a0d2953e..ab045a58c8 100644
--- a/usr/src/uts/common/sys/usb/clients/audio/usb_mixer.h
+++ b/usr/src/uts/common/sys/usb/clients/audio/usb_mixer.h
@@ -49,12 +49,11 @@ _NOTE(SCHEME_PROTECTS_DATA("unshared", usb_audio_formats))
typedef struct usb_audio_play_req {
int up_samples;
- audiohdl_t up_handle;
+ void *up_handle;
} usb_audio_play_req_t;
#define USB_AS_N_SRS 20
#define USB_AS_N_FORMATS 20
-#define USB_AS_N_COMBINATIONS USB_AS_N_FORMATS
#define USB_AS_N_CHANNELS 3
typedef struct usb_as_registration {
@@ -65,7 +64,6 @@ typedef struct usb_as_registration {
uint_t reg_srs[USB_AS_N_SRS];
usb_audio_formats_t reg_formats[USB_AS_N_FORMATS];
uint_t reg_channels[USB_AS_N_CHANNELS];
- am_ad_cap_comb_t reg_combinations[USB_AS_N_COMBINATIONS];
} usb_as_registration_t;
/* MCTLs between usb_ac and usb_as */
diff --git a/usr/src/uts/intel/usb_ac/Makefile b/usr/src/uts/intel/usb_ac/Makefile
index 5b18985111..a69a4cd371 100644
--- a/usr/src/uts/intel/usb_ac/Makefile
+++ b/usr/src/uts/intel/usb_ac/Makefile
@@ -120,16 +120,9 @@ EHCI_FILES = $(EHCI_OBJS:%.o=../ehci/%.ll)
warlock: $(WARLOCK_OK)
$(WARLOCK_OK): $(WARLOCK_OUT) warlock_ddi.files \
- warlock_audiosup.files warlock_mixer.files \
- warlock_standalone warlock_with_usba warlock_with_sada
+ warlock_standalone warlock_usba.files warlock_with_usba
$(TOUCH) $(WARLOCK_OK)
-
-warlock_with_sada: $(WLCMD_DIR)/usb_ac_with_sada.wlcmd \
- $(WARLOCK_OUT) \
- warlock_audiosup.files warlock_mixer.files warlock_amsrc2.files
- $(WARLOCK) -c $(WLCMD_DIR)/usb_ac_with_sada.wlcmd $(WARLOCK_OUT) \
- -l ../warlock/ddi_dki_impl.ll
-
+
warlock_with_usba: $(WLCMD_DIR)/usb_ac_with_usba.wlcmd $(WARLOCK_OUT) \
warlock_ddi.files warlock_usba.files warlock_ohci.files \
@@ -159,12 +152,3 @@ warlock_ehci.files:
warlock_ddi.files:
@cd ../warlock; pwd; $(MAKE) warlock
-
-warlock_audiosup.files:
- @cd ../audiosup; pwd; $(MAKE) warlock
-
-warlock_mixer.files:
- @cd ../mixer; pwd; $(MAKE) warlock
-
-warlock_amsrc2.files:
- @cd ../amsrc2; pwd; $(MAKE) warlock
diff --git a/usr/src/uts/intel/usb_as/Makefile b/usr/src/uts/intel/usb_as/Makefile
index 9d82ee38a0..e48617d312 100644
--- a/usr/src/uts/intel/usb_as/Makefile
+++ b/usr/src/uts/intel/usb_as/Makefile
@@ -112,25 +112,19 @@ TEST = test
# lock_lint rules
#
USB_AS_FILES = $(MODULE).ll
-USBA_FILES = $(USBA_OBJS:%.o=../usba/%.ll)
+USBA_FILES = $(USBA_WITHOUT_WUSB_OBJS:%.o=../usba/%.ll)
UHCI_FILES = $(UHCI_OBJS:%.o=../uhci/%.ll)
OHCI_FILES = $(OHCI_OBJS:%.o=../ohci/%.ll)
EHCI_FILES = $(EHCI_OBJS:%.o=../ehci/%.ll)
-AUDIO_SUP_FILES = $(AUDIO_SUP_OBJS:%.o=$(UTSBASE)/intel/audiosup/%.ll)
# Warlock targets
#
warlock: $(WARLOCK_OK)
-$(WARLOCK_OK): $(WARLOCK_OUT) warlock_ddi.files warlock_audiosup.files \
- warlock_standalone warlock_with_usba warlock_with_sada
+$(WARLOCK_OK): $(WARLOCK_OUT) warlock_ddi.files \
+ warlock_standalone warlock_usba.files warlock_with_usba
$(TOUCH) $(WARLOCK_OK)
-warlock_with_sada: $(WLCMD_DIR)/usb_as_with_sada.wlcmd \
- $(WARLOCK_OUT) warlock_audiosup.files
- $(WARLOCK) -c $(WLCMD_DIR)/usb_as_with_sada.wlcmd $(WARLOCK_OUT) \
- $(MIXER_FILES) $(AUDIO_SUP_FILES) $(AMSRC2_FILES) \
- -l ../warlock/ddi_dki_impl.ll
warlock_with_usba: $(WLCMD_DIR)/usb_as_with_usba.wlcmd $(WARLOCK_OUT) \
warlock_ddi.files warlock_ohci.files warlock_usba.files \
@@ -160,6 +154,3 @@ warlock_ehci.files:
warlock_ddi.files:
@cd ../warlock; pwd; $(MAKE) warlock
-
-warlock_audiosup.files:
- @cd ../audiosup; pwd; $(MAKE) warlock
diff --git a/usr/src/uts/sparc/usb_ac/Makefile b/usr/src/uts/sparc/usb_ac/Makefile
index bf3840846c..14560e1740 100644
--- a/usr/src/uts/sparc/usb_ac/Makefile
+++ b/usr/src/uts/sparc/usb_ac/Makefile
@@ -107,7 +107,7 @@ TEST = test
#
# lock_lint rules
#
-USBA_FILES = $(USBA_OBJS:%.o=../usba/%.ll)
+USBA_FILES = $(USBA_WITHOUT_WUSB_OBJS:%.o=../usba/%.ll)
UHCI_FILES = $(UHCI_OBJS:%.o=../uhci/%.ll)
OHCI_FILES = $(OHCI_OBJS:%.o=../ohci/%.ll)
EHCI_FILES = $(EHCI_OBJS:%.o=../ehci/%.ll)
@@ -119,15 +119,9 @@ EHCI_FILES = $(EHCI_OBJS:%.o=../ehci/%.ll)
warlock: $(WARLOCK_OK)
$(WARLOCK_OK): $(WARLOCK_OUT) warlock_ddi.files \
- warlock_audiosup.files warlock_mixer.files warlock_amsrc2.files \
- warlock_standalone warlock_with_usba warlock_with_sada
+ warlock_standalone warlock_usba.files warlock_with_usba
$(TOUCH) $(WARLOCK_OK)
-warlock_with_sada: $(WLCMD_DIR)/usb_ac_with_sada.wlcmd \
- $(WARLOCK_OUT) \
- warlock_audiosup.files warlock_amsrc2.files warlock_mixer.files
- $(WARLOCK) -c $(WLCMD_DIR)/usb_ac_with_sada.wlcmd $(WARLOCK_OUT) \
- -l ../warlock/ddi_dki_impl.ll
warlock_with_usba: $(WLCMD_DIR)/usb_ac_with_usba.wlcmd $(WARLOCK_OUT) \
warlock_ddi.files warlock_usba.files warlock_ohci.files \
@@ -157,12 +151,3 @@ warlock_ehci.files:
warlock_ddi.files:
@cd ../warlock; pwd; $(MAKE) warlock
-
-warlock_audiosup.files:
- @cd ../audiosup; pwd; $(MAKE) warlock
-
-warlock_amsrc2.files:
- @cd ../amsrc2; pwd; $(MAKE) warlock
-
-warlock_mixer.files:
- @cd ../mixer; pwd; $(MAKE) warlock
diff --git a/usr/src/uts/sparc/usb_as/Makefile b/usr/src/uts/sparc/usb_as/Makefile
index bc7db4c381..06a86518f9 100644
--- a/usr/src/uts/sparc/usb_as/Makefile
+++ b/usr/src/uts/sparc/usb_as/Makefile
@@ -108,7 +108,7 @@ TEST = test
#
# lock_lint rules
#
-USBA_FILES = $(USBA_OBJS:%.o=../usba/%.ll)
+USBA_FILES = $(USBA_WITHOUT_WUSB_OBJS:%.o=../usba/%.ll)
UHCI_FILES = $(UHCI_OBJS:%.o=../uhci/%.ll)
OHCI_FILES = $(OHCI_OBJS:%.o=../ohci/%.ll)
EHCI_FILES = $(EHCI_OBJS:%.o=../ehci/%.ll)
@@ -119,14 +119,10 @@ EHCI_FILES = $(EHCI_OBJS:%.o=../ehci/%.ll)
#
warlock: $(WARLOCK_OK)
-$(WARLOCK_OK): $(WARLOCK_OUT) warlock_ddi.files warlock_audiosup.files \
- warlock_standalone warlock_with_usba warlock_with_sada
+$(WARLOCK_OK): $(WARLOCK_OUT) warlock_ddi.files \
+ warlock_standalone warlock_usba.files warlock_with_usba
$(TOUCH) $(WARLOCK_OK)
-warlock_with_sada: $(WLCMD_DIR)/usb_as_with_sada.wlcmd \
- $(WARLOCK_OUT) warlock_audiosup.files
- $(WARLOCK) -c $(WLCMD_DIR)/usb_as_with_sada.wlcmd $(WARLOCK_OUT) \
- -l ../warlock/ddi_dki_impl.ll
warlock_with_usba: $(WLCMD_DIR)/usb_as_with_usba.wlcmd $(WARLOCK_OUT) \
warlock_ddi.files warlock_ohci.files warlock_usba.files \
@@ -157,6 +153,3 @@ warlock_ehci.files:
warlock_ddi.files:
@cd ../warlock; pwd; $(MAKE) warlock
-
-warlock_audiosup.files:
- @cd ../audiosup; pwd; $(MAKE) warlock