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
61enum function_group_type {
62 HDAUDIO_GROUP_TYPE_UNKNOWN = 0,
63 HDAUDIO_GROUP_TYPE_AFG,
64 HDAUDIO_GROUP_TYPE_VSM_FG,
65};
66
67struct hdaudio_softc;
68
69struct 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
80struct 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
91struct 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
103struct hdaudio_dma_position {
104 uint32_t position;
105 uint32_t reserved;
106} __packed;
107
108struct 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
118enum hdaudio_stream_type {
119 HDAUDIO_STREAM_ISS = 0,
120 HDAUDIO_STREAM_OSS = 1,
121 HDAUDIO_STREAM_BSS = 2
122};
123
124struct 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
138struct 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
162int hdaudio_attach(device_t, struct hdaudio_softc *);
163int hdaudio_detach(struct hdaudio_softc *, int);
164bool hdaudio_resume(struct hdaudio_softc *);
165int hdaudio_rescan(struct hdaudio_softc *, const char *, const int *);
166void hdaudio_childdet(struct hdaudio_softc *, device_t);
167
168uint32_t hdaudio_command(struct hdaudio_codec *, int, uint32_t, uint32_t);
169uint32_t hdaudio_command_unlocked(struct hdaudio_codec *, int, uint32_t,
170 uint32_t);
171int hdaudio_intr(struct hdaudio_softc *);
172
173int hdaudio_dma_alloc(struct hdaudio_softc *, struct hdaudio_dma *, int);
174void hdaudio_dma_free(struct hdaudio_softc *, struct hdaudio_dma *);
175
176struct hdaudio_stream * hdaudio_stream_establish(struct hdaudio_softc *,
177 enum hdaudio_stream_type,
178 int (*)(struct hdaudio_stream *), void *);
179void hdaudio_stream_disestablish(struct hdaudio_stream *);
180void hdaudio_stream_start(struct hdaudio_stream *, int, bus_size_t,
181 const audio_params_t *);
182void hdaudio_stream_stop(struct hdaudio_stream *);
183void hdaudio_stream_reset(struct hdaudio_stream *);
184int hdaudio_stream_tag(struct hdaudio_stream *);
185uint16_t hdaudio_stream_param(struct hdaudio_stream *, const audio_params_t *);
186
187#ifdef HDAUDIO_32BIT_ACCESS
188static 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}
194static 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))
204static 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}
213static 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