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