1 1.2 isaki /* $NetBSD: audio_dai.h,v 1.2 2019/05/08 13:40:17 isaki Exp $ */ 2 1.2 isaki 3 1.2 isaki /*- 4 1.2 isaki * Copyright (c) 2018 Jared McNeill <jmcneill (at) invisible.ca> 5 1.2 isaki * All rights reserved. 6 1.2 isaki * 7 1.2 isaki * Redistribution and use in source and binary forms, with or without 8 1.2 isaki * modification, are permitted provided that the following conditions 9 1.2 isaki * are met: 10 1.2 isaki * 1. Redistributions of source code must retain the above copyright 11 1.2 isaki * notice, this list of conditions and the following disclaimer. 12 1.2 isaki * 2. Redistributions in binary form must reproduce the above copyright 13 1.2 isaki * notice, this list of conditions and the following disclaimer in the 14 1.2 isaki * documentation and/or other materials provided with the distribution. 15 1.2 isaki * 16 1.2 isaki * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 1.2 isaki * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 1.2 isaki * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 1.2 isaki * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 1.2 isaki * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 1.2 isaki * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 1.2 isaki * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 1.2 isaki * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 1.2 isaki * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 1.2 isaki * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 1.2 isaki * SUCH DAMAGE. 27 1.2 isaki */ 28 1.2 isaki 29 1.2 isaki #ifndef _DEV_AUDIO_AUDIO_DAI_H 30 1.2 isaki #define _DEV_AUDIO_AUDIO_DAI_H 31 1.2 isaki 32 1.2 isaki #include <sys/errno.h> 33 1.2 isaki #include <dev/audio/audio_if.h> 34 1.2 isaki 35 1.2 isaki #define AUDIO_DAI_FORMAT_MASK __BITS(3,0) 36 1.2 isaki #define AUDIO_DAI_FORMAT_I2S 0 37 1.2 isaki #define AUDIO_DAI_FORMAT_RJ 1 38 1.2 isaki #define AUDIO_DAI_FORMAT_LJ 2 39 1.2 isaki #define AUDIO_DAI_FORMAT_DSPA 3 40 1.2 isaki #define AUDIO_DAI_FORMAT_DSPB 4 41 1.2 isaki #define AUDIO_DAI_FORMAT_AC97 5 42 1.2 isaki #define AUDIO_DAI_FORMAT_PDM 6 43 1.2 isaki 44 1.2 isaki #define AUDIO_DAI_POLARITY_MASK __BITS(5,4) 45 1.2 isaki #define AUDIO_DAI_POLARITY_NB_NF 0 46 1.2 isaki #define AUDIO_DAI_POLARITY_NB_IF 1 47 1.2 isaki #define AUDIO_DAI_POLARITY_IB_NF 2 48 1.2 isaki #define AUDIO_DAI_POLARITY_IB_IF 3 49 1.2 isaki #define AUDIO_DAI_POLARITY_F(n) (((n) & 0x1) != 0) 50 1.2 isaki #define AUDIO_DAI_POLARITY_B(n) (((n) & 0x2) != 0) 51 1.2 isaki 52 1.2 isaki #define AUDIO_DAI_CLOCK_MASK __BITS(9,8) 53 1.2 isaki #define AUDIO_DAI_CLOCK_CBM_CFM 0 54 1.2 isaki #define AUDIO_DAI_CLOCK_CBS_CFM 1 55 1.2 isaki #define AUDIO_DAI_CLOCK_CBM_CFS 2 56 1.2 isaki #define AUDIO_DAI_CLOCK_CBS_CFS 3 57 1.2 isaki 58 1.2 isaki #define AUDIO_DAI_CLOCK_IN 0 59 1.2 isaki #define AUDIO_DAI_CLOCK_OUT 1 60 1.2 isaki 61 1.2 isaki #define AUDIO_DAI_JACK_HP 0 62 1.2 isaki #define AUDIO_DAI_JACK_MIC 1 63 1.2 isaki 64 1.2 isaki typedef struct audio_dai_device { 65 1.2 isaki int (*dai_set_sysclk)(struct audio_dai_device *, u_int, int); 66 1.2 isaki int (*dai_set_format)(struct audio_dai_device *, u_int); 67 1.2 isaki int (*dai_add_device)(struct audio_dai_device *, struct audio_dai_device *); 68 1.2 isaki int (*dai_jack_detect)(struct audio_dai_device *, u_int, int); 69 1.2 isaki 70 1.2 isaki const struct audio_hw_if *dai_hw_if; /* audio driver callbacks */ 71 1.2 isaki 72 1.2 isaki device_t dai_dev; /* device */ 73 1.2 isaki void *dai_priv; /* driver private data */ 74 1.2 isaki } *audio_dai_tag_t; 75 1.2 isaki 76 1.2 isaki static inline device_t 77 1.2 isaki audio_dai_device(audio_dai_tag_t dai) 78 1.2 isaki { 79 1.2 isaki return dai->dai_dev; 80 1.2 isaki } 81 1.2 isaki 82 1.2 isaki static inline void * 83 1.2 isaki audio_dai_private(audio_dai_tag_t dai) 84 1.2 isaki { 85 1.2 isaki return dai->dai_priv; 86 1.2 isaki } 87 1.2 isaki 88 1.2 isaki static inline int 89 1.2 isaki audio_dai_set_sysclk(audio_dai_tag_t dai, u_int rate, int dir) 90 1.2 isaki { 91 1.2 isaki if (!dai->dai_set_sysclk) 92 1.2 isaki return 0; 93 1.2 isaki 94 1.2 isaki return dai->dai_set_sysclk(dai, rate, dir); 95 1.2 isaki } 96 1.2 isaki 97 1.2 isaki static inline int 98 1.2 isaki audio_dai_set_format(audio_dai_tag_t dai, u_int format) 99 1.2 isaki { 100 1.2 isaki if (!dai->dai_set_format) 101 1.2 isaki return 0; 102 1.2 isaki 103 1.2 isaki return dai->dai_set_format(dai, format); 104 1.2 isaki } 105 1.2 isaki 106 1.2 isaki static inline int 107 1.2 isaki audio_dai_add_device(audio_dai_tag_t dai, audio_dai_tag_t aux) 108 1.2 isaki { 109 1.2 isaki if (!dai->dai_add_device) 110 1.2 isaki return 0; 111 1.2 isaki 112 1.2 isaki return dai->dai_add_device(dai, aux); 113 1.2 isaki } 114 1.2 isaki 115 1.2 isaki static inline int 116 1.2 isaki audio_dai_jack_detect(audio_dai_tag_t dai, u_int jack, bool present) 117 1.2 isaki { 118 1.2 isaki if (!dai->dai_jack_detect) 119 1.2 isaki return 0; 120 1.2 isaki 121 1.2 isaki return dai->dai_jack_detect(dai, jack, present); 122 1.2 isaki } 123 1.2 isaki 124 1.2 isaki static inline int 125 1.2 isaki audio_dai_open(audio_dai_tag_t dai, int flags) 126 1.2 isaki { 127 1.2 isaki if (!dai->dai_hw_if->open) 128 1.2 isaki return 0; 129 1.2 isaki return dai->dai_hw_if->open(dai->dai_priv, flags); 130 1.2 isaki } 131 1.2 isaki 132 1.2 isaki static inline void 133 1.2 isaki audio_dai_close(audio_dai_tag_t dai) 134 1.2 isaki { 135 1.2 isaki if (!dai->dai_hw_if->close) 136 1.2 isaki return; 137 1.2 isaki dai->dai_hw_if->close(dai->dai_priv); 138 1.2 isaki } 139 1.2 isaki 140 1.2 isaki static inline int 141 1.2 isaki audio_dai_query_format(audio_dai_tag_t dai, audio_format_query_t *afp) 142 1.2 isaki { 143 1.2 isaki if (!dai->dai_hw_if->query_format) 144 1.2 isaki return 0; 145 1.2 isaki return dai->dai_hw_if->query_format(dai->dai_priv, afp); 146 1.2 isaki } 147 1.2 isaki 148 1.2 isaki static inline int 149 1.2 isaki audio_dai_mi_set_format(audio_dai_tag_t dai, int setmode, 150 1.2 isaki const audio_params_t *play, const audio_params_t *rec, 151 1.2 isaki audio_filter_reg_t *pfil, audio_filter_reg_t *rfil) 152 1.2 isaki { 153 1.2 isaki if (!dai->dai_hw_if->set_format) 154 1.2 isaki return 0; 155 1.2 isaki return dai->dai_hw_if->set_format(dai->dai_priv, setmode, 156 1.2 isaki play, rec, pfil, rfil); 157 1.2 isaki } 158 1.2 isaki 159 1.2 isaki static inline int 160 1.2 isaki audio_dai_round_blocksize(audio_dai_tag_t dai, int bs, int mode, 161 1.2 isaki const audio_params_t *params) 162 1.2 isaki { 163 1.2 isaki if (!dai->dai_hw_if->round_blocksize) 164 1.2 isaki return bs; 165 1.2 isaki return dai->dai_hw_if->round_blocksize(dai->dai_priv, bs, 166 1.2 isaki mode, params); 167 1.2 isaki } 168 1.2 isaki 169 1.2 isaki static inline int 170 1.2 isaki audio_dai_commit_settings(audio_dai_tag_t dai) 171 1.2 isaki { 172 1.2 isaki if (!dai->dai_hw_if->commit_settings) 173 1.2 isaki return 0; 174 1.2 isaki return dai->dai_hw_if->commit_settings(dai->dai_priv); 175 1.2 isaki } 176 1.2 isaki 177 1.2 isaki static inline int 178 1.2 isaki audio_dai_halt(audio_dai_tag_t dai, int dir) 179 1.2 isaki { 180 1.2 isaki switch (dir) { 181 1.2 isaki case AUMODE_PLAY: 182 1.2 isaki if (!dai->dai_hw_if->halt_output) 183 1.2 isaki return 0; 184 1.2 isaki return dai->dai_hw_if->halt_output(dai->dai_priv); 185 1.2 isaki case AUMODE_RECORD: 186 1.2 isaki if (!dai->dai_hw_if->halt_input) 187 1.2 isaki return 0; 188 1.2 isaki return dai->dai_hw_if->halt_input(dai->dai_priv); 189 1.2 isaki default: 190 1.2 isaki return EINVAL; 191 1.2 isaki } 192 1.2 isaki } 193 1.2 isaki 194 1.2 isaki static inline int 195 1.2 isaki audio_dai_trigger(audio_dai_tag_t dai, void *start, void *end, int blksize, 196 1.2 isaki void (*intr)(void *), void *intrarg, const audio_params_t *params, 197 1.2 isaki int dir) 198 1.2 isaki { 199 1.2 isaki switch (dir) { 200 1.2 isaki case AUMODE_PLAY: 201 1.2 isaki if (!dai->dai_hw_if->trigger_output) 202 1.2 isaki return 0; 203 1.2 isaki return dai->dai_hw_if->trigger_output(dai->dai_priv, start, 204 1.2 isaki end, blksize, intr, intrarg, params); 205 1.2 isaki case AUMODE_RECORD: 206 1.2 isaki if (!dai->dai_hw_if->trigger_input) 207 1.2 isaki return 0; 208 1.2 isaki return dai->dai_hw_if->trigger_input(dai->dai_priv, start, 209 1.2 isaki end, blksize, intr, intrarg, params); 210 1.2 isaki default: 211 1.2 isaki return EINVAL; 212 1.2 isaki } 213 1.2 isaki } 214 1.2 isaki 215 1.2 isaki static inline void * 216 1.2 isaki audio_dai_allocm(audio_dai_tag_t dai, int dir, size_t size) 217 1.2 isaki { 218 1.2 isaki if (!dai->dai_hw_if->allocm) 219 1.2 isaki return NULL; 220 1.2 isaki return dai->dai_hw_if->allocm(dai->dai_priv, dir, size); 221 1.2 isaki } 222 1.2 isaki 223 1.2 isaki static inline void 224 1.2 isaki audio_dai_freem(audio_dai_tag_t dai, void *addr, size_t size) 225 1.2 isaki { 226 1.2 isaki if (!dai->dai_hw_if->freem) 227 1.2 isaki return; 228 1.2 isaki dai->dai_hw_if->freem(dai->dai_priv, addr, size); 229 1.2 isaki } 230 1.2 isaki 231 1.2 isaki static inline size_t 232 1.2 isaki audio_dai_round_buffersize(audio_dai_tag_t dai, int dir, size_t bufsize) 233 1.2 isaki { 234 1.2 isaki if (!dai->dai_hw_if->round_buffersize) 235 1.2 isaki return bufsize; 236 1.2 isaki return dai->dai_hw_if->round_buffersize(dai->dai_priv, dir, bufsize); 237 1.2 isaki } 238 1.2 isaki 239 1.2 isaki static inline int 240 1.2 isaki audio_dai_get_props(audio_dai_tag_t dai) 241 1.2 isaki { 242 1.2 isaki if (!dai->dai_hw_if->get_props) 243 1.2 isaki return 0; 244 1.2 isaki return dai->dai_hw_if->get_props(dai->dai_priv); 245 1.2 isaki } 246 1.2 isaki 247 1.2 isaki static inline int 248 1.2 isaki audio_dai_getdev(audio_dai_tag_t dai, struct audio_device *adev) 249 1.2 isaki { 250 1.2 isaki if (!dai->dai_hw_if->getdev) 251 1.2 isaki return ENXIO; 252 1.2 isaki return dai->dai_hw_if->getdev(dai->dai_priv, adev); 253 1.2 isaki } 254 1.2 isaki 255 1.2 isaki static inline int 256 1.2 isaki audio_dai_get_port(audio_dai_tag_t dai, mixer_ctrl_t *mc) 257 1.2 isaki { 258 1.2 isaki if (!dai->dai_hw_if->get_port) 259 1.2 isaki return ENXIO; 260 1.2 isaki return dai->dai_hw_if->get_port(dai->dai_priv, mc); 261 1.2 isaki } 262 1.2 isaki 263 1.2 isaki static inline int 264 1.2 isaki audio_dai_set_port(audio_dai_tag_t dai, mixer_ctrl_t *mc) 265 1.2 isaki { 266 1.2 isaki if (!dai->dai_hw_if->set_port) 267 1.2 isaki return ENXIO; 268 1.2 isaki return dai->dai_hw_if->set_port(dai->dai_priv, mc); 269 1.2 isaki } 270 1.2 isaki 271 1.2 isaki static inline int 272 1.2 isaki audio_dai_query_devinfo(audio_dai_tag_t dai, mixer_devinfo_t *di) 273 1.2 isaki { 274 1.2 isaki if (!dai->dai_hw_if->query_devinfo) 275 1.2 isaki return ENXIO; 276 1.2 isaki return dai->dai_hw_if->query_devinfo(dai->dai_priv, di); 277 1.2 isaki } 278 1.2 isaki 279 1.2 isaki static inline void 280 1.2 isaki audio_dai_get_locks(audio_dai_tag_t dai, kmutex_t **intr, kmutex_t **thread) 281 1.2 isaki { 282 1.2 isaki if (!dai->dai_hw_if->get_locks) { 283 1.2 isaki *intr = NULL; 284 1.2 isaki *thread = NULL; 285 1.2 isaki return; 286 1.2 isaki } 287 1.2 isaki 288 1.2 isaki dai->dai_hw_if->get_locks(dai->dai_priv, intr, thread); 289 1.2 isaki } 290 1.2 isaki 291 1.2 isaki #endif /* _DEV_AUDIO_AUDIO_DAI_H */ 292