Home | History | Annotate | Line # | Download | only in audio
      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