1 | /* $NetBSD: hdaudiovar.h,v 1.5 2015/12/23 12:45:06 jmcneill Exp $ */ |
2 | |
3 | /* |
4 | * Copyright (c) 2009 Precedence Technologies Ltd <support@precedence.co.uk> |
5 | * Copyright (c) 2009 Jared D. McNeill <jmcneill@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/auconv.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_subsystem; |
149 | |
150 | kmutex_t sc_corb_mtx; |
151 | struct hdaudio_dma sc_corb; |
152 | struct hdaudio_dma sc_rirb; |
153 | uint16_t sc_rirbrp; |
154 | |
155 | struct hdaudio_codec sc_codec[HDAUDIO_MAX_CODECS]; |
156 | |
157 | struct hdaudio_stream sc_stream[HDAUDIO_MAX_STREAMS]; |
158 | uint32_t sc_stream_mask; |
159 | kmutex_t sc_stream_mtx; |
160 | }; |
161 | |
162 | int hdaudio_attach(device_t, struct hdaudio_softc *); |
163 | int hdaudio_detach(struct hdaudio_softc *, int); |
164 | bool hdaudio_resume(struct hdaudio_softc *); |
165 | int hdaudio_rescan(struct hdaudio_softc *, const char *, const int *); |
166 | void hdaudio_childdet(struct hdaudio_softc *, device_t); |
167 | |
168 | uint32_t hdaudio_command(struct hdaudio_codec *, int, uint32_t, uint32_t); |
169 | uint32_t hdaudio_command_unlocked(struct hdaudio_codec *, int, uint32_t, |
170 | uint32_t); |
171 | int hdaudio_intr(struct hdaudio_softc *); |
172 | |
173 | int hdaudio_dma_alloc(struct hdaudio_softc *, struct hdaudio_dma *, int); |
174 | void hdaudio_dma_free(struct hdaudio_softc *, struct hdaudio_dma *); |
175 | |
176 | struct hdaudio_stream * hdaudio_stream_establish(struct hdaudio_softc *, |
177 | enum hdaudio_stream_type, |
178 | int (*)(struct hdaudio_stream *), void *); |
179 | void hdaudio_stream_disestablish(struct hdaudio_stream *); |
180 | void hdaudio_stream_start(struct hdaudio_stream *, int, bus_size_t, |
181 | const audio_params_t *); |
182 | void hdaudio_stream_stop(struct hdaudio_stream *); |
183 | void hdaudio_stream_reset(struct hdaudio_stream *); |
184 | int hdaudio_stream_tag(struct hdaudio_stream *); |
185 | uint16_t hdaudio_stream_param(struct hdaudio_stream *, const audio_params_t *); |
186 | |
187 | #ifdef HDAUDIO_32BIT_ACCESS |
188 | static inline uint8_t |
189 | _hda_read1(struct hdaudio_softc *sc, bus_size_t off) |
190 | { |
191 | return bus_space_read_4(sc->sc_memt, sc->sc_memh, off & -4) >> |
192 | (8 * (off & 3)); |
193 | } |
194 | static inline uint16_t |
195 | _hda_read2(struct hdaudio_softc *sc, bus_size_t off) |
196 | { |
197 | return bus_space_read_4(sc->sc_memt, sc->sc_memh, off & -4) >> |
198 | (8 * (off & 2)); |
199 | } |
200 | #define hda_read1 _hda_read1 |
201 | #define hda_read2 _hda_read2 |
202 | #define hda_read4(sc, off) \ |
203 | bus_space_read_4((sc)->sc_memt, (sc)->sc_memh, (off)) |
204 | static inline void |
205 | _hda_write1(struct hdaudio_softc *sc, bus_size_t off, uint8_t val) |
206 | { |
207 | const size_t shift = 8 * (off & 3); |
208 | off &= -4; |
209 | uint32_t tmp = bus_space_read_4(sc->sc_memt, sc->sc_memh, off); |
210 | tmp = (val << shift) | (tmp & ~(0xff << shift)); |
211 | bus_space_write_4(sc->sc_memt, sc->sc_memh, off, tmp); |
212 | } |
213 | static inline void |
214 | _hda_write2(struct hdaudio_softc *sc, bus_size_t off, uint16_t val) |
215 | { |
216 | const size_t shift = 8 * (off & 2); |
217 | off &= -4; |
218 | uint32_t tmp = bus_space_read_4(sc->sc_memt, sc->sc_memh, off); |
219 | tmp = (val << shift) | (tmp & ~(0xffff << shift)); |
220 | bus_space_write_4(sc->sc_memt, sc->sc_memh, off, tmp); |
221 | } |
222 | #define hda_write1 _hda_write1 |
223 | #define hda_write2 _hda_write2 |
224 | #define hda_write4(sc, off, val) \ |
225 | bus_space_write_4((sc)->sc_memt, (sc)->sc_memh, (off), (val)) |
226 | #else |
227 | #define hda_read1(sc, off) \ |
228 | bus_space_read_1((sc)->sc_memt, (sc)->sc_memh, (off)) |
229 | #define hda_read2(sc, off) \ |
230 | bus_space_read_2((sc)->sc_memt, (sc)->sc_memh, (off)) |
231 | #define hda_read4(sc, off) \ |
232 | bus_space_read_4((sc)->sc_memt, (sc)->sc_memh, (off)) |
233 | #define hda_write1(sc, off, val) \ |
234 | bus_space_write_1((sc)->sc_memt, (sc)->sc_memh, (off), (val)) |
235 | #define hda_write2(sc, off, val) \ |
236 | bus_space_write_2((sc)->sc_memt, (sc)->sc_memh, (off), (val)) |
237 | #define hda_write4(sc, off, val) \ |
238 | bus_space_write_4((sc)->sc_memt, (sc)->sc_memh, (off), (val)) |
239 | #endif |
240 | |
241 | #endif /* !_HDAUDIOVAR_H */ |
242 | |