xref: /titanic_50/usr/src/uts/common/sys/audio/audio_driver.h (revision 2c30fa4582c5d6c659e059e719c5f6163f7ef1e3)
188447a05SGarrett D'Amore /*
288447a05SGarrett D'Amore  * CDDL HEADER START
388447a05SGarrett D'Amore  *
488447a05SGarrett D'Amore  * The contents of this file are subject to the terms of the
588447a05SGarrett D'Amore  * Common Development and Distribution License (the "License").
688447a05SGarrett D'Amore  * You may not use this file except in compliance with the License.
788447a05SGarrett D'Amore  *
888447a05SGarrett D'Amore  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
988447a05SGarrett D'Amore  * or http://www.opensolaris.org/os/licensing.
1088447a05SGarrett D'Amore  * See the License for the specific language governing permissions
1188447a05SGarrett D'Amore  * and limitations under the License.
1288447a05SGarrett D'Amore  *
1388447a05SGarrett D'Amore  * When distributing Covered Code, include this CDDL HEADER in each
1488447a05SGarrett D'Amore  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1588447a05SGarrett D'Amore  * If applicable, add the following below this CDDL HEADER, with the
1688447a05SGarrett D'Amore  * fields enclosed by brackets "[]" replaced with your own identifying
1788447a05SGarrett D'Amore  * information: Portions Copyright [yyyy] [name of copyright owner]
1888447a05SGarrett D'Amore  *
1988447a05SGarrett D'Amore  * CDDL HEADER END
2088447a05SGarrett D'Amore  */
2188447a05SGarrett D'Amore /*
2288447a05SGarrett D'Amore  * Copyright (C) 4Front Technologies 1996-2008.
2388447a05SGarrett D'Amore  *
24*2c30fa45SGarrett D'Amore  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2588447a05SGarrett D'Amore  */
2688447a05SGarrett D'Amore 
2788447a05SGarrett D'Amore #ifndef	_SYS_AUDIO_AUDIO_DRIVER_H
2888447a05SGarrett D'Amore #define	_SYS_AUDIO_AUDIO_DRIVER_H
2988447a05SGarrett D'Amore 
3088447a05SGarrett D'Amore #include <sys/types.h>
3188447a05SGarrett D'Amore #include <sys/list.h>
3288447a05SGarrett D'Amore #include <sys/ddi.h>
3388447a05SGarrett D'Amore #include <sys/sunddi.h>
3488447a05SGarrett D'Amore #include <sys/audio/audio_common.h>
3588447a05SGarrett D'Amore 
3688447a05SGarrett D'Amore 
3788447a05SGarrett D'Amore #ifdef	__cplusplus
3888447a05SGarrett D'Amore extern "C" {
3988447a05SGarrett D'Amore #endif
4088447a05SGarrett D'Amore 
4188447a05SGarrett D'Amore #ifdef	_KERNEL
4288447a05SGarrett D'Amore 
4388447a05SGarrett D'Amore struct audio_engine_ops {
4488447a05SGarrett D'Amore 	int	audio_engine_version;
4568c47f65SGarrett D'Amore #define	AUDIO_ENGINE_VERSION	2
4688447a05SGarrett D'Amore 
4788447a05SGarrett D'Amore 	/*
4888447a05SGarrett D'Amore 	 * Initialize engine, including buffer allocation.  Arguments
4988447a05SGarrett D'Amore 	 * that are pointers are hints.  On return, they are updated with
5088447a05SGarrett D'Amore 	 * the actual values configured by the driver.
5188447a05SGarrett D'Amore 	 */
5268c47f65SGarrett D'Amore 	int	(*audio_engine_open)(void *, int, uint_t *, caddr_t *);
5388447a05SGarrett D'Amore 	void	(*audio_engine_close)(void *);
5488447a05SGarrett D'Amore 
5588447a05SGarrett D'Amore 	/*
5688447a05SGarrett D'Amore 	 * Start and stop are used to actually get the hardware running
5788447a05SGarrett D'Amore 	 * or stop the hardware.  Until this is kicked off, the engine
5888447a05SGarrett D'Amore 	 * will not actually transfer data.  These are not destructive to
5988447a05SGarrett D'Amore 	 * ring positions, etc.  (Think of it like pause/play).
6088447a05SGarrett D'Amore 	 */
6188447a05SGarrett D'Amore 	int	(*audio_engine_start)(void *);
6288447a05SGarrett D'Amore 	void	(*audio_engine_stop)(void *);
6388447a05SGarrett D'Amore 
6488447a05SGarrett D'Amore 	/*
6588447a05SGarrett D'Amore 	 * Obtain the engine offset.  Offsets start at zero at engine_open,
6688447a05SGarrett D'Amore 	 * and keep counting upwards.  Count is returned in frames.
6788447a05SGarrett D'Amore 	 */
6888447a05SGarrett D'Amore 	uint64_t	(*audio_engine_count)(void *);
6988447a05SGarrett D'Amore 
7088447a05SGarrett D'Amore 	/*
7188447a05SGarrett D'Amore 	 * The following entry points return the currently configured
7288447a05SGarrett D'Amore 	 * status of the engine.  It is assumed that the engine's
7388447a05SGarrett D'Amore 	 * configuration is relatively fixed, and does not change
7488447a05SGarrett D'Amore 	 * while open, or in response to open.
7588447a05SGarrett D'Amore 	 *
7688447a05SGarrett D'Amore 	 * However, in the future we might like to allow for the
7788447a05SGarrett D'Amore 	 * device to change the settings while it is not open, which
7888447a05SGarrett D'Amore 	 * could allow for mixerctl to change the configured channels,
7988447a05SGarrett D'Amore 	 * for example.  In order to synchronize this properly, we'll
8088447a05SGarrett D'Amore 	 * need the engine to perform a notification/request.  That
8188447a05SGarrett D'Amore 	 * will be added later.
8288447a05SGarrett D'Amore 	 *
8388447a05SGarrett D'Amore 	 * AC3: We will have to figure out how to support dynamically
8488447a05SGarrett D'Amore 	 * selecting different sampling frequencies for AC3, since
8588447a05SGarrett D'Amore 	 * it needs to be able to support 32, 44.1, and 48 kHz.
8688447a05SGarrett D'Amore 	 * Perhaps special flags used during open() would do the trick.
8788447a05SGarrett D'Amore 	 */
8888447a05SGarrett D'Amore 	int	(*audio_engine_format)(void *);
8988447a05SGarrett D'Amore 	int	(*audio_engine_channels)(void *);
9088447a05SGarrett D'Amore 	int	(*audio_engine_rate)(void *);
9188447a05SGarrett D'Amore 
9288447a05SGarrett D'Amore 	/*
9388447a05SGarrett D'Amore 	 * DMA cache synchronization.  The framework does this on
9488447a05SGarrett D'Amore 	 * behalf of the driver for both input and output.  The driver
9588447a05SGarrett D'Amore 	 * is responsible for tracking the direction (based on the
9688447a05SGarrett D'Amore 	 * flags passed to ae_open()), and dealing with any partial
9788447a05SGarrett D'Amore 	 * synchronization if any is needed.
9888447a05SGarrett D'Amore 	 */
9968c47f65SGarrett D'Amore 	void	(*audio_engine_sync)(void *, uint_t);
10088447a05SGarrett D'Amore 
10188447a05SGarrett D'Amore 	/*
10288447a05SGarrett D'Amore 	 * The framework may like to know how deep the device queues data.
10388447a05SGarrett D'Amore 	 * This can be used to provide a more accurate latency calculation.
10488447a05SGarrett D'Amore 	 */
10568c47f65SGarrett D'Amore 	uint_t	(*audio_engine_qlen)(void *);
10688447a05SGarrett D'Amore 
10788447a05SGarrett D'Amore 	/*
10888447a05SGarrett D'Amore 	 * If the driver doesn't use simple interleaving, then we need to
10988447a05SGarrett D'Amore 	 * know more about the offsets of channels within the buffer.
11088447a05SGarrett D'Amore 	 * We obtain both the starting offset within the buffer, and the
11188447a05SGarrett D'Amore 	 * increment for each new sample.  As usual, these are given in
11288447a05SGarrett D'Amore 	 * samples.  If this entry point is NULL, the framework assumes
11388447a05SGarrett D'Amore 	 * that simple interlevaing is used instead.
11488447a05SGarrett D'Amore 	 */
11568c47f65SGarrett D'Amore 	void	(*audio_engine_chinfo)(void *, int chan, uint_t *offset,
11668c47f65SGarrett D'Amore 	    uint_t *incr);
117f9ead4a5SGarrett D'Amore 
118f9ead4a5SGarrett D'Amore 	/*
119f9ead4a5SGarrett D'Amore 	 * The following entry point is used to determine the play ahead
120f9ead4a5SGarrett D'Amore 	 * desired by the engine.  Engines with less consistent scheduling,
121f9ead4a5SGarrett D'Amore 	 * or with a need for deeper queuing, implement this.  If not
122f9ead4a5SGarrett D'Amore 	 * implemented, the framework assumes 1.5 * fragfr.
123f9ead4a5SGarrett D'Amore 	 */
12468c47f65SGarrett D'Amore 	uint_t	(*audio_engine_playahead)(void *);
12588447a05SGarrett D'Amore };
12688447a05SGarrett D'Amore 
12768c47f65SGarrett D'Amore /*
12868c47f65SGarrett D'Amore  * Drivers call these.
12968c47f65SGarrett D'Amore  */
13088447a05SGarrett D'Amore void audio_init_ops(struct dev_ops *, const char *);
13188447a05SGarrett D'Amore void audio_fini_ops(struct dev_ops *);
13288447a05SGarrett D'Amore 
13388447a05SGarrett D'Amore audio_dev_t *audio_dev_alloc(dev_info_t *, int);
13488447a05SGarrett D'Amore void audio_dev_free(audio_dev_t *);
13588447a05SGarrett D'Amore 
13688447a05SGarrett D'Amore void audio_dev_set_description(audio_dev_t *, const char *);
13788447a05SGarrett D'Amore void audio_dev_set_version(audio_dev_t *, const char *);
13888447a05SGarrett D'Amore void audio_dev_add_info(audio_dev_t *, const char *);
13988447a05SGarrett D'Amore 
14068c47f65SGarrett D'Amore audio_engine_t *audio_engine_alloc(audio_engine_ops_t *, uint_t);
14188447a05SGarrett D'Amore void audio_engine_set_private(audio_engine_t *, void *);
14288447a05SGarrett D'Amore void *audio_engine_get_private(audio_engine_t *);
14388447a05SGarrett D'Amore void audio_engine_free(audio_engine_t *);
14488447a05SGarrett D'Amore 
14588447a05SGarrett D'Amore void audio_dev_add_engine(audio_dev_t *, audio_engine_t *);
14688447a05SGarrett D'Amore void audio_dev_remove_engine(audio_dev_t *, audio_engine_t *);
14788447a05SGarrett D'Amore int audio_dev_register(audio_dev_t *);
14888447a05SGarrett D'Amore int audio_dev_unregister(audio_dev_t *);
14968c47f65SGarrett D'Amore void audio_dev_suspend(audio_dev_t *);
15068c47f65SGarrett D'Amore void audio_dev_resume(audio_dev_t *);
15188447a05SGarrett D'Amore void audio_dev_warn(audio_dev_t *, const char *, ...);
15268c47f65SGarrett D'Amore 
15388447a05SGarrett D'Amore /* DEBUG ONLY */
15488447a05SGarrett D'Amore void audio_dump_bytes(const uint8_t *w, int dcount);
15588447a05SGarrett D'Amore void audio_dump_words(const uint16_t *w, int dcount);
15688447a05SGarrett D'Amore void audio_dump_dwords(const uint32_t *w, int dcount);
15788447a05SGarrett D'Amore 
15888447a05SGarrett D'Amore 
15988447a05SGarrett D'Amore /* Engine flags */
16088447a05SGarrett D'Amore #define	ENGINE_OUTPUT_CAP	(1U << 2)
16188447a05SGarrett D'Amore #define	ENGINE_INPUT_CAP	(1U << 3)
16288447a05SGarrett D'Amore #define	ENGINE_CAPS		(ENGINE_OUTPUT_CAP | ENGINE_INPUT_CAP)
16388447a05SGarrett D'Amore #define	ENGINE_DRIVER_FLAGS	(0xffff)	/* flags usable by driver */
16488447a05SGarrett D'Amore 
16588447a05SGarrett D'Amore #define	ENGINE_OUTPUT		(1U << 16)	/* fields not for driver use */
16688447a05SGarrett D'Amore #define	ENGINE_INPUT		(1U << 17)
16788447a05SGarrett D'Amore #define	ENGINE_EXCLUSIVE	(1U << 20)	/* exclusive use, e.g. AC3 */
16888447a05SGarrett D'Amore #define	ENGINE_NDELAY		(1U << 21)	/* non-blocking open */
16988447a05SGarrett D'Amore 
17088447a05SGarrett D'Amore /*
17188447a05SGarrett D'Amore  * entry points used by legacy SADA drivers
17288447a05SGarrett D'Amore  */
17388447a05SGarrett D'Amore int audio_legacy_open(queue_t *, dev_t *, int, int, cred_t *);
17488447a05SGarrett D'Amore int audio_legacy_close(queue_t *, int, cred_t *);
17588447a05SGarrett D'Amore int audio_legacy_wput(queue_t *, mblk_t *);
17688447a05SGarrett D'Amore int audio_legacy_wsrv(queue_t *);
17788447a05SGarrett D'Amore 
17888447a05SGarrett D'Amore 
17988447a05SGarrett D'Amore 
18088447a05SGarrett D'Amore /*
18188447a05SGarrett D'Amore  * Audio device controls
18288447a05SGarrett D'Amore  */
18388447a05SGarrett D'Amore 
18488447a05SGarrett D'Amore /*
18588447a05SGarrett D'Amore  * Control read or write driver function type.
18688447a05SGarrett D'Amore  *
18788447a05SGarrett D'Amore  * Returns zero on success, errno on failure.
18888447a05SGarrett D'Amore  */
18988447a05SGarrett D'Amore typedef int (*audio_ctrl_wr_t)(void *, uint64_t);
19088447a05SGarrett D'Amore typedef int (*audio_ctrl_rd_t)(void *, uint64_t *);
19188447a05SGarrett D'Amore 
19288447a05SGarrett D'Amore 
19388447a05SGarrett D'Amore /*
19488447a05SGarrett D'Amore  * This will allocate and register a control for my audio device.
19588447a05SGarrett D'Amore  *
19688447a05SGarrett D'Amore  * On success this will return a control structure else NULL.
19788447a05SGarrett D'Amore  */
19888447a05SGarrett D'Amore audio_ctrl_t *audio_dev_add_control(audio_dev_t *,
19988447a05SGarrett D'Amore     audio_ctrl_desc_t *, audio_ctrl_rd_t, audio_ctrl_wr_t, void *);
20088447a05SGarrett D'Amore 
20188447a05SGarrett D'Amore /*
20288447a05SGarrett D'Amore  * Add a synthetic PCM volume control.  This should only be used by
20388447a05SGarrett D'Amore  * devices which have no physical PCM volume controls.  The control
20488447a05SGarrett D'Amore  * implements a simple attenuator on the PCM data; unlike AC'97 there
20588447a05SGarrett D'Amore  * is no "gain", so using this instead of a hardware control may
20688447a05SGarrett D'Amore  * result in loss range.  The control is implemented using
20788447a05SGarrett D'Amore  * AUDIO_CTRL_ID_VOLUME.
20888447a05SGarrett D'Amore  */
209*2c30fa45SGarrett D'Amore void audio_dev_add_soft_volume(audio_dev_t *);
21088447a05SGarrett D'Amore 
21188447a05SGarrett D'Amore /*
21288447a05SGarrett D'Amore  * This will remove a control from an audio device.
21388447a05SGarrett D'Amore  */
21488447a05SGarrett D'Amore void audio_dev_del_control(audio_ctrl_t *);
21588447a05SGarrett D'Amore 
21688447a05SGarrett D'Amore /*
21788447a05SGarrett D'Amore  * This will tell the framework that controls have changed
21888447a05SGarrett D'Amore  * and it should update its values.
21988447a05SGarrett D'Amore  */
22088447a05SGarrett D'Amore void audio_dev_update_controls(audio_dev_t *);
22188447a05SGarrett D'Amore 
22288447a05SGarrett D'Amore /*
22388447a05SGarrett D'Amore  * This is used to read the current value of a control.
22488447a05SGarrett D'Amore  * Note, this will cause a callback into the driver to get the value.
22588447a05SGarrett D'Amore  *
22688447a05SGarrett D'Amore  * On return zero is returned on success else errno is returned.
22788447a05SGarrett D'Amore  */
22888447a05SGarrett D'Amore int audio_control_read(audio_ctrl_t *, uint64_t *);
22988447a05SGarrett D'Amore 
23088447a05SGarrett D'Amore /*
23188447a05SGarrett D'Amore  * This is used to write a value to a control.
23288447a05SGarrett D'Amore  * Note, this will cause a callback into the driver to write the value.
23388447a05SGarrett D'Amore  *
23488447a05SGarrett D'Amore  * On return zero is returned on success else errno is returned.
23588447a05SGarrett D'Amore  */
23688447a05SGarrett D'Amore int audio_control_write(audio_ctrl_t *, uint64_t);
23788447a05SGarrett D'Amore 
23888447a05SGarrett D'Amore #endif	/* _KERNEL */
23988447a05SGarrett D'Amore 
24088447a05SGarrett D'Amore #ifdef	__cplusplus
24188447a05SGarrett D'Amore }
24288447a05SGarrett D'Amore #endif
24388447a05SGarrett D'Amore 
24488447a05SGarrett D'Amore #endif	/* _SYS_AUDIO_AUDIO_DRIVER_H */
245