1 | /* $NetBSD: esmvar.h,v 1.18 2011/11/23 23:07:35 jmcneill Exp $ */ |
2 | |
3 | /*- |
4 | * Copyright (c) 2002, 2003 Matt Fredette |
5 | * All rights reserved. |
6 | * |
7 | * Copyright (c) 2000, 2001 Rene Hexel <rh@NetBSD.org> |
8 | * All rights reserved. |
9 | * |
10 | * Copyright (c) 2000 Taku YAMAMOTO <taku@cent.saitama-u.ac.jp> |
11 | * All rights reserved. |
12 | * |
13 | * Redistribution and use in source and binary forms, with or without |
14 | * modification, are permitted provided that the following conditions |
15 | * are met: |
16 | * 1. Redistributions of source code must retain the above copyright |
17 | * notice, this list of conditions and the following disclaimer. |
18 | * 2. Redistributions in binary form must reproduce the above copyright |
19 | * notice, this list of conditions and the following disclaimer in the |
20 | * documentation and/or other materials provided with the distribution. |
21 | * |
22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
32 | * SUCH DAMAGE. |
33 | * |
34 | * Taku Id: maestro.c,v 1.12 2000/09/06 03:32:34 taku Exp |
35 | * FreeBSD: /c/ncvs/src/sys/dev/sound/pci/maestro.c,v 1.4 2000/12/18 01:36:35 cg Exp |
36 | * |
37 | */ |
38 | |
39 | /* |
40 | * Credits: |
41 | * |
42 | * This code is based on the FreeBSD driver written by Taku YAMAMOTO |
43 | * |
44 | * |
45 | * Original credits from the FreeBSD driver: |
46 | * |
47 | * Part of this code (especially in many magic numbers) was heavily inspired |
48 | * by the Linux driver originally written by |
49 | * Alan Cox <alan.cox@linux.org>, modified heavily by |
50 | * Zach Brown <zab@zabbo.net>. |
51 | * |
52 | * busdma()-ize and buffer size reduction were suggested by |
53 | * Cameron Grant <gandalf@vilnya.demon.co.uk>. |
54 | * Also he showed me the way to use busdma() suite. |
55 | * |
56 | * Internal speaker problems on NEC VersaPro's and Dell Inspiron 7500 |
57 | * were looked at by |
58 | * Munehiro Matsuda <haro@tk.kubota.co.jp>, |
59 | * who brought patches based on the Linux driver with some simplification. |
60 | */ |
61 | |
62 | /* IRQ timer fequency limits */ |
63 | #define MAESTRO_MINFREQ 24 |
64 | #define MAESTRO_MAXFREQ 48000 |
65 | |
66 | /* |
67 | * This driver allocates a contiguous 256KB region of memory. |
68 | * The Maestro's DMA interface, called the WaveCache, is weak |
69 | * (or at least incorrectly documented), and forces us to keep |
70 | * things very simple. This region is very carefully divided up |
71 | * into 64KB quarters, making 64KB a fundamental constant for |
72 | * this implementation - and this is as large as we can allow |
73 | * the upper-layer playback and record buffers to become. |
74 | */ |
75 | #define MAESTRO_QUARTER_SZ (64 * 1024) |
76 | |
77 | /* |
78 | * The first quarter of memory is used while recording. The |
79 | * first 512 bytes of it is reserved as a scratch area for the |
80 | * APUs that want to write (uninteresting, to us) FIFO status |
81 | * information. After some guard space, another 512 bytes is |
82 | * reserved for the APUs doing mixing. The remainder of this |
83 | * quarter of memory is wasted. |
84 | */ |
85 | #define MAESTRO_FIFO_OFF (MAESTRO_QUARTER_SZ * 0) |
86 | #define MAESTRO_FIFO_SZ (512) |
87 | #define MAESTRO_MIXBUF_OFF (MAESTRO_FIFO_OFF + 4096) |
88 | #define MAESTRO_MIXBUF_SZ (512) |
89 | |
90 | /* |
91 | * The second quarter of memory is the playback buffer. |
92 | */ |
93 | #define MAESTRO_PLAYBUF_OFF (MAESTRO_QUARTER_SZ * 1) |
94 | #define MAESTRO_PLAYBUF_SZ MAESTRO_QUARTER_SZ |
95 | |
96 | /* |
97 | * The third quarter of memory is the mono record buffer. |
98 | * This is the only record buffer that the upper layer knows. |
99 | * When recording in stereo, our driver combines (in software) |
100 | * separately recorded left and right buffers here. |
101 | */ |
102 | #define MAESTRO_RECBUF_OFF (MAESTRO_QUARTER_SZ * 2) |
103 | #define MAESTRO_RECBUF_SZ MAESTRO_QUARTER_SZ |
104 | |
105 | /* |
106 | * The fourth quarter of memory is the stereo record buffer. |
107 | * When recording in stereo, the left and right channels are |
108 | * recorded separately into the two halves of this buffer. |
109 | */ |
110 | #define MAESTRO_RECBUF_L_OFF (MAESTRO_QUARTER_SZ * 3) |
111 | #define MAESTRO_RECBUF_L_SZ (MAESTRO_QUARTER_SZ / 2) |
112 | #define MAESTRO_RECBUF_R_OFF (MAESTRO_RECBUF_L_OFF + MAESTRO_RECBUF_L_SZ) |
113 | #define MAESTRO_RECBUF_R_SZ (MAESTRO_QUARTER_SZ / 2) |
114 | |
115 | /* |
116 | * The size and alignment of the entire region. We keep |
117 | * the region aligned to a 128KB boundary, since this should |
118 | * force A16..A0 on all chip-generated addresses to correspond |
119 | * exactly to APU register contents. |
120 | */ |
121 | #define MAESTRO_DMA_SZ (MAESTRO_QUARTER_SZ * 4) |
122 | #define MAESTRO_DMA_ALIGN (128 * 1024) |
123 | |
124 | struct esm_dma { |
125 | bus_dmamap_t map; |
126 | void * addr; |
127 | bus_dma_segment_t segs[1]; |
128 | int nsegs; |
129 | size_t size; |
130 | struct esm_dma *next; |
131 | }; |
132 | |
133 | #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr) |
134 | #define KERNADDR(p) ((void *)((p)->addr)) |
135 | |
136 | struct esm_chinfo { |
137 | uint32_t base; /* DMA base */ |
138 | void * buffer; /* upper layer buffer */ |
139 | uint32_t offset; /* offset into buffer */ |
140 | uint32_t blocksize; /* block size in bytes */ |
141 | uint32_t bufsize; /* buffer size in bytes */ |
142 | unsigned num; /* logical channel number */ |
143 | uint16_t aputype; /* APU channel type */ |
144 | uint16_t apubase; /* first sample number */ |
145 | uint16_t apublk; /* blk size in samples per ch */ |
146 | uint16_t apubuf; /* buf size in samples per ch */ |
147 | uint16_t nextirq; /* pos to trigger next IRQ at */ |
148 | uint16_t wcreg_tpl; /* wavecache tag and format */ |
149 | uint16_t sample_rate; |
150 | }; |
151 | |
152 | struct esm_softc { |
153 | device_t sc_dev; |
154 | kmutex_t sc_lock; |
155 | kmutex_t sc_intr_lock; |
156 | |
157 | bus_space_tag_t st; |
158 | bus_space_handle_t sh; |
159 | bus_size_t sz; |
160 | |
161 | pcitag_t tag; |
162 | pci_chipset_tag_t pc; |
163 | bus_dma_tag_t dmat; |
164 | pcireg_t subid; |
165 | |
166 | void *ih; |
167 | |
168 | struct ac97_codec_if *codec_if; |
169 | struct ac97_host_if host_if; |
170 | enum ac97_host_flags codec_flags; |
171 | |
172 | struct esm_dma sc_dma; |
173 | int rings_alloced; |
174 | |
175 | int pactive, ractive; |
176 | struct esm_chinfo pch; |
177 | struct esm_chinfo rch; |
178 | |
179 | void (*sc_pintr)(void *); |
180 | void *sc_parg; |
181 | |
182 | void (*sc_rintr)(void *); |
183 | void *sc_rarg; |
184 | }; |
185 | |
186 | enum esm_quirk_flags { |
187 | ESM_QUIRKF_GPIO = 0x1, /* needs GPIO operation */ |
188 | ESM_QUIRKF_SWAPPEDCH = 0x2, /* left/right is reversed */ |
189 | }; |
190 | |
191 | struct esm_quirks { |
192 | pci_vendor_id_t eq_vendor; /* subsystem vendor */ |
193 | pci_product_id_t eq_product; /* and product */ |
194 | |
195 | enum esm_quirk_flags eq_quirks; /* needed quirks */ |
196 | }; |
197 | |
198 | int esm_read_codec(void *, uint8_t, uint16_t *); |
199 | int esm_write_codec(void *, uint8_t, uint16_t); |
200 | int esm_attach_codec(void *, struct ac97_codec_if *); |
201 | int esm_reset_codec(void *); |
202 | enum ac97_host_flags esm_flags_codec(void *); |
203 | |
204 | void esm_init(struct esm_softc *); |
205 | void esm_initcodec(struct esm_softc *); |
206 | |
207 | int esm_init_output(void *, void *, int); |
208 | int esm_init_input(void *, void *, int); |
209 | int esm_trigger_output(void *, void *, void *, int, void (*)(void *), |
210 | void *, const audio_params_t *); |
211 | int esm_trigger_input(void *, void *, void *, int, void (*)(void *), |
212 | void *, const audio_params_t *); |
213 | int esm_halt_output(void *); |
214 | int esm_halt_input(void *); |
215 | int esm_getdev(void *, struct audio_device *); |
216 | int esm_round_blocksize(void *, int, int, const audio_params_t *); |
217 | int esm_query_encoding(void *, struct audio_encoding *); |
218 | int esm_set_params(void *, int, int, audio_params_t *, audio_params_t *, |
219 | stream_filter_list_t *, stream_filter_list_t *); |
220 | int esm_set_port(void *, mixer_ctrl_t *); |
221 | int esm_get_port(void *, mixer_ctrl_t *); |
222 | int esm_query_devinfo(void *, mixer_devinfo_t *); |
223 | void *esm_malloc(void *, int, size_t); |
224 | void esm_free(void *, void *, size_t); |
225 | size_t esm_round_buffersize(void *, int, size_t); |
226 | paddr_t esm_mappage(void *, void *, off_t, int); |
227 | int esm_get_props(void *); |
228 | void esm_get_locks(void *, kmutex_t **, kmutex_t **); |
229 | |
230 | enum esm_quirk_flags esm_get_quirks(pcireg_t); |
231 | |