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