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