xref: /openbsd-src/sys/dev/pci/cs4281.c (revision 91f110e064cd7c194e59e019b83bb7496c1c84d4)
1 /*	$OpenBSD: cs4281.c,v 1.30 2013/12/06 21:03:03 deraadt Exp $ */
2 /*	$Tera: cs4281.c,v 1.18 2000/12/27 14:24:45 tacha Exp $	*/
3 
4 /*
5  * Copyright (c) 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 CS4281 driver.
36  * Data sheets can be found
37  * http://www.cirrus.com/pubs/4281.pdf?DocumentID=30
38  * ftp://ftp.alsa-project.org/pub/manuals/cirrus/cs4281tm.pdf
39  *
40  * TODO:
41  *   1: midi and FM support
42  */
43 
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/kernel.h>
47 #include <sys/malloc.h>
48 #include <sys/fcntl.h>
49 #include <sys/device.h>
50 
51 #include <dev/pci/pcidevs.h>
52 #include <dev/pci/pcivar.h>
53 #include <dev/pci/cs4281reg.h>
54 
55 #include <sys/audioio.h>
56 #include <dev/audio_if.h>
57 #include <dev/midi_if.h>
58 #include <dev/mulaw.h>
59 #include <dev/auconv.h>
60 
61 #include <dev/ic/ac97.h>
62 
63 #include <machine/bus.h>
64 
65 #define CSCC_PCI_BA0 0x10
66 #define CSCC_PCI_BA1 0x14
67 
68 struct cs4281_dma {
69 	bus_dmamap_t map;
70 	caddr_t addr;		/* real dma buffer */
71 	caddr_t dum;		/* dummy buffer for audio driver */
72 	bus_dma_segment_t segs[1];
73 	int nsegs;
74 	size_t size;
75 	struct cs4281_dma *next;
76 };
77 #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr)
78 #define BUFADDR(p)  ((void *)((p)->dum))
79 #define KERNADDR(p) ((void *)((p)->addr))
80 
81 /*
82  * Software state
83  */
84 struct cs4281_softc {
85 	struct device		sc_dev;
86 
87 	pci_intr_handle_t	*sc_ih;
88 
89         /* I/O (BA0) */
90 	bus_space_tag_t		ba0t;
91 	bus_space_handle_t	ba0h;
92 
93 	/* BA1 */
94 	bus_space_tag_t		ba1t;
95 	bus_space_handle_t	ba1h;
96 
97 	/* DMA */
98 	bus_dma_tag_t		sc_dmatag;
99 	struct cs4281_dma	*sc_dmas;
100 	size_t dma_size;
101 	size_t dma_align;
102 
103 	int	hw_blocksize;
104 
105         /* playback */
106 	void	(*sc_pintr)(void *);	/* dma completion intr handler */
107 	void	*sc_parg;		/* arg for sc_intr() */
108 	char	*sc_ps, *sc_pe, *sc_pn;
109 	int	sc_pcount;
110 	int	sc_pi;
111 	struct cs4281_dma *sc_pdma;
112 	char	*sc_pbuf;
113 	int	(*halt_output)(void *);
114 #ifdef DIAGNOSTIC
115         char	sc_prun;
116 #endif
117 
118 	/* capturing */
119 	void	(*sc_rintr)(void *);	/* dma completion intr handler */
120 	void	*sc_rarg;		/* arg for sc_intr() */
121 	char	*sc_rs, *sc_re, *sc_rn;
122 	int	sc_rcount;
123 	int	sc_ri;
124 	struct	cs4281_dma *sc_rdma;
125 	char	*sc_rbuf;
126 	int	sc_rparam;		/* record format */
127 	int	(*halt_input)(void *);
128 #ifdef DIAGNOSTIC
129         char	sc_rrun;
130 #endif
131 
132 #if NMIDI > 0
133         void	(*sc_iintr)(void *, int);	/* midi input ready handler */
134         void	(*sc_ointr)(void *);		/* midi output ready handler */
135         void	*sc_arg;
136 #endif
137 
138 	/* AC97 CODEC */
139 	struct ac97_codec_if *codec_if;
140 	struct ac97_host_if host_if;
141 
142         /* Power Management */
143 	u_int16_t ac97_reg[CS4281_SAVE_REG_MAX + 1];   /* Save ac97 registers */
144 };
145 
146 #define BA0READ4(sc, r) bus_space_read_4((sc)->ba0t, (sc)->ba0h, (r))
147 #define BA0WRITE4(sc, r, x) bus_space_write_4((sc)->ba0t, (sc)->ba0h, (r), (x))
148 
149 #if defined(ENABLE_SECONDARY_CODEC)
150 #define MAX_CHANNELS  (4)
151 #define MAX_FIFO_SIZE 32 /* 128/4 channels */
152 #else
153 #define MAX_CHANNELS  (2)
154 #define MAX_FIFO_SIZE 64 /* 128/2 channels */
155 #endif
156 
157 int cs4281_match(struct device *, void *, void *);
158 void cs4281_attach(struct device *, struct device *, void *);
159 int cs4281_activate(struct device *, int);
160 int cs4281_intr(void *);
161 int cs4281_query_encoding(void *, struct audio_encoding *);
162 int cs4281_set_params(void *, int, int, struct audio_params *,
163 				     struct audio_params *);
164 int cs4281_halt_output(void *);
165 int cs4281_halt_input(void *);
166 int cs4281_getdev(void *, struct audio_device *);
167 int cs4281_trigger_output(void *, void *, void *, int, void (*)(void *),
168 			  void *, struct audio_params *);
169 int cs4281_trigger_input(void *, void *, void *, int, void (*)(void *),
170 			 void *, struct audio_params *);
171 u_int8_t cs4281_sr2regval(int);
172 void cs4281_set_dac_rate(struct cs4281_softc *, int);
173 void cs4281_set_adc_rate(struct cs4281_softc *, int);
174 int cs4281_init(struct cs4281_softc *);
175 
176 int cs4281_open(void *, int);
177 void cs4281_close(void *);
178 int cs4281_round_blocksize(void *, int);
179 int cs4281_get_props(void *);
180 int cs4281_attach_codec(void *, struct ac97_codec_if *);
181 int cs4281_read_codec(void *, u_int8_t , u_int16_t *);
182 int cs4281_write_codec(void *, u_int8_t, u_int16_t);
183 void cs4281_reset_codec(void *);
184 
185 int cs4281_mixer_set_port(void *, mixer_ctrl_t *);
186 int cs4281_mixer_get_port(void *, mixer_ctrl_t *);
187 int cs4281_query_devinfo(void *, mixer_devinfo_t *);
188 void *cs4281_malloc(void *, int, size_t, int, int);
189 size_t cs4281_round_buffersize(void *, int, size_t);
190 void cs4281_free(void *, void *, int);
191 paddr_t cs4281_mappage(void *, void *, off_t, int);
192 
193 int cs4281_allocmem(struct cs4281_softc *, size_t, int, int,
194 				     struct cs4281_dma *);
195 int cs4281_src_wait(struct cs4281_softc *);
196 
197 #if defined(CS4281_DEBUG)
198 #undef DPRINTF
199 #undef DPRINTFN
200 #define DPRINTF(x)	    if (cs4281_debug) printf x
201 #define DPRINTFN(n,x)	    if (cs4281_debug>(n)) printf x
202 int cs4281_debug = 5;
203 #else
204 #define DPRINTF(x)
205 #define DPRINTFN(n,x)
206 #endif
207 
208 struct audio_hw_if cs4281_hw_if = {
209 	cs4281_open,
210 	cs4281_close,
211 	NULL,
212 	cs4281_query_encoding,
213 	cs4281_set_params,
214 	cs4281_round_blocksize,
215 	NULL,
216 	NULL,
217 	NULL,
218 	NULL,
219 	NULL,
220 	cs4281_halt_output,
221 	cs4281_halt_input,
222 	NULL,
223 	cs4281_getdev,
224 	NULL,
225 	cs4281_mixer_set_port,
226 	cs4281_mixer_get_port,
227 	cs4281_query_devinfo,
228 	cs4281_malloc,
229 	cs4281_free,
230 	cs4281_round_buffersize,
231 	NULL, /* cs4281_mappage, */
232 	cs4281_get_props,
233 	cs4281_trigger_output,
234 	cs4281_trigger_input,
235 	NULL
236 };
237 
238 #if NMIDI > 0
239 /* Midi Interface */
240 void cs4281_midi_close(void *);
241 void cs4281_midi_getinfo(void *, struct midi_info *);
242 int cs4281_midi_open(void *, int, void (*)(void *, int),
243 		     void (*)(void *), void *);
244 int cs4281_midi_output(void *, int);
245 
246 struct midi_hw_if cs4281_midi_hw_if = {
247 	cs4281_midi_open,
248 	cs4281_midi_close,
249 	cs4281_midi_output,
250 	cs4281_midi_getinfo,
251 	0,
252 };
253 #endif
254 
255 struct cfattach clct_ca = {
256 	sizeof(struct cs4281_softc), cs4281_match, cs4281_attach, NULL,
257 	cs4281_activate
258 };
259 
260 struct cfdriver clct_cd = {
261 	NULL, "clct", DV_DULL
262 };
263 
264 struct audio_device cs4281_device = {
265 	"CS4281",
266 	"",
267 	"cs4281"
268 };
269 
270 
271 int
272 cs4281_match(parent, match, aux)
273 	struct device *parent;
274 	void *match;
275 	void *aux;
276 {
277 	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
278 
279 	if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_CIRRUS ||
280 	    PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_CIRRUS_CS4281)
281 		return (0);
282 
283 	return (1);
284 }
285 
286 void
287 cs4281_attach(parent, self, aux)
288 	struct device *parent;
289 	struct device *self;
290 	void *aux;
291 {
292 	struct cs4281_softc *sc = (struct cs4281_softc *)self;
293 	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
294 	pci_chipset_tag_t pc = pa->pa_pc;
295 	char const *intrstr;
296 	pci_intr_handle_t ih;
297 
298 	/* Map I/O register */
299 	if (pci_mapreg_map(pa, CSCC_PCI_BA0,
300 	    PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->ba0t,
301 	    &sc->ba0h, NULL, NULL, 0)) {
302 		printf("%s: can't map BA0 space\n", sc->sc_dev.dv_xname);
303 		return;
304 	}
305 	if (pci_mapreg_map(pa, CSCC_PCI_BA1,
306 	    PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->ba1t,
307 	    &sc->ba1h, NULL, NULL, 0)) {
308 		printf("%s: can't map BA1 space\n", sc->sc_dev.dv_xname);
309 		return;
310 	}
311 
312 	sc->sc_dmatag = pa->pa_dmat;
313 
314 	/*
315 	 * Set Power State D0.
316 	 * Without doing this, 0xffffffff is read from all registers after
317 	 * using Windows and rebooting into OpenBSD.
318 	 * On my IBM ThinkPad X20, it is set to D3 after using Windows2000.
319 	 */
320 	pci_set_powerstate(pc, pa->pa_tag, PCI_PMCSR_STATE_D0);
321 
322 	/* Map and establish the interrupt. */
323 	if (pci_intr_map(pa, &ih)) {
324 		printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
325 		return;
326 	}
327 	intrstr = pci_intr_string(pc, ih);
328 
329 	sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO | IPL_MPSAFE,
330 	    cs4281_intr, sc, sc->sc_dev.dv_xname);
331 	if (sc->sc_ih == NULL) {
332 		printf("%s: couldn't establish interrupt",sc->sc_dev.dv_xname);
333 		if (intrstr != NULL)
334 			printf(" at %s", intrstr);
335 		printf("\n");
336 		return;
337 	}
338 	printf(" %s\n", intrstr);
339 
340 	/*
341 	 * Sound System start-up
342 	 */
343 	if (cs4281_init(sc) != 0)
344 		return;
345 
346 	sc->halt_input  = cs4281_halt_input;
347 	sc->halt_output = cs4281_halt_output;
348 
349 	sc->dma_size     = CS4281_BUFFER_SIZE / MAX_CHANNELS;
350 	sc->dma_align    = 0x10;
351 	sc->hw_blocksize = sc->dma_size / 2;
352 
353 	/* AC 97 attachment */
354 	sc->host_if.arg = sc;
355 	sc->host_if.attach = cs4281_attach_codec;
356 	sc->host_if.read   = cs4281_read_codec;
357 	sc->host_if.write  = cs4281_write_codec;
358 	sc->host_if.reset  = cs4281_reset_codec;
359 	if (ac97_attach(&sc->host_if) != 0) {
360 		printf("%s: ac97_attach failed\n", sc->sc_dev.dv_xname);
361 		return;
362 	}
363 	audio_attach_mi(&cs4281_hw_if, sc, &sc->sc_dev);
364 
365 #if NMIDI > 0
366 	midi_attach_mi(&cs4281_midi_hw_if, sc, &sc->sc_dev);
367 #endif
368 }
369 
370 
371 int
372 cs4281_intr(p)
373 	void *p;
374 {
375 	struct cs4281_softc *sc = p;
376 	u_int32_t intr, val;
377 	char *empty_dma;
378 
379 	mtx_enter(&audio_lock);
380 	intr = BA0READ4(sc, CS4281_HISR);
381 	if (!(intr & (HISR_DMA0 | HISR_DMA1 | HISR_MIDI))) {
382 		BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM);
383 		mtx_leave(&audio_lock);
384 		return (0);
385 	}
386 	DPRINTF(("cs4281_intr:"));
387 
388 	if (intr & HISR_DMA0)
389 		val = BA0READ4(sc, CS4281_HDSR0); /* clear intr condition */
390 	if (intr & HISR_DMA1)
391 		val = BA0READ4(sc, CS4281_HDSR1); /* clear intr condition */
392 	BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM);
393 
394 	/* Playback Interrupt */
395 	if (intr & HISR_DMA0) {
396 		DPRINTF((" PB DMA 0x%x(%d)", (int)BA0READ4(sc, CS4281_DCA0),
397 			 (int)BA0READ4(sc, CS4281_DCC0)));
398 		if (sc->sc_pintr) {
399 			if ((sc->sc_pi%sc->sc_pcount) == 0)
400 				sc->sc_pintr(sc->sc_parg);
401 		} else {
402 			printf("unexpected play intr\n");
403 		}
404 		/* copy buffer */
405 		++sc->sc_pi;
406 		empty_dma = sc->sc_pdma->addr;
407 		if (sc->sc_pi&1)
408 			empty_dma += sc->hw_blocksize;
409 		memcpy(empty_dma, sc->sc_pn, sc->hw_blocksize);
410 		sc->sc_pn += sc->hw_blocksize;
411 		if (sc->sc_pn >= sc->sc_pe)
412 			sc->sc_pn = sc->sc_ps;
413 	}
414 	if (intr & HISR_DMA1) {
415 		val = BA0READ4(sc, CS4281_HDSR1);
416 		/* copy from dma */
417 		DPRINTF((" CP DMA 0x%x(%d)", (int)BA0READ4(sc, CS4281_DCA1),
418 			 (int)BA0READ4(sc, CS4281_DCC1)));
419 		++sc->sc_ri;
420 		empty_dma = sc->sc_rdma->addr;
421 		if ((sc->sc_ri & 1) == 0)
422 			empty_dma += sc->hw_blocksize;
423 		memcpy(sc->sc_rn, empty_dma, sc->hw_blocksize);
424 		if (sc->sc_rn >= sc->sc_re)
425 			sc->sc_rn = sc->sc_rs;
426 		if (sc->sc_rintr) {
427 			if ((sc->sc_ri % sc->sc_rcount) == 0)
428 				sc->sc_rintr(sc->sc_rarg);
429 		} else {
430 			printf("unexpected record intr\n");
431 		}
432 	}
433 	DPRINTF(("\n"));
434 	mtx_leave(&audio_lock);
435 	return (1);
436 }
437 
438 int
439 cs4281_query_encoding(addr, fp)
440 	void *addr;
441 	struct audio_encoding *fp;
442 {
443 	switch (fp->index) {
444 	case 0:
445 		strlcpy(fp->name, AudioEulinear, sizeof fp->name);
446 		fp->encoding = AUDIO_ENCODING_ULINEAR;
447 		fp->precision = 8;
448 		fp->flags = 0;
449 		break;
450 	case 1:
451 		strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
452 		fp->encoding = AUDIO_ENCODING_ULAW;
453 		fp->precision = 8;
454 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
455 		break;
456 	case 2:
457 		strlcpy(fp->name, AudioEalaw, sizeof fp->name);
458 		fp->encoding = AUDIO_ENCODING_ALAW;
459 		fp->precision = 8;
460 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
461 		break;
462 	case 3:
463 		strlcpy(fp->name, AudioEslinear, sizeof fp->name);
464 		fp->encoding = AUDIO_ENCODING_SLINEAR;
465 		fp->precision = 8;
466 		fp->flags = 0;
467 		break;
468 	case 4:
469 		strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
470 		fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
471 		fp->precision = 16;
472 		fp->flags = 0;
473 		break;
474 	case 5:
475 		strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
476 		fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
477 		fp->precision = 16;
478 		fp->flags = 0;
479 		break;
480 	case 6:
481 		strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
482 		fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
483 		fp->precision = 16;
484 		fp->flags = 0;
485 		break;
486 	case 7:
487 		strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
488 		fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
489 		fp->precision = 16;
490 		fp->flags = 0;
491 		break;
492 	default:
493 		return EINVAL;
494 	}
495 	fp->bps = AUDIO_BPS(fp->precision);
496 	fp->msb = 1;
497 
498 	return (0);
499 }
500 
501 int
502 cs4281_set_params(addr, setmode, usemode, play, rec)
503 	void *addr;
504 	int setmode, usemode;
505 	struct audio_params *play, *rec;
506 {
507 	struct cs4281_softc *sc = addr;
508 	struct audio_params *p;
509 	int mode;
510 
511 	for (mode = AUMODE_RECORD; mode != -1;
512 	    mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
513 		if ((setmode & mode) == 0)
514 			continue;
515 
516 		p = mode == AUMODE_PLAY ? play : rec;
517 
518 		if (p == play) {
519 			DPRINTFN(5,("play: samp=%ld precision=%d channels=%d\n",
520 				p->sample_rate, p->precision, p->channels));
521 		} else {
522 			DPRINTFN(5,("rec: samp=%ld precision=%d channels=%d\n",
523 				p->sample_rate, p->precision, p->channels));
524 		}
525 		if (p->sample_rate < 6023)
526 			p->sample_rate = 6023;
527 		if (p->sample_rate > 48000)
528 			p->sample_rate = 48000;
529 		if (p->precision > 16)
530 			p->precision = 16;
531 		if (p->channels > 2)
532 			p->channels = 2;
533 		p->factor = 1;
534 		p->sw_code = 0;
535 
536 		switch (p->encoding) {
537 		case AUDIO_ENCODING_SLINEAR_BE:
538 			break;
539 		case AUDIO_ENCODING_SLINEAR_LE:
540 			break;
541 		case AUDIO_ENCODING_ULINEAR_BE:
542 			break;
543 		case AUDIO_ENCODING_ULINEAR_LE:
544 			break;
545 		case AUDIO_ENCODING_ULAW:
546 			if (mode == AUMODE_PLAY) {
547 				p->sw_code = mulaw_to_slinear8;
548 			} else {
549 				p->sw_code = slinear8_to_mulaw;
550 			}
551 			break;
552 		case AUDIO_ENCODING_ALAW:
553 			if (mode == AUMODE_PLAY) {
554 				p->sw_code = alaw_to_slinear8;
555 			} else {
556 				p->sw_code = slinear8_to_alaw;
557 			}
558 			break;
559 		default:
560 			return (EINVAL);
561 		}
562 		p->bps = AUDIO_BPS(p->precision);
563 		p->msb = 1;
564 	}
565 
566 	/* set sample rate */
567 	cs4281_set_dac_rate(sc, play->sample_rate);
568 	cs4281_set_adc_rate(sc, rec->sample_rate);
569 	return (0);
570 }
571 
572 int
573 cs4281_halt_output(addr)
574 	void *addr;
575 {
576 	struct cs4281_softc *sc = addr;
577 
578 	BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) | DCRn_MSK);
579 #ifdef DIAGNOSTIC
580 	sc->sc_prun = 0;
581 #endif
582 	return (0);
583 }
584 
585 int
586 cs4281_halt_input(addr)
587 	void *addr;
588 {
589 	struct cs4281_softc *sc = addr;
590 
591 	BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) | DCRn_MSK);
592 #ifdef DIAGNOSTIC
593 	sc->sc_rrun = 0;
594 #endif
595 	return (0);
596 }
597 
598 /* trivial */
599 int
600 cs4281_getdev(addr, retp)
601      void *addr;
602      struct audio_device *retp;
603 {
604 	*retp = cs4281_device;
605 	return (0);
606 }
607 
608 
609 int
610 cs4281_trigger_output(addr, start, end, blksize, intr, arg, param)
611 	void *addr;
612 	void *start, *end;
613 	int blksize;
614 	void (*intr)(void *);
615 	void *arg;
616 	struct audio_params *param;
617 {
618 	struct cs4281_softc *sc = addr;
619 	u_int32_t fmt=0;
620 	struct cs4281_dma *p;
621 	int dma_count;
622 
623 #ifdef DIAGNOSTIC
624 	if (sc->sc_prun)
625 		printf("cs4281_trigger_output: already running\n");
626 	sc->sc_prun = 1;
627 #endif
628 
629 	DPRINTF(("cs4281_trigger_output: sc=%p start=%p end=%p "
630 		 "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
631 	sc->sc_pintr = intr;
632 	sc->sc_parg  = arg;
633 
634 	/* stop playback DMA */
635 	BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) | DCRn_MSK);
636 
637 	DPRINTF(("param: precision=%d  factor=%d channels=%d encoding=%d\n",
638 	       param->precision, param->factor, param->channels,
639 	       param->encoding));
640 	for (p = sc->sc_dmas; p != NULL && BUFADDR(p) != start; p = p->next)
641 		;
642 	if (p == NULL) {
643 		printf("cs4281_trigger_output: bad addr %p\n", start);
644 		mtx_leave(&audio_lock);
645 		return (EINVAL);
646 	}
647 
648 	sc->sc_pcount = blksize / sc->hw_blocksize;
649 	sc->sc_ps = (char *)start;
650 	sc->sc_pe = (char *)end;
651 	sc->sc_pdma = p;
652 	sc->sc_pbuf = KERNADDR(p);
653 	sc->sc_pi = 0;
654 	sc->sc_pn = sc->sc_ps;
655 	if (blksize >= sc->dma_size) {
656 		sc->sc_pn = sc->sc_ps + sc->dma_size;
657 		memcpy(sc->sc_pbuf, start, sc->dma_size);
658 		++sc->sc_pi;
659 	} else {
660 		sc->sc_pn = sc->sc_ps + sc->hw_blocksize;
661 		memcpy(sc->sc_pbuf, start, sc->hw_blocksize);
662 	}
663 
664 	dma_count = sc->dma_size;
665 	if (param->precision * param->factor != 8)
666 		dma_count /= 2;   /* 16 bit */
667 	if (param->channels > 1)
668 		dma_count /= 2;   /* Stereo */
669 
670 	DPRINTF(("cs4281_trigger_output: DMAADDR(p)=0x%x count=%d\n",
671 		 (int)DMAADDR(p), dma_count));
672 	BA0WRITE4(sc, CS4281_DBA0, DMAADDR(p));
673 	BA0WRITE4(sc, CS4281_DBC0, dma_count-1);
674 
675 	/* set playback format */
676 	fmt = BA0READ4(sc, CS4281_DMR0) & ~DMRn_FMTMSK;
677 	if (param->precision * param->factor == 8)
678 		fmt |= DMRn_SIZE8;
679 	if (param->channels == 1)
680 		fmt |= DMRn_MONO;
681 	if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
682 	    param->encoding == AUDIO_ENCODING_SLINEAR_BE)
683 		fmt |= DMRn_BEND;
684 	if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
685 	    param->encoding == AUDIO_ENCODING_ULINEAR_LE)
686 		fmt |= DMRn_USIGN;
687 	BA0WRITE4(sc, CS4281_DMR0, fmt);
688 
689 	/* set sample rate */
690 	cs4281_set_dac_rate(sc, param->sample_rate);
691 
692 	/* start DMA */
693 	mtx_enter(&audio_lock);
694 	BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) & ~DCRn_MSK);
695 	/* Enable interrupts */
696 	BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM);
697 
698 	BA0WRITE4(sc, CS4281_PPRVC, 7);
699 	BA0WRITE4(sc, CS4281_PPLVC, 7);
700 
701 	DPRINTF(("HICR =0x%08x(expected 0x00000001)\n", BA0READ4(sc, CS4281_HICR)));
702 	DPRINTF(("HIMR =0x%08x(expected 0x00f0fc3f)\n", BA0READ4(sc, CS4281_HIMR)));
703 	DPRINTF(("DMR0 =0x%08x(expected 0x2???0018)\n", BA0READ4(sc, CS4281_DMR0)));
704 	DPRINTF(("DCR0 =0x%08x(expected 0x00030000)\n", BA0READ4(sc, CS4281_DCR0)));
705 	DPRINTF(("FCR0 =0x%08x(expected 0x81000f00)\n", BA0READ4(sc, CS4281_FCR0)));
706 	DPRINTF(("DACSR=0x%08x(expected 1 for 44kHz 5 for 8kHz)\n",
707 		 BA0READ4(sc, CS4281_DACSR)));
708 	DPRINTF(("SRCSA=0x%08x(expected 0x0b0a0100)\n", BA0READ4(sc, CS4281_SRCSA)));
709 	DPRINTF(("SSPM&SSPM_PSRCEN =0x%08x(expected 0x00000010)\n",
710 		 BA0READ4(sc, CS4281_SSPM) & SSPM_PSRCEN));
711 	mtx_leave(&audio_lock);
712 	return (0);
713 }
714 
715 int
716 cs4281_trigger_input(addr, start, end, blksize, intr, arg, param)
717 	void *addr;
718 	void *start, *end;
719 	int blksize;
720 	void (*intr)(void *);
721 	void *arg;
722 	struct audio_params *param;
723 {
724 	struct cs4281_softc *sc = addr;
725 	struct cs4281_dma *p;
726 	u_int32_t fmt=0;
727 	int dma_count;
728 
729 	printf("cs4281_trigger_input: not implemented yet\n");
730 #ifdef DIAGNOSTIC
731 	if (sc->sc_rrun)
732 		printf("cs4281_trigger_input: already running\n");
733 	sc->sc_rrun = 1;
734 #endif
735 	DPRINTF(("cs4281_trigger_input: sc=%p start=%p end=%p "
736 	    "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
737 	sc->sc_rintr = intr;
738 	sc->sc_rarg  = arg;
739 
740 	/* stop recording DMA */
741 	BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) | DCRn_MSK);
742 
743 	for (p = sc->sc_dmas; p && BUFADDR(p) != start; p = p->next)
744 		;
745 	if (!p) {
746 		printf("cs4281_trigger_input: bad addr %p\n", start);
747 		return (EINVAL);
748 	}
749 
750 	sc->sc_rcount = blksize / sc->hw_blocksize;
751 	sc->sc_rs = (char *)start;
752 	sc->sc_re = (char *)end;
753 	sc->sc_rdma = p;
754 	sc->sc_rbuf = KERNADDR(p);
755 	sc->sc_ri = 0;
756 	sc->sc_rn = sc->sc_rs;
757 
758 	dma_count = sc->dma_size;
759 	if (param->precision * param->factor == 8)
760 		dma_count /= 2;
761 	if (param->channels > 1)
762 		dma_count /= 2;
763 
764 	DPRINTF(("cs4281_trigger_input: DMAADDR(p)=0x%x count=%d\n",
765 		 (int)DMAADDR(p), dma_count));
766 	BA0WRITE4(sc, CS4281_DBA1, DMAADDR(p));
767 	BA0WRITE4(sc, CS4281_DBC1, dma_count-1);
768 
769 	/* set recording format */
770 	fmt = BA0READ4(sc, CS4281_DMR1) & ~DMRn_FMTMSK;
771 	if (param->precision * param->factor == 8)
772 		fmt |= DMRn_SIZE8;
773 	if (param->channels == 1)
774 		fmt |= DMRn_MONO;
775 	if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
776 	    param->encoding == AUDIO_ENCODING_SLINEAR_BE)
777 		fmt |= DMRn_BEND;
778 	if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
779 	    param->encoding == AUDIO_ENCODING_ULINEAR_LE)
780 		fmt |= DMRn_USIGN;
781 	BA0WRITE4(sc, CS4281_DMR1, fmt);
782 
783 	/* set sample rate */
784 	cs4281_set_adc_rate(sc, param->sample_rate);
785 
786 	/* Start DMA */
787 	mtx_enter(&audio_lock);
788 	BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) & ~DCRn_MSK);
789 	/* Enable interrupts */
790 	BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM);
791 
792 	DPRINTF(("HICR=0x%08x\n", BA0READ4(sc, CS4281_HICR)));
793 	DPRINTF(("HIMR=0x%08x\n", BA0READ4(sc, CS4281_HIMR)));
794 	DPRINTF(("DMR1=0x%08x\n", BA0READ4(sc, CS4281_DMR1)));
795 	DPRINTF(("DCR1=0x%08x\n", BA0READ4(sc, CS4281_DCR1)));
796 	mtx_leave(&audio_lock);
797 	return (0);
798 }
799 
800 /* convert sample rate to register value */
801 u_int8_t
802 cs4281_sr2regval(rate)
803      int rate;
804 {
805 	u_int8_t retval;
806 
807 	/* We don't have to change here. but anyway ... */
808 	if (rate > 48000)
809 		rate = 48000;
810 	if (rate < 6023)
811 		rate = 6023;
812 
813 	switch (rate) {
814 	case 8000:
815 		retval = 5;
816 		break;
817 	case 11025:
818 		retval = 4;
819 		break;
820 	case 16000:
821 		retval = 3;
822 		break;
823 	case 22050:
824 		retval = 2;
825 		break;
826 	case 44100:
827 		retval = 1;
828 		break;
829 	case 48000:
830 		retval = 0;
831 		break;
832 	default:
833 		retval = 1536000/rate; /* == 24576000/(rate*16) */
834 	}
835 	return (retval);
836 }
837 
838 
839 void
840 cs4281_set_dac_rate(sc, rate)
841 	struct cs4281_softc *sc;
842 	int rate;
843 {
844 	BA0WRITE4(sc, CS4281_DACSR, cs4281_sr2regval(rate));
845 }
846 
847 void
848 cs4281_set_adc_rate(sc, rate)
849 	struct cs4281_softc *sc;
850 	int rate;
851 {
852 	BA0WRITE4(sc, CS4281_ADCSR, cs4281_sr2regval(rate));
853 }
854 
855 int
856 cs4281_init(sc)
857      struct cs4281_softc *sc;
858 {
859 	int n;
860 	u_int16_t data;
861 	u_int32_t dat32;
862 
863 	/* set "Configuration Write Protect" register to
864 	 * 0x4281 to allow to write */
865 	BA0WRITE4(sc, CS4281_CWPR, 0x4281);
866 
867 	/*
868 	 * Unset "Full Power-Down bit of Extended PCI Power Management
869 	 * Control" register to release the reset state.
870 	 */
871 	dat32 = BA0READ4(sc, CS4281_EPPMC);
872 	if (dat32 & EPPMC_FPDN)
873 		BA0WRITE4(sc, CS4281_EPPMC, dat32 & ~EPPMC_FPDN);
874 
875 	/* Start PLL out in known state */
876 	BA0WRITE4(sc, CS4281_CLKCR1, 0);
877 	/* Start serial ports out in known state */
878 	BA0WRITE4(sc, CS4281_SERMC, 0);
879 
880 	/* Reset codec */
881 	BA0WRITE4(sc, CS4281_ACCTL, 0);
882 	delay(50);	/* delay 50us */
883 
884 	BA0WRITE4(sc, CS4281_SPMC, 0);
885 	delay(100);	/* delay 100us */
886 	BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN);
887 #if defined(ENABLE_SECONDARY_CODEC)
888 	BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN | SPCM_ASDIN2E);
889 	BA0WRITE4(sc, CS4281_SERMC, SERMC_TCID);
890 #endif
891 	delay(50000);   /* XXX: delay 50ms */
892 
893 	/* Turn on Sound System clocks based on ABITCLK */
894 	BA0WRITE4(sc, CS4281_CLKCR1, CLKCR1_DLLP);
895 	delay(50000);   /* XXX: delay 50ms */
896 	BA0WRITE4(sc, CS4281_CLKCR1, CLKCR1_SWCE | CLKCR1_DLLP);
897 
898 	/* Set enables for sections that are needed in the SSPM registers */
899 	BA0WRITE4(sc, CS4281_SSPM,
900 		  SSPM_MIXEN |		/* Mixer */
901 		  SSPM_CSRCEN |		/* Capture SRC */
902 		  SSPM_PSRCEN |		/* Playback SRC */
903 		  SSPM_JSEN |		/* Joystick */
904 		  SSPM_ACLEN |		/* AC LINK */
905 		  SSPM_FMEN		/* FM */
906 		  );
907 
908 	/* Wait for clock stabilization */
909 	n = 0;
910 	while ((BA0READ4(sc, CS4281_CLKCR1)& (CLKCR1_DLLRDY | CLKCR1_CLKON))
911 	    != (CLKCR1_DLLRDY | CLKCR1_CLKON)) {
912 		delay(100);
913 		if (++n > 1000)
914 			return (-1);
915 	}
916 
917 	/* Enable ASYNC generation */
918 	BA0WRITE4(sc, CS4281_ACCTL, ACCTL_ESYN);
919 
920 	/* Wait for Codec ready. Linux driver wait 50ms here */
921 	n = 0;
922 	while((BA0READ4(sc, CS4281_ACSTS) & ACSTS_CRDY) == 0) {
923 		delay(100);
924 		if (++n > 1000)
925 			return (-1);
926 	}
927 
928 #if defined(ENABLE_SECONDARY_CODEC)
929 	/* secondary codec ready*/
930 	n = 0;
931 	while((BA0READ4(sc, CS4281_ACSTS2) & ACSTS2_CRDY2) == 0) {
932 		delay(100);
933 		if (++n > 1000)
934 			return (-1);
935 	}
936 #endif
937 
938 	/* Set the serial timing configuration */
939 	/* XXX: undocumented but the Linux driver do this */
940 	BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97);
941 
942 	/* Wait for Codec ready signal */
943 	n = 0;
944 	do {
945 		delay(1000);
946 		if (++n > 1000) {
947 			printf("%s: Timeout waiting for Codec ready\n",
948 			       sc->sc_dev.dv_xname);
949 			return -1;
950 		}
951 		dat32 = BA0READ4(sc, CS4281_ACSTS) & ACSTS_CRDY;
952 	} while (dat32 == 0);
953 
954 	/* Enable Valid Frame output on ASDOUT */
955 	BA0WRITE4(sc, CS4281_ACCTL, ACCTL_ESYN | ACCTL_VFRM);
956 
957 	/* Wait until Codec Calibration is finished. Codec register 26h */
958 	n = 0;
959 	do {
960 		delay(1);
961 		if (++n > 1000) {
962 			printf("%s: Timeout waiting for Codec calibration\n",
963 			       sc->sc_dev.dv_xname);
964 			return -1;
965 		}
966 		cs4281_read_codec(sc, AC97_REG_POWER, &data);
967 	} while ((data & 0x0f) != 0x0f);
968 
969 	/* Set the serial timing configuration again */
970 	/* XXX: undocumented but the Linux driver do this */
971 	BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97);
972 
973 	/* Wait until we've sampled input slots 3 & 4 as valid */
974 	n = 0;
975 	do {
976 		delay(1000);
977 		if (++n > 1000) {
978 			printf("%s: Timeout waiting for sampled input slots as valid\n",
979 			       sc->sc_dev.dv_xname);
980 			return -1;
981 		}
982 		dat32 = BA0READ4(sc, CS4281_ACISV) & (ACISV_ISV3 | ACISV_ISV4);
983 	} while (dat32 != (ACISV_ISV3 | ACISV_ISV4));
984 
985 	/* Start digital data transfer of audio data to the codec */
986 	BA0WRITE4(sc, CS4281_ACOSV, (ACOSV_SLV3 | ACOSV_SLV4));
987 
988 	cs4281_write_codec(sc, AC97_REG_HEADPHONE_VOLUME, 0);
989 	cs4281_write_codec(sc, AC97_REG_MASTER_VOLUME, 0);
990 
991 	/* Power on the DAC */
992 	cs4281_read_codec(sc, AC97_REG_POWER, &data);
993 	cs4281_write_codec(sc, AC97_REG_POWER, data &= 0xfdff);
994 
995 	/* Wait until we sample a DAC ready state.
996 	 * Not documented, but Linux driver does.
997 	 */
998 	for (n = 0; n < 32; ++n) {
999 		delay(1000);
1000 		cs4281_read_codec(sc, AC97_REG_POWER, &data);
1001 		if (data & 0x02)
1002 			break;
1003 	}
1004 
1005 	/* Power on the ADC */
1006 	cs4281_read_codec(sc, AC97_REG_POWER, &data);
1007 	cs4281_write_codec(sc, AC97_REG_POWER, data &= 0xfeff);
1008 
1009 	/* Wait until we sample ADC ready state.
1010 	 * Not documented, but Linux driver does.
1011 	 */
1012 	for (n = 0; n < 32; ++n) {
1013 		delay(1000);
1014 		cs4281_read_codec(sc, AC97_REG_POWER, &data);
1015 		if (data & 0x01)
1016 			break;
1017 	}
1018 
1019 #if 0
1020 	/* Initialize SSCR register features */
1021 	/* XXX: hardware volume setting */
1022 	BA0WRITE4(sc, CS4281_SSCR, ~SSCR_HVC); /* disable HW volume setting */
1023 #endif
1024 
1025 	/* disable Sound Blaster Pro emulation */
1026 	/* XXX:
1027 	 * Cannot set since the documents does not describe which bit is
1028 	 * correspond to SSCR_SB. Since the reset value of SSCR is 0,
1029 	 * we can ignore it.*/
1030 #if 0
1031 	BA0WRITE4(sc, CS4281_SSCR, SSCR_SB);
1032 #endif
1033 
1034 	/* map AC97 PCM playback to DMA Channel 0 */
1035 	/* Reset FEN bit to setup first */
1036 	BA0WRITE4(sc, CS4281_FCR0, (BA0READ4(sc,CS4281_FCR0) & ~FCRn_FEN));
1037 	/*
1038 	 *| RS[4:0]/|        |
1039 	 *| LS[4:0] |  AC97  | Slot Function
1040 	 *|---------+--------+--------------------
1041 	 *|     0   |    3   | Left PCM Playback
1042 	 *|     1   |    4   | Right PCM Playback
1043 	 *|     2   |    5   | Phone Line 1 DAC
1044 	 *|     3   |    6   | Center PCM Playback
1045 	 *....
1046 	 *  quoted from Table 29(p109)
1047 	 */
1048 	dat32 = 0x01 << 24 |   /* RS[4:0] =  1 see above */
1049 		0x00 << 16 |   /* LS[4:0] =  0 see above */
1050 		0x0f <<  8 |   /* SZ[6:0] = 15 size of buffer */
1051 		0x00 <<  0 ;   /* OF[6:0] =  0 offset */
1052 	BA0WRITE4(sc, CS4281_FCR0, dat32);
1053 	BA0WRITE4(sc, CS4281_FCR0, dat32 | FCRn_FEN);
1054 
1055 	/* map AC97 PCM record to DMA Channel 1 */
1056 	/* Reset FEN bit to setup first */
1057 	BA0WRITE4(sc, CS4281_FCR1, (BA0READ4(sc,CS4281_FCR1) & ~FCRn_FEN));
1058 	/*
1059 	 *| RS[4:0]/|
1060 	 *| LS[4:0] | AC97 | Slot Function
1061 	 *|---------+------+-------------------
1062 	 *|   10    |   3  | Left PCM Record
1063 	 *|   11    |   4  | Right PCM Record
1064 	 *|   12    |   5  | Phone Line 1 ADC
1065 	 *|   13    |   6  | Mic ADC
1066 	 *....
1067 	 * quoted from Table 30(p109)
1068 	 */
1069 	dat32 = 0x0b << 24 |    /* RS[4:0] = 11 See above */
1070 		0x0a << 16 |    /* LS[4:0] = 10 See above */
1071 		0x0f <<  8 |    /* SZ[6:0] = 15 Size of buffer */
1072 		0x10 <<  0 ;    /* OF[6:0] = 16 offset */
1073 
1074 	/* XXX: I cannot understand why FCRn_PSH is needed here. */
1075 	BA0WRITE4(sc, CS4281_FCR1, dat32 | FCRn_PSH);
1076 	BA0WRITE4(sc, CS4281_FCR1, dat32 | FCRn_FEN);
1077 
1078 #if 0
1079 	/* Disable DMA Channel 2, 3 */
1080 	BA0WRITE4(sc, CS4281_FCR2, (BA0READ4(sc,CS4281_FCR2) & ~FCRn_FEN));
1081 	BA0WRITE4(sc, CS4281_FCR3, (BA0READ4(sc,CS4281_FCR3) & ~FCRn_FEN));
1082 #endif
1083 
1084 	/* Set the SRC Slot Assignment accordingly */
1085 	/*| PLSS[4:0]/
1086 	 *| PRSS[4:0] | AC97 | Slot Function
1087 	 *|-----------+------+----------------
1088 	 *|     0     |  3   | Left PCM Playback
1089 	 *|     1     |  4   | Right PCM Playback
1090 	 *|     2     |  5   | phone line 1 DAC
1091 	 *|     3     |  6   | Center PCM Playback
1092 	 *|     4     |  7   | Left Surround PCM Playback
1093 	 *|     5     |  8   | Right Surround PCM Playback
1094 	 *......
1095 	 *
1096 	 *| CLSS[4:0]/
1097 	 *| CRSS[4:0] | AC97 | Codec |Slot Function
1098 	 *|-----------+------+-------+-----------------
1099 	 *|    10     |   3  |Primary| Left PCM Record
1100 	 *|    11     |   4  |Primary| Right PCM Record
1101 	 *|    12     |   5  |Primary| Phone Line 1 ADC
1102 	 *|    13     |   6  |Primary| Mic ADC
1103 	 *|.....
1104 	 *|    20     |   3  |  Sec. | Left PCM Record
1105 	 *|    21     |   4  |  Sec. | Right PCM Record
1106 	 *|    22     |   5  |  Sec. | Phone Line 1 ADC
1107 	 *|    23     |   6  |  Sec. | Mic ADC
1108 	 */
1109 	dat32 = 0x0b << 24 |   /* CRSS[4:0] Right PCM Record(primary) */
1110 		0x0a << 16 |   /* CLSS[4:0] Left  PCM Record(primary) */
1111 		0x01 <<  8 |   /* PRSS[4:0] Right PCM Playback */
1112 		0x00 <<  0;    /* PLSS[4:0] Left  PCM Playback */
1113 	BA0WRITE4(sc, CS4281_SRCSA, dat32);
1114 
1115 	/* Set interrupt to occurred at Half and Full terminal
1116 	 * count interrupt enable for DMA channel 0 and 1.
1117 	 * To keep DMA stop, set MSK.
1118 	 */
1119 	dat32 = DCRn_HTCIE | DCRn_TCIE | DCRn_MSK;
1120 	BA0WRITE4(sc, CS4281_DCR0, dat32);
1121 	BA0WRITE4(sc, CS4281_DCR1, dat32);
1122 
1123 	/* Set Auto-Initialize Control enable */
1124 	BA0WRITE4(sc, CS4281_DMR0,
1125 		  DMRn_DMA | DMRn_AUTO | DMRn_TR_READ);
1126 	BA0WRITE4(sc, CS4281_DMR1,
1127 		  DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE);
1128 
1129 	/* Clear DMA Mask in HIMR */
1130 	dat32 = BA0READ4(sc, CS4281_HIMR) & 0xfffbfcff;
1131 	BA0WRITE4(sc, CS4281_HIMR, dat32);
1132 	return (0);
1133 }
1134 
1135 int
1136 cs4281_activate(struct device *self, int act)
1137 {
1138 	struct cs4281_softc *sc = (struct cs4281_softc *)self;
1139 	int rv = 0;
1140 
1141 	switch (act) {
1142 	case DVACT_SUSPEND:
1143 		/* should I powerdown here ? */
1144 		cs4281_write_codec(sc, AC97_REG_POWER, CS4281_POWER_DOWN_ALL);
1145 		break;
1146 	case DVACT_RESUME:
1147 		cs4281_init(sc);
1148 		ac97_resume(&sc->host_if, sc->codec_if);
1149 		rv = config_activate_children(self, act);
1150 		break;
1151 	default:
1152 		rv = config_activate_children(self, act);
1153 		break;
1154 	}
1155 	return (rv);
1156 }
1157 
1158 void
1159 cs4281_reset_codec(void *addr)
1160 {
1161 	struct cs4281_softc *sc;
1162 	u_int16_t data;
1163 	u_int32_t dat32;
1164 	int n;
1165 
1166 	sc = addr;
1167 
1168 	DPRINTFN(3,("cs4281_reset_codec\n"));
1169 
1170 	/* Reset codec */
1171 	BA0WRITE4(sc, CS4281_ACCTL, 0);
1172 	delay(50);    /* delay 50us */
1173 
1174 	BA0WRITE4(sc, CS4281_SPMC, 0);
1175 	delay(100);	/* delay 100us */
1176 	BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN);
1177 #if defined(ENABLE_SECONDARY_CODEC)
1178 	BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN | SPCM_ASDIN2E);
1179 	BA0WRITE4(sc, CS4281_SERMC, SERMC_TCID);
1180 #endif
1181 	delay(50000);   /* XXX: delay 50ms */
1182 
1183 	/* Enable ASYNC generation */
1184 	BA0WRITE4(sc, CS4281_ACCTL, ACCTL_ESYN);
1185 
1186 	/* Wait for Codec ready. Linux driver wait 50ms here */
1187 	n = 0;
1188 	while((BA0READ4(sc, CS4281_ACSTS) & ACSTS_CRDY) == 0) {
1189 		delay(100);
1190 		if (++n > 1000) {
1191 			printf("reset_codec: AC97 codec ready timeout\n");
1192 			return;
1193 		}
1194 	}
1195 #if defined(ENABLE_SECONDARY_CODEC)
1196 	/* secondary codec ready*/
1197 	n = 0;
1198 	while((BA0READ4(sc, CS4281_ACSTS2) & ACSTS2_CRDY2) == 0) {
1199 		delay(100);
1200 		if (++n > 1000)
1201 			return;
1202 	}
1203 #endif
1204 	/* Set the serial timing configuration */
1205 	/* XXX: undocumented but the Linux driver do this */
1206 	BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97);
1207 
1208 	/* Wait for Codec ready signal */
1209 	n = 0;
1210 	do {
1211 		delay(1000);
1212 		if (++n > 1000) {
1213 			printf("%s: Timeout waiting for Codec ready\n",
1214 			       sc->sc_dev.dv_xname);
1215 			return;
1216 		}
1217 		dat32 = BA0READ4(sc, CS4281_ACSTS) & ACSTS_CRDY;
1218 	} while (dat32 == 0);
1219 
1220 	/* Enable Valid Frame output on ASDOUT */
1221 	BA0WRITE4(sc, CS4281_ACCTL, ACCTL_ESYN | ACCTL_VFRM);
1222 
1223 	/* Wait until Codec Calibration is finished. Codec register 26h */
1224 	n = 0;
1225 	do {
1226 		delay(1);
1227 		if (++n > 1000) {
1228 			printf("%s: Timeout waiting for Codec calibration\n",
1229 			       sc->sc_dev.dv_xname);
1230 			return ;
1231 		}
1232 		cs4281_read_codec(sc, AC97_REG_POWER, &data);
1233 	} while ((data & 0x0f) != 0x0f);
1234 
1235 	/* Set the serial timing configuration again */
1236 	/* XXX: undocumented but the Linux driver do this */
1237 	BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97);
1238 
1239 	/* Wait until we've sampled input slots 3 & 4 as valid */
1240 	n = 0;
1241 	do {
1242 		delay(1000);
1243 		if (++n > 1000) {
1244 			printf("%s: Timeout waiting for sampled input slots as valid\n",
1245 			       sc->sc_dev.dv_xname);
1246 			return;
1247 		}
1248 		dat32 = BA0READ4(sc, CS4281_ACISV) & (ACISV_ISV3 | ACISV_ISV4) ;
1249 	} while (dat32 != (ACISV_ISV3 | ACISV_ISV4));
1250 
1251 	/* Start digital data transfer of audio data to the codec */
1252 	BA0WRITE4(sc, CS4281_ACOSV, (ACOSV_SLV3 | ACOSV_SLV4));
1253 }
1254 
1255 int
1256 cs4281_open(void *addr, int flags)
1257 {
1258 	return (0);
1259 }
1260 
1261 void
1262 cs4281_close(void *addr)
1263 {
1264 	struct cs4281_softc *sc;
1265 
1266 	sc = addr;
1267 
1268 	(*sc->halt_output)(sc);
1269 	(*sc->halt_input)(sc);
1270 
1271 	sc->sc_pintr = 0;
1272 	sc->sc_rintr = 0;
1273 }
1274 
1275 int
1276 cs4281_round_blocksize(void *addr, int blk)
1277 {
1278 	struct cs4281_softc *sc;
1279 	int retval;
1280 
1281 	DPRINTFN(5,("cs4281_round_blocksize blk=%d -> ", blk));
1282 
1283 	sc=addr;
1284 	if (blk < sc->hw_blocksize)
1285 		retval = sc->hw_blocksize;
1286 	else
1287 		retval = blk & -(sc->hw_blocksize);
1288 
1289 	DPRINTFN(5,("%d\n", retval));
1290 
1291 	return (retval);
1292 }
1293 
1294 int
1295 cs4281_mixer_set_port(void *addr, mixer_ctrl_t *cp)
1296 {
1297 	struct cs4281_softc *sc;
1298 	int val;
1299 
1300 	sc = addr;
1301 	val = sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp);
1302 	DPRINTFN(3,("mixer_set_port: val=%d\n", val));
1303 	return (val);
1304 }
1305 
1306 int
1307 cs4281_mixer_get_port(void *addr, mixer_ctrl_t *cp)
1308 {
1309 	struct cs4281_softc *sc;
1310 
1311 	sc = addr;
1312 	return (sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp));
1313 }
1314 
1315 
1316 int
1317 cs4281_query_devinfo(void *addr, mixer_devinfo_t *dip)
1318 {
1319 	struct cs4281_softc *sc;
1320 
1321 	sc = addr;
1322 	return (sc->codec_if->vtbl->query_devinfo(sc->codec_if, dip));
1323 }
1324 
1325 void *
1326 cs4281_malloc(void *addr, int direction, size_t size, int pool, int flags)
1327 {
1328 	struct cs4281_softc *sc;
1329 	struct cs4281_dma   *p;
1330 	int error;
1331 
1332 	sc = addr;
1333 
1334 	p = malloc(sizeof(*p), pool, flags);
1335 	if (!p)
1336 		return (0);
1337 
1338 	error = cs4281_allocmem(sc, size, pool, flags, p);
1339 
1340 	if (error) {
1341 		free(p, pool);
1342 		return (0);
1343 	}
1344 
1345 	p->next = sc->sc_dmas;
1346 	sc->sc_dmas = p;
1347 	return (BUFADDR(p));
1348 }
1349 
1350 
1351 
1352 void
1353 cs4281_free(void *addr, void *ptr, int pool)
1354 {
1355 	struct cs4281_softc *sc;
1356 	struct cs4281_dma **pp, *p;
1357 
1358 	sc = addr;
1359 	for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) {
1360 		if (BUFADDR(p) == ptr) {
1361 			bus_dmamap_unload(sc->sc_dmatag, p->map);
1362 			bus_dmamap_destroy(sc->sc_dmatag, p->map);
1363 			bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
1364 			bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
1365 			free(p->dum, pool);
1366 			*pp = p->next;
1367 			free(p, pool);
1368 			return;
1369 		}
1370 	}
1371 }
1372 
1373 size_t
1374 cs4281_round_buffersize(void *addr, int direction, size_t size)
1375 {
1376 	/* The real dma buffersize are 4KB for CS4280
1377 	 * and 64kB/MAX_CHANNELS for CS4281.
1378 	 * But they are too small for high quality audio,
1379 	 * let the upper layer(audio) use a larger buffer.
1380 	 * (originally suggested by Lennart Augustsson.)
1381 	 */
1382 	return (size);
1383 }
1384 
1385 paddr_t
1386 cs4281_mappage(void *addr, void *mem, off_t off, int prot)
1387 {
1388 	struct cs4281_softc *sc;
1389 	struct cs4281_dma *p;
1390 
1391 	sc = addr;
1392 	if (off < 0)
1393 		return -1;
1394 
1395 	for (p = sc->sc_dmas; p && BUFADDR(p) != mem; p = p->next)
1396 		;
1397 
1398 	if (!p) {
1399 		DPRINTF(("cs4281_mappage: bad buffer address\n"));
1400 		return (-1);
1401 	}
1402 
1403 	return (bus_dmamem_mmap(sc->sc_dmatag, p->segs, p->nsegs, off, prot,
1404 	    BUS_DMA_WAITOK));
1405 }
1406 
1407 
1408 int
1409 cs4281_get_props(void *addr)
1410 {
1411 	int retval;
1412 
1413 	retval = AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
1414 #ifdef MMAP_READY
1415 	retval |= AUDIO_PROP_MMAP;
1416 #endif
1417 	return (retval);
1418 }
1419 
1420 /* AC97 */
1421 int
1422 cs4281_attach_codec(void *addr, struct ac97_codec_if *codec_if)
1423 {
1424 	struct cs4281_softc *sc;
1425 
1426 	DPRINTF(("cs4281_attach_codec:\n"));
1427 	sc = addr;
1428 	sc->codec_if = codec_if;
1429 	return (0);
1430 }
1431 
1432 
1433 int
1434 cs4281_read_codec(void *addr, u_int8_t ac97_addr, u_int16_t *ac97_data)
1435 {
1436 	struct cs4281_softc *sc;
1437 	u_int32_t acctl;
1438 	int n;
1439 
1440 	sc = addr;
1441 
1442 	DPRINTFN(5,("read_codec: add=0x%02x ", ac97_addr));
1443 	/*
1444 	 * Make sure that there is not data sitting around from a preivous
1445 	 * uncompleted access.
1446 	 */
1447 	BA0READ4(sc, CS4281_ACSDA);
1448 
1449 	/* Set up AC97 control registers. */
1450 	BA0WRITE4(sc, CS4281_ACCAD, ac97_addr);
1451 	BA0WRITE4(sc, CS4281_ACCDA, 0);
1452 
1453 	acctl = ACCTL_ESYN | ACCTL_VFRM | ACCTL_CRW  | ACCTL_DCV;
1454 	BA0WRITE4(sc, CS4281_ACCTL, acctl);
1455 
1456 	if (cs4281_src_wait(sc) < 0) {
1457 		printf("%s: AC97 read prob. (DCV!=0) for add=0x%0x\n",
1458 		       sc->sc_dev.dv_xname, ac97_addr);
1459 		return 1;
1460 	}
1461 
1462 	/* wait for valid status bit is active */
1463 	n = 0;
1464 	while ((BA0READ4(sc, CS4281_ACSTS) & ACSTS_VSTS) == 0) {
1465 		delay(1);
1466 		while (++n > 1000) {
1467 			printf("%s: AC97 read fail (VSTS==0) for add=0x%0x\n",
1468 			       sc->sc_dev.dv_xname, ac97_addr);
1469 			return 1;
1470 		}
1471 	}
1472 	*ac97_data = BA0READ4(sc, CS4281_ACSDA);
1473 	DPRINTFN(5,("data=0x%04x\n", *ac97_data));
1474 	return (0);
1475 }
1476 
1477 int
1478 cs4281_write_codec(void *addr, u_int8_t ac97_addr, u_int16_t ac97_data)
1479 {
1480 	struct cs4281_softc *sc;
1481 	u_int32_t acctl;
1482 
1483 	sc = addr;
1484 
1485 	DPRINTFN(5,("write_codec: add=0x%02x  data=0x%04x\n", ac97_addr, ac97_data));
1486 	BA0WRITE4(sc, CS4281_ACCAD, ac97_addr);
1487 	BA0WRITE4(sc, CS4281_ACCDA, ac97_data);
1488 
1489 	acctl = ACCTL_ESYN | ACCTL_VFRM | ACCTL_DCV;
1490 	BA0WRITE4(sc, CS4281_ACCTL, acctl);
1491 
1492 	if (cs4281_src_wait(sc) < 0) {
1493 		printf("%s: AC97 write fail (DCV!=0) for add=0x%02x data="
1494 		       "0x%04x\n", sc->sc_dev.dv_xname, ac97_addr, ac97_data);
1495 		return (1);
1496 	}
1497 	return (0);
1498 }
1499 
1500 int
1501 cs4281_allocmem(struct cs4281_softc *sc, size_t size, int pool, int flags,
1502 		struct cs4281_dma *p)
1503 {
1504 	int error;
1505 	size_t align;
1506 
1507 	align   = sc->dma_align;
1508 	p->size = sc->dma_size;
1509 	/* allocate memory for upper audio driver */
1510 	p->dum  = malloc(size, pool, flags);
1511 	if (!p->dum)
1512 		return (1);
1513 	error = bus_dmamem_alloc(sc->sc_dmatag, p->size, align, 0,
1514 				 p->segs, nitems(p->segs),
1515 				 &p->nsegs, BUS_DMA_NOWAIT);
1516 	if (error) {
1517 		printf("%s: unable to allocate dma. error=%d\n",
1518 		       sc->sc_dev.dv_xname, error);
1519 		return (error);
1520 	}
1521 
1522 	error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size,
1523 			       &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
1524 	if (error) {
1525 		printf("%s: unable to map dma, error=%d\n",
1526 		       sc->sc_dev.dv_xname, error);
1527 		goto free;
1528 	}
1529 
1530 	error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size,
1531 				  0, BUS_DMA_NOWAIT, &p->map);
1532 	if (error) {
1533 		printf("%s: unable to create dma map, error=%d\n",
1534 		       sc->sc_dev.dv_xname, error);
1535 		goto unmap;
1536 	}
1537 
1538 	error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL,
1539 				BUS_DMA_NOWAIT);
1540 	if (error) {
1541 		printf("%s: unable to load dma map, error=%d\n",
1542 		       sc->sc_dev.dv_xname, error);
1543 		goto destroy;
1544 	}
1545 	return (0);
1546 
1547 destroy:
1548 	bus_dmamap_destroy(sc->sc_dmatag, p->map);
1549 unmap:
1550 	bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
1551 free:
1552 	bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
1553 	return (error);
1554 }
1555 
1556 
1557 int
1558 cs4281_src_wait(sc)
1559 	struct cs4281_softc *sc;
1560 {
1561 	int n;
1562 
1563 	n = 0;
1564 	while ((BA0READ4(sc, CS4281_ACCTL) & ACCTL_DCV)) {
1565 		delay(1000);
1566 		if (++n > 1000)
1567 			return (-1);
1568 	}
1569 	return (0);
1570 }
1571