Line data Source code
1 : /* $OpenBSD: cs4280.c,v 1.52 2018/09/03 05:37:32 miko Exp $ */
2 : /* $NetBSD: cs4280.c,v 1.5 2000/06/26 04:56:23 simonb Exp $ */
3 :
4 : /*
5 : * Copyright (c) 1999, 2000 Tatoku Ogaito. All rights reserved.
6 : *
7 : * Redistribution and use in source and binary forms, with or without
8 : * modification, are permitted provided that the following conditions
9 : * are met:
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : * 2. Redistributions in binary form must reproduce the above copyright
13 : * notice, this list of conditions and the following disclaimer in the
14 : * documentation and/or other materials provided with the distribution.
15 : * 3. All advertising materials mentioning features or use of this software
16 : * must display the following acknowledgement:
17 : * This product includes software developed by Tatoku Ogaito
18 : * for the NetBSD Project.
19 : * 4. The name of the author may not be used to endorse or promote products
20 : * derived from this software without specific prior written permission
21 : *
22 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 : * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 : */
33 :
34 : /*
35 : * Cirrus Logic CS4280 (and maybe CS461x) driver.
36 : * Data sheets can be found
37 : * http://www.cirrus.com/ftp/pubs/4280.pdf
38 : * http://www.cirrus.com/ftp/pubs/4297.pdf
39 : * ftp://ftp.alsa-project.org/pub/manuals/cirrus/embedded_audio_spec.pdf
40 : * ftp://ftp.alsa-project.org/pub/manuals/cirrus/embedded_audio_spec.doc
41 : */
42 :
43 : /*
44 : * TODO
45 : * Implement MIDI
46 : * Joystick support
47 : */
48 :
49 : #ifdef CS4280_DEBUG
50 : #ifndef MIDI_READY
51 : #define MIDI_READY
52 : #endif /* ! MIDI_READY */
53 : #endif
54 :
55 : #ifdef MIDI_READY
56 : #include "midi.h"
57 : #endif
58 :
59 : #if defined(CS4280_DEBUG)
60 : #define DPRINTF(x) if (cs4280debug) printf x
61 : #define DPRINTFN(n,x) if (cs4280debug>(n)) printf x
62 : int cs4280debug = 0;
63 : #else
64 : #define DPRINTF(x)
65 : #define DPRINTFN(n,x)
66 : #endif
67 :
68 : #include <sys/param.h>
69 : #include <sys/systm.h>
70 : #include <sys/kernel.h>
71 : #include <sys/fcntl.h>
72 : #include <sys/malloc.h>
73 : #include <sys/device.h>
74 :
75 : #include <dev/pci/pcidevs.h>
76 : #include <dev/pci/pcivar.h>
77 : #include <dev/pci/cs4280reg.h>
78 :
79 : #include <sys/audioio.h>
80 : #include <dev/audio_if.h>
81 :
82 : #include <dev/ic/ac97.h>
83 :
84 : #include <machine/bus.h>
85 :
86 : #define CSCC_PCI_BA0 0x10
87 : #define CSCC_PCI_BA1 0x14
88 :
89 : struct cs4280_dma {
90 : bus_dmamap_t map;
91 : caddr_t addr; /* real dma buffer */
92 : caddr_t dum; /* dummy buffer for audio driver */
93 : bus_dma_segment_t segs[1];
94 : int nsegs;
95 : size_t size;
96 : struct cs4280_dma *next;
97 : };
98 : #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr)
99 : #define BUFADDR(p) ((void *)((p)->dum))
100 : #define KERNADDR(p) ((void *)((p)->addr))
101 :
102 : /*
103 : * Software state
104 : */
105 : struct cs4280_softc {
106 : struct device sc_dev;
107 :
108 : pci_intr_handle_t * sc_ih;
109 :
110 : /* I/O (BA0) */
111 : bus_space_tag_t ba0t;
112 : bus_space_handle_t ba0h;
113 :
114 : /* BA1 */
115 : bus_space_tag_t ba1t;
116 : bus_space_handle_t ba1h;
117 :
118 : /* DMA */
119 : bus_dma_tag_t sc_dmatag;
120 : struct cs4280_dma *sc_dmas;
121 :
122 : void (*sc_pintr)(void *); /* dma completion intr handler */
123 : void *sc_parg; /* arg for sc_intr() */
124 : char *sc_ps, *sc_pe, *sc_pn;
125 : int sc_pcount;
126 : int sc_pi;
127 : struct cs4280_dma *sc_pdma;
128 : char *sc_pbuf;
129 : #ifdef DIAGNOSTIC
130 : char sc_prun;
131 : #endif
132 :
133 : void (*sc_rintr)(void *); /* dma completion intr handler */
134 : void *sc_rarg; /* arg for sc_intr() */
135 : char *sc_rs, *sc_re, *sc_rn;
136 : int sc_rcount;
137 : int sc_ri;
138 : struct cs4280_dma *sc_rdma;
139 : char *sc_rbuf;
140 : int sc_rparam; /* record format */
141 : #ifdef DIAGNOSTIC
142 : char sc_rrun;
143 : #endif
144 :
145 : #if NMIDI > 0
146 : void (*sc_iintr)(void *, int); /* midi input ready handler */
147 : void (*sc_ointr)(void *); /* midi output ready handler */
148 : void *sc_arg;
149 : #endif
150 :
151 : u_int32_t pctl;
152 : u_int32_t cctl;
153 :
154 : struct ac97_codec_if *codec_if;
155 : struct ac97_host_if host_if;
156 :
157 : u_int16_t ac97_reg[CS4280_SAVE_REG_MAX + 1]; /* Save ac97 registers */
158 : };
159 :
160 : #define BA0READ4(sc, r) bus_space_read_4((sc)->ba0t, (sc)->ba0h, (r))
161 : #define BA0WRITE4(sc, r, x) bus_space_write_4((sc)->ba0t, (sc)->ba0h, (r), (x))
162 : #define BA1READ4(sc, r) bus_space_read_4((sc)->ba1t, (sc)->ba1h, (r))
163 : #define BA1WRITE4(sc, r, x) bus_space_write_4((sc)->ba1t, (sc)->ba1h, (r), (x))
164 :
165 : int cs4280_match(struct device *, void *, void *);
166 : void cs4280_attach(struct device *, struct device *, void *);
167 : int cs4280_activate(struct device *, int);
168 : void cs4280_attachhook(struct device *);
169 : int cs4280_intr(void *);
170 : void cs4280_reset(void *);
171 : int cs4280_download_image(struct cs4280_softc *);
172 :
173 : int cs4280_download(struct cs4280_softc *, const u_int32_t *, u_int32_t, u_int32_t);
174 : int cs4280_allocmem(struct cs4280_softc *, size_t, size_t,
175 : struct cs4280_dma *);
176 : int cs4280_freemem(struct cs4280_softc *, struct cs4280_dma *);
177 :
178 : #ifdef CS4280_DEBUG
179 : int cs4280_check_images(struct cs4280_softc *);
180 : int cs4280_checkimage(struct cs4280_softc *, u_int32_t *, u_int32_t,
181 : u_int32_t);
182 : #endif
183 :
184 : struct cfdriver clcs_cd = {
185 : NULL, "clcs", DV_DULL
186 : };
187 :
188 : struct cfattach clcs_ca = {
189 : sizeof(struct cs4280_softc), cs4280_match, cs4280_attach, NULL,
190 : cs4280_activate
191 : };
192 :
193 : int cs4280_init(struct cs4280_softc *, int);
194 : int cs4280_init2(struct cs4280_softc *, int);
195 : int cs4280_open(void *, int);
196 : void cs4280_close(void *);
197 :
198 : int cs4280_set_params(void *, int, int, struct audio_params *, struct audio_params *);
199 : int cs4280_round_blocksize(void *, int);
200 :
201 : int cs4280_halt_output(void *);
202 : int cs4280_halt_input(void *);
203 :
204 : int cs4280_mixer_set_port(void *, mixer_ctrl_t *);
205 : int cs4280_mixer_get_port(void *, mixer_ctrl_t *);
206 : int cs4280_query_devinfo(void *addr, mixer_devinfo_t *dip);
207 : void *cs4280_malloc(void *, int, size_t, int, int);
208 : void cs4280_free(void *, void *, int);
209 : int cs4280_get_props(void *);
210 : int cs4280_trigger_output(void *, void *, void *, int, void (*)(void *),
211 : void *, struct audio_params *);
212 : int cs4280_trigger_input(void *, void *, void *, int, void (*)(void *),
213 : void *, struct audio_params *);
214 :
215 :
216 : void cs4280_set_dac_rate(struct cs4280_softc *, int );
217 : void cs4280_set_adc_rate(struct cs4280_softc *, int );
218 : int cs4280_get_portnum_by_name(struct cs4280_softc *, char *, char *,
219 : char *);
220 : int cs4280_src_wait(struct cs4280_softc *);
221 : int cs4280_attach_codec(void *sc, struct ac97_codec_if *);
222 : int cs4280_read_codec(void *sc, u_int8_t a, u_int16_t *d);
223 : int cs4280_write_codec(void *sc, u_int8_t a, u_int16_t d);
224 : void cs4280_reset_codec(void *sc);
225 :
226 : void cs4280_clear_fifos(struct cs4280_softc *);
227 :
228 : #if NMIDI > 0
229 : void cs4280_midi_close(void *);
230 : void cs4280_midi_getinfo(void *, struct midi_info *);
231 : int cs4280_midi_open(void *, int, void (*)(void *, int),
232 : void (*)(void *), void *);
233 : int cs4280_midi_output(void *, int);
234 : #endif
235 :
236 : struct audio_hw_if cs4280_hw_if = {
237 : cs4280_open,
238 : cs4280_close,
239 : cs4280_set_params,
240 : cs4280_round_blocksize,
241 : NULL,
242 : NULL,
243 : NULL,
244 : NULL,
245 : NULL,
246 : cs4280_halt_output,
247 : cs4280_halt_input,
248 : NULL,
249 : NULL,
250 : cs4280_mixer_set_port,
251 : cs4280_mixer_get_port,
252 : cs4280_query_devinfo,
253 : cs4280_malloc,
254 : cs4280_free,
255 : NULL,
256 : cs4280_get_props,
257 : cs4280_trigger_output,
258 : cs4280_trigger_input
259 : };
260 :
261 : #if NMIDI > 0
262 : struct midi_hw_if cs4280_midi_hw_if = {
263 : cs4280_midi_open,
264 : cs4280_midi_close,
265 : cs4280_midi_output,
266 : 0, /* flush */
267 : cs4280_midi_getinfo,
268 : 0, /* ioctl */
269 : };
270 : #endif
271 :
272 :
273 : const struct pci_matchid cs4280_devices[] = {
274 : { PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CS4280 },
275 : { PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CS4610 },
276 : { PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CS4615 },
277 : };
278 :
279 : int
280 0 : cs4280_match(struct device *parent, void *ma, void *aux)
281 : {
282 0 : return (pci_matchbyid((struct pci_attach_args *)aux, cs4280_devices,
283 : nitems(cs4280_devices)));
284 : }
285 :
286 : int
287 0 : cs4280_read_codec(void *sc_, u_int8_t add, u_int16_t *data)
288 : {
289 0 : struct cs4280_softc *sc = sc_;
290 : int n;
291 :
292 : DPRINTFN(5,("read_codec: add=0x%02x ", add));
293 : /*
294 : * Make sure that there is not data sitting around from a preivous
295 : * uncompleted access.
296 : */
297 0 : BA0READ4(sc, CS4280_ACSDA);
298 :
299 : /* Set up AC97 control registers. */
300 0 : BA0WRITE4(sc, CS4280_ACCAD, add);
301 0 : BA0WRITE4(sc, CS4280_ACCDA, 0);
302 0 : BA0WRITE4(sc, CS4280_ACCTL,
303 : ACCTL_RSTN | ACCTL_ESYN | ACCTL_VFRM | ACCTL_CRW | ACCTL_DCV );
304 :
305 0 : if (cs4280_src_wait(sc) < 0) {
306 0 : printf("%s: AC97 read prob. (DCV!=0) for add=0x%02x\n",
307 0 : sc->sc_dev.dv_xname, add);
308 0 : return (1);
309 : }
310 :
311 : /* wait for valid status bit is active */
312 : n = 0;
313 0 : while (!(BA0READ4(sc, CS4280_ACSTS) & ACSTS_VSTS)) {
314 0 : delay(1);
315 0 : while (++n > 1000) {
316 0 : printf("%s: AC97 read fail (VSTS==0) for add=0x%02x\n",
317 0 : sc->sc_dev.dv_xname, add);
318 0 : return (1);
319 : }
320 : }
321 0 : *data = BA0READ4(sc, CS4280_ACSDA);
322 : DPRINTFN(5,("data=0x%04x\n", *data));
323 0 : return (0);
324 0 : }
325 :
326 : int
327 0 : cs4280_write_codec(void *sc_, u_int8_t add, u_int16_t data)
328 : {
329 0 : struct cs4280_softc *sc = sc_;
330 :
331 : DPRINTFN(5,("write_codec: add=0x%02x data=0x%04x\n", add, data));
332 0 : BA0WRITE4(sc, CS4280_ACCAD, add);
333 0 : BA0WRITE4(sc, CS4280_ACCDA, data);
334 0 : BA0WRITE4(sc, CS4280_ACCTL,
335 : ACCTL_RSTN | ACCTL_ESYN | ACCTL_VFRM | ACCTL_DCV );
336 :
337 0 : if (cs4280_src_wait(sc) < 0) {
338 0 : printf("%s: AC97 write fail (DCV!=0) for add=0x%02x data="
339 0 : "0x%04x\n", sc->sc_dev.dv_xname, add, data);
340 0 : return (1);
341 : }
342 0 : return (0);
343 0 : }
344 :
345 : int
346 0 : cs4280_src_wait(struct cs4280_softc *sc)
347 : {
348 : int n;
349 :
350 : n = 0;
351 0 : while ((BA0READ4(sc, CS4280_ACCTL) & ACCTL_DCV)) {
352 0 : delay(1000);
353 0 : if (++n > 1000)
354 0 : return (-1);
355 : }
356 0 : return (0);
357 0 : }
358 :
359 :
360 : void
361 0 : cs4280_set_adc_rate(struct cs4280_softc *sc, int rate)
362 : {
363 : /* calculate capture rate:
364 : *
365 : * capture_coefficient_increment = -round(rate*128*65536/48000;
366 : * capture_phase_increment = floor(48000*65536*1024/rate);
367 : * cx = round(48000*65536*1024 - capture_phase_increment*rate);
368 : * cy = floor(cx/200);
369 : * capture_sample_rate_correction = cx - 200*cy;
370 : * capture_delay = ceil(24*48000/rate);
371 : * capture_num_triplets = floor(65536*rate/24000);
372 : * capture_group_length = 24000/GCD(rate, 24000);
373 : * where GCD means "Greatest Common Divisor".
374 : *
375 : * capture_coefficient_increment, capture_phase_increment and
376 : * capture_num_triplets are 32-bit signed quantities.
377 : * capture_sample_rate_correction and capture_group_length are
378 : * 16-bit signed quantities.
379 : * capture_delay is a 14-bit unsigned quantity.
380 : */
381 : u_int32_t cci,cpi,cnt,cx,cy, tmp1;
382 : u_int16_t csrc, cgl, cdlay;
383 :
384 : /* XXX
385 : * Even though, embedded_audio_spec says capture rate range 11025 to
386 : * 48000, dhwiface.cpp says,
387 : *
388 : * "We can only decimate by up to a factor of 1/9th the hardware rate.
389 : * Return an error if an attempt is made to stray outside that limit."
390 : *
391 : * so assume range as 48000/9 to 48000
392 : */
393 :
394 0 : if (rate < 8000)
395 0 : rate = 8000;
396 0 : if (rate > 48000)
397 0 : rate = 48000;
398 :
399 0 : cx = rate << 16;
400 0 : cci = cx / 48000;
401 0 : cx -= cci * 48000;
402 0 : cx <<= 7;
403 0 : cci <<= 7;
404 0 : cci += cx / 48000;
405 0 : cci = - cci;
406 :
407 : cx = 48000 << 16;
408 0 : cpi = cx / rate;
409 0 : cx -= cpi * rate;
410 0 : cx <<= 10;
411 0 : cpi <<= 10;
412 0 : cy = cx / rate;
413 0 : cpi += cy;
414 0 : cx -= cy * rate;
415 :
416 0 : cy = cx / 200;
417 0 : csrc = cx - 200*cy;
418 :
419 0 : cdlay = ((48000 * 24) + rate - 1) / rate;
420 : #if 0
421 : cdlay &= 0x3fff; /* make sure cdlay is 14-bit */
422 : #endif
423 :
424 : cnt = rate << 16;
425 0 : cnt /= 24000;
426 :
427 : cgl = 1;
428 0 : for (tmp1 = 2; tmp1 <= 64; tmp1 *= 2) {
429 0 : if (((rate / tmp1) * tmp1) != rate)
430 0 : cgl *= 2;
431 : }
432 0 : if (((rate / 3) * 3) != rate)
433 0 : cgl *= 3;
434 0 : for (tmp1 = 5; tmp1 <= 125; tmp1 *= 5) {
435 0 : if (((rate / tmp1) * tmp1) != rate)
436 0 : cgl *= 5;
437 : }
438 : #if 0
439 : /* XXX what manual says */
440 : tmp1 = BA1READ4(sc, CS4280_CSRC) & ~CSRC_MASK;
441 : tmp1 |= csrc<<16;
442 : BA1WRITE4(sc, CS4280_CSRC, tmp1);
443 : #else
444 : /* suggested by cs461x.c (ALSA driver) */
445 0 : BA1WRITE4(sc, CS4280_CSRC, CS4280_MK_CSRC(csrc, cy));
446 : #endif
447 :
448 : #if 0
449 : /* I am confused. The sample rate calculation section says
450 : * cci *is* 32-bit signed quantity but in the parameter description
451 : * section, CCI only assigned 16bit.
452 : * I believe size of the variable.
453 : */
454 : tmp1 = BA1READ4(sc, CS4280_CCI) & ~CCI_MASK;
455 : tmp1 |= cci<<16;
456 : BA1WRITE4(sc, CS4280_CCI, tmp1);
457 : #else
458 0 : BA1WRITE4(sc, CS4280_CCI, cci);
459 : #endif
460 :
461 0 : tmp1 = BA1READ4(sc, CS4280_CD) & ~CD_MASK;
462 0 : tmp1 |= cdlay <<18;
463 0 : BA1WRITE4(sc, CS4280_CD, tmp1);
464 :
465 0 : BA1WRITE4(sc, CS4280_CPI, cpi);
466 :
467 0 : tmp1 = BA1READ4(sc, CS4280_CGL) & ~CGL_MASK;
468 0 : tmp1 |= cgl;
469 0 : BA1WRITE4(sc, CS4280_CGL, tmp1);
470 :
471 0 : BA1WRITE4(sc, CS4280_CNT, cnt);
472 :
473 0 : tmp1 = BA1READ4(sc, CS4280_CGC) & ~CGC_MASK;
474 0 : tmp1 |= cgl;
475 0 : BA1WRITE4(sc, CS4280_CGC, tmp1);
476 0 : }
477 :
478 : void
479 0 : cs4280_set_dac_rate(struct cs4280_softc *sc, int rate)
480 : {
481 : /*
482 : * playback rate may range from 8000Hz to 48000Hz
483 : *
484 : * play_phase_increment = floor(rate*65536*1024/48000)
485 : * px = round(rate*65536*1024 - play_phase_incremnt*48000)
486 : * py=floor(px/200)
487 : * play_sample_rate_correction = px - 200*py
488 : *
489 : * play_phase_increment is a 32bit signed quantity.
490 : * play_sample_rate_correction is a 16bit signed quantity.
491 : */
492 : int32_t ppi;
493 : int16_t psrc;
494 : u_int32_t px, py;
495 :
496 0 : if (rate < 8000)
497 0 : rate = 8000;
498 0 : if (rate > 48000)
499 0 : rate = 48000;
500 0 : px = rate << 16;
501 0 : ppi = px/48000;
502 0 : px -= ppi*48000;
503 0 : ppi <<= 10;
504 0 : px <<= 10;
505 0 : py = px / 48000;
506 0 : ppi += py;
507 0 : px -= py*48000;
508 0 : py = px/200;
509 0 : px -= py*200;
510 0 : psrc = px;
511 : #if 0
512 : /* what manual says */
513 : px = BA1READ4(sc, CS4280_PSRC) & ~PSRC_MASK;
514 : BA1WRITE4(sc, CS4280_PSRC,
515 : ( ((psrc<<16) & PSRC_MASK) | px ));
516 : #else
517 : /* suggested by cs461x.c (ALSA driver) */
518 0 : BA1WRITE4(sc, CS4280_PSRC, CS4280_MK_PSRC(psrc,py));
519 : #endif
520 0 : BA1WRITE4(sc, CS4280_PPI, ppi);
521 0 : }
522 :
523 : void
524 0 : cs4280_attachhook(struct device *self)
525 : {
526 0 : struct cs4280_softc *sc = (struct cs4280_softc *)self;
527 0 : mixer_ctrl_t ctl;
528 :
529 : /* Initialization */
530 0 : if (cs4280_init2(sc, 1) != 0)
531 0 : return;
532 :
533 0 : printf("%s: firmware loaded\n", sc->sc_dev.dv_xname);
534 :
535 : /* Turn mute off of DAC, CD and master volumes by default */
536 0 : ctl.type = AUDIO_MIXER_ENUM;
537 0 : ctl.un.ord = 0; /* off */
538 :
539 0 : ctl.dev = cs4280_get_portnum_by_name(sc, AudioCoutputs,
540 : AudioNmaster, AudioNmute);
541 0 : cs4280_mixer_set_port(sc, &ctl);
542 :
543 0 : ctl.dev = cs4280_get_portnum_by_name(sc, AudioCinputs,
544 : AudioNdac, AudioNmute);
545 0 : cs4280_mixer_set_port(sc, &ctl);
546 :
547 0 : ctl.dev = cs4280_get_portnum_by_name(sc, AudioCinputs,
548 : AudioNcd, AudioNmute);
549 0 : cs4280_mixer_set_port(sc, &ctl);
550 :
551 0 : audio_attach_mi(&cs4280_hw_if, sc, &sc->sc_dev);
552 :
553 : #if NMIDI > 0
554 : midi_attach_mi(&cs4280_midi_hw_if, sc, &sc->sc_dev);
555 : #endif
556 0 : }
557 :
558 : void
559 0 : cs4280_attach(struct device *parent, struct device *self, void *aux)
560 : {
561 0 : struct cs4280_softc *sc = (struct cs4280_softc *) self;
562 0 : struct pci_attach_args *pa = (struct pci_attach_args *) aux;
563 0 : pci_chipset_tag_t pc = pa->pa_pc;
564 : char const *intrstr;
565 0 : pci_intr_handle_t ih;
566 : u_int32_t mem;
567 :
568 : /* Map I/O register */
569 0 : if (pci_mapreg_map(pa, CSCC_PCI_BA0,
570 : PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
571 0 : &sc->ba0t, &sc->ba0h, NULL, NULL, 0)) {
572 0 : printf(": can't map BA0 space\n");
573 0 : return;
574 : }
575 0 : if (pci_mapreg_map(pa, CSCC_PCI_BA1,
576 : PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
577 0 : &sc->ba1t, &sc->ba1h, NULL, NULL, 0)) {
578 0 : printf(": can't map BA1 space\n");
579 0 : return;
580 : }
581 :
582 0 : sc->sc_dmatag = pa->pa_dmat;
583 :
584 : /* Get out of power save mode if needed. */
585 0 : pci_set_powerstate(pc, pa->pa_tag, PCI_PMCSR_STATE_D0);
586 :
587 : /* LATENCY_TIMER setting */
588 0 : mem = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG);
589 0 : if ( PCI_LATTIMER(mem) < 32 ) {
590 0 : mem &= 0xffff00ff;
591 0 : mem |= 0x00002000;
592 0 : pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG, mem);
593 0 : }
594 :
595 : /* Map and establish the interrupt. */
596 0 : if (pci_intr_map(pa, &ih)) {
597 0 : printf(": couldn't map interrupt\n");
598 0 : return;
599 : }
600 0 : intrstr = pci_intr_string(pc, ih);
601 :
602 0 : sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO | IPL_MPSAFE,
603 0 : cs4280_intr, sc, sc->sc_dev.dv_xname);
604 0 : if (sc->sc_ih == NULL) {
605 0 : printf(": couldn't establish interrupt");
606 0 : if (intrstr != NULL)
607 0 : printf(" at %s", intrstr);
608 0 : printf("\n");
609 0 : return;
610 : }
611 0 : printf(": %s\n", intrstr);
612 :
613 : /* Initialization */
614 0 : if (cs4280_init(sc, 1) != 0)
615 0 : return;
616 :
617 0 : config_mountroot(self, cs4280_attachhook);
618 :
619 : /* AC 97 attachement */
620 0 : sc->host_if.arg = sc;
621 0 : sc->host_if.attach = cs4280_attach_codec;
622 0 : sc->host_if.read = cs4280_read_codec;
623 0 : sc->host_if.write = cs4280_write_codec;
624 0 : sc->host_if.reset = cs4280_reset_codec;
625 :
626 0 : if (ac97_attach(&sc->host_if) != 0) {
627 0 : printf("%s: ac97_attach failed\n", sc->sc_dev.dv_xname);
628 0 : return;
629 : }
630 0 : }
631 :
632 : int
633 0 : cs4280_intr(void *p)
634 : {
635 : /*
636 : * XXX
637 : *
638 : * Since CS4280 has only 4kB dma buffer and
639 : * interrupt occurs every 2kB block, I create dummy buffer
640 : * which returns to audio driver and actual dma buffer
641 : * using in DMA transfer.
642 : *
643 : *
644 : * ring buffer in audio.c is pointed by BUFADDR
645 : * <------ ring buffer size == 64kB ------>
646 : * <-----> blksize == 2048*(sc->sc_[pr]count) kB
647 : * |= = = =|= = = =|= = = =|= = = =|= = = =|
648 : * | | | | | | <- call audio_intp every
649 : * sc->sc_[pr]_count time.
650 : *
651 : * actual dma buffer is pointed by KERNADDR
652 : * <-> dma buffer size = 4kB
653 : * |= =|
654 : *
655 : *
656 : */
657 0 : struct cs4280_softc *sc = p;
658 : u_int32_t intr, mem;
659 : char * empty_dma;
660 : int handled = 0;
661 :
662 0 : mtx_enter(&audio_lock);
663 : /* grab interrupt register then clear it */
664 0 : intr = BA0READ4(sc, CS4280_HISR);
665 0 : BA0WRITE4(sc, CS4280_HICR, HICR_CHGM | HICR_IEV);
666 :
667 : /* Playback Interrupt */
668 0 : if (intr & HISR_PINT) {
669 : handled = 1;
670 0 : mem = BA1READ4(sc, CS4280_PFIE);
671 0 : BA1WRITE4(sc, CS4280_PFIE, (mem & ~PFIE_PI_MASK) | PFIE_PI_DISABLE);
672 0 : if (sc->sc_pintr) {
673 0 : if ((sc->sc_pi%sc->sc_pcount) == 0)
674 0 : sc->sc_pintr(sc->sc_parg);
675 : } else {
676 0 : printf("unexpected play intr\n");
677 : }
678 : /* copy buffer */
679 0 : ++sc->sc_pi;
680 0 : empty_dma = sc->sc_pdma->addr;
681 0 : if (sc->sc_pi&1)
682 0 : empty_dma += CS4280_ICHUNK;
683 0 : memcpy(empty_dma, sc->sc_pn, CS4280_ICHUNK);
684 0 : sc->sc_pn += CS4280_ICHUNK;
685 0 : if (sc->sc_pn >= sc->sc_pe)
686 0 : sc->sc_pn = sc->sc_ps;
687 0 : BA1WRITE4(sc, CS4280_PFIE, mem);
688 0 : }
689 : /* Capture Interrupt */
690 0 : if (intr & HISR_CINT) {
691 : int i;
692 : int16_t rdata;
693 :
694 : handled = 1;
695 0 : mem = BA1READ4(sc, CS4280_CIE);
696 0 : BA1WRITE4(sc, CS4280_CIE, (mem & ~CIE_CI_MASK) | CIE_CI_DISABLE);
697 0 : ++sc->sc_ri;
698 0 : empty_dma = sc->sc_rdma->addr;
699 0 : if ((sc->sc_ri&1) == 0)
700 0 : empty_dma += CS4280_ICHUNK;
701 :
702 : /*
703 : * XXX
704 : * I think this audio data conversion should be
705 : * happened in upper layer, but I put this here
706 : * since there is no conversion function available.
707 : */
708 0 : switch(sc->sc_rparam) {
709 : case CF_16BIT_STEREO:
710 : /* just copy it */
711 0 : memcpy(sc->sc_rn, empty_dma, CS4280_ICHUNK);
712 0 : sc->sc_rn += CS4280_ICHUNK;
713 0 : break;
714 : case CF_16BIT_MONO:
715 0 : for (i = 0; i < 512; i++) {
716 0 : rdata = *((int16_t *)empty_dma)>>1;
717 0 : empty_dma += 2;
718 0 : rdata += *((int16_t *)empty_dma)>>1;
719 0 : empty_dma += 2;
720 0 : *((int16_t *)sc->sc_rn) = rdata;
721 0 : sc->sc_rn += 2;
722 : }
723 : break;
724 : case CF_8BIT_STEREO:
725 0 : for (i = 0; i < 512; i++) {
726 0 : rdata = *((int16_t*)empty_dma);
727 0 : empty_dma += 2;
728 0 : *sc->sc_rn++ = rdata >> 8;
729 0 : rdata = *((int16_t*)empty_dma);
730 0 : empty_dma += 2;
731 0 : *sc->sc_rn++ = rdata >> 8;
732 : }
733 : break;
734 : case CF_8BIT_MONO:
735 0 : for (i = 0; i < 512; i++) {
736 0 : rdata = *((int16_t*)empty_dma) >>1;
737 0 : empty_dma += 2;
738 0 : rdata += *((int16_t*)empty_dma) >>1;
739 0 : empty_dma += 2;
740 0 : *sc->sc_rn++ = rdata >>8;
741 : }
742 : break;
743 : default:
744 : /* Should not reach here */
745 0 : printf("unknown sc->sc_rparam: %d\n", sc->sc_rparam);
746 0 : }
747 0 : if (sc->sc_rn >= sc->sc_re)
748 0 : sc->sc_rn = sc->sc_rs;
749 0 : BA1WRITE4(sc, CS4280_CIE, mem);
750 0 : if (sc->sc_rintr) {
751 0 : if ((sc->sc_ri%(sc->sc_rcount)) == 0)
752 0 : sc->sc_rintr(sc->sc_rarg);
753 : } else {
754 0 : printf("unexpected record intr\n");
755 : }
756 0 : }
757 :
758 : #if NMIDI > 0
759 : /* Midi port Interrupt */
760 : if (intr & HISR_MIDI) {
761 : int data;
762 :
763 : handled = 1;
764 : DPRINTF(("i: %d: ",
765 : BA0READ4(sc, CS4280_MIDSR)));
766 : /* Read the received data */
767 : while ((sc->sc_iintr != NULL) &&
768 : ((BA0READ4(sc, CS4280_MIDSR) & MIDSR_RBE) == 0)) {
769 : data = BA0READ4(sc, CS4280_MIDRP) & MIDRP_MASK;
770 : DPRINTF(("r:%x\n",data));
771 : sc->sc_iintr(sc->sc_arg, data);
772 : }
773 :
774 : /* Write the data */
775 : #if 1
776 : /* XXX:
777 : * It seems "Transmit Buffer Full" never activate until EOI
778 : * is delivered. Shall I throw EOI top of this routine ?
779 : */
780 : if ((BA0READ4(sc, CS4280_MIDSR) & MIDSR_TBF) == 0) {
781 : DPRINTF(("w: "));
782 : if (sc->sc_ointr != NULL)
783 : sc->sc_ointr(sc->sc_arg);
784 : }
785 : #else
786 : while ((sc->sc_ointr != NULL) &&
787 : ((BA0READ4(sc, CS4280_MIDSR) & MIDSR_TBF) == 0)) {
788 : DPRINTF(("w: "));
789 : sc->sc_ointr(sc->sc_arg);
790 : }
791 : #endif
792 : DPRINTF(("\n"));
793 : }
794 : #endif
795 0 : mtx_leave(&audio_lock);
796 0 : return handled;
797 : }
798 :
799 :
800 : /* Download Proceessor Code and Data image */
801 :
802 : int
803 0 : cs4280_download(struct cs4280_softc *sc, const u_int32_t *src, u_int32_t offset,
804 : u_int32_t len)
805 : {
806 : u_int32_t ctr;
807 :
808 : #ifdef CS4280_DEBUG
809 : u_int32_t con, data;
810 : u_int8_t c0,c1,c2,c3;
811 : #endif
812 0 : if ((offset&3) || (len&3))
813 0 : return (-1);
814 :
815 0 : len /= sizeof(u_int32_t);
816 0 : for (ctr = 0; ctr < len; ctr++) {
817 : /* XXX:
818 : * I cannot confirm this is the right thing or not
819 : * on BIG-ENDIAN machines.
820 : */
821 0 : BA1WRITE4(sc, offset+ctr*4, htole32(*(src+ctr)));
822 : #ifdef CS4280_DEBUG
823 : data = htole32(*(src+ctr));
824 : c0 = bus_space_read_1(sc->ba1t, sc->ba1h, offset+ctr*4+0);
825 : c1 = bus_space_read_1(sc->ba1t, sc->ba1h, offset+ctr*4+1);
826 : c2 = bus_space_read_1(sc->ba1t, sc->ba1h, offset+ctr*4+2);
827 : c3 = bus_space_read_1(sc->ba1t, sc->ba1h, offset+ctr*4+3);
828 : con = ( (c3<<24) | (c2<<16) | (c1<<8) | c0 );
829 : if (data != con ) {
830 : printf("0x%06x: write=0x%08x read=0x%08x\n",
831 : offset+ctr*4, data, con);
832 : return (-1);
833 : }
834 : #endif
835 : }
836 0 : return (0);
837 0 : }
838 :
839 : struct BA1struct *BA1Struct;
840 :
841 : int
842 0 : cs4280_download_image(struct cs4280_softc *sc)
843 : {
844 : int idx, err = 0;
845 : u_int32_t offset = 0;
846 : static u_char *cs4280_firmware;
847 : static size_t cs4280_firmwarelen;
848 :
849 0 : if (cs4280_firmware == NULL) {
850 0 : err = loadfirmware("cs4280", &cs4280_firmware,
851 : &cs4280_firmwarelen);
852 0 : if (err)
853 0 : return (err);
854 : }
855 :
856 0 : BA1Struct = (struct BA1struct *)cs4280_firmware;
857 :
858 0 : for (idx = 0; idx < BA1_MEMORY_COUNT; ++idx) {
859 0 : err = cs4280_download(sc, &BA1Struct->map[offset],
860 0 : BA1Struct->memory[idx].offset, BA1Struct->memory[idx].size);
861 0 : if (err != 0) {
862 0 : printf("%s: load_image failed at %d\n",
863 0 : sc->sc_dev.dv_xname, idx);
864 0 : return (-1);
865 : }
866 0 : offset += BA1Struct->memory[idx].size / sizeof(u_int32_t);
867 : }
868 0 : return (err);
869 0 : }
870 :
871 : #ifdef CS4280_DEBUG
872 : int
873 : cs4280_checkimage(struct cs4280_softc *sc, u_int32_t *src, u_int32_t offset,
874 : u_int32_t len)
875 : {
876 : u_int32_t ctr, data;
877 : int err = 0;
878 :
879 : if ((offset&3) || (len&3))
880 : return -1;
881 :
882 : len /= sizeof(u_int32_t);
883 : for (ctr = 0; ctr < len; ctr++) {
884 : /* I cannot confirm this is the right thing
885 : * on BIG-ENDIAN machines
886 : */
887 : data = BA1READ4(sc, offset+ctr*4);
888 : if (data != htole32(*(src+ctr))) {
889 : printf("0x%06x: 0x%08x(0x%08x)\n",
890 : offset+ctr*4, data, *(src+ctr));
891 : *(src+ctr) = data;
892 : ++err;
893 : }
894 : }
895 : return (err);
896 : }
897 :
898 : int
899 : cs4280_check_images(struct cs4280_softc *sc)
900 : {
901 : int idx, err;
902 : u_int32_t offset = 0;
903 :
904 : err = 0;
905 : /*for (idx=0; idx < BA1_MEMORY_COUNT; ++idx) { */
906 : for (idx = 0; idx < 1; ++idx) {
907 : err = cs4280_checkimage(sc, &BA1Struct->map[offset],
908 : BA1Struct->memory[idx].offset,
909 : BA1Struct->memory[idx].size);
910 : if (err != 0) {
911 : printf("%s: check_image failed at %d\n",
912 : sc->sc_dev.dv_xname, idx);
913 : }
914 : offset += BA1Struct->memory[idx].size / sizeof(u_int32_t);
915 : }
916 : return (err);
917 : }
918 :
919 : #endif
920 :
921 : int
922 0 : cs4280_attach_codec(void *sc_, struct ac97_codec_if *codec_if)
923 : {
924 0 : struct cs4280_softc *sc = sc_;
925 :
926 0 : sc->codec_if = codec_if;
927 0 : return (0);
928 : }
929 :
930 : void
931 0 : cs4280_reset_codec(void *sc_)
932 : {
933 0 : struct cs4280_softc *sc = sc_;
934 : int n;
935 :
936 : /* Reset codec */
937 0 : BA0WRITE4(sc, CS4280_ACCTL, 0);
938 0 : delay(100); /* delay 100us */
939 0 : BA0WRITE4(sc, CS4280_ACCTL, ACCTL_RSTN);
940 :
941 : /*
942 : * It looks like we do the following procedure, too
943 : */
944 :
945 : /* Enable AC-link sync generation */
946 0 : BA0WRITE4(sc, CS4280_ACCTL, ACCTL_ESYN | ACCTL_RSTN);
947 0 : delay(50*1000); /* XXX delay 50ms */
948 :
949 : /* Assert valid frame signal */
950 0 : BA0WRITE4(sc, CS4280_ACCTL, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
951 :
952 : /* Wait for valid AC97 input slot */
953 : n = 0;
954 0 : while (BA0READ4(sc, CS4280_ACISV) != (ACISV_ISV3 | ACISV_ISV4)) {
955 0 : delay(1000);
956 0 : if (++n > 1000) {
957 0 : printf("reset_codec: AC97 inputs slot ready timeout\n");
958 0 : return;
959 : }
960 : }
961 0 : }
962 :
963 :
964 : /* Processor Soft Reset */
965 : void
966 0 : cs4280_reset(void *sc_)
967 : {
968 0 : struct cs4280_softc *sc = sc_;
969 :
970 : /* Set RSTSP bit in SPCR (also clear RUN, RUNFR, and DRQEN) */
971 0 : BA1WRITE4(sc, CS4280_SPCR, SPCR_RSTSP);
972 0 : delay(100);
973 : /* Clear RSTSP bit in SPCR */
974 0 : BA1WRITE4(sc, CS4280_SPCR, 0);
975 : /* enable DMA reqest */
976 0 : BA1WRITE4(sc, CS4280_SPCR, SPCR_DRQEN);
977 0 : }
978 :
979 : int
980 0 : cs4280_open(void *addr, int flags)
981 : {
982 0 : return (0);
983 : }
984 :
985 : void
986 0 : cs4280_close(void *addr)
987 : {
988 0 : struct cs4280_softc *sc = addr;
989 :
990 : /* XXX: already called in audio_close() */
991 0 : cs4280_halt_output(sc);
992 0 : cs4280_halt_input(sc);
993 :
994 0 : sc->sc_pintr = 0;
995 0 : sc->sc_rintr = 0;
996 0 : }
997 :
998 : int
999 0 : cs4280_set_params(void *addr, int setmode, int usemode,
1000 : struct audio_params *play, struct audio_params *rec)
1001 : {
1002 0 : struct cs4280_softc *sc = addr;
1003 : struct audio_params *p;
1004 : int mode;
1005 :
1006 0 : for (mode = AUMODE_RECORD; mode != -1;
1007 0 : mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1 ) {
1008 0 : if ((setmode & mode) == 0)
1009 : continue;
1010 :
1011 0 : p = mode == AUMODE_PLAY ? play : rec;
1012 : if (p == play) {
1013 : DPRINTFN(5,("play: sample=%ld precision=%d channels=%d\n",
1014 : p->sample_rate, p->precision, p->channels));
1015 : } else {
1016 : DPRINTFN(5,("rec: sample=%ld precision=%d channels=%d\n",
1017 : p->sample_rate, p->precision, p->channels));
1018 : }
1019 : /* play back data format may be 8- or 16-bit and
1020 : * either stereo or mono.
1021 : * playback rate may range from 8000Hz to 48000Hz
1022 : *
1023 : * capture data format must be 16bit stereo
1024 : * and sample rate range from 11025Hz to 48000Hz.
1025 : *
1026 : * XXX: it looks like to work with 8000Hz,
1027 : * although data sheets say lower limit is
1028 : * 11025 Hz.
1029 : */
1030 0 : if (p->sample_rate < 8000)
1031 0 : p->sample_rate = 8000;
1032 0 : if (p->sample_rate > 48000)
1033 0 : p->sample_rate = 48000;
1034 0 : if (p->precision > 16)
1035 0 : p->precision = 16;
1036 0 : if (p->channels > 2)
1037 0 : p->channels = 2;
1038 :
1039 : /* capturing data is slinear */
1040 0 : switch (p->encoding) {
1041 : case AUDIO_ENCODING_SLINEAR_LE:
1042 : break;
1043 : default:
1044 0 : return (EINVAL);
1045 : }
1046 0 : p->bps = AUDIO_BPS(p->precision);
1047 0 : p->msb = 1;
1048 0 : }
1049 :
1050 : /* set sample rate */
1051 0 : cs4280_set_dac_rate(sc, play->sample_rate);
1052 0 : cs4280_set_adc_rate(sc, rec->sample_rate);
1053 0 : return (0);
1054 0 : }
1055 :
1056 : int
1057 0 : cs4280_round_blocksize(void *hdl, int blk)
1058 : {
1059 0 : return (blk < CS4280_ICHUNK ? CS4280_ICHUNK : blk & -CS4280_ICHUNK);
1060 : }
1061 :
1062 : int
1063 0 : cs4280_get_props(void *hdl)
1064 : {
1065 0 : return (AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX);
1066 : #ifdef notyet
1067 : /* XXX
1068 : * How can I mmap ?
1069 : */
1070 : AUDIO_PROP_MMAP
1071 : #endif
1072 :
1073 : }
1074 :
1075 : int
1076 0 : cs4280_mixer_get_port(void *addr, mixer_ctrl_t *cp)
1077 : {
1078 0 : struct cs4280_softc *sc = addr;
1079 :
1080 0 : return (sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp));
1081 : }
1082 :
1083 : int
1084 0 : cs4280_query_devinfo(void *addr, mixer_devinfo_t *dip)
1085 : {
1086 0 : struct cs4280_softc *sc = addr;
1087 :
1088 0 : return (sc->codec_if->vtbl->query_devinfo(sc->codec_if, dip));
1089 : }
1090 :
1091 : int
1092 0 : cs4280_get_portnum_by_name(struct cs4280_softc *sc, char *class, char *device,
1093 : char *qualifier)
1094 : {
1095 0 : return (sc->codec_if->vtbl->get_portnum_by_name(sc->codec_if, class,
1096 : device, qualifier));
1097 : }
1098 :
1099 : int
1100 0 : cs4280_halt_output(void *addr)
1101 : {
1102 0 : struct cs4280_softc *sc = addr;
1103 : u_int32_t mem;
1104 :
1105 0 : mtx_enter(&audio_lock);
1106 0 : mem = BA1READ4(sc, CS4280_PCTL);
1107 0 : BA1WRITE4(sc, CS4280_PCTL, mem & ~PCTL_MASK);
1108 : #ifdef DIAGNOSTIC
1109 0 : sc->sc_prun = 0;
1110 : #endif
1111 0 : mtx_leave(&audio_lock);
1112 0 : return (0);
1113 : }
1114 :
1115 : int
1116 0 : cs4280_halt_input(void *addr)
1117 : {
1118 0 : struct cs4280_softc *sc = addr;
1119 : u_int32_t mem;
1120 :
1121 0 : mtx_enter(&audio_lock);
1122 0 : mem = BA1READ4(sc, CS4280_CCTL);
1123 0 : BA1WRITE4(sc, CS4280_CCTL, mem & ~CCTL_MASK);
1124 : #ifdef DIAGNOSTIC
1125 0 : sc->sc_rrun = 0;
1126 : #endif
1127 0 : mtx_leave(&audio_lock);
1128 0 : return (0);
1129 : }
1130 :
1131 : int
1132 0 : cs4280_mixer_set_port(void *addr, mixer_ctrl_t *cp)
1133 : {
1134 0 : struct cs4280_softc *sc = addr;
1135 : int val;
1136 :
1137 0 : val = sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp);
1138 : DPRINTFN(3,("mixer_set_port: val=%d\n", val));
1139 0 : return (val);
1140 : }
1141 :
1142 :
1143 : int
1144 0 : cs4280_freemem(struct cs4280_softc *sc, struct cs4280_dma *p)
1145 : {
1146 0 : bus_dmamap_unload(sc->sc_dmatag, p->map);
1147 0 : bus_dmamap_destroy(sc->sc_dmatag, p->map);
1148 0 : bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
1149 0 : bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
1150 0 : return (0);
1151 : }
1152 :
1153 : int
1154 0 : cs4280_allocmem(struct cs4280_softc *sc, size_t size, size_t align,
1155 : struct cs4280_dma *p)
1156 : {
1157 : int error;
1158 :
1159 : /* XXX */
1160 0 : p->size = size;
1161 0 : error = bus_dmamem_alloc(sc->sc_dmatag, p->size, align, 0,
1162 : p->segs, sizeof(p->segs)/sizeof(p->segs[0]),
1163 : &p->nsegs, BUS_DMA_NOWAIT);
1164 0 : if (error) {
1165 0 : printf("%s: unable to allocate dma, error=%d\n",
1166 0 : sc->sc_dev.dv_xname, error);
1167 0 : return (error);
1168 : }
1169 :
1170 0 : error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size,
1171 : &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
1172 0 : if (error) {
1173 0 : printf("%s: unable to map dma, error=%d\n",
1174 0 : sc->sc_dev.dv_xname, error);
1175 0 : goto free;
1176 : }
1177 :
1178 0 : error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size,
1179 : 0, BUS_DMA_NOWAIT, &p->map);
1180 0 : if (error) {
1181 0 : printf("%s: unable to create dma map, error=%d\n",
1182 0 : sc->sc_dev.dv_xname, error);
1183 0 : goto unmap;
1184 : }
1185 :
1186 0 : error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL,
1187 : BUS_DMA_NOWAIT);
1188 0 : if (error) {
1189 0 : printf("%s: unable to load dma map, error=%d\n",
1190 0 : sc->sc_dev.dv_xname, error);
1191 : goto destroy;
1192 : }
1193 0 : return (0);
1194 :
1195 : destroy:
1196 0 : bus_dmamap_destroy(sc->sc_dmatag, p->map);
1197 : unmap:
1198 0 : bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
1199 : free:
1200 0 : bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
1201 0 : return (error);
1202 0 : }
1203 :
1204 :
1205 : void *
1206 0 : cs4280_malloc(void *addr, int direction, size_t size, int pool, int flags)
1207 : {
1208 0 : struct cs4280_softc *sc = addr;
1209 : struct cs4280_dma *p;
1210 : caddr_t q;
1211 : int error;
1212 :
1213 : DPRINTFN(5,("cs4280_malloc: size=%d pool=%d flags=%d\n", size, pool, flags));
1214 0 : q = malloc(size, pool, flags);
1215 0 : if (!q)
1216 0 : return (0);
1217 0 : p = malloc(sizeof(*p), pool, flags);
1218 0 : if (!p) {
1219 0 : free(q,pool, 0);
1220 0 : return (0);
1221 : }
1222 : /*
1223 : * cs4280 has fixed 4kB buffer
1224 : */
1225 0 : error = cs4280_allocmem(sc, CS4280_DCHUNK, CS4280_DALIGN, p);
1226 :
1227 0 : if (error) {
1228 0 : free(q, pool, 0);
1229 0 : free(p, pool, 0);
1230 0 : return (0);
1231 : }
1232 :
1233 0 : p->next = sc->sc_dmas;
1234 0 : sc->sc_dmas = p;
1235 0 : p->dum = q; /* return to audio driver */
1236 :
1237 0 : return (p->dum);
1238 0 : }
1239 :
1240 : void
1241 0 : cs4280_free(void *addr, void *ptr, int pool)
1242 : {
1243 0 : struct cs4280_softc *sc = addr;
1244 : struct cs4280_dma **pp, *p;
1245 :
1246 0 : for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) {
1247 0 : if (BUFADDR(p) == ptr) {
1248 0 : cs4280_freemem(sc, p);
1249 0 : *pp = p->next;
1250 0 : free(p->dum, pool, 0);
1251 0 : free(p, pool, 0);
1252 0 : return;
1253 : }
1254 : }
1255 0 : }
1256 :
1257 : int
1258 0 : cs4280_trigger_output(void *addr, void *start, void *end, int blksize,
1259 : void (*intr)(void *), void *arg, struct audio_params *param)
1260 : {
1261 0 : struct cs4280_softc *sc = addr;
1262 : u_int32_t pfie, pctl, mem, pdtc;
1263 : struct cs4280_dma *p;
1264 :
1265 : #ifdef DIAGNOSTIC
1266 0 : if (sc->sc_prun)
1267 0 : printf("cs4280_trigger_output: already running\n");
1268 0 : sc->sc_prun = 1;
1269 : #endif
1270 : DPRINTF(("cs4280_trigger_output: sc=%p start=%p end=%p "
1271 : "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
1272 0 : sc->sc_pintr = intr;
1273 0 : sc->sc_parg = arg;
1274 :
1275 : /* stop playback DMA */
1276 0 : mem = BA1READ4(sc, CS4280_PCTL);
1277 0 : BA1WRITE4(sc, CS4280_PCTL, mem & ~PCTL_MASK);
1278 :
1279 : /* setup PDTC */
1280 0 : pdtc = BA1READ4(sc, CS4280_PDTC);
1281 0 : pdtc &= ~PDTC_MASK;
1282 0 : pdtc |= CS4280_MK_PDTC(param->precision * param->channels);
1283 0 : BA1WRITE4(sc, CS4280_PDTC, pdtc);
1284 :
1285 : DPRINTF(("param: precision=%d channels=%d encoding=%d\n",
1286 : param->precision, param->channels,
1287 : param->encoding));
1288 0 : for (p = sc->sc_dmas; p != NULL && BUFADDR(p) != start; p = p->next)
1289 : ;
1290 0 : if (p == NULL) {
1291 0 : printf("cs4280_trigger_output: bad addr %p\n", start);
1292 0 : return (EINVAL);
1293 : }
1294 0 : if (DMAADDR(p) % CS4280_DALIGN != 0 ) {
1295 0 : printf("cs4280_trigger_output: DMAADDR(p)=0x%lx does not start"
1296 : "4kB align\n", DMAADDR(p));
1297 0 : return (EINVAL);
1298 : }
1299 :
1300 0 : sc->sc_pcount = blksize / CS4280_ICHUNK; /* CS4280_ICHUNK is fixed hardware blksize*/
1301 0 : sc->sc_ps = (char *)start;
1302 0 : sc->sc_pe = (char *)end;
1303 0 : sc->sc_pdma = p;
1304 0 : sc->sc_pbuf = KERNADDR(p);
1305 0 : sc->sc_pi = 0;
1306 0 : sc->sc_pn = sc->sc_ps;
1307 0 : if (blksize >= CS4280_DCHUNK) {
1308 0 : sc->sc_pn = sc->sc_ps + CS4280_DCHUNK;
1309 0 : memcpy(sc->sc_pbuf, start, CS4280_DCHUNK);
1310 0 : ++sc->sc_pi;
1311 0 : } else {
1312 0 : sc->sc_pn = sc->sc_ps + CS4280_ICHUNK;
1313 0 : memcpy(sc->sc_pbuf, start, CS4280_ICHUNK);
1314 : }
1315 :
1316 : /* initiate playback dma */
1317 0 : mtx_enter(&audio_lock);
1318 0 : BA1WRITE4(sc, CS4280_PBA, DMAADDR(p));
1319 :
1320 : /* set PFIE */
1321 0 : pfie = BA1READ4(sc, CS4280_PFIE) & ~PFIE_MASK;
1322 :
1323 0 : if (param->precision == 8)
1324 0 : pfie |= PFIE_8BIT;
1325 0 : if (param->channels == 1)
1326 0 : pfie |= PFIE_MONO;
1327 :
1328 0 : if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
1329 0 : param->encoding == AUDIO_ENCODING_SLINEAR_BE)
1330 0 : pfie |= PFIE_SWAPPED;
1331 0 : if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
1332 0 : param->encoding == AUDIO_ENCODING_ULINEAR_LE)
1333 0 : pfie |= PFIE_UNSIGNED;
1334 :
1335 0 : BA1WRITE4(sc, CS4280_PFIE, pfie | PFIE_PI_ENABLE);
1336 :
1337 0 : cs4280_set_dac_rate(sc, param->sample_rate);
1338 :
1339 0 : pctl = BA1READ4(sc, CS4280_PCTL) & ~PCTL_MASK;
1340 0 : pctl |= sc->pctl;
1341 0 : BA1WRITE4(sc, CS4280_PCTL, pctl);
1342 0 : mtx_leave(&audio_lock);
1343 0 : return (0);
1344 0 : }
1345 :
1346 : int
1347 0 : cs4280_trigger_input(void *addr, void *start, void *end, int blksize,
1348 : void (*intr)(void *), void *arg, struct audio_params *param)
1349 : {
1350 0 : struct cs4280_softc *sc = addr;
1351 : u_int32_t cctl, cie;
1352 : struct cs4280_dma *p;
1353 :
1354 : #ifdef DIAGNOSTIC
1355 0 : if (sc->sc_rrun)
1356 0 : printf("cs4280_trigger_input: already running\n");
1357 0 : sc->sc_rrun = 1;
1358 : #endif
1359 : DPRINTF(("cs4280_trigger_input: sc=%p start=%p end=%p "
1360 : "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
1361 0 : sc->sc_rintr = intr;
1362 0 : sc->sc_rarg = arg;
1363 :
1364 0 : sc->sc_ri = 0;
1365 0 : sc->sc_rcount = blksize / CS4280_ICHUNK; /* CS4280_ICHUNK is fixed hardware blksize*/
1366 0 : sc->sc_rs = (char *)start;
1367 0 : sc->sc_re = (char *)end;
1368 0 : sc->sc_rn = sc->sc_rs;
1369 :
1370 : /* setup format information for internal converter */
1371 0 : sc->sc_rparam = 0;
1372 0 : if (param->precision == 8) {
1373 0 : sc->sc_rparam += CF_8BIT;
1374 0 : sc->sc_rcount <<= 1;
1375 0 : }
1376 0 : if (param->channels == 1) {
1377 0 : sc->sc_rparam += CF_MONO;
1378 0 : sc->sc_rcount <<= 1;
1379 0 : }
1380 :
1381 : /* stop capture DMA */
1382 0 : cctl = BA1READ4(sc, CS4280_CCTL) & ~CCTL_MASK;
1383 0 : BA1WRITE4(sc, CS4280_CCTL, cctl);
1384 :
1385 0 : for (p = sc->sc_dmas; p && BUFADDR(p) != start; p = p->next)
1386 : ;
1387 0 : if (!p) {
1388 0 : printf("cs4280_trigger_input: bad addr %p\n", start);
1389 0 : return (EINVAL);
1390 : }
1391 0 : if (DMAADDR(p) % CS4280_DALIGN != 0) {
1392 0 : printf("cs4280_trigger_input: DMAADDR(p)=0x%lx does not start"
1393 : "4kB align\n", DMAADDR(p));
1394 0 : return (EINVAL);
1395 : }
1396 0 : sc->sc_rdma = p;
1397 0 : sc->sc_rbuf = KERNADDR(p);
1398 :
1399 : /* initiate capture dma */
1400 0 : mtx_enter(&audio_lock);
1401 0 : BA1WRITE4(sc, CS4280_CBA, DMAADDR(p));
1402 :
1403 : /* set CIE */
1404 0 : cie = BA1READ4(sc, CS4280_CIE) & ~CIE_CI_MASK;
1405 0 : BA1WRITE4(sc, CS4280_CIE, cie | CIE_CI_ENABLE);
1406 :
1407 0 : cs4280_set_adc_rate(sc, param->sample_rate);
1408 :
1409 0 : cctl = BA1READ4(sc, CS4280_CCTL) & ~CCTL_MASK;
1410 0 : cctl |= sc->cctl;
1411 0 : BA1WRITE4(sc, CS4280_CCTL, cctl);
1412 0 : mtx_leave(&audio_lock);
1413 0 : return (0);
1414 0 : }
1415 :
1416 :
1417 : int
1418 0 : cs4280_init(struct cs4280_softc *sc, int init)
1419 : {
1420 : int n;
1421 : u_int32_t mem;
1422 :
1423 : /* Start PLL out in known state */
1424 0 : BA0WRITE4(sc, CS4280_CLKCR1, 0);
1425 : /* Start serial ports out in known state */
1426 0 : BA0WRITE4(sc, CS4280_SERMC1, 0);
1427 :
1428 : /* Specify type of CODEC */
1429 : /* XXX should no be here */
1430 : #define SERACC_CODEC_TYPE_1_03
1431 : #ifdef SERACC_CODEC_TYPE_1_03
1432 0 : BA0WRITE4(sc, CS4280_SERACC, SERACC_HSP | SERACC_CTYPE_1_03); /* AC 97 1.03 */
1433 : #else
1434 : BA0WRITE4(sc, CS4280_SERACC, SERACC_HSP | SERACC_CTYPE_2_0); /* AC 97 2.0 */
1435 : #endif
1436 :
1437 : /* Reset codec */
1438 0 : BA0WRITE4(sc, CS4280_ACCTL, 0);
1439 0 : delay(100); /* delay 100us */
1440 0 : BA0WRITE4(sc, CS4280_ACCTL, ACCTL_RSTN);
1441 :
1442 : /* Enable AC-link sync generation */
1443 0 : BA0WRITE4(sc, CS4280_ACCTL, ACCTL_ESYN | ACCTL_RSTN);
1444 0 : delay(50*1000); /* delay 50ms */
1445 :
1446 : /* Set the serial port timing configuration */
1447 0 : BA0WRITE4(sc, CS4280_SERMC1, SERMC1_PTC_AC97);
1448 :
1449 : /* Setup clock control */
1450 0 : BA0WRITE4(sc, CS4280_PLLCC, PLLCC_CDR_STATE|PLLCC_LPF_STATE);
1451 0 : BA0WRITE4(sc, CS4280_PLLM, PLLM_STATE);
1452 0 : BA0WRITE4(sc, CS4280_CLKCR2, CLKCR2_PDIVS_8);
1453 :
1454 : /* Power up the PLL */
1455 0 : BA0WRITE4(sc, CS4280_CLKCR1, CLKCR1_PLLP);
1456 0 : delay(50*1000); /* delay 50ms */
1457 :
1458 : /* Turn on clock */
1459 0 : mem = BA0READ4(sc, CS4280_CLKCR1) | CLKCR1_SWCE;
1460 0 : BA0WRITE4(sc, CS4280_CLKCR1, mem);
1461 :
1462 : /* Set the serial port FIFO pointer to the
1463 : * first sample in FIFO. (not documented) */
1464 0 : cs4280_clear_fifos(sc);
1465 :
1466 : #if 0
1467 : /* Set the serial port FIFO pointer to the first sample in the FIFO */
1468 : BA0WRITE4(sc, CS4280_SERBSP, 0);
1469 : #endif
1470 :
1471 : /* Configure the serial port */
1472 0 : BA0WRITE4(sc, CS4280_SERC1, SERC1_SO1EN | SERC1_SO1F_AC97);
1473 0 : BA0WRITE4(sc, CS4280_SERC2, SERC2_SI1EN | SERC2_SI1F_AC97);
1474 0 : BA0WRITE4(sc, CS4280_SERMC1, SERMC1_MSPE | SERMC1_PTC_AC97);
1475 :
1476 : /* Wait for CODEC ready */
1477 : n = 0;
1478 0 : while ((BA0READ4(sc, CS4280_ACSTS) & ACSTS_CRDY) == 0) {
1479 0 : delay(125);
1480 0 : if (++n > 1000) {
1481 0 : printf("%s: codec ready timeout\n",
1482 0 : sc->sc_dev.dv_xname);
1483 0 : return(1);
1484 : }
1485 : }
1486 :
1487 : /* Assert valid frame signal */
1488 0 : BA0WRITE4(sc, CS4280_ACCTL, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
1489 :
1490 : /* Wait for valid AC97 input slot */
1491 : n = 0;
1492 0 : while ((BA0READ4(sc, CS4280_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) !=
1493 : (ACISV_ISV3 | ACISV_ISV4)) {
1494 0 : delay(1000);
1495 0 : if (++n > 1000) {
1496 0 : printf("AC97 inputs slot ready timeout\n");
1497 0 : return(1);
1498 : }
1499 : }
1500 :
1501 : /* Set AC97 output slot valid signals */
1502 0 : BA0WRITE4(sc, CS4280_ACOSV, ACOSV_SLV3 | ACOSV_SLV4);
1503 :
1504 : /* reset the processor */
1505 0 : cs4280_reset(sc);
1506 0 : return (0);
1507 0 : }
1508 :
1509 : int
1510 0 : cs4280_init2(struct cs4280_softc *sc, int init)
1511 : {
1512 : int n;
1513 : u_int32_t mem;
1514 :
1515 : /* Download the image to the processor */
1516 0 : if (cs4280_download_image(sc) != 0) {
1517 0 : printf("%s: image download error\n", sc->sc_dev.dv_xname);
1518 0 : return(1);
1519 : }
1520 :
1521 : /* Save playback parameter and then write zero.
1522 : * this ensures that DMA doesn't immediately occur upon
1523 : * starting the processor core
1524 : */
1525 0 : mem = BA1READ4(sc, CS4280_PCTL);
1526 0 : sc->pctl = mem & PCTL_MASK; /* save startup value */
1527 0 : cs4280_halt_output(sc);
1528 :
1529 : /* Save capture parameter and then write zero.
1530 : * this ensures that DMA doesn't immediately occur upon
1531 : * starting the processor core
1532 : */
1533 0 : mem = BA1READ4(sc, CS4280_CCTL);
1534 0 : sc->cctl = mem & CCTL_MASK; /* save startup value */
1535 0 : cs4280_halt_input(sc);
1536 :
1537 : /* MSH: need to power up ADC and DAC? */
1538 :
1539 : /* Processor Startup Procedure */
1540 0 : BA1WRITE4(sc, CS4280_FRMT, FRMT_FTV);
1541 0 : BA1WRITE4(sc, CS4280_SPCR, SPCR_RUN | SPCR_RUNFR | SPCR_DRQEN);
1542 :
1543 : /* Monitor RUNFR bit in SPCR for 1 to 0 transition */
1544 : n = 0;
1545 0 : while (BA1READ4(sc, CS4280_SPCR) & SPCR_RUNFR) {
1546 0 : delay(10);
1547 0 : if (++n > 1000) {
1548 0 : printf("SPCR 1->0 transition timeout\n");
1549 0 : return(1);
1550 : }
1551 : }
1552 :
1553 : n = 0;
1554 0 : while (!(BA1READ4(sc, CS4280_SPCS) & SPCS_SPRUN)) {
1555 0 : delay(10);
1556 0 : if (++n > 1000) {
1557 0 : printf("SPCS 0->1 transition timeout\n");
1558 0 : return(1);
1559 : }
1560 : }
1561 : /* Processor is now running !!! */
1562 :
1563 : /* Setup volume */
1564 0 : BA1WRITE4(sc, CS4280_PVOL, 0x80008000);
1565 0 : BA1WRITE4(sc, CS4280_CVOL, 0x80008000);
1566 :
1567 : /* Interrupt enable */
1568 0 : BA0WRITE4(sc, CS4280_HICR, HICR_IEV|HICR_CHGM);
1569 :
1570 : /* playback interrupt enable */
1571 0 : mem = BA1READ4(sc, CS4280_PFIE) & ~PFIE_PI_MASK;
1572 : mem |= PFIE_PI_ENABLE;
1573 0 : BA1WRITE4(sc, CS4280_PFIE, mem);
1574 : /* capture interrupt enable */
1575 0 : mem = BA1READ4(sc, CS4280_CIE) & ~CIE_CI_MASK;
1576 0 : mem |= CIE_CI_ENABLE;
1577 0 : BA1WRITE4(sc, CS4280_CIE, mem);
1578 :
1579 : #if NMIDI > 0
1580 : /* Reset midi port */
1581 : mem = BA0READ4(sc, CS4280_MIDCR) & ~MIDCR_MASK;
1582 : BA0WRITE4(sc, CS4280_MIDCR, mem | MIDCR_MRST);
1583 : DPRINTF(("midi reset: 0x%x\n", BA0READ4(sc, CS4280_MIDCR)));
1584 : /* midi interrupt enable */
1585 : mem |= MIDCR_TXE | MIDCR_RXE | MIDCR_RIE | MIDCR_TIE;
1586 : BA0WRITE4(sc, CS4280_MIDCR, mem);
1587 : #endif
1588 0 : return(0);
1589 0 : }
1590 :
1591 : int
1592 0 : cs4280_activate(struct device *self, int act)
1593 : {
1594 0 : struct cs4280_softc *sc = (struct cs4280_softc *)self;
1595 : int rv = 0;
1596 :
1597 0 : switch (act) {
1598 : case DVACT_SUSPEND:
1599 : /* should I powerdown here ? */
1600 0 : cs4280_write_codec(sc, AC97_REG_POWER, CS4280_POWER_DOWN_ALL);
1601 0 : break;
1602 : case DVACT_RESUME:
1603 0 : cs4280_close(sc);
1604 0 : cs4280_init(sc, 0);
1605 0 : cs4280_init2(sc, 0);
1606 0 : ac97_resume(&sc->host_if, sc->codec_if);
1607 0 : rv = config_activate_children(self, act);
1608 0 : break;
1609 : default:
1610 0 : rv = config_activate_children(self, act);
1611 0 : break;
1612 : }
1613 0 : return (rv);
1614 : }
1615 :
1616 : void
1617 0 : cs4280_clear_fifos(struct cs4280_softc *sc)
1618 : {
1619 : int pd = 0, cnt, n;
1620 : u_int32_t mem;
1621 :
1622 : /*
1623 : * If device power down, power up the device and keep power down
1624 : * state.
1625 : */
1626 0 : mem = BA0READ4(sc, CS4280_CLKCR1);
1627 0 : if (!(mem & CLKCR1_SWCE)) {
1628 0 : printf("cs4280_clear_fifo: power down found.\n");
1629 0 : BA0WRITE4(sc, CS4280_CLKCR1, mem | CLKCR1_SWCE);
1630 : pd = 1;
1631 0 : }
1632 0 : BA0WRITE4(sc, CS4280_SERBWP, 0);
1633 0 : for (cnt = 0; cnt < 256; cnt++) {
1634 : n = 0;
1635 0 : while (BA0READ4(sc, CS4280_SERBST) & SERBST_WBSY) {
1636 0 : delay(1000);
1637 0 : if (++n > 1000) {
1638 0 : printf("clear_fifo: fist timeout cnt=%d\n", cnt);
1639 0 : break;
1640 : }
1641 : }
1642 0 : BA0WRITE4(sc, CS4280_SERBAD, cnt);
1643 0 : BA0WRITE4(sc, CS4280_SERBCM, SERBCM_WRC);
1644 : }
1645 0 : if (pd)
1646 0 : BA0WRITE4(sc, CS4280_CLKCR1, mem);
1647 0 : }
1648 :
1649 : #if NMIDI > 0
1650 : int
1651 : cs4280_midi_open(void *addr, int flags, void (*iintr)(void, int),
1652 : void (*ointr)(void *), void *arg)
1653 : {
1654 : struct cs4280_softc *sc = addr;
1655 : u_int32_t mem;
1656 :
1657 : DPRINTF(("midi_open\n"));
1658 : sc->sc_iintr = iintr;
1659 : sc->sc_ointr = ointr;
1660 : sc->sc_arg = arg;
1661 :
1662 : /* midi interrupt enable */
1663 : mem = BA0READ4(sc, CS4280_MIDCR) & ~MIDCR_MASK;
1664 : mem |= MIDCR_TXE | MIDCR_RXE | MIDCR_RIE | MIDCR_TIE | MIDCR_MLB;
1665 : BA0WRITE4(sc, CS4280_MIDCR, mem);
1666 : #ifdef CS4280_DEBUG
1667 : if (mem != BA0READ4(sc, CS4280_MIDCR)) {
1668 : DPRINTF(("midi_open: MIDCR=%d\n", BA0READ4(sc, CS4280_MIDCR)));
1669 : return(EINVAL);
1670 : }
1671 : DPRINTF(("MIDCR=0x%x\n", BA0READ4(sc, CS4280_MIDCR)));
1672 : #endif
1673 : return (0);
1674 : }
1675 :
1676 : void
1677 : cs4280_midi_close(void *addr)
1678 : {
1679 : struct cs4280_softc *sc = addr;
1680 : u_int32_t mem;
1681 :
1682 : DPRINTF(("midi_close\n"));
1683 : mem = BA0READ4(sc, CS4280_MIDCR);
1684 : mem &= ~MIDCR_MASK;
1685 : BA0WRITE4(sc, CS4280_MIDCR, mem);
1686 :
1687 : sc->sc_iintr = 0;
1688 : sc->sc_ointr = 0;
1689 : }
1690 :
1691 : int
1692 : cs4280_midi_output(void *addr, int d)
1693 : {
1694 : struct cs4280_softc *sc = addr;
1695 : u_int32_t mem;
1696 : int x;
1697 :
1698 : for (x = 0; x != MIDI_BUSY_WAIT; x++) {
1699 : if ((BA0READ4(sc, CS4280_MIDSR) & MIDSR_TBF) == 0) {
1700 : mem = BA0READ4(sc, CS4280_MIDWP) & ~MIDWP_MASK;
1701 : mem |= d & MIDWP_MASK;
1702 : DPRINTFN(5,("midi_output d=0x%08x",d));
1703 : BA0WRITE4(sc, CS4280_MIDWP, mem);
1704 : if (mem != BA0READ4(sc, CS4280_MIDWP)) {
1705 : DPRINTF(("Bad write data: %d %d",
1706 : mem, BA0READ4(sc, CS4280_MIDWP)));
1707 : return(EIO);
1708 : }
1709 : return (0);
1710 : }
1711 : delay(MIDI_BUSY_DELAY);
1712 : }
1713 : return (EIO);
1714 : }
1715 :
1716 : void
1717 : cs4280_midi_getinfo(void *addr, struct midi_info *mi)
1718 : {
1719 : mi->name = "CS4280 MIDI UART";
1720 : mi->props = MIDI_PROP_CAN_INPUT | MIDI_PROP_OUT_INTR;
1721 : }
1722 :
1723 : #endif
|