File: | dev/pci/yds.c |
Warning: | line 411, column 2 Value stored to 'ecs' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: yds.c,v 1.56 2022/01/09 05:42:58 jsg Exp $ */ |
2 | /* $NetBSD: yds.c,v 1.5 2001/05/21 23:55:04 minoura Exp $ */ |
3 | |
4 | /* |
5 | * Copyright (c) 2000, 2001 Kazuki Sakamoto and Minoura Makoto. |
6 | * All rights reserved. |
7 | * |
8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions |
10 | * are met: |
11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the |
15 | * documentation and/or other materials provided with the distribution. |
16 | * |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | */ |
28 | |
29 | /* |
30 | * Yamaha YMF724[B-F]/740[B-C]/744/754 |
31 | * |
32 | * Documentation links: |
33 | * - ftp://ftp.alsa-project.org/pub/manuals/yamaha/ |
34 | * - ftp://ftp.alsa-project.org/pub/manuals/yamaha/pci/ |
35 | * |
36 | * TODO: |
37 | * - FM synth volume (difficult: mixed before ac97) |
38 | * - Digital in/out (SPDIF) support |
39 | * - Effect?? |
40 | */ |
41 | |
42 | #include <sys/param.h> |
43 | #include <sys/systm.h> |
44 | #include <sys/kernel.h> |
45 | #include <sys/fcntl.h> |
46 | #include <sys/malloc.h> |
47 | #include <sys/device.h> |
48 | #include <sys/queue.h> |
49 | |
50 | #include <dev/pci/pcidevs.h> |
51 | #include <dev/pci/pcireg.h> |
52 | #include <dev/pci/pcivar.h> |
53 | |
54 | #include <sys/audioio.h> |
55 | #include <dev/audio_if.h> |
56 | #include <dev/midi_if.h> |
57 | #include <dev/ic/ac97.h> |
58 | |
59 | #include <machine/bus.h> |
60 | #include <machine/intr.h> |
61 | |
62 | #include <dev/pci/ydsreg.h> |
63 | #include <dev/pci/ydsvar.h> |
64 | |
65 | /* Debug */ |
66 | #undef YDS_USE_REC_SLOT |
67 | #define YDS_USE_P44 |
68 | |
69 | #ifdef AUDIO_DEBUG |
70 | # define DPRINTF(x) if (ydsdebug) printf x |
71 | # define DPRINTFN(n,x) if (ydsdebug>(n)) printf x |
72 | int ydsdebug = 0; |
73 | #else |
74 | # define DPRINTF(x) |
75 | # define DPRINTFN(n,x) |
76 | #endif |
77 | #ifdef YDS_USE_REC_SLOT |
78 | # define YDS_INPUT_SLOT1 0 /* REC slot = ADC + loopbacks */ |
79 | #else |
80 | # define YDS_INPUT_SLOT1 1 /* ADC slot */ |
81 | #endif |
82 | |
83 | static int ac97_id2; |
84 | |
85 | int yds_match(struct device *, void *, void *); |
86 | void yds_attach(struct device *, struct device *, void *); |
87 | int yds_activate(struct device *, int); |
88 | int yds_intr(void *); |
89 | |
90 | static void nswaph(u_int32_t *p, int wcount); |
91 | |
92 | #define DMAADDR(p)((p)->map->dm_segs[0].ds_addr) ((p)->map->dm_segs[0].ds_addr) |
93 | #define KERNADDR(p)((void *)((p)->addr)) ((void *)((p)->addr)) |
94 | |
95 | int yds_allocmem(struct yds_softc *, size_t, size_t, |
96 | struct yds_dma *); |
97 | int yds_freemem(struct yds_softc *, struct yds_dma *); |
98 | |
99 | #ifndef AUDIO_DEBUG |
100 | #define YWRITE1(sc, r, x)(((sc)->memt)->write_1(((sc)->memh), ((r)), ((x)))) bus_space_write_1((sc)->memt, (sc)->memh, (r), (x))(((sc)->memt)->write_1(((sc)->memh), ((r)), ((x)))) |
101 | #define YWRITE2(sc, r, x)(((sc)->memt)->write_2(((sc)->memh), ((r)), ((x)))) bus_space_write_2((sc)->memt, (sc)->memh, (r), (x))(((sc)->memt)->write_2(((sc)->memh), ((r)), ((x)))) |
102 | #define YWRITE4(sc, r, x)(((sc)->memt)->write_4(((sc)->memh), ((r)), ((x)))) bus_space_write_4((sc)->memt, (sc)->memh, (r), (x))(((sc)->memt)->write_4(((sc)->memh), ((r)), ((x)))) |
103 | #define YREAD1(sc, r)(((sc)->memt)->read_1(((sc)->memh), ((r)))) bus_space_read_1((sc)->memt, (sc)->memh, (r))(((sc)->memt)->read_1(((sc)->memh), ((r)))) |
104 | #define YREAD2(sc, r)(((sc)->memt)->read_2(((sc)->memh), ((r)))) bus_space_read_2((sc)->memt, (sc)->memh, (r))(((sc)->memt)->read_2(((sc)->memh), ((r)))) |
105 | #define YREAD4(sc, r)(((sc)->memt)->read_4(((sc)->memh), ((r)))) bus_space_read_4((sc)->memt, (sc)->memh, (r))(((sc)->memt)->read_4(((sc)->memh), ((r)))) |
106 | #else |
107 | |
108 | u_int16_t YREAD2(struct yds_softc *sc,bus_size_t r)(((struct yds_softc *sc)->memt)->read_2(((struct yds_softc *sc)->memh), ((bus_size_t r)))); |
109 | u_int32_t YREAD4(struct yds_softc *sc,bus_size_t r)(((struct yds_softc *sc)->memt)->read_4(((struct yds_softc *sc)->memh), ((bus_size_t r)))); |
110 | void YWRITE1(struct yds_softc *sc,bus_size_t r,u_int8_t x)(((struct yds_softc *sc)->memt)->write_1(((struct yds_softc *sc)->memh), ((bus_size_t r)), ((u_int8_t x)))); |
111 | void YWRITE2(struct yds_softc *sc,bus_size_t r,u_int16_t x)(((struct yds_softc *sc)->memt)->write_2(((struct yds_softc *sc)->memh), ((bus_size_t r)), ((u_int16_t x)))); |
112 | void YWRITE4(struct yds_softc *sc,bus_size_t r,u_int32_t x)(((struct yds_softc *sc)->memt)->write_4(((struct yds_softc *sc)->memh), ((bus_size_t r)), ((u_int32_t x)))); |
113 | |
114 | u_int16_t YREAD2(struct yds_softc *sc,bus_size_t r)(((struct yds_softc *sc)->memt)->read_2(((struct yds_softc *sc)->memh), ((bus_size_t r)))) |
115 | { |
116 | DPRINTFN(5, (" YREAD2(0x%lX)\n",(unsigned long)r)); |
117 | return bus_space_read_2(sc->memt,sc->memh,r)((sc->memt)->read_2((sc->memh), (r))); |
118 | } |
119 | u_int32_t YREAD4(struct yds_softc *sc,bus_size_t r)(((struct yds_softc *sc)->memt)->read_4(((struct yds_softc *sc)->memh), ((bus_size_t r)))) |
120 | { |
121 | DPRINTFN(5, (" YREAD4(0x%lX)\n",(unsigned long)r)); |
122 | return bus_space_read_4(sc->memt,sc->memh,r)((sc->memt)->read_4((sc->memh), (r))); |
123 | } |
124 | void YWRITE1(struct yds_softc *sc,bus_size_t r,u_int8_t x)(((struct yds_softc *sc)->memt)->write_1(((struct yds_softc *sc)->memh), ((bus_size_t r)), ((u_int8_t x)))) |
125 | { |
126 | DPRINTFN(5, (" YWRITE1(0x%lX,0x%lX)\n",(unsigned long)r,(unsigned long)x)); |
127 | bus_space_write_1(sc->memt,sc->memh,r,x)((sc->memt)->write_1((sc->memh), (r), (x))); |
128 | } |
129 | void YWRITE2(struct yds_softc *sc,bus_size_t r,u_int16_t x)(((struct yds_softc *sc)->memt)->write_2(((struct yds_softc *sc)->memh), ((bus_size_t r)), ((u_int16_t x)))) |
130 | { |
131 | DPRINTFN(5, (" YWRITE2(0x%lX,0x%lX)\n",(unsigned long)r,(unsigned long)x)); |
132 | bus_space_write_2(sc->memt,sc->memh,r,x)((sc->memt)->write_2((sc->memh), (r), (x))); |
133 | } |
134 | void YWRITE4(struct yds_softc *sc,bus_size_t r,u_int32_t x)(((struct yds_softc *sc)->memt)->write_4(((struct yds_softc *sc)->memh), ((bus_size_t r)), ((u_int32_t x)))) |
135 | { |
136 | DPRINTFN(5, (" YWRITE4(0x%lX,0x%lX)\n",(unsigned long)r,(unsigned long)x)); |
137 | bus_space_write_4(sc->memt,sc->memh,r,x)((sc->memt)->write_4((sc->memh), (r), (x))); |
138 | } |
139 | #endif |
140 | |
141 | #define YWRITEREGION4(sc, r, x, c)(((sc)->memt)->write_region_4(((sc)->memh), ((r)), ( (x)), ((c) / 4))) \ |
142 | bus_space_write_region_4((sc)->memt, (sc)->memh, (r), (x), (c) / 4)(((sc)->memt)->write_region_4(((sc)->memh), ((r)), ( (x)), ((c) / 4))) |
143 | |
144 | struct cfattach yds_ca = { |
145 | sizeof(struct yds_softc), yds_match, yds_attach, NULL((void *)0), |
146 | yds_activate |
147 | }; |
148 | |
149 | struct cfdriver yds_cd = { |
150 | NULL((void *)0), "yds", DV_DULL |
151 | }; |
152 | |
153 | int yds_open(void *, int); |
154 | void yds_close(void *); |
155 | int yds_set_params(void *, int, int, |
156 | struct audio_params *, struct audio_params *); |
157 | int yds_round_blocksize(void *, int); |
158 | int yds_trigger_output(void *, void *, void *, int, void (*)(void *), |
159 | void *, struct audio_params *); |
160 | int yds_trigger_input(void *, void *, void *, int, void (*)(void *), |
161 | void *, struct audio_params *); |
162 | int yds_halt_output(void *); |
163 | int yds_halt_input(void *); |
164 | int yds_mixer_set_port(void *, mixer_ctrl_t *); |
165 | int yds_mixer_get_port(void *, mixer_ctrl_t *); |
166 | void *yds_malloc(void *, int, size_t, int, int); |
167 | void yds_free(void *, void *, int); |
168 | size_t yds_round_buffersize(void *, int, size_t); |
169 | int yds_get_props(void *); |
170 | int yds_query_devinfo(void *addr, mixer_devinfo_t *dip); |
171 | |
172 | int yds_attach_codec(void *sc, struct ac97_codec_if *); |
173 | int yds_read_codec(void *sc, u_int8_t a, u_int16_t *d); |
174 | int yds_write_codec(void *sc, u_int8_t a, u_int16_t d); |
175 | void yds_reset_codec(void *sc); |
176 | int yds_get_portnum_by_name(struct yds_softc *, char *, char *, |
177 | char *); |
178 | |
179 | static u_int yds_get_dstype(int); |
180 | static int yds_download_mcode(struct yds_softc *); |
181 | static int yds_allocate_slots(struct yds_softc *, int); |
182 | static void yds_configure_legacy(struct yds_softc *arg); |
183 | static void yds_enable_dsp(struct yds_softc *); |
184 | static int yds_disable_dsp(struct yds_softc *); |
185 | static int yds_ready_codec(struct yds_codec_softc *); |
186 | static int yds_halt(struct yds_softc *); |
187 | static u_int32_t yds_get_lpfq(u_int); |
188 | static u_int32_t yds_get_lpfk(u_int); |
189 | static struct yds_dma *yds_find_dma(struct yds_softc *, void *); |
190 | |
191 | int yds_init(struct yds_softc *, int); |
192 | void yds_attachhook(struct device *); |
193 | |
194 | #ifdef AUDIO_DEBUG |
195 | static void yds_dump_play_slot(struct yds_softc *, int); |
196 | #define YDS_DUMP_PLAY_SLOT(n,sc,bank) \ |
197 | if (ydsdebug > (n)) yds_dump_play_slot(sc, bank) |
198 | #else |
199 | #define YDS_DUMP_PLAY_SLOT(n,sc,bank) |
200 | #endif /* AUDIO_DEBUG */ |
201 | |
202 | static struct audio_hw_if yds_hw_if = { |
203 | yds_open, |
204 | yds_close, |
205 | yds_set_params, |
206 | yds_round_blocksize, |
207 | NULL((void *)0), |
208 | NULL((void *)0), |
209 | NULL((void *)0), |
210 | NULL((void *)0), |
211 | NULL((void *)0), |
212 | yds_halt_output, |
213 | yds_halt_input, |
214 | NULL((void *)0), |
215 | NULL((void *)0), |
216 | yds_mixer_set_port, |
217 | yds_mixer_get_port, |
218 | yds_query_devinfo, |
219 | yds_malloc, |
220 | yds_free, |
221 | yds_round_buffersize, |
222 | yds_get_props, |
223 | yds_trigger_output, |
224 | yds_trigger_input |
225 | }; |
226 | |
227 | const static struct { |
228 | u_int id; |
229 | u_int flags; |
230 | #define YDS_CAP_MCODE_10x0001 0x0001 |
231 | #define YDS_CAP_MCODE_1E0x0002 0x0002 |
232 | #define YDS_CAP_LEGACY_SELECTABLE0x0004 0x0004 |
233 | #define YDS_CAP_LEGACY_FLEXIBLE0x0008 0x0008 |
234 | #define YDS_CAP_HAS_P440x0010 0x0010 |
235 | #define YDS_CAP_LEGACY_SMOD_DISABLE0x1000 0x1000 |
236 | } yds_chip_capability_list[] = { |
237 | { PCI_PRODUCT_YAMAHA_YMF7240x0004, |
238 | YDS_CAP_MCODE_10x0001|YDS_CAP_LEGACY_SELECTABLE0x0004 }, |
239 | /* 740[C] has only 32 slots. But anyway we use only 2 */ |
240 | { PCI_PRODUCT_YAMAHA_YMF7400x000a, |
241 | YDS_CAP_MCODE_10x0001|YDS_CAP_LEGACY_SELECTABLE0x0004 }, /* XXX NOT TESTED */ |
242 | { PCI_PRODUCT_YAMAHA_YMF740C0x000c, |
243 | YDS_CAP_MCODE_1E0x0002|YDS_CAP_LEGACY_SELECTABLE0x0004 }, |
244 | { PCI_PRODUCT_YAMAHA_YMF724F0x000d, |
245 | YDS_CAP_MCODE_1E0x0002|YDS_CAP_LEGACY_SELECTABLE0x0004 }, |
246 | { PCI_PRODUCT_YAMAHA_YMF7440x0010, |
247 | YDS_CAP_MCODE_1E0x0002|YDS_CAP_LEGACY_FLEXIBLE0x0008 }, |
248 | { PCI_PRODUCT_YAMAHA_YMF7540x0012, |
249 | YDS_CAP_MCODE_1E0x0002|YDS_CAP_LEGACY_FLEXIBLE0x0008|YDS_CAP_HAS_P440x0010 }, |
250 | /* How about 734/737/738?? */ |
251 | { 0, 0 } |
252 | }; |
253 | #ifdef AUDIO_DEBUG |
254 | #define YDS_CAP_BITS "\020\005P44\004LEGFLEX\003LEGSEL\002MCODE1E\001MCODE1" |
255 | #endif |
256 | |
257 | #ifdef AUDIO_DEBUG |
258 | static void |
259 | yds_dump_play_slot(struct yds_softc *sc, int bank) |
260 | { |
261 | int i, j; |
262 | u_int32_t *p; |
263 | u_int32_t num; |
264 | struct yds_dma *dma; |
265 | |
266 | for (i = 0; i < N_PLAY_SLOTS2; i++) { |
267 | printf("pbankp[%d] = %p,", i*2, sc->pbankp[i*2]); |
268 | printf("pbankp[%d] = %p\n", i*2+1, sc->pbankp[i*2+1]); |
269 | } |
270 | |
271 | p = (u_int32_t*)sc->ptbl; |
272 | for (i = 0; i < N_PLAY_SLOTS2+1; i++) { |
273 | printf("ptbl + %d:0x%x\n", i, *p); |
274 | p++; |
275 | } |
276 | |
277 | num = *(u_int32_t*)sc->ptbl; |
278 | printf("num = %d\n", num); |
279 | |
280 | for (i = 0; i < num; i++) { |
281 | |
282 | p = (u_int32_t *)sc->pbankp[i]; |
283 | |
284 | dma = yds_find_dma(sc,(void *)p); |
285 | |
286 | for (j = 0; j < sizeof(struct play_slot_ctrl_bank) / |
287 | sizeof(u_int32_t); j++) { |
288 | printf(" 0x%02x: 0x%08x\n", |
289 | (unsigned) (j * sizeof(u_int32_t)), |
290 | (unsigned) *p++); |
291 | } |
292 | /* |
293 | p = (u_int32_t *)sc->pbankp[i*2 + 1]; |
294 | printf(" pbankp[%d] : %p\n", i*2 + 1, p); |
295 | for (j = 0; j < sizeof(struct play_slot_ctrl_bank) / |
296 | sizeof(u_int32_t); j++) { |
297 | printf(" 0x%02x: 0x%08x\n", |
298 | j * sizeof(u_int32_t), *p++); |
299 | delay(1); |
300 | } |
301 | */ |
302 | } |
303 | } |
304 | #endif /* AUDIO_DEBUG */ |
305 | |
306 | static u_int |
307 | yds_get_dstype(int id) |
308 | { |
309 | int i; |
310 | |
311 | for (i = 0; yds_chip_capability_list[i].id; i++) { |
312 | if (PCI_PRODUCT(id)(((id) >> 16) & 0xffff) == yds_chip_capability_list[i].id) |
313 | return yds_chip_capability_list[i].flags; |
314 | } |
315 | |
316 | return -1; |
317 | } |
318 | |
319 | static void |
320 | nswaph(u_int32_t *p, int wcount) |
321 | { |
322 | for (; wcount; wcount -=4) { |
323 | *p = ntohl(*p)(__uint32_t)(__builtin_constant_p(*p) ? (__uint32_t)(((__uint32_t )(*p) & 0xff) << 24 | ((__uint32_t)(*p) & 0xff00 ) << 8 | ((__uint32_t)(*p) & 0xff0000) >> 8 | ((__uint32_t)(*p) & 0xff000000) >> 24) : __swap32md (*p)); |
324 | p++; |
325 | } |
326 | } |
327 | |
328 | static int |
329 | yds_download_mcode(struct yds_softc *sc) |
330 | { |
331 | u_int ctrl; |
332 | const u_int32_t *p; |
333 | size_t size; |
334 | u_char *buf; |
335 | size_t buflen; |
336 | int error; |
337 | struct yds_firmware *yf; |
338 | |
339 | error = loadfirmware("yds", &buf, &buflen); |
340 | if (error) |
341 | return 1; |
342 | yf = (struct yds_firmware *)buf; |
343 | |
344 | if (sc->sc_flags & YDS_CAP_MCODE_10x0001) { |
345 | p = (u_int32_t *)&yf->data[ntohl(yf->dsplen)(__uint32_t)(__builtin_constant_p(yf->dsplen) ? (__uint32_t )(((__uint32_t)(yf->dsplen) & 0xff) << 24 | ((__uint32_t )(yf->dsplen) & 0xff00) << 8 | ((__uint32_t)(yf-> dsplen) & 0xff0000) >> 8 | ((__uint32_t)(yf->dsplen ) & 0xff000000) >> 24) : __swap32md(yf->dsplen))]; |
346 | size = ntohl(yf->ds1len)(__uint32_t)(__builtin_constant_p(yf->ds1len) ? (__uint32_t )(((__uint32_t)(yf->ds1len) & 0xff) << 24 | ((__uint32_t )(yf->ds1len) & 0xff00) << 8 | ((__uint32_t)(yf-> ds1len) & 0xff0000) >> 8 | ((__uint32_t)(yf->ds1len ) & 0xff000000) >> 24) : __swap32md(yf->ds1len)); |
347 | } else if (sc->sc_flags & YDS_CAP_MCODE_1E0x0002) { |
348 | p = (u_int32_t *)&yf->data[ntohl(yf->dsplen)(__uint32_t)(__builtin_constant_p(yf->dsplen) ? (__uint32_t )(((__uint32_t)(yf->dsplen) & 0xff) << 24 | ((__uint32_t )(yf->dsplen) & 0xff00) << 8 | ((__uint32_t)(yf-> dsplen) & 0xff0000) >> 8 | ((__uint32_t)(yf->dsplen ) & 0xff000000) >> 24) : __swap32md(yf->dsplen)) + ntohl(yf->ds1len)(__uint32_t)(__builtin_constant_p(yf->ds1len) ? (__uint32_t )(((__uint32_t)(yf->ds1len) & 0xff) << 24 | ((__uint32_t )(yf->ds1len) & 0xff00) << 8 | ((__uint32_t)(yf-> ds1len) & 0xff0000) >> 8 | ((__uint32_t)(yf->ds1len ) & 0xff000000) >> 24) : __swap32md(yf->ds1len))]; |
349 | size = ntohl(yf->ds1elen)(__uint32_t)(__builtin_constant_p(yf->ds1elen) ? (__uint32_t )(((__uint32_t)(yf->ds1elen) & 0xff) << 24 | ((__uint32_t )(yf->ds1elen) & 0xff00) << 8 | ((__uint32_t)(yf ->ds1elen) & 0xff0000) >> 8 | ((__uint32_t)(yf-> ds1elen) & 0xff000000) >> 24) : __swap32md(yf->ds1elen )); |
350 | } else { |
351 | free(buf, M_DEVBUF2, buflen); |
352 | return 1; /* unknown */ |
353 | } |
354 | |
355 | if (size > buflen) { |
356 | printf("%s: old firmware file, update please\n", |
357 | sc->sc_dev.dv_xname); |
358 | free(buf, M_DEVBUF2, buflen); |
359 | return 1; |
360 | } |
361 | |
362 | if (yds_disable_dsp(sc)) { |
363 | free(buf, M_DEVBUF2, buflen); |
364 | return 1; |
365 | } |
366 | |
367 | /* Software reset */ |
368 | YWRITE4(sc, YDS_MODE, YDS_MODE_RESET)(((sc)->memt)->write_4(((sc)->memh), ((0x0108)), ((0x00010000 )))); |
369 | YWRITE4(sc, YDS_MODE, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x0108)), ((0 )))); |
370 | |
371 | YWRITE4(sc, YDS_MAPOF_REC, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x0150)), ((0 )))); |
372 | YWRITE4(sc, YDS_MAPOF_EFFECT, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x0154)), ((0 )))); |
373 | YWRITE4(sc, YDS_PLAY_CTRLBASE, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x0158)), ((0 )))); |
374 | YWRITE4(sc, YDS_REC_CTRLBASE, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x015c)), ((0 )))); |
375 | YWRITE4(sc, YDS_EFFECT_CTRLBASE, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x0160)), ((0 )))); |
376 | YWRITE4(sc, YDS_WORK_BASE, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x0164)), ((0 )))); |
377 | |
378 | ctrl = YREAD2(sc, YDS_GLOBAL_CONTROL)(((sc)->memt)->read_2(((sc)->memh), ((0x0008)))); |
379 | YWRITE2(sc, YDS_GLOBAL_CONTROL, ctrl & ~0x0007)(((sc)->memt)->write_2(((sc)->memh), ((0x0008)), ((ctrl & ~0x0007)))); |
380 | |
381 | /* Download DSP microcode. */ |
382 | nswaph((u_int32_t *)&yf->data[0], ntohl(yf->dsplen)(__uint32_t)(__builtin_constant_p(yf->dsplen) ? (__uint32_t )(((__uint32_t)(yf->dsplen) & 0xff) << 24 | ((__uint32_t )(yf->dsplen) & 0xff00) << 8 | ((__uint32_t)(yf-> dsplen) & 0xff0000) >> 8 | ((__uint32_t)(yf->dsplen ) & 0xff000000) >> 24) : __swap32md(yf->dsplen))); |
383 | YWRITEREGION4(sc, YDS_DSP_INSTRAM, (u_int32_t *)&yf->data[0],(((sc)->memt)->write_region_4(((sc)->memh), ((0x1000 )), (((u_int32_t *)&yf->data[0])), (((__uint32_t)(__builtin_constant_p (yf->dsplen) ? (__uint32_t)(((__uint32_t)(yf->dsplen) & 0xff) << 24 | ((__uint32_t)(yf->dsplen) & 0xff00 ) << 8 | ((__uint32_t)(yf->dsplen) & 0xff0000) >> 8 | ((__uint32_t)(yf->dsplen) & 0xff000000) >> 24 ) : __swap32md(yf->dsplen))) / 4))) |
384 | ntohl(yf->dsplen))(((sc)->memt)->write_region_4(((sc)->memh), ((0x1000 )), (((u_int32_t *)&yf->data[0])), (((__uint32_t)(__builtin_constant_p (yf->dsplen) ? (__uint32_t)(((__uint32_t)(yf->dsplen) & 0xff) << 24 | ((__uint32_t)(yf->dsplen) & 0xff00 ) << 8 | ((__uint32_t)(yf->dsplen) & 0xff0000) >> 8 | ((__uint32_t)(yf->dsplen) & 0xff000000) >> 24 ) : __swap32md(yf->dsplen))) / 4))); |
385 | |
386 | /* Download CONTROL microcode. */ |
387 | nswaph((u_int32_t *)p, size); |
388 | YWRITEREGION4(sc, YDS_CTRL_INSTRAM, p, size)(((sc)->memt)->write_region_4(((sc)->memh), ((0x4000 )), ((p)), ((size) / 4))); |
389 | |
390 | yds_enable_dsp(sc); |
391 | delay(10*1000)(*delay_func)(10*1000); /* necessary on my 724F (??) */ |
392 | |
393 | free(buf, M_DEVBUF2, buflen); |
394 | return 0; |
395 | } |
396 | |
397 | static int |
398 | yds_allocate_slots(struct yds_softc *sc, int resuming) |
399 | { |
400 | size_t pcs, rcs, ecs, ws, memsize; |
401 | void *mp; |
402 | u_int32_t da; /* DMA address */ |
403 | char *va; /* KVA */ |
404 | off_t cb; |
405 | int i; |
406 | struct yds_dma *p; |
407 | |
408 | /* Alloc DSP Control Data */ |
409 | pcs = YREAD4(sc, YDS_PLAY_CTRLSIZE)(((sc)->memt)->read_4(((sc)->memh), ((0x0140)))) * sizeof(u_int32_t); |
410 | rcs = YREAD4(sc, YDS_REC_CTRLSIZE)(((sc)->memt)->read_4(((sc)->memh), ((0x0144)))) * sizeof(u_int32_t); |
411 | ecs = YREAD4(sc, YDS_EFFECT_CTRLSIZE)(((sc)->memt)->read_4(((sc)->memh), ((0x0148)))) * sizeof(u_int32_t); |
Value stored to 'ecs' is never read | |
412 | ws = WORK_SIZE0x0400; |
413 | YWRITE4(sc, YDS_WORK_SIZE, ws / sizeof(u_int32_t))(((sc)->memt)->write_4(((sc)->memh), ((0x014c)), ((ws / sizeof(u_int32_t))))); |
414 | |
415 | DPRINTF(("play control size : %d\n", (unsigned int)pcs)); |
416 | DPRINTF(("rec control size : %d\n", (unsigned int)rcs)); |
417 | DPRINTF(("eff control size : %d\n", (unsigned int)ecs)); |
418 | DPRINTF(("work size : %d\n", (unsigned int)ws)); |
419 | #ifdef DIAGNOSTIC1 |
420 | if (pcs != sizeof(struct play_slot_ctrl_bank)) { |
421 | printf("%s: invalid play slot ctrldata %d != %d\n", |
422 | sc->sc_dev.dv_xname, (unsigned int)pcs, |
423 | (unsigned int)sizeof(struct play_slot_ctrl_bank)); |
424 | } |
425 | if (rcs != sizeof(struct rec_slot_ctrl_bank)) { |
426 | printf("%s: invalid rec slot ctrldata %d != %d\n", |
427 | sc->sc_dev.dv_xname, (unsigned int)rcs, |
428 | (unsigned int)sizeof(struct rec_slot_ctrl_bank)); |
429 | } |
430 | #endif |
431 | |
432 | memsize = N_PLAY_SLOTS2*N_PLAY_SLOT_CTRL_BANK2*pcs + |
433 | N_REC_SLOT_CTRL2*N_REC_SLOT_CTRL_BANK2*rcs + ws; |
434 | memsize += (N_PLAY_SLOTS2+1)*sizeof(u_int32_t); |
435 | |
436 | p = &sc->sc_ctrldata; |
437 | if (!resuming) { |
438 | i = yds_allocmem(sc, memsize, 16, p); |
439 | if (i) { |
440 | printf("%s: couldn't alloc/map DSP DMA buffer, reason %d\n", |
441 | sc->sc_dev.dv_xname, i); |
442 | return 1; |
443 | } |
444 | } |
445 | mp = KERNADDR(p)((void *)((p)->addr)); |
446 | da = DMAADDR(p)((p)->map->dm_segs[0].ds_addr); |
447 | |
448 | DPRINTF(("mp:%p, DMA addr:%p\n", |
449 | mp, (void *) sc->sc_ctrldata.map->dm_segs[0].ds_addr)); |
450 | |
451 | bzero(mp, memsize)__builtin_bzero((mp), (memsize)); |
452 | |
453 | /* Work space */ |
454 | cb = 0; |
455 | va = (u_int8_t*)mp; |
456 | YWRITE4(sc, YDS_WORK_BASE, da + cb)(((sc)->memt)->write_4(((sc)->memh), ((0x0164)), ((da + cb)))); |
457 | cb += ws; |
458 | |
459 | /* Play control data table */ |
460 | sc->ptbl = (u_int32_t *)(va + cb); |
461 | sc->ptbloff = cb; |
462 | YWRITE4(sc, YDS_PLAY_CTRLBASE, da + cb)(((sc)->memt)->write_4(((sc)->memh), ((0x0158)), ((da + cb)))); |
463 | cb += (N_PLAY_SLOT_CTRL2 + 1) * sizeof(u_int32_t); |
464 | |
465 | /* Record slot control data */ |
466 | sc->rbank = (struct rec_slot_ctrl_bank *)(va + cb); |
467 | YWRITE4(sc, YDS_REC_CTRLBASE, da + cb)(((sc)->memt)->write_4(((sc)->memh), ((0x015c)), ((da + cb)))); |
468 | sc->rbankoff = cb; |
469 | cb += N_REC_SLOT_CTRL2 * N_REC_SLOT_CTRL_BANK2 * rcs; |
470 | |
471 | #if 0 |
472 | /* Effect slot control data -- unused */ |
473 | YWRITE4(sc, YDS_EFFECT_CTRLBASE, da + cb)(((sc)->memt)->write_4(((sc)->memh), ((0x0160)), ((da + cb)))); |
474 | cb += N_EFFECT_SLOT_CTRL * N_EFFECT_SLOT_CTRL_BANK * ecs; |
475 | #endif |
476 | |
477 | /* Play slot control data */ |
478 | sc->pbankoff = da + cb; |
479 | for (i=0; i<N_PLAY_SLOT_CTRL2; i++) { |
480 | sc->pbankp[i*2] = (struct play_slot_ctrl_bank *)(va + cb); |
481 | *(sc->ptbl + i+1) = da + cb; |
482 | cb += pcs; |
483 | |
484 | sc->pbankp[i*2+1] = (struct play_slot_ctrl_bank *)(va + cb); |
485 | cb += pcs; |
486 | } |
487 | /* Sync play control data table */ |
488 | bus_dmamap_sync(sc->sc_dmatag, p->map,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (p ->map), (sc->ptbloff), ((2 +1) * sizeof(u_int32_t)), (0x04 )) |
489 | sc->ptbloff, (N_PLAY_SLOT_CTRL+1) * sizeof(u_int32_t),(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (p ->map), (sc->ptbloff), ((2 +1) * sizeof(u_int32_t)), (0x04 )) |
490 | BUS_DMASYNC_PREWRITE)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (p ->map), (sc->ptbloff), ((2 +1) * sizeof(u_int32_t)), (0x04 )); |
491 | |
492 | return 0; |
493 | } |
494 | |
495 | static void |
496 | yds_enable_dsp(struct yds_softc *sc) |
497 | { |
498 | YWRITE4(sc, YDS_CONFIG, YDS_DSP_SETUP)(((sc)->memt)->write_4(((sc)->memh), ((0x0114)), ((0x00000001 )))); |
499 | } |
500 | |
501 | static int |
502 | yds_disable_dsp(struct yds_softc *sc) |
503 | { |
504 | int to; |
505 | u_int32_t data; |
506 | |
507 | data = YREAD4(sc, YDS_CONFIG)(((sc)->memt)->read_4(((sc)->memh), ((0x0114)))); |
508 | if (data) |
509 | YWRITE4(sc, YDS_CONFIG, YDS_DSP_DISABLE)(((sc)->memt)->write_4(((sc)->memh), ((0x0114)), ((0 )))); |
510 | |
511 | for (to = 0; to < YDS_WORK_TIMEOUT250000; to++) { |
512 | if ((YREAD4(sc, YDS_STATUS)(((sc)->memt)->read_4(((sc)->memh), ((0x0100)))) & YDS_STAT_WORK0x00000002) == 0) |
513 | return 0; |
514 | delay(1)(*delay_func)(1); |
515 | } |
516 | |
517 | return 1; |
518 | } |
519 | |
520 | int |
521 | yds_match(struct device *parent, void *match, void *aux) |
522 | { |
523 | struct pci_attach_args *pa = (struct pci_attach_args *) aux; |
524 | |
525 | switch (PCI_VENDOR(pa->pa_id)(((pa->pa_id) >> 0) & 0xffff)) { |
526 | case PCI_VENDOR_YAMAHA0x1073: |
527 | switch (PCI_PRODUCT(pa->pa_id)(((pa->pa_id) >> 16) & 0xffff)) { |
528 | case PCI_PRODUCT_YAMAHA_YMF7240x0004: |
529 | case PCI_PRODUCT_YAMAHA_YMF7400x000a: |
530 | case PCI_PRODUCT_YAMAHA_YMF740C0x000c: |
531 | case PCI_PRODUCT_YAMAHA_YMF724F0x000d: |
532 | case PCI_PRODUCT_YAMAHA_YMF7440x0010: |
533 | case PCI_PRODUCT_YAMAHA_YMF7540x0012: |
534 | /* 734, 737, 738?? */ |
535 | return (1); |
536 | } |
537 | break; |
538 | } |
539 | |
540 | return (0); |
541 | } |
542 | |
543 | /* |
544 | * This routine is called after all the ISA devices are configured, |
545 | * to avoid conflict. |
546 | */ |
547 | static void |
548 | yds_configure_legacy(struct yds_softc *sc) |
549 | #define FLEXIBLE (sc->sc_flags & YDS_CAP_LEGACY_FLEXIBLE0x0008) |
550 | #define SELECTABLE (sc->sc_flags & YDS_CAP_LEGACY_SELECTABLE0x0004) |
551 | { |
552 | pcireg_t reg; |
553 | struct device *dev; |
554 | int i; |
555 | bus_addr_t opl_addrs[] = {0x388, 0x398, 0x3A0, 0x3A8}; |
556 | bus_addr_t mpu_addrs[] = {0x330, 0x300, 0x332, 0x334}; |
557 | |
558 | if (!FLEXIBLE && !SELECTABLE) |
559 | return; |
560 | |
561 | reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, YDS_PCI_LEGACY0x40); |
562 | reg &= ~0x8133c03f; /* these bits are out of interest */ |
563 | reg |= (YDS_PCI_EX_LEGACY_IMOD(0x8000 << 16) | YDS_PCI_LEGACY_FMEN0x0002 | |
564 | YDS_PCI_LEGACY_MEN0x0008 /*| YDS_PCI_LEGACY_MIEN*/); |
565 | if (sc->sc_flags & YDS_CAP_LEGACY_SMOD_DISABLE0x1000) |
566 | reg |= YDS_PCI_EX_LEGACY_SMOD_DISABLE(0x0800 << 16); |
567 | if (FLEXIBLE) { |
568 | pci_conf_write(sc->sc_pc, sc->sc_pcitag, YDS_PCI_LEGACY0x40, reg); |
569 | delay(100*1000)(*delay_func)(100*1000); |
570 | } |
571 | |
572 | /* Look for OPL */ |
573 | dev = 0; |
574 | for (i = 0; i < sizeof(opl_addrs) / sizeof (bus_addr_t); i++) { |
575 | if (SELECTABLE) { |
576 | pci_conf_write(sc->sc_pc, sc->sc_pcitag, |
577 | YDS_PCI_LEGACY0x40, reg | (i << (0+16))); |
578 | delay(100*1000)(*delay_func)(100*1000); /* wait 100ms */ |
579 | } else |
580 | pci_conf_write(sc->sc_pc, sc->sc_pcitag, |
581 | YDS_PCI_FM_BA0x60, opl_addrs[i]); |
582 | if (bus_space_map(sc->sc_opl_iotsc_legacy_iot, |
583 | opl_addrs[i], 4, 0, &sc->sc_opl_ioh) == 0) { |
584 | struct audio_attach_args aa; |
585 | |
586 | aa.type = AUDIODEV_TYPE_OPL2; |
587 | aa.hwif = aa.hdl = NULL((void *)0); |
588 | dev = config_found(&sc->sc_dev, &aa, audioprint)config_found_sm((&sc->sc_dev), (&aa), (audioprint) , ((void *)0)); |
589 | if (dev == 0) |
590 | bus_space_unmap(sc->sc_opl_iotsc_legacy_iot, |
591 | sc->sc_opl_ioh, 4); |
592 | else { |
593 | if (SELECTABLE) |
594 | reg |= (i << (0+16)); |
595 | break; |
596 | } |
597 | } |
598 | } |
599 | if (dev == 0) { |
600 | reg &= ~YDS_PCI_LEGACY_FMEN0x0002; |
601 | pci_conf_write(sc->sc_pc, sc->sc_pcitag, |
602 | YDS_PCI_LEGACY0x40, reg); |
603 | } else { |
604 | /* Max. volume */ |
605 | YWRITE4(sc, YDS_LEGACY_OUT_VOLUME, 0x3fff3fff)(((sc)->memt)->write_4(((sc)->memh), ((0x0080)), ((0x3fff3fff )))); |
606 | YWRITE4(sc, YDS_LEGACY_REC_VOLUME, 0x3fff3fff)(((sc)->memt)->write_4(((sc)->memh), ((0x0094)), ((0x3fff3fff )))); |
607 | } |
608 | |
609 | /* Look for MPU */ |
610 | dev = 0; |
611 | for (i = 0; i < sizeof(mpu_addrs) / sizeof (bus_addr_t); i++) { |
612 | if (SELECTABLE) |
613 | pci_conf_write(sc->sc_pc, sc->sc_pcitag, |
614 | YDS_PCI_LEGACY0x40, reg | (i << (4+16))); |
615 | else |
616 | pci_conf_write(sc->sc_pc, sc->sc_pcitag, |
617 | YDS_PCI_MPU_BA0x64, mpu_addrs[i]); |
618 | if (bus_space_map(sc->sc_mpu_iotsc_legacy_iot, |
619 | mpu_addrs[i], 2, 0, &sc->sc_mpu_ioh) == 0) { |
620 | struct audio_attach_args aa; |
621 | |
622 | aa.type = AUDIODEV_TYPE_MPU3; |
623 | aa.hwif = aa.hdl = NULL((void *)0); |
624 | dev = config_found(&sc->sc_dev, &aa, audioprint)config_found_sm((&sc->sc_dev), (&aa), (audioprint) , ((void *)0)); |
625 | if (dev == 0) |
626 | bus_space_unmap(sc->sc_mpu_iotsc_legacy_iot, |
627 | sc->sc_mpu_ioh, 2); |
628 | else { |
629 | if (SELECTABLE) |
630 | reg |= (i << (4+16)); |
631 | break; |
632 | } |
633 | } |
634 | } |
635 | if (dev == 0) { |
636 | reg &= ~(YDS_PCI_LEGACY_MEN0x0008 | YDS_PCI_LEGACY_MIEN0x0010); |
637 | pci_conf_write(sc->sc_pc, sc->sc_pcitag, |
638 | YDS_PCI_LEGACY0x40, reg); |
639 | } |
640 | sc->sc_mpu = dev; |
641 | } |
642 | #undef FLEXIBLE |
643 | #undef SELECTABLE |
644 | |
645 | void |
646 | yds_attach(struct device *parent, struct device *self, void *aux) |
647 | { |
648 | struct yds_softc *sc = (struct yds_softc *)self; |
649 | struct pci_attach_args *pa = (struct pci_attach_args *)aux; |
650 | pci_chipset_tag_t pc = pa->pa_pc; |
651 | char const *intrstr; |
652 | pci_intr_handle_t ih; |
653 | bus_size_t size; |
654 | pcireg_t reg; |
655 | int i; |
656 | |
657 | /* Map register to memory */ |
658 | if (pci_mapreg_map(pa, YDS_PCI_MBA0x10, PCI_MAPREG_TYPE_MEM0x00000000, 0, |
659 | &sc->memt, &sc->memh, NULL((void *)0), &size, 0)) { |
660 | printf(": can't map mem space\n"); |
661 | return; |
662 | } |
663 | |
664 | /* Map and establish the interrupt. */ |
665 | if (pci_intr_map(pa, &ih)) { |
666 | printf(": couldn't map interrupt\n"); |
667 | bus_space_unmap(sc->memt, sc->memh, size); |
668 | return; |
669 | } |
670 | intrstr = pci_intr_string(pc, ih); |
671 | sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO0xb | IPL_MPSAFE0x100, |
672 | yds_intr, sc, self->dv_xname); |
673 | if (sc->sc_ih == NULL((void *)0)) { |
674 | printf(": couldn't establish interrupt"); |
675 | if (intrstr != NULL((void *)0)) |
676 | printf(" at %s", intrstr); |
677 | printf("\n"); |
678 | bus_space_unmap(sc->memt, sc->memh, size); |
679 | return; |
680 | } |
681 | printf(": %s\n", intrstr); |
682 | |
683 | sc->sc_dmatag = pa->pa_dmat; |
684 | sc->sc_pc = pc; |
685 | sc->sc_pcitag = pa->pa_tag; |
686 | sc->sc_id = pa->pa_id; |
687 | sc->sc_revision = PCI_REVISION(pa->pa_class)(((pa->pa_class) >> 0) & 0xff); |
688 | sc->sc_flags = yds_get_dstype(sc->sc_id); |
689 | if (sc->sc_dev.dv_cfdata->cf_flags & YDS_CAP_LEGACY_SMOD_DISABLE0x1000) |
690 | sc->sc_flags |= YDS_CAP_LEGACY_SMOD_DISABLE0x1000; |
691 | #ifdef AUDIO_DEBUG |
692 | if (ydsdebug) |
693 | printf("%s: chip has %b\n", sc->sc_dev.dv_xname, |
694 | sc->sc_flags, YDS_CAP_BITS); |
695 | #endif |
696 | |
697 | /* Disable legacy mode */ |
698 | reg = pci_conf_read(pc, pa->pa_tag, YDS_PCI_LEGACY0x40); |
699 | pci_conf_write(pc, pa->pa_tag, YDS_PCI_LEGACY0x40, |
700 | reg & YDS_PCI_LEGACY_LAD0x8000); |
701 | |
702 | /* Mute all volumes */ |
703 | for (i = 0x80; i < 0xc0; i += 2) |
704 | YWRITE2(sc, i, 0)(((sc)->memt)->write_2(((sc)->memh), ((i)), ((0)))); |
705 | |
706 | sc->sc_legacy_iot = pa->pa_iot; |
707 | config_mountroot(self, yds_attachhook); |
708 | } |
709 | |
710 | void |
711 | yds_attachhook(struct device *self) |
712 | { |
713 | struct yds_softc *sc = (struct yds_softc *)self; |
714 | struct yds_codec_softc *codec; |
715 | mixer_ctrl_t ctl; |
716 | int r, i; |
717 | |
718 | /* Initialize the device */ |
719 | if (yds_init(sc, 0) == -1) |
720 | return; |
721 | |
722 | /* |
723 | * Attach ac97 codec |
724 | */ |
725 | for (i = 0; i < 2; i++) { |
726 | static struct { |
727 | int data; |
728 | int addr; |
729 | } statregs[] = { |
730 | {AC97_STAT_DATA10x0064, AC97_STAT_ADDR10x0066}, |
731 | {AC97_STAT_DATA20x0068, AC97_STAT_ADDR20x006a}, |
732 | }; |
733 | |
734 | if (i == 1 && ac97_id2 == -1) |
735 | break; /* secondary ac97 not available */ |
736 | |
737 | codec = &sc->sc_codec[i]; |
738 | memcpy(&codec->sc_dev, &sc->sc_dev, sizeof(codec->sc_dev))__builtin_memcpy((&codec->sc_dev), (&sc->sc_dev ), (sizeof(codec->sc_dev))); |
739 | codec->sc = sc; |
740 | codec->id = i == 1 ? ac97_id2 : 0; |
741 | codec->status_data = statregs[i].data; |
742 | codec->status_addr = statregs[i].addr; |
743 | codec->host_if.arg = codec; |
744 | codec->host_if.attach = yds_attach_codec; |
745 | codec->host_if.read = yds_read_codec; |
746 | codec->host_if.write = yds_write_codec; |
747 | codec->host_if.reset = yds_reset_codec; |
748 | |
749 | if ((r = ac97_attach(&codec->host_if)) != 0) { |
750 | printf("%s: can't attach codec (error 0x%X)\n", |
751 | sc->sc_dev.dv_xname, r); |
752 | return; |
753 | } |
754 | } |
755 | |
756 | /* Just enable the DAC and master volumes by default */ |
757 | ctl.type = AUDIO_MIXER_ENUM1; |
758 | ctl.un.ord = 0; /* off */ |
759 | ctl.dev = yds_get_portnum_by_name(sc, AudioCoutputs"outputs", |
760 | AudioNmaster"master", AudioNmute"mute"); |
761 | yds_mixer_set_port(sc, &ctl); |
762 | ctl.dev = yds_get_portnum_by_name(sc, AudioCinputs"inputs", |
763 | AudioNdac"dac", AudioNmute"mute"); |
764 | yds_mixer_set_port(sc, &ctl); |
765 | ctl.dev = yds_get_portnum_by_name(sc, AudioCinputs"inputs", |
766 | AudioNcd"cd", AudioNmute"mute"); |
767 | yds_mixer_set_port(sc, &ctl); |
768 | ctl.dev = yds_get_portnum_by_name(sc, AudioCrecord"record", |
769 | AudioNvolume"volume", AudioNmute"mute"); |
770 | yds_mixer_set_port(sc, &ctl); |
771 | |
772 | ctl.dev = yds_get_portnum_by_name(sc, AudioCrecord"record", |
773 | AudioNsource"source", NULL((void *)0)); |
774 | ctl.type = AUDIO_MIXER_ENUM1; |
775 | ctl.un.ord = 0; |
776 | yds_mixer_set_port(sc, &ctl); |
777 | |
778 | /* Set a reasonable default volume */ |
779 | ctl.type = AUDIO_MIXER_VALUE3; |
780 | ctl.un.value.num_channels = 2; |
781 | ctl.un.value.level[AUDIO_MIXER_LEVEL_LEFT0] = |
782 | ctl.un.value.level[AUDIO_MIXER_LEVEL_RIGHT1] = 127; |
783 | |
784 | ctl.dev = sc->sc_codec[0].codec_if->vtbl->get_portnum_by_name( |
785 | sc->sc_codec[0].codec_if, AudioCoutputs"outputs", AudioNmaster"master", NULL((void *)0)); |
786 | yds_mixer_set_port(sc, &ctl); |
787 | |
788 | audio_attach_mi(&yds_hw_if, sc, &sc->sc_dev); |
789 | |
790 | /* Watch for power changes */ |
791 | sc->suspend = DVACT_RESUME4; |
792 | yds_configure_legacy(sc); |
793 | } |
794 | |
795 | int |
796 | yds_attach_codec(void *sc_, struct ac97_codec_if *codec_if) |
797 | { |
798 | struct yds_codec_softc *sc = sc_; |
799 | |
800 | sc->codec_if = codec_if; |
801 | return 0; |
802 | } |
803 | |
804 | static int |
805 | yds_ready_codec(struct yds_codec_softc *sc) |
806 | { |
807 | int to; |
808 | |
809 | for (to = 0; to < AC97_TIMEOUT1000; to++) { |
810 | if ((YREAD2(sc->sc, sc->status_addr)(((sc->sc)->memt)->read_2(((sc->sc)->memh), (( sc->status_addr)))) & AC97_BUSY0x8000) == 0) |
811 | return 0; |
812 | delay(1)(*delay_func)(1); |
813 | } |
814 | |
815 | return 1; |
816 | } |
817 | |
818 | int |
819 | yds_read_codec(void *sc_, u_int8_t reg, u_int16_t *data) |
820 | { |
821 | struct yds_codec_softc *sc = sc_; |
822 | |
823 | YWRITE2(sc->sc, AC97_CMD_ADDR, AC97_CMD_READ | AC97_ID(sc->id) | reg)(((sc->sc)->memt)->write_2(((sc->sc)->memh), ( (0x0062)), ((0x8000 | ((sc->id) << 8) | reg)))); |
824 | |
825 | if (yds_ready_codec(sc)) { |
826 | printf("%s: yds_read_codec timeout\n", |
827 | sc->sc->sc_dev.dv_xname); |
828 | return EIO5; |
829 | } |
830 | |
831 | if (PCI_PRODUCT(sc->sc->sc_id)(((sc->sc->sc_id) >> 16) & 0xffff) == PCI_PRODUCT_YAMAHA_YMF7440x0010 && |
832 | sc->sc->sc_revision < 2) { |
833 | int i; |
834 | |
835 | for (i = 0; i < 600; i++) |
836 | YREAD2(sc->sc, sc->status_data)(((sc->sc)->memt)->read_2(((sc->sc)->memh), (( sc->status_data)))); |
837 | } |
838 | *data = YREAD2(sc->sc, sc->status_data)(((sc->sc)->memt)->read_2(((sc->sc)->memh), (( sc->status_data)))); |
839 | |
840 | return 0; |
841 | } |
842 | |
843 | int |
844 | yds_write_codec(void *sc_, u_int8_t reg, u_int16_t data) |
845 | { |
846 | struct yds_codec_softc *sc = sc_; |
847 | |
848 | YWRITE2(sc->sc, AC97_CMD_ADDR, AC97_CMD_WRITE | AC97_ID(sc->id) | reg)(((sc->sc)->memt)->write_2(((sc->sc)->memh), ( (0x0062)), ((0x0000 | ((sc->id) << 8) | reg)))); |
849 | YWRITE2(sc->sc, AC97_CMD_DATA, data)(((sc->sc)->memt)->write_2(((sc->sc)->memh), ( (0x0060)), ((data)))); |
850 | |
851 | if (yds_ready_codec(sc)) { |
852 | printf("%s: yds_write_codec timeout\n", |
853 | sc->sc->sc_dev.dv_xname); |
854 | return EIO5; |
855 | } |
856 | |
857 | return 0; |
858 | } |
859 | |
860 | /* |
861 | * XXX: Must handle the secondary differently!! |
862 | */ |
863 | void |
864 | yds_reset_codec(void *sc_) |
865 | { |
866 | struct yds_codec_softc *codec = sc_; |
867 | struct yds_softc *sc = codec->sc; |
868 | pcireg_t reg; |
869 | |
870 | /* reset AC97 codec */ |
871 | reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, YDS_PCI_DSCTRL0x48); |
872 | if (reg & 0x03) { |
873 | pci_conf_write(sc->sc_pc, sc->sc_pcitag, |
874 | YDS_PCI_DSCTRL0x48, reg & ~0x03); |
875 | pci_conf_write(sc->sc_pc, sc->sc_pcitag, |
876 | YDS_PCI_DSCTRL0x48, reg | 0x03); |
877 | pci_conf_write(sc->sc_pc, sc->sc_pcitag, |
878 | YDS_PCI_DSCTRL0x48, reg & ~0x03); |
879 | delay(50000)(*delay_func)(50000); |
880 | } |
881 | |
882 | yds_ready_codec(sc_); |
883 | } |
884 | |
885 | int |
886 | yds_intr(void *p) |
887 | { |
888 | struct yds_softc *sc = p; |
889 | u_int status; |
890 | |
891 | mtx_enter(&audio_lock); |
892 | status = YREAD4(sc, YDS_STATUS)(((sc)->memt)->read_4(((sc)->memh), ((0x0100)))); |
893 | DPRINTFN(1, ("yds_intr: status=%08x\n", status)); |
894 | if ((status & (YDS_STAT_INT0x80000000|YDS_STAT_TINT0x00008000)) == 0) { |
895 | #if 0 |
896 | if (sc->sc_mpu) |
897 | return mpu_intr(sc->sc_mpu); |
898 | #endif |
899 | mtx_leave(&audio_lock); |
900 | return 0; |
901 | } |
902 | |
903 | if (status & YDS_STAT_TINT0x00008000) { |
904 | YWRITE4(sc, YDS_STATUS, YDS_STAT_TINT)(((sc)->memt)->write_4(((sc)->memh), ((0x0100)), ((0x00008000 )))); |
905 | printf ("yds_intr: timeout!\n"); |
906 | } |
907 | |
908 | if (status & YDS_STAT_INT0x80000000) { |
909 | int nbank = (YREAD4(sc, YDS_CONTROL_SELECT)(((sc)->memt)->read_4(((sc)->memh), ((0x0104)))) == 0); |
910 | |
911 | /* Clear interrupt flag */ |
912 | YWRITE4(sc, YDS_STATUS, YDS_STAT_INT)(((sc)->memt)->write_4(((sc)->memh), ((0x0100)), ((0x80000000 )))); |
913 | |
914 | /* Buffer for the next frame is always ready. */ |
915 | YWRITE4(sc, YDS_MODE, YREAD4(sc, YDS_MODE) | YDS_MODE_ACTV2)(((sc)->memt)->write_4(((sc)->memh), ((0x0108)), ((( ((sc)->memt)->read_4(((sc)->memh), ((0x0108)))) | 0x00000002 )))); |
916 | |
917 | if (sc->sc_play.intr) { |
918 | u_int dma, cpu, blk, len; |
919 | |
920 | /* Sync play slot control data */ |
921 | bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->pbankoff), (sizeof(struct play_slot_ctrl_bank )* (*sc->ptbl)* 2), (0x08| 0x02)) |
922 | sc->pbankoff,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->pbankoff), (sizeof(struct play_slot_ctrl_bank )* (*sc->ptbl)* 2), (0x08| 0x02)) |
923 | sizeof(struct play_slot_ctrl_bank)*(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->pbankoff), (sizeof(struct play_slot_ctrl_bank )* (*sc->ptbl)* 2), (0x08| 0x02)) |
924 | (*sc->ptbl)*(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->pbankoff), (sizeof(struct play_slot_ctrl_bank )* (*sc->ptbl)* 2), (0x08| 0x02)) |
925 | N_PLAY_SLOT_CTRL_BANK,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->pbankoff), (sizeof(struct play_slot_ctrl_bank )* (*sc->ptbl)* 2), (0x08| 0x02)) |
926 | BUS_DMASYNC_POSTWRITE|(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->pbankoff), (sizeof(struct play_slot_ctrl_bank )* (*sc->ptbl)* 2), (0x08| 0x02)) |
927 | BUS_DMASYNC_POSTREAD)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->pbankoff), (sizeof(struct play_slot_ctrl_bank )* (*sc->ptbl)* 2), (0x08| 0x02)); |
928 | dma = sc->pbankp[nbank]->pgstart; |
929 | cpu = sc->sc_play.offset; |
930 | blk = sc->sc_play.blksize; |
931 | len = sc->sc_play.length; |
932 | |
933 | if (((dma > cpu) && (dma - cpu > blk * 2)) || |
934 | ((cpu > dma) && (dma + len - cpu > blk * 2))) { |
935 | /* We can fill the next block */ |
936 | /* Sync ring buffer for previous write */ |
937 | bus_dmamap_sync(sc->sc_dmatag,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_play.dma->map), (cpu), (blk), (0x08)) |
938 | sc->sc_play.dma->map,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_play.dma->map), (cpu), (blk), (0x08)) |
939 | cpu, blk,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_play.dma->map), (cpu), (blk), (0x08)) |
940 | BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_play.dma->map), (cpu), (blk), (0x08)); |
941 | sc->sc_play.intr(sc->sc_play.intr_arg); |
942 | sc->sc_play.offset += blk; |
943 | if (sc->sc_play.offset >= len) { |
944 | sc->sc_play.offset -= len; |
945 | #ifdef DIAGNOSTIC1 |
946 | if (sc->sc_play.offset != 0) |
947 | printf ("Audio ringbuffer botch\n"); |
948 | #endif |
949 | } |
950 | /* Sync ring buffer for next write */ |
951 | bus_dmamap_sync(sc->sc_dmatag,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_play.dma->map), (cpu), (blk), (0x04)) |
952 | sc->sc_play.dma->map,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_play.dma->map), (cpu), (blk), (0x04)) |
953 | cpu, blk,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_play.dma->map), (cpu), (blk), (0x04)) |
954 | BUS_DMASYNC_PREWRITE)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_play.dma->map), (cpu), (blk), (0x04)); |
955 | } |
956 | } |
957 | if (sc->sc_rec.intr) { |
958 | u_int dma, cpu, blk, len; |
959 | |
960 | /* Sync rec slot control data */ |
961 | bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2* 2), (0x08| 0x02)) |
962 | sc->rbankoff,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2* 2), (0x08| 0x02)) |
963 | sizeof(struct rec_slot_ctrl_bank)*(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2* 2), (0x08| 0x02)) |
964 | N_REC_SLOT_CTRL*(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2* 2), (0x08| 0x02)) |
965 | N_REC_SLOT_CTRL_BANK,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2* 2), (0x08| 0x02)) |
966 | BUS_DMASYNC_POSTWRITE|(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2* 2), (0x08| 0x02)) |
967 | BUS_DMASYNC_POSTREAD)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2* 2), (0x08| 0x02)); |
968 | dma = sc->rbank[YDS_INPUT_SLOT1*2 + nbank].pgstartadr; |
969 | cpu = sc->sc_rec.offset; |
970 | blk = sc->sc_rec.blksize; |
971 | len = sc->sc_rec.length; |
972 | |
973 | if (((dma > cpu) && (dma - cpu > blk * 2)) || |
974 | ((cpu > dma) && (dma + len - cpu > blk * 2))) { |
975 | /* We can drain the current block */ |
976 | /* Sync ring buffer first */ |
977 | bus_dmamap_sync(sc->sc_dmatag,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_rec.dma->map), (cpu), (blk), (0x02)) |
978 | sc->sc_rec.dma->map,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_rec.dma->map), (cpu), (blk), (0x02)) |
979 | cpu, blk,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_rec.dma->map), (cpu), (blk), (0x02)) |
980 | BUS_DMASYNC_POSTREAD)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_rec.dma->map), (cpu), (blk), (0x02)); |
981 | sc->sc_rec.intr(sc->sc_rec.intr_arg); |
982 | sc->sc_rec.offset += blk; |
983 | if (sc->sc_rec.offset >= len) { |
984 | sc->sc_rec.offset -= len; |
985 | #ifdef DIAGNOSTIC1 |
986 | if (sc->sc_rec.offset != 0) |
987 | printf ("Audio ringbuffer botch\n"); |
988 | #endif |
989 | } |
990 | /* Sync ring buffer for next read */ |
991 | bus_dmamap_sync(sc->sc_dmatag,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_rec.dma->map), (cpu), (blk), (0x01)) |
992 | sc->sc_rec.dma->map,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_rec.dma->map), (cpu), (blk), (0x01)) |
993 | cpu, blk,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_rec.dma->map), (cpu), (blk), (0x01)) |
994 | BUS_DMASYNC_PREREAD)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_rec.dma->map), (cpu), (blk), (0x01)); |
995 | } |
996 | } |
997 | } |
998 | mtx_leave(&audio_lock); |
999 | return 1; |
1000 | } |
1001 | |
1002 | int |
1003 | yds_allocmem(struct yds_softc *sc, size_t size, size_t align, struct yds_dma *p) |
1004 | { |
1005 | int error; |
1006 | |
1007 | p->size = size; |
1008 | error = bus_dmamem_alloc(sc->sc_dmatag, p->size, align, 0,(*(sc->sc_dmatag)->_dmamem_alloc)((sc->sc_dmatag), ( p->size), (align), (0), (p->segs), ((sizeof((p->segs )) / sizeof((p->segs)[0]))), (&p->nsegs), (0x0001)) |
1009 | p->segs, nitems(p->segs),(*(sc->sc_dmatag)->_dmamem_alloc)((sc->sc_dmatag), ( p->size), (align), (0), (p->segs), ((sizeof((p->segs )) / sizeof((p->segs)[0]))), (&p->nsegs), (0x0001)) |
1010 | &p->nsegs, BUS_DMA_NOWAIT)(*(sc->sc_dmatag)->_dmamem_alloc)((sc->sc_dmatag), ( p->size), (align), (0), (p->segs), ((sizeof((p->segs )) / sizeof((p->segs)[0]))), (&p->nsegs), (0x0001)); |
1011 | if (error) |
1012 | return (error); |
1013 | |
1014 | error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size,(*(sc->sc_dmatag)->_dmamem_map)((sc->sc_dmatag), (p-> segs), (p->nsegs), (p->size), (&p->addr), (0x0001 |0x0004)) |
1015 | &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)(*(sc->sc_dmatag)->_dmamem_map)((sc->sc_dmatag), (p-> segs), (p->nsegs), (p->size), (&p->addr), (0x0001 |0x0004)); |
1016 | if (error) |
1017 | goto free; |
1018 | |
1019 | error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size,(*(sc->sc_dmatag)->_dmamap_create)((sc->sc_dmatag), ( p->size), (1), (p->size), (0), (0x0001), (&p->map )) |
1020 | 0, BUS_DMA_NOWAIT, &p->map)(*(sc->sc_dmatag)->_dmamap_create)((sc->sc_dmatag), ( p->size), (1), (p->size), (0), (0x0001), (&p->map )); |
1021 | if (error) |
1022 | goto unmap; |
1023 | |
1024 | error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL,(*(sc->sc_dmatag)->_dmamap_load)((sc->sc_dmatag), (p ->map), (p->addr), (p->size), (((void *)0)), (0x0001 )) |
1025 | BUS_DMA_NOWAIT)(*(sc->sc_dmatag)->_dmamap_load)((sc->sc_dmatag), (p ->map), (p->addr), (p->size), (((void *)0)), (0x0001 )); |
1026 | if (error) |
1027 | goto destroy; |
1028 | return (0); |
1029 | |
1030 | destroy: |
1031 | bus_dmamap_destroy(sc->sc_dmatag, p->map)(*(sc->sc_dmatag)->_dmamap_destroy)((sc->sc_dmatag), (p->map)); |
1032 | unmap: |
1033 | bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size)(*(sc->sc_dmatag)->_dmamem_unmap)((sc->sc_dmatag), ( p->addr), (p->size)); |
1034 | free: |
1035 | bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs)(*(sc->sc_dmatag)->_dmamem_free)((sc->sc_dmatag), (p ->segs), (p->nsegs)); |
1036 | return (error); |
1037 | } |
1038 | |
1039 | int |
1040 | yds_freemem(struct yds_softc *sc, struct yds_dma *p) |
1041 | { |
1042 | bus_dmamap_unload(sc->sc_dmatag, p->map)(*(sc->sc_dmatag)->_dmamap_unload)((sc->sc_dmatag), ( p->map)); |
1043 | bus_dmamap_destroy(sc->sc_dmatag, p->map)(*(sc->sc_dmatag)->_dmamap_destroy)((sc->sc_dmatag), (p->map)); |
1044 | bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size)(*(sc->sc_dmatag)->_dmamem_unmap)((sc->sc_dmatag), ( p->addr), (p->size)); |
1045 | bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs)(*(sc->sc_dmatag)->_dmamem_free)((sc->sc_dmatag), (p ->segs), (p->nsegs)); |
1046 | return 0; |
1047 | } |
1048 | |
1049 | int |
1050 | yds_open(void *addr, int flags) |
1051 | { |
1052 | struct yds_softc *sc = addr; |
1053 | int mode; |
1054 | |
1055 | /* Select bank 0. */ |
1056 | YWRITE4(sc, YDS_CONTROL_SELECT, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x0104)), ((0 )))); |
1057 | |
1058 | /* Start the DSP operation. */ |
1059 | mode = YREAD4(sc, YDS_MODE)(((sc)->memt)->read_4(((sc)->memh), ((0x0108)))); |
1060 | mode |= YDS_MODE_ACTV0x00000001; |
1061 | mode &= ~YDS_MODE_ACTV20x00000002; |
1062 | YWRITE4(sc, YDS_MODE, mode)(((sc)->memt)->write_4(((sc)->memh), ((0x0108)), ((mode )))); |
1063 | |
1064 | return 0; |
1065 | } |
1066 | |
1067 | /* |
1068 | * Close function is called at splaudio(). |
1069 | */ |
1070 | void |
1071 | yds_close(void *addr) |
1072 | { |
1073 | struct yds_softc *sc = addr; |
1074 | |
1075 | yds_halt_output(sc); |
1076 | yds_halt_input(sc); |
1077 | yds_halt(sc); |
1078 | } |
1079 | |
1080 | int |
1081 | yds_set_params(void *addr, int setmode, int usemode, |
1082 | struct audio_params *play, struct audio_params *rec) |
1083 | { |
1084 | struct audio_params *p; |
1085 | int mode; |
1086 | |
1087 | for (mode = AUMODE_RECORD0x02; mode != -1; |
1088 | mode = mode == AUMODE_RECORD0x02 ? AUMODE_PLAY0x01 : -1) { |
1089 | if ((setmode & mode) == 0) |
1090 | continue; |
1091 | |
1092 | p = mode == AUMODE_PLAY0x01 ? play : rec; |
1093 | |
1094 | if (p->sample_rate < 4000) |
1095 | p->sample_rate = 4000; |
1096 | if (p->sample_rate > 48000) |
1097 | p->sample_rate = 48000; |
1098 | if (p->precision > 16) |
1099 | p->precision = 16; |
1100 | if (p->channels > 2) |
1101 | p->channels = 2; |
1102 | |
1103 | switch (p->encoding) { |
1104 | case AUDIO_ENCODING_SLINEAR_LE6: |
1105 | if (p->precision != 16) |
1106 | return EINVAL22; |
1107 | break; |
1108 | case AUDIO_ENCODING_ULINEAR_LE8: |
1109 | case AUDIO_ENCODING_ULINEAR_BE9: |
1110 | if (p->precision != 8) |
1111 | return EINVAL22; |
1112 | break; |
1113 | default: |
1114 | return (EINVAL22); |
1115 | } |
1116 | p->bps = AUDIO_BPS(p->precision)(p->precision) <= 8 ? 1 : ((p->precision) <= 16 ? 2 : 4); |
1117 | p->msb = 1; |
1118 | } |
1119 | |
1120 | return 0; |
1121 | } |
1122 | |
1123 | int |
1124 | yds_round_blocksize(void *addr, int blk) |
1125 | { |
1126 | /* |
1127 | * Block size must be bigger than a frame. |
1128 | * That is 1024bytes at most, i.e. for 48000Hz, 16bit, 2ch. |
1129 | */ |
1130 | if (blk < 1024) |
1131 | blk = 1024; |
1132 | |
1133 | return blk & ~4; |
1134 | } |
1135 | |
1136 | static u_int32_t |
1137 | yds_get_lpfq(u_int sample_rate) |
1138 | { |
1139 | int i; |
1140 | static struct lpfqt { |
1141 | u_int rate; |
1142 | u_int32_t lpfq; |
1143 | } lpfqt[] = { |
1144 | {8000, 0x32020000}, |
1145 | {11025, 0x31770000}, |
1146 | {16000, 0x31390000}, |
1147 | {22050, 0x31c90000}, |
1148 | {32000, 0x33d00000}, |
1149 | {48000, 0x40000000}, |
1150 | {0, 0} |
1151 | }; |
1152 | |
1153 | if (sample_rate == 44100) /* for P44 slot? */ |
1154 | return 0x370A0000; |
1155 | |
1156 | for (i = 0; lpfqt[i].rate != 0; i++) |
1157 | if (sample_rate <= lpfqt[i].rate) |
1158 | break; |
1159 | |
1160 | return lpfqt[i].lpfq; |
1161 | } |
1162 | |
1163 | static u_int32_t |
1164 | yds_get_lpfk(u_int sample_rate) |
1165 | { |
1166 | int i; |
1167 | static struct lpfkt { |
1168 | u_int rate; |
1169 | u_int32_t lpfk; |
1170 | } lpfkt[] = { |
1171 | {8000, 0x18b20000}, |
1172 | {11025, 0x20930000}, |
1173 | {16000, 0x2b9a0000}, |
1174 | {22050, 0x35a10000}, |
1175 | {32000, 0x3eaa0000}, |
1176 | {48000, 0x40000000}, |
1177 | {0, 0} |
1178 | }; |
1179 | |
1180 | if (sample_rate == 44100) /* for P44 slot? */ |
1181 | return 0x46460000; |
1182 | |
1183 | for (i = 0; lpfkt[i].rate != 0; i++) |
1184 | if (sample_rate <= lpfkt[i].rate) |
1185 | break; |
1186 | |
1187 | return lpfkt[i].lpfk; |
1188 | } |
1189 | |
1190 | int |
1191 | yds_trigger_output(void *addr, void *start, void *end, int blksize, |
1192 | void (*intr)(void *), void *arg, struct audio_params *param) |
1193 | #define P44 (sc->sc_flags & YDS_CAP_HAS_P440x0010) |
1194 | { |
1195 | struct yds_softc *sc = addr; |
1196 | struct yds_dma *p; |
1197 | struct play_slot_ctrl_bank *psb; |
1198 | const u_int gain = 0x40000000; |
1199 | bus_addr_t s; |
1200 | size_t l; |
1201 | int i; |
1202 | int p44, channels; |
1203 | |
1204 | mtx_enter(&audio_lock); |
1205 | #ifdef DIAGNOSTIC1 |
1206 | if (sc->sc_play.intr) |
1207 | panic("yds_trigger_output: already running"); |
1208 | #endif |
1209 | sc->sc_play.intr = intr; |
1210 | sc->sc_play.intr_arg = arg; |
1211 | sc->sc_play.offset = 0; |
1212 | sc->sc_play.blksize = blksize; |
1213 | |
1214 | DPRINTFN(1, ("yds_trigger_output: sc=%p start=%p end=%p " |
1215 | "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg)); |
1216 | |
1217 | p = yds_find_dma(sc, start); |
1218 | if (!p) { |
1219 | printf("yds_trigger_output: bad addr %p\n", start); |
1220 | mtx_leave(&audio_lock); |
1221 | return (EINVAL22); |
1222 | } |
1223 | sc->sc_play.dma = p; |
1224 | |
1225 | #ifdef DIAGNOSTIC1 |
1226 | { |
1227 | u_int32_t ctrlsize; |
1228 | if ((ctrlsize = YREAD4(sc, YDS_PLAY_CTRLSIZE)(((sc)->memt)->read_4(((sc)->memh), ((0x0140))))) != |
1229 | sizeof(struct play_slot_ctrl_bank) / sizeof(u_int32_t)) |
1230 | panic("%s: invalid play slot ctrldata %d %zd", |
1231 | sc->sc_dev.dv_xname, ctrlsize, |
1232 | sizeof(struct play_slot_ctrl_bank)); |
1233 | } |
1234 | #endif |
1235 | |
1236 | #ifdef YDS_USE_P44 |
1237 | /* The document says the P44 SRC supports only stereo, 16bit PCM. */ |
1238 | if (P44) |
1239 | p44 = ((param->sample_rate == 44100) && |
1240 | (param->channels == 2) && |
1241 | (param->precision == 16)); |
1242 | else |
1243 | #endif |
1244 | p44 = 0; |
1245 | channels = p44 ? 1 : param->channels; |
1246 | |
1247 | s = DMAADDR(p)((p)->map->dm_segs[0].ds_addr); |
1248 | l = ((char *)end - (char *)start); |
1249 | sc->sc_play.length = l; |
1250 | |
1251 | *sc->ptbl = channels; /* Num of play */ |
1252 | |
1253 | psb = sc->pbankp[0]; |
1254 | memset(psb, 0, sizeof(*psb))__builtin_memset((psb), (0), (sizeof(*psb))); |
1255 | psb->format = ((channels == 2 ? PSLT_FORMAT_STEREO0x00010000 : 0) | |
1256 | (param->precision == 8 ? PSLT_FORMAT_8BIT0x80000000 : 0) | |
1257 | (p44 ? PSLT_FORMAT_SRC4410x10000000 : 0)); |
1258 | psb->pgbase = s; |
1259 | psb->pgloopend = l; |
1260 | if (!p44) { |
1261 | psb->pgdeltaend = (param->sample_rate * 65536 / 48000) << 12; |
1262 | psb->lpfkend = yds_get_lpfk(param->sample_rate); |
1263 | psb->eggainend = gain; |
1264 | psb->lpfq = yds_get_lpfq(param->sample_rate); |
1265 | psb->pgdelta = psb->pgdeltaend; |
1266 | psb->lpfk = yds_get_lpfk(param->sample_rate); |
1267 | psb->eggain = gain; |
1268 | } |
1269 | |
1270 | for (i = 0; i < channels; i++) { |
1271 | /* i == 0: left or mono, i == 1: right */ |
1272 | psb = sc->pbankp[i*2]; |
1273 | if (i) |
1274 | /* copy from left */ |
1275 | *psb = *(sc->pbankp[0]); |
1276 | if (channels == 2) { |
1277 | /* stereo */ |
1278 | if (i == 0) { |
1279 | psb->lchgain = psb->lchgainend = gain; |
1280 | } else { |
1281 | psb->lchgain = psb->lchgainend = 0; |
1282 | psb->rchgain = psb->rchgainend = gain; |
1283 | psb->format |= PSLT_FORMAT_RCH0x00000001; |
1284 | } |
1285 | } else if (!p44) { |
1286 | /* mono */ |
1287 | psb->lchgain = psb->rchgain = gain; |
1288 | psb->lchgainend = psb->rchgainend = gain; |
1289 | } |
1290 | /* copy to the other bank */ |
1291 | *(sc->pbankp[i*2+1]) = *psb; |
1292 | } |
1293 | |
1294 | YDS_DUMP_PLAY_SLOT(5, sc, 0); |
1295 | YDS_DUMP_PLAY_SLOT(5, sc, 1); |
1296 | |
1297 | if (p44) |
1298 | YWRITE4(sc, YDS_P44_OUT_VOLUME, 0x3fff3fff)(((sc)->memt)->write_4(((sc)->memh), ((0x00B0)), ((0x3fff3fff )))); |
1299 | else |
1300 | YWRITE4(sc, YDS_DAC_OUT_VOLUME, 0x3fff3fff)(((sc)->memt)->write_4(((sc)->memh), ((0x0084)), ((0x3fff3fff )))); |
1301 | |
1302 | /* Now the play slot for the next frame is set up!! */ |
1303 | /* Sync play slot control data for both directions */ |
1304 | bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->ptbloff), (sizeof(struct play_slot_ctrl_bank ) * channels * 2), (0x04|0x01)) |
1305 | sc->ptbloff,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->ptbloff), (sizeof(struct play_slot_ctrl_bank ) * channels * 2), (0x04|0x01)) |
1306 | sizeof(struct play_slot_ctrl_bank) *(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->ptbloff), (sizeof(struct play_slot_ctrl_bank ) * channels * 2), (0x04|0x01)) |
1307 | channels * N_PLAY_SLOT_CTRL_BANK,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->ptbloff), (sizeof(struct play_slot_ctrl_bank ) * channels * 2), (0x04|0x01)) |
1308 | BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->ptbloff), (sizeof(struct play_slot_ctrl_bank ) * channels * 2), (0x04|0x01)); |
1309 | /* Sync ring buffer */ |
1310 | bus_dmamap_sync(sc->sc_dmatag, p->map, 0, blksize,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (p ->map), (0), (blksize), (0x04)) |
1311 | BUS_DMASYNC_PREWRITE)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (p ->map), (0), (blksize), (0x04)); |
1312 | /* HERE WE GO!! */ |
1313 | YWRITE4(sc, YDS_MODE,(((sc)->memt)->write_4(((sc)->memh), ((0x0108)), ((( ((sc)->memt)->read_4(((sc)->memh), ((0x0108)))) | 0x00000001 | 0x00000002)))) |
1314 | YREAD4(sc, YDS_MODE) | YDS_MODE_ACTV | YDS_MODE_ACTV2)(((sc)->memt)->write_4(((sc)->memh), ((0x0108)), ((( ((sc)->memt)->read_4(((sc)->memh), ((0x0108)))) | 0x00000001 | 0x00000002)))); |
1315 | mtx_leave(&audio_lock); |
1316 | return 0; |
1317 | } |
1318 | #undef P44 |
1319 | |
1320 | int |
1321 | yds_trigger_input(void *addr, void *start, void *end, int blksize, |
1322 | void (*intr)(void *), void *arg, struct audio_params *param) |
1323 | { |
1324 | struct yds_softc *sc = addr; |
1325 | struct yds_dma *p; |
1326 | u_int srate, format; |
1327 | struct rec_slot_ctrl_bank *rsb; |
1328 | bus_addr_t s; |
1329 | size_t l; |
1330 | |
1331 | mtx_enter(&audio_lock); |
1332 | #ifdef DIAGNOSTIC1 |
1333 | if (sc->sc_rec.intr) |
1334 | panic("yds_trigger_input: already running"); |
1335 | #endif |
1336 | sc->sc_rec.intr = intr; |
1337 | sc->sc_rec.intr_arg = arg; |
1338 | sc->sc_rec.offset = 0; |
1339 | sc->sc_rec.blksize = blksize; |
1340 | |
1341 | DPRINTFN(1, ("yds_trigger_input: " |
1342 | "sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n", |
1343 | addr, start, end, blksize, intr, arg)); |
1344 | DPRINTFN(1, (" parameters: rate=%lu, precision=%u, channels=%u\n", |
1345 | param->sample_rate, param->precision, param->channels)); |
1346 | |
1347 | p = yds_find_dma(sc, start); |
1348 | if (!p) { |
1349 | printf("yds_trigger_input: bad addr %p\n", start); |
1350 | mtx_leave(&audio_lock); |
1351 | return (EINVAL22); |
1352 | } |
1353 | sc->sc_rec.dma = p; |
1354 | |
1355 | s = DMAADDR(p)((p)->map->dm_segs[0].ds_addr); |
1356 | l = ((char *)end - (char *)start); |
1357 | sc->sc_rec.length = l; |
1358 | |
1359 | rsb = &sc->rbank[0]; |
1360 | memset(rsb, 0, sizeof(*rsb))__builtin_memset((rsb), (0), (sizeof(*rsb))); |
1361 | rsb->pgbase = s; |
1362 | rsb->pgloopendadr = l; |
1363 | /* Seems all 4 banks must be set up... */ |
1364 | sc->rbank[1] = *rsb; |
1365 | sc->rbank[2] = *rsb; |
1366 | sc->rbank[3] = *rsb; |
1367 | |
1368 | YWRITE4(sc, YDS_ADC_IN_VOLUME, 0x3fff3fff)(((sc)->memt)->write_4(((sc)->memh), ((0x00A8)), ((0x3fff3fff )))); |
1369 | YWRITE4(sc, YDS_REC_IN_VOLUME, 0x3fff3fff)(((sc)->memt)->write_4(((sc)->memh), ((0x00AC)), ((0x3fff3fff )))); |
1370 | srate = 48000 * 4096 / param->sample_rate - 1; |
1371 | format = ((param->precision == 8 ? YDS_FORMAT_8BIT0x01 : 0) | |
1372 | (param->channels == 2 ? YDS_FORMAT_STEREO0x02 : 0)); |
1373 | DPRINTF(("srate=%d, format=%08x\n", srate, format)); |
1374 | #ifdef YDS_USE_REC_SLOT |
1375 | YWRITE4(sc, YDS_DAC_REC_VOLUME, 0x3fff3fff)(((sc)->memt)->write_4(((sc)->memh), ((0x0098)), ((0x3fff3fff )))); |
1376 | YWRITE4(sc, YDS_P44_REC_VOLUME, 0x3fff3fff)(((sc)->memt)->write_4(((sc)->memh), ((0x00B4)), ((0x3fff3fff )))); |
1377 | YWRITE4(sc, YDS_MAPOF_REC, YDS_RECSLOT_VALID)(((sc)->memt)->write_4(((sc)->memh), ((0x0150)), ((0x00000001 )))); |
1378 | YWRITE4(sc, YDS_REC_SAMPLE_RATE, srate)(((sc)->memt)->write_4(((sc)->memh), ((0x00c4)), ((srate )))); |
1379 | YWRITE4(sc, YDS_REC_FORMAT, format)(((sc)->memt)->write_4(((sc)->memh), ((0x00cc)), ((format )))); |
1380 | #else |
1381 | YWRITE4(sc, YDS_MAPOF_REC, YDS_ADCSLOT_VALID)(((sc)->memt)->write_4(((sc)->memh), ((0x0150)), ((0x00000002 )))); |
1382 | YWRITE4(sc, YDS_ADC_SAMPLE_RATE, srate)(((sc)->memt)->write_4(((sc)->memh), ((0x00c0)), ((srate )))); |
1383 | YWRITE4(sc, YDS_ADC_FORMAT, format)(((sc)->memt)->write_4(((sc)->memh), ((0x00c8)), ((format )))); |
1384 | #endif |
1385 | /* Now the rec slot for the next frame is set up!! */ |
1386 | /* Sync record slot control data */ |
1387 | bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2* 2), (0x04|0x01)) |
1388 | sc->rbankoff,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2* 2), (0x04|0x01)) |
1389 | sizeof(struct rec_slot_ctrl_bank)*(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2* 2), (0x04|0x01)) |
1390 | N_REC_SLOT_CTRL*(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2* 2), (0x04|0x01)) |
1391 | N_REC_SLOT_CTRL_BANK,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2* 2), (0x04|0x01)) |
1392 | BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2* 2), (0x04|0x01)); |
1393 | /* Sync ring buffer */ |
1394 | bus_dmamap_sync(sc->sc_dmatag, p->map, 0, blksize,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (p ->map), (0), (blksize), (0x01)) |
1395 | BUS_DMASYNC_PREREAD)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (p ->map), (0), (blksize), (0x01)); |
1396 | /* HERE WE GO!! */ |
1397 | YWRITE4(sc, YDS_MODE,(((sc)->memt)->write_4(((sc)->memh), ((0x0108)), ((( ((sc)->memt)->read_4(((sc)->memh), ((0x0108)))) | 0x00000001 | 0x00000002)))) |
1398 | YREAD4(sc, YDS_MODE) | YDS_MODE_ACTV | YDS_MODE_ACTV2)(((sc)->memt)->write_4(((sc)->memh), ((0x0108)), ((( ((sc)->memt)->read_4(((sc)->memh), ((0x0108)))) | 0x00000001 | 0x00000002)))); |
1399 | mtx_leave(&audio_lock); |
1400 | return 0; |
1401 | } |
1402 | |
1403 | static int |
1404 | yds_halt(struct yds_softc *sc) |
1405 | { |
1406 | u_int32_t mode; |
1407 | |
1408 | /* Stop the DSP operation. */ |
1409 | mode = YREAD4(sc, YDS_MODE)(((sc)->memt)->read_4(((sc)->memh), ((0x0108)))); |
1410 | YWRITE4(sc, YDS_MODE, mode & ~(YDS_MODE_ACTV|YDS_MODE_ACTV2))(((sc)->memt)->write_4(((sc)->memh), ((0x0108)), ((mode & ~(0x00000001|0x00000002))))); |
1411 | |
1412 | /* Paranoia... mute all */ |
1413 | YWRITE4(sc, YDS_P44_OUT_VOLUME, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x00B0)), ((0 )))); |
1414 | YWRITE4(sc, YDS_DAC_OUT_VOLUME, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x0084)), ((0 )))); |
1415 | YWRITE4(sc, YDS_ADC_IN_VOLUME, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x00A8)), ((0 )))); |
1416 | YWRITE4(sc, YDS_REC_IN_VOLUME, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x00AC)), ((0 )))); |
1417 | YWRITE4(sc, YDS_DAC_REC_VOLUME, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x0098)), ((0 )))); |
1418 | YWRITE4(sc, YDS_P44_REC_VOLUME, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x00B4)), ((0 )))); |
1419 | |
1420 | return 0; |
1421 | } |
1422 | |
1423 | int |
1424 | yds_halt_output(void *addr) |
1425 | { |
1426 | struct yds_softc *sc = addr; |
1427 | |
1428 | DPRINTF(("yds: yds_halt_output\n")); |
1429 | mtx_enter(&audio_lock); |
1430 | if (sc->sc_play.intr) { |
1431 | sc->sc_play.intr = 0; |
1432 | /* Sync play slot control data */ |
1433 | bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->pbankoff), (sizeof(struct play_slot_ctrl_bank )* (*sc->ptbl)*2), (0x08|0x02)) |
1434 | sc->pbankoff,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->pbankoff), (sizeof(struct play_slot_ctrl_bank )* (*sc->ptbl)*2), (0x08|0x02)) |
1435 | sizeof(struct play_slot_ctrl_bank)*(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->pbankoff), (sizeof(struct play_slot_ctrl_bank )* (*sc->ptbl)*2), (0x08|0x02)) |
1436 | (*sc->ptbl)*N_PLAY_SLOT_CTRL_BANK,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->pbankoff), (sizeof(struct play_slot_ctrl_bank )* (*sc->ptbl)*2), (0x08|0x02)) |
1437 | BUS_DMASYNC_POSTWRITE|BUS_DMASYNC_POSTREAD)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->pbankoff), (sizeof(struct play_slot_ctrl_bank )* (*sc->ptbl)*2), (0x08|0x02)); |
1438 | /* Stop the play slot operation */ |
1439 | sc->pbankp[0]->status = |
1440 | sc->pbankp[1]->status = |
1441 | sc->pbankp[2]->status = |
1442 | sc->pbankp[3]->status = 1; |
1443 | /* Sync ring buffer */ |
1444 | bus_dmamap_sync(sc->sc_dmatag, sc->sc_play.dma->map,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_play.dma->map), (0), (sc->sc_play.length), (0x08 )) |
1445 | 0, sc->sc_play.length, BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_play.dma->map), (0), (sc->sc_play.length), (0x08 )); |
1446 | } |
1447 | mtx_leave(&audio_lock); |
1448 | return 0; |
1449 | } |
1450 | |
1451 | int |
1452 | yds_halt_input(void *addr) |
1453 | { |
1454 | struct yds_softc *sc = addr; |
1455 | |
1456 | DPRINTF(("yds: yds_halt_input\n")); |
1457 | mtx_enter(&audio_lock); |
1458 | if (sc->sc_rec.intr) { |
1459 | /* Stop the rec slot operation */ |
1460 | YWRITE4(sc, YDS_MAPOF_REC, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x0150)), ((0 )))); |
1461 | sc->sc_rec.intr = 0; |
1462 | /* Sync rec slot control data */ |
1463 | bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2*2), (0x08|0x02)) |
1464 | sc->rbankoff,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2*2), (0x08|0x02)) |
1465 | sizeof(struct rec_slot_ctrl_bank)*(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2*2), (0x08|0x02)) |
1466 | N_REC_SLOT_CTRL*N_REC_SLOT_CTRL_BANK,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2*2), (0x08|0x02)) |
1467 | BUS_DMASYNC_POSTWRITE|BUS_DMASYNC_POSTREAD)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2*2), (0x08|0x02)); |
1468 | /* Sync ring buffer */ |
1469 | bus_dmamap_sync(sc->sc_dmatag, sc->sc_rec.dma->map,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_rec.dma->map), (0), (sc->sc_rec.length), (0x02) ) |
1470 | 0, sc->sc_rec.length, BUS_DMASYNC_POSTREAD)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_rec.dma->map), (0), (sc->sc_rec.length), (0x02) ); |
1471 | } |
1472 | sc->sc_rec.intr = NULL((void *)0); |
1473 | mtx_leave(&audio_lock); |
1474 | return 0; |
1475 | } |
1476 | |
1477 | int |
1478 | yds_mixer_set_port(void *addr, mixer_ctrl_t *cp) |
1479 | { |
1480 | struct yds_softc *sc = addr; |
1481 | |
1482 | return (sc->sc_codec[0].codec_if->vtbl->mixer_set_port( |
1483 | sc->sc_codec[0].codec_if, cp)); |
1484 | } |
1485 | |
1486 | int |
1487 | yds_mixer_get_port(void *addr, mixer_ctrl_t *cp) |
1488 | { |
1489 | struct yds_softc *sc = addr; |
1490 | |
1491 | return (sc->sc_codec[0].codec_if->vtbl->mixer_get_port( |
1492 | sc->sc_codec[0].codec_if, cp)); |
1493 | } |
1494 | |
1495 | int |
1496 | yds_query_devinfo(void *addr, mixer_devinfo_t *dip) |
1497 | { |
1498 | struct yds_softc *sc = addr; |
1499 | |
1500 | return (sc->sc_codec[0].codec_if->vtbl->query_devinfo( |
1501 | sc->sc_codec[0].codec_if, dip)); |
1502 | } |
1503 | |
1504 | int |
1505 | yds_get_portnum_by_name(struct yds_softc *sc, char *class, char *device, |
1506 | char *qualifier) |
1507 | { |
1508 | return (sc->sc_codec[0].codec_if->vtbl->get_portnum_by_name( |
1509 | sc->sc_codec[0].codec_if, class, device, qualifier)); |
1510 | } |
1511 | |
1512 | void * |
1513 | yds_malloc(void *addr, int direction, size_t size, int pool, int flags) |
1514 | { |
1515 | struct yds_softc *sc = addr; |
1516 | struct yds_dma *p; |
1517 | int error; |
1518 | |
1519 | p = malloc(sizeof(*p), pool, flags); |
1520 | if (!p) |
1521 | return (0); |
1522 | error = yds_allocmem(sc, size, 16, p); |
1523 | if (error) { |
1524 | free(p, pool, sizeof *p); |
1525 | return (0); |
1526 | } |
1527 | p->next = sc->sc_dmas; |
1528 | sc->sc_dmas = p; |
1529 | return (KERNADDR(p)((void *)((p)->addr))); |
1530 | } |
1531 | |
1532 | void |
1533 | yds_free(void *addr, void *ptr, int pool) |
1534 | { |
1535 | struct yds_softc *sc = addr; |
1536 | struct yds_dma **pp, *p; |
1537 | |
1538 | for (pp = &sc->sc_dmas; (p = *pp) != NULL((void *)0); pp = &p->next) { |
1539 | if (KERNADDR(p)((void *)((p)->addr)) == ptr) { |
1540 | yds_freemem(sc, p); |
1541 | *pp = p->next; |
1542 | free(p, pool, sizeof *p); |
1543 | return; |
1544 | } |
1545 | } |
1546 | } |
1547 | |
1548 | static struct yds_dma * |
1549 | yds_find_dma(struct yds_softc *sc, void *addr) |
1550 | { |
1551 | struct yds_dma *p; |
1552 | |
1553 | for (p = sc->sc_dmas; p && KERNADDR(p)((void *)((p)->addr)) != addr; p = p->next) |
1554 | ; |
1555 | |
1556 | return p; |
1557 | } |
1558 | |
1559 | size_t |
1560 | yds_round_buffersize(void *addr, int direction, size_t size) |
1561 | { |
1562 | /* |
1563 | * Buffer size should be at least twice as bigger as a frame. |
1564 | */ |
1565 | if (size < 1024 * 3) |
1566 | size = 1024 * 3; |
1567 | return (size); |
1568 | } |
1569 | |
1570 | int |
1571 | yds_get_props(void *addr) |
1572 | { |
1573 | return (AUDIO_PROP_MMAP0x02 | AUDIO_PROP_INDEPENDENT0x04 | |
1574 | AUDIO_PROP_FULLDUPLEX0x01); |
1575 | } |
1576 | |
1577 | int |
1578 | yds_activate(struct device *self, int act) |
1579 | { |
1580 | struct yds_softc *sc = (struct yds_softc *)self; |
1581 | int rv = 0; |
1582 | |
1583 | switch (act) { |
1584 | case DVACT_QUIESCE2: |
1585 | if (sc->sc_play.intr || sc->sc_rec.intr) |
1586 | sc->sc_resume_active = 1; |
1587 | else |
1588 | sc->sc_resume_active = 0; |
1589 | rv = config_activate_children(self, act); |
1590 | if (sc->sc_resume_active) |
1591 | yds_close(sc); |
1592 | break; |
1593 | case DVACT_RESUME4: |
1594 | yds_halt(sc); |
1595 | yds_init(sc, 1); |
1596 | ac97_resume(&sc->sc_codec[0].host_if, sc->sc_codec[0].codec_if); |
1597 | if (sc->sc_resume_active) |
1598 | yds_open(sc, 0); |
1599 | rv = config_activate_children(self, act); |
1600 | break; |
1601 | default: |
1602 | rv = config_activate_children(self, act); |
1603 | break; |
1604 | } |
1605 | return (rv); |
1606 | } |
1607 | |
1608 | int |
1609 | yds_init(struct yds_softc *sc, int resuming) |
1610 | { |
1611 | u_int32_t reg; |
1612 | |
1613 | pci_chipset_tag_t pc = sc->sc_pc; |
1614 | |
1615 | int to; |
1616 | |
1617 | DPRINTF(("in yds_init()\n")); |
1618 | |
1619 | /* Download microcode */ |
1620 | if (!resuming) { |
1621 | if (yds_download_mcode(sc)) { |
1622 | printf("%s: download microcode failed\n", sc->sc_dev.dv_xname); |
1623 | return -1; |
1624 | } |
1625 | } |
1626 | /* Allocate DMA buffers */ |
1627 | if (yds_allocate_slots(sc, resuming)) { |
1628 | printf("%s: could not allocate slots\n", sc->sc_dev.dv_xname); |
1629 | return -1; |
1630 | } |
1631 | |
1632 | /* Warm reset */ |
1633 | reg = pci_conf_read(pc, sc->sc_pcitag, YDS_PCI_DSCTRL0x48); |
1634 | pci_conf_write(pc, sc->sc_pcitag, YDS_PCI_DSCTRL0x48, reg | YDS_DSCTRL_WRST0x00000004); |
1635 | delay(50000)(*delay_func)(50000); |
1636 | |
1637 | /* |
1638 | * Detect primary/secondary AC97 |
1639 | * YMF754 Hardware Specification Rev 1.01 page 24 |
1640 | */ |
1641 | reg = pci_conf_read(pc, sc->sc_pcitag, YDS_PCI_DSCTRL0x48); |
1642 | pci_conf_write(pc, sc->sc_pcitag, YDS_PCI_DSCTRL0x48, |
1643 | reg & ~YDS_DSCTRL_CRST0x00000001); |
1644 | delay(400000)(*delay_func)(400000); /* Needed for 740C. */ |
1645 | |
1646 | /* Primary */ |
1647 | for (to = 0; to < AC97_TIMEOUT1000; to++) { |
1648 | if ((YREAD2(sc, AC97_STAT_ADDR1)(((sc)->memt)->read_2(((sc)->memh), ((0x0066)))) & AC97_BUSY0x8000) == 0) |
1649 | break; |
1650 | delay(1)(*delay_func)(1); |
1651 | } |
1652 | if (to == AC97_TIMEOUT1000) { |
1653 | printf("%s: no AC97 available\n", sc->sc_dev.dv_xname); |
1654 | return -1; |
1655 | } |
1656 | |
1657 | /* Secondary */ |
1658 | /* Secondary AC97 is used for 4ch audio. Currently unused. */ |
1659 | ac97_id2 = -1; |
1660 | if ((YREAD2(sc, YDS_ACTIVITY)(((sc)->memt)->read_2(((sc)->memh), ((0x0006)))) & YDS_ACTIVITY_DOCKA0x0010) == 0) |
1661 | goto detected; |
1662 | #if 0 /* reset secondary... */ |
1663 | YWRITE2(sc, YDS_GPIO_OCTRL,(((sc)->memt)->write_2(((sc)->memh), ((0x0056)), ((( ((sc)->memt)->read_2(((sc)->memh), ((0x0056)))) & ~0x0004)))) |
1664 | YREAD2(sc, YDS_GPIO_OCTRL) & ~YDS_GPIO_GPO2)(((sc)->memt)->write_2(((sc)->memh), ((0x0056)), ((( ((sc)->memt)->read_2(((sc)->memh), ((0x0056)))) & ~0x0004)))); |
1665 | YWRITE2(sc, YDS_GPIO_FUNCE,(((sc)->memt)->write_2(((sc)->memh), ((0x0058)), ((( (((sc)->memt)->read_2(((sc)->memh), ((0x0058))))& (~0x0004))|0x0040)))) |
1666 | (YREAD2(sc, YDS_GPIO_FUNCE)&(~YDS_GPIO_GPC2))|YDS_GPIO_GPE2)(((sc)->memt)->write_2(((sc)->memh), ((0x0058)), ((( (((sc)->memt)->read_2(((sc)->memh), ((0x0058))))& (~0x0004))|0x0040)))); |
1667 | #endif |
1668 | for (to = 0; to < AC97_TIMEOUT1000; to++) { |
1669 | if ((YREAD2(sc, AC97_STAT_ADDR2)(((sc)->memt)->read_2(((sc)->memh), ((0x006a)))) & AC97_BUSY0x8000) == 0) |
1670 | break; |
1671 | delay(1)(*delay_func)(1); |
1672 | } |
1673 | if (to < AC97_TIMEOUT1000) { |
1674 | /* detect id */ |
1675 | for (ac97_id2 = 1; ac97_id2 < 4; ac97_id2++) { |
1676 | YWRITE2(sc, AC97_CMD_ADDR,(((sc)->memt)->write_2(((sc)->memh), ((0x0062)), ((0x8000 | ((ac97_id2) << 8) | 0x28)))) |
1677 | AC97_CMD_READ | AC97_ID(ac97_id2) | 0x28)(((sc)->memt)->write_2(((sc)->memh), ((0x0062)), ((0x8000 | ((ac97_id2) << 8) | 0x28)))); |
1678 | |
1679 | for (to = 0; to < AC97_TIMEOUT1000; to++) { |
1680 | if ((YREAD2(sc, AC97_STAT_ADDR2)(((sc)->memt)->read_2(((sc)->memh), ((0x006a)))) & AC97_BUSY0x8000) |
1681 | == 0) |
1682 | goto detected; |
1683 | delay(1)(*delay_func)(1); |
1684 | } |
1685 | } |
1686 | if (ac97_id2 == 4) |
1687 | ac97_id2 = -1; |
1688 | detected: |
1689 | ; |
1690 | } |
1691 | |
1692 | pci_conf_write(pc, sc->sc_pcitag, YDS_PCI_DSCTRL0x48, |
1693 | reg | YDS_DSCTRL_CRST0x00000001); |
1694 | delay (20)(*delay_func)(20); |
1695 | pci_conf_write(pc, sc->sc_pcitag, YDS_PCI_DSCTRL0x48, |
1696 | reg & ~YDS_DSCTRL_CRST0x00000001); |
1697 | delay (400000)(*delay_func)(400000); |
1698 | for (to = 0; to < AC97_TIMEOUT1000; to++) { |
1699 | if ((YREAD2(sc, AC97_STAT_ADDR1)(((sc)->memt)->read_2(((sc)->memh), ((0x0066)))) & AC97_BUSY0x8000) == 0) |
1700 | break; |
1701 | delay(1)(*delay_func)(1); |
1702 | } |
1703 | |
1704 | DPRINTF(("out of yds_init()\n")); |
1705 | |
1706 | return 0; |
1707 | } |