xref: /onnv-gate/usr/src/uts/common/sys/audio/audio_driver.h (revision 12165:e481916a5729)
19484Sgarrett.damore@Sun.COM /*
29484Sgarrett.damore@Sun.COM  * CDDL HEADER START
39484Sgarrett.damore@Sun.COM  *
49484Sgarrett.damore@Sun.COM  * The contents of this file are subject to the terms of the
59484Sgarrett.damore@Sun.COM  * Common Development and Distribution License (the "License").
69484Sgarrett.damore@Sun.COM  * You may not use this file except in compliance with the License.
79484Sgarrett.damore@Sun.COM  *
89484Sgarrett.damore@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99484Sgarrett.damore@Sun.COM  * or http://www.opensolaris.org/os/licensing.
109484Sgarrett.damore@Sun.COM  * See the License for the specific language governing permissions
119484Sgarrett.damore@Sun.COM  * and limitations under the License.
129484Sgarrett.damore@Sun.COM  *
139484Sgarrett.damore@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
149484Sgarrett.damore@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159484Sgarrett.damore@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
169484Sgarrett.damore@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
179484Sgarrett.damore@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
189484Sgarrett.damore@Sun.COM  *
199484Sgarrett.damore@Sun.COM  * CDDL HEADER END
209484Sgarrett.damore@Sun.COM  */
219484Sgarrett.damore@Sun.COM /*
229484Sgarrett.damore@Sun.COM  * Copyright (C) 4Front Technologies 1996-2008.
239484Sgarrett.damore@Sun.COM  *
24*12165Sgdamore@opensolaris.org  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
259484Sgarrett.damore@Sun.COM  */
269484Sgarrett.damore@Sun.COM 
279484Sgarrett.damore@Sun.COM #ifndef	_SYS_AUDIO_AUDIO_DRIVER_H
289484Sgarrett.damore@Sun.COM #define	_SYS_AUDIO_AUDIO_DRIVER_H
299484Sgarrett.damore@Sun.COM 
309484Sgarrett.damore@Sun.COM #include <sys/types.h>
319484Sgarrett.damore@Sun.COM #include <sys/list.h>
329484Sgarrett.damore@Sun.COM #include <sys/ddi.h>
339484Sgarrett.damore@Sun.COM #include <sys/sunddi.h>
349484Sgarrett.damore@Sun.COM #include <sys/audio/audio_common.h>
359484Sgarrett.damore@Sun.COM 
369484Sgarrett.damore@Sun.COM 
379484Sgarrett.damore@Sun.COM #ifdef	__cplusplus
389484Sgarrett.damore@Sun.COM extern "C" {
399484Sgarrett.damore@Sun.COM #endif
409484Sgarrett.damore@Sun.COM 
419484Sgarrett.damore@Sun.COM #ifdef	_KERNEL
429484Sgarrett.damore@Sun.COM 
439484Sgarrett.damore@Sun.COM struct audio_engine_ops {
449484Sgarrett.damore@Sun.COM 	int	audio_engine_version;
4511936Sgdamore@opensolaris.org #define	AUDIO_ENGINE_VERSION	2
469484Sgarrett.damore@Sun.COM 
479484Sgarrett.damore@Sun.COM 	/*
489484Sgarrett.damore@Sun.COM 	 * Initialize engine, including buffer allocation.  Arguments
499484Sgarrett.damore@Sun.COM 	 * that are pointers are hints.  On return, they are updated with
509484Sgarrett.damore@Sun.COM 	 * the actual values configured by the driver.
519484Sgarrett.damore@Sun.COM 	 */
5211936Sgdamore@opensolaris.org 	int	(*audio_engine_open)(void *, int, uint_t *, caddr_t *);
539484Sgarrett.damore@Sun.COM 	void	(*audio_engine_close)(void *);
549484Sgarrett.damore@Sun.COM 
559484Sgarrett.damore@Sun.COM 	/*
569484Sgarrett.damore@Sun.COM 	 * Start and stop are used to actually get the hardware running
579484Sgarrett.damore@Sun.COM 	 * or stop the hardware.  Until this is kicked off, the engine
589484Sgarrett.damore@Sun.COM 	 * will not actually transfer data.  These are not destructive to
599484Sgarrett.damore@Sun.COM 	 * ring positions, etc.  (Think of it like pause/play).
609484Sgarrett.damore@Sun.COM 	 */
619484Sgarrett.damore@Sun.COM 	int	(*audio_engine_start)(void *);
629484Sgarrett.damore@Sun.COM 	void	(*audio_engine_stop)(void *);
639484Sgarrett.damore@Sun.COM 
649484Sgarrett.damore@Sun.COM 	/*
659484Sgarrett.damore@Sun.COM 	 * Obtain the engine offset.  Offsets start at zero at engine_open,
669484Sgarrett.damore@Sun.COM 	 * and keep counting upwards.  Count is returned in frames.
679484Sgarrett.damore@Sun.COM 	 */
689484Sgarrett.damore@Sun.COM 	uint64_t	(*audio_engine_count)(void *);
699484Sgarrett.damore@Sun.COM 
709484Sgarrett.damore@Sun.COM 	/*
719484Sgarrett.damore@Sun.COM 	 * The following entry points return the currently configured
729484Sgarrett.damore@Sun.COM 	 * status of the engine.  It is assumed that the engine's
739484Sgarrett.damore@Sun.COM 	 * configuration is relatively fixed, and does not change
749484Sgarrett.damore@Sun.COM 	 * while open, or in response to open.
759484Sgarrett.damore@Sun.COM 	 *
769484Sgarrett.damore@Sun.COM 	 * However, in the future we might like to allow for the
779484Sgarrett.damore@Sun.COM 	 * device to change the settings while it is not open, which
789484Sgarrett.damore@Sun.COM 	 * could allow for mixerctl to change the configured channels,
799484Sgarrett.damore@Sun.COM 	 * for example.  In order to synchronize this properly, we'll
809484Sgarrett.damore@Sun.COM 	 * need the engine to perform a notification/request.  That
819484Sgarrett.damore@Sun.COM 	 * will be added later.
829484Sgarrett.damore@Sun.COM 	 *
839484Sgarrett.damore@Sun.COM 	 * AC3: We will have to figure out how to support dynamically
849484Sgarrett.damore@Sun.COM 	 * selecting different sampling frequencies for AC3, since
859484Sgarrett.damore@Sun.COM 	 * it needs to be able to support 32, 44.1, and 48 kHz.
869484Sgarrett.damore@Sun.COM 	 * Perhaps special flags used during open() would do the trick.
879484Sgarrett.damore@Sun.COM 	 */
889484Sgarrett.damore@Sun.COM 	int	(*audio_engine_format)(void *);
899484Sgarrett.damore@Sun.COM 	int	(*audio_engine_channels)(void *);
909484Sgarrett.damore@Sun.COM 	int	(*audio_engine_rate)(void *);
919484Sgarrett.damore@Sun.COM 
929484Sgarrett.damore@Sun.COM 	/*
939484Sgarrett.damore@Sun.COM 	 * DMA cache synchronization.  The framework does this on
949484Sgarrett.damore@Sun.COM 	 * behalf of the driver for both input and output.  The driver
959484Sgarrett.damore@Sun.COM 	 * is responsible for tracking the direction (based on the
969484Sgarrett.damore@Sun.COM 	 * flags passed to ae_open()), and dealing with any partial
979484Sgarrett.damore@Sun.COM 	 * synchronization if any is needed.
989484Sgarrett.damore@Sun.COM 	 */
9911936Sgdamore@opensolaris.org 	void	(*audio_engine_sync)(void *, uint_t);
1009484Sgarrett.damore@Sun.COM 
1019484Sgarrett.damore@Sun.COM 	/*
1029484Sgarrett.damore@Sun.COM 	 * The framework may like to know how deep the device queues data.
1039484Sgarrett.damore@Sun.COM 	 * This can be used to provide a more accurate latency calculation.
1049484Sgarrett.damore@Sun.COM 	 */
10511936Sgdamore@opensolaris.org 	uint_t	(*audio_engine_qlen)(void *);
1069484Sgarrett.damore@Sun.COM 
1079484Sgarrett.damore@Sun.COM 	/*
1089484Sgarrett.damore@Sun.COM 	 * If the driver doesn't use simple interleaving, then we need to
1099484Sgarrett.damore@Sun.COM 	 * know more about the offsets of channels within the buffer.
1109484Sgarrett.damore@Sun.COM 	 * We obtain both the starting offset within the buffer, and the
1119484Sgarrett.damore@Sun.COM 	 * increment for each new sample.  As usual, these are given in
1129484Sgarrett.damore@Sun.COM 	 * samples.  If this entry point is NULL, the framework assumes
1139484Sgarrett.damore@Sun.COM 	 * that simple interlevaing is used instead.
1149484Sgarrett.damore@Sun.COM 	 */
11511936Sgdamore@opensolaris.org 	void	(*audio_engine_chinfo)(void *, int chan, uint_t *offset,
11611936Sgdamore@opensolaris.org 	    uint_t *incr);
11711213Sgdamore@opensolaris.org 
11811213Sgdamore@opensolaris.org 	/*
11911213Sgdamore@opensolaris.org 	 * The following entry point is used to determine the play ahead
12011213Sgdamore@opensolaris.org 	 * desired by the engine.  Engines with less consistent scheduling,
12111213Sgdamore@opensolaris.org 	 * or with a need for deeper queuing, implement this.  If not
12211213Sgdamore@opensolaris.org 	 * implemented, the framework assumes 1.5 * fragfr.
12311213Sgdamore@opensolaris.org 	 */
12411936Sgdamore@opensolaris.org 	uint_t	(*audio_engine_playahead)(void *);
1259484Sgarrett.damore@Sun.COM };
1269484Sgarrett.damore@Sun.COM 
12711936Sgdamore@opensolaris.org /*
12811936Sgdamore@opensolaris.org  * Drivers call these.
12911936Sgdamore@opensolaris.org  */
1309484Sgarrett.damore@Sun.COM void audio_init_ops(struct dev_ops *, const char *);
1319484Sgarrett.damore@Sun.COM void audio_fini_ops(struct dev_ops *);
1329484Sgarrett.damore@Sun.COM 
1339484Sgarrett.damore@Sun.COM audio_dev_t *audio_dev_alloc(dev_info_t *, int);
1349484Sgarrett.damore@Sun.COM void audio_dev_free(audio_dev_t *);
1359484Sgarrett.damore@Sun.COM 
1369484Sgarrett.damore@Sun.COM void audio_dev_set_description(audio_dev_t *, const char *);
1379484Sgarrett.damore@Sun.COM void audio_dev_set_version(audio_dev_t *, const char *);
1389484Sgarrett.damore@Sun.COM void audio_dev_add_info(audio_dev_t *, const char *);
1399484Sgarrett.damore@Sun.COM 
14011936Sgdamore@opensolaris.org audio_engine_t *audio_engine_alloc(audio_engine_ops_t *, uint_t);
1419484Sgarrett.damore@Sun.COM void audio_engine_set_private(audio_engine_t *, void *);
1429484Sgarrett.damore@Sun.COM void *audio_engine_get_private(audio_engine_t *);
1439484Sgarrett.damore@Sun.COM void audio_engine_free(audio_engine_t *);
1449484Sgarrett.damore@Sun.COM 
1459484Sgarrett.damore@Sun.COM void audio_dev_add_engine(audio_dev_t *, audio_engine_t *);
1469484Sgarrett.damore@Sun.COM void audio_dev_remove_engine(audio_dev_t *, audio_engine_t *);
1479484Sgarrett.damore@Sun.COM int audio_dev_register(audio_dev_t *);
1489484Sgarrett.damore@Sun.COM int audio_dev_unregister(audio_dev_t *);
14911936Sgdamore@opensolaris.org void audio_dev_suspend(audio_dev_t *);
15011936Sgdamore@opensolaris.org void audio_dev_resume(audio_dev_t *);
1519484Sgarrett.damore@Sun.COM void audio_dev_warn(audio_dev_t *, const char *, ...);
15211936Sgdamore@opensolaris.org 
1539484Sgarrett.damore@Sun.COM /* DEBUG ONLY */
1549484Sgarrett.damore@Sun.COM void audio_dump_bytes(const uint8_t *w, int dcount);
1559484Sgarrett.damore@Sun.COM void audio_dump_words(const uint16_t *w, int dcount);
1569484Sgarrett.damore@Sun.COM void audio_dump_dwords(const uint32_t *w, int dcount);
1579484Sgarrett.damore@Sun.COM 
1589484Sgarrett.damore@Sun.COM 
1599484Sgarrett.damore@Sun.COM /* Engine flags */
1609484Sgarrett.damore@Sun.COM #define	ENGINE_OUTPUT_CAP	(1U << 2)
1619484Sgarrett.damore@Sun.COM #define	ENGINE_INPUT_CAP	(1U << 3)
1629484Sgarrett.damore@Sun.COM #define	ENGINE_CAPS		(ENGINE_OUTPUT_CAP | ENGINE_INPUT_CAP)
1639484Sgarrett.damore@Sun.COM #define	ENGINE_DRIVER_FLAGS	(0xffff)	/* flags usable by driver */
1649484Sgarrett.damore@Sun.COM 
1659484Sgarrett.damore@Sun.COM #define	ENGINE_OUTPUT		(1U << 16)	/* fields not for driver use */
1669484Sgarrett.damore@Sun.COM #define	ENGINE_INPUT		(1U << 17)
1679484Sgarrett.damore@Sun.COM #define	ENGINE_EXCLUSIVE	(1U << 20)	/* exclusive use, e.g. AC3 */
1689484Sgarrett.damore@Sun.COM #define	ENGINE_NDELAY		(1U << 21)	/* non-blocking open */
1699484Sgarrett.damore@Sun.COM 
1709484Sgarrett.damore@Sun.COM /*
1719484Sgarrett.damore@Sun.COM  * entry points used by legacy SADA drivers
1729484Sgarrett.damore@Sun.COM  */
1739484Sgarrett.damore@Sun.COM int audio_legacy_open(queue_t *, dev_t *, int, int, cred_t *);
1749484Sgarrett.damore@Sun.COM int audio_legacy_close(queue_t *, int, cred_t *);
1759484Sgarrett.damore@Sun.COM int audio_legacy_wput(queue_t *, mblk_t *);
1769484Sgarrett.damore@Sun.COM int audio_legacy_wsrv(queue_t *);
1779484Sgarrett.damore@Sun.COM 
1789484Sgarrett.damore@Sun.COM 
1799484Sgarrett.damore@Sun.COM 
1809484Sgarrett.damore@Sun.COM /*
1819484Sgarrett.damore@Sun.COM  * Audio device controls
1829484Sgarrett.damore@Sun.COM  */
1839484Sgarrett.damore@Sun.COM 
1849484Sgarrett.damore@Sun.COM /*
1859484Sgarrett.damore@Sun.COM  * Control read or write driver function type.
1869484Sgarrett.damore@Sun.COM  *
1879484Sgarrett.damore@Sun.COM  * Returns zero on success, errno on failure.
1889484Sgarrett.damore@Sun.COM  */
1899484Sgarrett.damore@Sun.COM typedef int (*audio_ctrl_wr_t)(void *, uint64_t);
1909484Sgarrett.damore@Sun.COM typedef int (*audio_ctrl_rd_t)(void *, uint64_t *);
1919484Sgarrett.damore@Sun.COM 
1929484Sgarrett.damore@Sun.COM 
1939484Sgarrett.damore@Sun.COM /*
1949484Sgarrett.damore@Sun.COM  * This will allocate and register a control for my audio device.
1959484Sgarrett.damore@Sun.COM  *
1969484Sgarrett.damore@Sun.COM  * On success this will return a control structure else NULL.
1979484Sgarrett.damore@Sun.COM  */
1989484Sgarrett.damore@Sun.COM audio_ctrl_t *audio_dev_add_control(audio_dev_t *,
1999484Sgarrett.damore@Sun.COM     audio_ctrl_desc_t *, audio_ctrl_rd_t, audio_ctrl_wr_t, void *);
2009484Sgarrett.damore@Sun.COM 
2019484Sgarrett.damore@Sun.COM /*
2029484Sgarrett.damore@Sun.COM  * Add a synthetic PCM volume control.  This should only be used by
2039484Sgarrett.damore@Sun.COM  * devices which have no physical PCM volume controls.  The control
2049484Sgarrett.damore@Sun.COM  * implements a simple attenuator on the PCM data; unlike AC'97 there
2059484Sgarrett.damore@Sun.COM  * is no "gain", so using this instead of a hardware control may
2069484Sgarrett.damore@Sun.COM  * result in loss range.  The control is implemented using
2079484Sgarrett.damore@Sun.COM  * AUDIO_CTRL_ID_VOLUME.
2089484Sgarrett.damore@Sun.COM  */
209*12165Sgdamore@opensolaris.org void audio_dev_add_soft_volume(audio_dev_t *);
2109484Sgarrett.damore@Sun.COM 
2119484Sgarrett.damore@Sun.COM /*
2129484Sgarrett.damore@Sun.COM  * This will remove a control from an audio device.
2139484Sgarrett.damore@Sun.COM  */
2149484Sgarrett.damore@Sun.COM void audio_dev_del_control(audio_ctrl_t *);
2159484Sgarrett.damore@Sun.COM 
2169484Sgarrett.damore@Sun.COM /*
2179484Sgarrett.damore@Sun.COM  * This will tell the framework that controls have changed
2189484Sgarrett.damore@Sun.COM  * and it should update its values.
2199484Sgarrett.damore@Sun.COM  */
2209484Sgarrett.damore@Sun.COM void audio_dev_update_controls(audio_dev_t *);
2219484Sgarrett.damore@Sun.COM 
2229484Sgarrett.damore@Sun.COM /*
2239484Sgarrett.damore@Sun.COM  * This is used to read the current value of a control.
2249484Sgarrett.damore@Sun.COM  * Note, this will cause a callback into the driver to get the value.
2259484Sgarrett.damore@Sun.COM  *
2269484Sgarrett.damore@Sun.COM  * On return zero is returned on success else errno is returned.
2279484Sgarrett.damore@Sun.COM  */
2289484Sgarrett.damore@Sun.COM int audio_control_read(audio_ctrl_t *, uint64_t *);
2299484Sgarrett.damore@Sun.COM 
2309484Sgarrett.damore@Sun.COM /*
2319484Sgarrett.damore@Sun.COM  * This is used to write a value to a control.
2329484Sgarrett.damore@Sun.COM  * Note, this will cause a callback into the driver to write the value.
2339484Sgarrett.damore@Sun.COM  *
2349484Sgarrett.damore@Sun.COM  * On return zero is returned on success else errno is returned.
2359484Sgarrett.damore@Sun.COM  */
2369484Sgarrett.damore@Sun.COM int audio_control_write(audio_ctrl_t *, uint64_t);
2379484Sgarrett.damore@Sun.COM 
2389484Sgarrett.damore@Sun.COM #endif	/* _KERNEL */
2399484Sgarrett.damore@Sun.COM 
2409484Sgarrett.damore@Sun.COM #ifdef	__cplusplus
2419484Sgarrett.damore@Sun.COM }
2429484Sgarrett.damore@Sun.COM #endif
2439484Sgarrett.damore@Sun.COM 
2449484Sgarrett.damore@Sun.COM #endif	/* _SYS_AUDIO_AUDIO_DRIVER_H */
245