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