1 /* $NetBSD: hdaudiovar.h,v 1.8 2019/07/25 00:30:45 jmcneill Exp $ */ 2 3 /* 4 * Copyright (c) 2009 Precedence Technologies Ltd <support (at) precedence.co.uk> 5 * Copyright (c) 2009 Jared D. McNeill <jmcneill (at) invisible.ca> 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Precedence Technologies Ltd 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #ifndef _HDAUDIOVAR_H 33 #define _HDAUDIOVAR_H 34 35 #include <dev/audio/audio_if.h> 36 37 #ifdef _KERNEL_OPT 38 #include "opt_hdaudio.h" 39 #endif 40 41 #define HDAUDIO_MAX_CODECS 15 42 43 #define hda_print(sc, ...) \ 44 aprint_normal_dev((sc)->sc_dev, __VA_ARGS__) 45 #define hda_print1(sc, ...) \ 46 aprint_normal(__VA_ARGS__) 47 #define hda_error(sc, ...) \ 48 aprint_error_dev((sc)->sc_dev, __VA_ARGS__) 49 #ifdef HDAUDIO_DEBUG 50 #define hda_trace(sc, ...) \ 51 aprint_normal_dev((sc)->sc_dev, __VA_ARGS__) 52 #define hda_trace1(sc, ...) \ 53 aprint_normal(__VA_ARGS__) 54 #else 55 #define hda_trace(sc, ...) do { } while (0) 56 #define hda_trace1(sc, ...) do { } while (0) 57 #endif 58 #define hda_delay(us) \ 59 delay((us)) 60 61 enum function_group_type { 62 HDAUDIO_GROUP_TYPE_UNKNOWN = 0, 63 HDAUDIO_GROUP_TYPE_AFG, 64 HDAUDIO_GROUP_TYPE_VSM_FG, 65 }; 66 67 struct hdaudio_softc; 68 69 struct hdaudio_function_group { 70 device_t fg_device; 71 struct hdaudio_codec *fg_codec; 72 enum function_group_type fg_type; 73 int fg_nid; 74 uint16_t fg_vendor; 75 uint16_t fg_product; 76 77 int (*fg_unsol)(device_t, uint8_t); 78 }; 79 80 struct hdaudio_codec { 81 bool co_valid; 82 u_int co_addr; 83 u_int co_nfg; 84 struct hdaudio_function_group *co_fg; 85 struct hdaudio_softc *co_host; 86 }; 87 88 #define DMA_KERNADDR(dma) ((dma)->dma_addr) 89 #define DMA_DMAADDR(dma) ((dma)->dma_map->dm_segs[0].ds_addr) 90 91 struct hdaudio_dma { 92 bus_dmamap_t dma_map; 93 void *dma_addr; 94 bus_dma_segment_t dma_segs[1]; 95 int dma_nsegs; 96 bus_size_t dma_size; 97 bool dma_valid; 98 uint8_t dma_sizereg; 99 }; 100 101 #define HDAUDIO_MAX_STREAMS 30 102 103 struct hdaudio_dma_position { 104 uint32_t position; 105 uint32_t reserved; 106 } __packed; 107 108 struct hdaudio_bdl_entry { 109 uint32_t address_lo; 110 uint32_t address_hi; 111 uint32_t length; 112 uint32_t flags; 113 #define HDAUDIO_BDL_ENTRY_IOC 0x00000001 114 } __packed; 115 116 #define HDAUDIO_BDL_MAX 256 117 118 enum hdaudio_stream_type { 119 HDAUDIO_STREAM_ISS = 0, 120 HDAUDIO_STREAM_OSS = 1, 121 HDAUDIO_STREAM_BSS = 2 122 }; 123 124 struct hdaudio_stream { 125 struct hdaudio_softc *st_host; 126 bool st_enable; 127 enum hdaudio_stream_type st_type; 128 int st_shift; 129 int st_num; 130 131 int (*st_intr)(struct hdaudio_stream *); 132 void *st_cookie; 133 134 struct hdaudio_dma st_data; 135 struct hdaudio_dma st_bdl; 136 }; 137 138 struct hdaudio_softc { 139 device_t sc_dev; 140 141 bus_dma_tag_t sc_dmat; 142 bus_space_tag_t sc_memt; 143 bus_space_handle_t sc_memh; 144 bus_addr_t sc_membase; 145 bus_size_t sc_memsize; 146 bool sc_memvalid; 147 148 uint32_t sc_flags; 149 #define HDAUDIO_FLAG_32BIT __BIT(0) 150 151 uint32_t sc_subsystem; 152 153 kmutex_t sc_corb_mtx; 154 struct hdaudio_dma sc_corb; 155 struct hdaudio_dma sc_rirb; 156 uint16_t sc_rirbrp; 157 158 struct hdaudio_codec sc_codec[HDAUDIO_MAX_CODECS]; 159 160 struct hdaudio_stream sc_stream[HDAUDIO_MAX_STREAMS]; 161 uint32_t sc_stream_mask; 162 kmutex_t sc_stream_mtx; 163 }; 164 165 int hdaudio_attach(device_t, struct hdaudio_softc *); 166 int hdaudio_detach(struct hdaudio_softc *, int); 167 bool hdaudio_resume(struct hdaudio_softc *); 168 int hdaudio_rescan(struct hdaudio_softc *, const char *, const int *); 169 void hdaudio_childdet(struct hdaudio_softc *, device_t); 170 171 uint32_t hdaudio_command(struct hdaudio_codec *, int, uint32_t, uint32_t); 172 uint32_t hdaudio_command_unlocked(struct hdaudio_codec *, int, uint32_t, 173 uint32_t); 174 int hdaudio_intr(struct hdaudio_softc *); 175 176 int hdaudio_dma_alloc(struct hdaudio_softc *, struct hdaudio_dma *, int); 177 void hdaudio_dma_free(struct hdaudio_softc *, struct hdaudio_dma *); 178 179 struct hdaudio_stream * hdaudio_stream_establish(struct hdaudio_softc *, 180 enum hdaudio_stream_type, 181 int (*)(struct hdaudio_stream *), void *); 182 void hdaudio_stream_disestablish(struct hdaudio_stream *); 183 void hdaudio_stream_start(struct hdaudio_stream *, int, bus_size_t, 184 const audio_params_t *); 185 void hdaudio_stream_stop(struct hdaudio_stream *); 186 void hdaudio_stream_reset(struct hdaudio_stream *); 187 int hdaudio_stream_tag(struct hdaudio_stream *); 188 uint16_t hdaudio_stream_param(struct hdaudio_stream *, const audio_params_t *); 189 190 static __inline uint8_t 191 _hda_read1(struct hdaudio_softc *sc, bus_size_t off) 192 { 193 if (ISSET(sc->sc_flags, HDAUDIO_FLAG_32BIT)) { 194 return bus_space_read_4(sc->sc_memt, sc->sc_memh, off & -4) >> 195 (8 * (off & 3)); 196 } else { 197 return bus_space_read_1(sc->sc_memt, sc->sc_memh, off); 198 } 199 } 200 201 static __inline uint16_t 202 _hda_read2(struct hdaudio_softc *sc, bus_size_t off) 203 { 204 if (ISSET(sc->sc_flags, HDAUDIO_FLAG_32BIT)) { 205 return bus_space_read_4(sc->sc_memt, sc->sc_memh, off & -4) >> 206 (8 * (off & 2)); 207 } else { 208 return bus_space_read_2(sc->sc_memt, sc->sc_memh, off); 209 } 210 } 211 212 #define hda_read1 _hda_read1 213 #define hda_read2 _hda_read2 214 #define hda_read4(sc, off) \ 215 bus_space_read_4((sc)->sc_memt, (sc)->sc_memh, (off)) 216 217 static __inline void 218 _hda_write1(struct hdaudio_softc *sc, bus_size_t off, uint8_t val) 219 { 220 if (ISSET(sc->sc_flags, HDAUDIO_FLAG_32BIT)) { 221 const size_t shift = 8 * (off & 3); 222 off &= -4; 223 uint32_t tmp = bus_space_read_4(sc->sc_memt, sc->sc_memh, off); 224 tmp = (val << shift) | (tmp & ~(0xff << shift)); 225 bus_space_write_4(sc->sc_memt, sc->sc_memh, off, tmp); 226 } else { 227 bus_space_write_1(sc->sc_memt, sc->sc_memh, off, val); 228 } 229 } 230 231 static __inline void 232 _hda_write2(struct hdaudio_softc *sc, bus_size_t off, uint16_t val) 233 { 234 if (ISSET(sc->sc_flags, HDAUDIO_FLAG_32BIT)) { 235 const size_t shift = 8 * (off & 2); 236 off &= -4; 237 uint32_t tmp = bus_space_read_4(sc->sc_memt, sc->sc_memh, off); 238 tmp = (val << shift) | (tmp & ~(0xffff << shift)); 239 bus_space_write_4(sc->sc_memt, sc->sc_memh, off, tmp); 240 } else { 241 bus_space_write_2(sc->sc_memt, sc->sc_memh, off, val); 242 } 243 } 244 245 #define hda_write1 _hda_write1 246 #define hda_write2 _hda_write2 247 #define hda_write4(sc, off, val) \ 248 bus_space_write_4((sc)->sc_memt, (sc)->sc_memh, (off), (val)) 249 250 #endif /* !_HDAUDIOVAR_H */ 251