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