hdaudiovar.h revision 1.3 1 /* $NetBSD: hdaudiovar.h,v 1.3 2015/05/30 13:47:03 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/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