xref: /openbsd/sys/dev/pci/auixp.c (revision 771fbea0)
1 /* $OpenBSD: auixp.c,v 1.43 2020/06/27 00:33:59 jsg Exp $ */
2 /* $NetBSD: auixp.c,v 1.9 2005/06/27 21:13:09 thorpej Exp $ */
3 
4 /*
5  * Copyright (c) 2004, 2005 Reinoud Zandijk <reinoud@netbsd.org>
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 /*
29  * Audio driver for ATI IXP-{150,200,...} audio driver hardware.
30  *
31  * Recording and playback has been tested OK on various sample rates and
32  * encodings.
33  *
34  * Known problems and issues :
35  * - SPDIF is untested and needs some work still (LED stays off)
36  * - 32 bit audio playback failed last time i tried but that might an AC'97
37  *   codec support problem.
38  * - 32 bit recording works but can't try out playing: see above.
39  * - no suspend/resume support yet.
40  * - multiple codecs are `supported' but not tested; the implemetation needs
41  *   some cleaning up.
42  */
43 
44 /*#define DEBUG_AUIXP*/
45 
46 #include <sys/param.h>
47 #include <sys/errno.h>
48 #include <sys/systm.h>
49 #include <sys/malloc.h>
50 #include <sys/device.h>
51 #include <sys/conf.h>
52 #include <sys/exec.h>
53 #include <sys/selinfo.h>
54 #include <sys/audioio.h>
55 #include <sys/queue.h>
56 
57 #include <machine/bus.h>
58 
59 #include <dev/pci/pcidevs.h>
60 #include <dev/pci/pcivar.h>
61 
62 #include <dev/audio_if.h>
63 #include <dev/ic/ac97.h>
64 
65 #include <dev/pci/auixpreg.h>
66 #include <dev/pci/auixpvar.h>
67 
68 /* codec detection constant indicating the interrupt flags */
69 #define ALL_CODECS_NOT_READY \
70     (ATI_REG_ISR_CODEC0_NOT_READY | ATI_REG_ISR_CODEC1_NOT_READY |\
71      ATI_REG_ISR_CODEC2_NOT_READY)
72 #define CODEC_CHECK_BITS (ALL_CODECS_NOT_READY|ATI_REG_ISR_NEW_FRAME)
73 
74 /* why isn't this base address register not in the headerfile? */
75 #define PCI_CBIO 0x10
76 
77 /* macro's used */
78 #define KERNADDR(p)	((void *)((p)->addr))
79 #define	DMAADDR(p)	((p)->map->dm_segs[0].ds_addr)
80 
81 const struct pci_matchid auixp_pci_devices[] = {
82 	{ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_SB200_AUDIO },
83 	{ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_SB300_AUDIO },
84 	{ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_SB400_AUDIO },
85 	{ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_SB600_AUDIO }
86 };
87 
88 struct cfdriver auixp_cd = {
89 	NULL, "auixp", DV_DULL
90 };
91 
92 int	auixp_match( struct device *, void *, void *);
93 void	auixp_attach(struct device *, struct device *, void *);
94 int	auixp_detach(struct device *, int);
95 
96 int	auixp_activate(struct device *, int);
97 
98 struct cfattach auixp_ca = {
99 	sizeof(struct auixp_softc), auixp_match, auixp_attach,
100 	NULL, auixp_activate
101 };
102 
103 int	auixp_open(void *v, int flags);
104 void	auixp_close(void *v);
105 int	auixp_set_params(void *, int, int, struct audio_params *,
106     struct audio_params *);
107 int	auixp_commit_settings(void *);
108 int	auixp_round_blocksize(void *, int);
109 int	auixp_trigger_output(void *, void *, void *, int,
110     void (*)(void *), void *, struct audio_params *);
111 int	auixp_trigger_input(void *, void *, void *, int,
112     void (*)(void *), void *, struct audio_params *);
113 int	auixp_halt_output(void *);
114 int	auixp_halt_input(void *);
115 int	auixp_set_port(void *, mixer_ctrl_t *);
116 int	auixp_get_port(void *, mixer_ctrl_t *);
117 int	auixp_query_devinfo(void *, mixer_devinfo_t *);
118 void *	auixp_malloc(void *, int, size_t, int, int);
119 void	auixp_free(void *, void *, int);
120 int	auixp_get_props(void *);
121 int	auixp_intr(void *);
122 int	auixp_allocmem(struct auixp_softc *, size_t, size_t,
123     struct auixp_dma *);
124 int	auixp_freemem(struct auixp_softc *, struct auixp_dma *);
125 
126 /* Supporting subroutines */
127 int	auixp_init(struct auixp_softc *);
128 void	auixp_autodetect_codecs(struct auixp_softc *);
129 void	auixp_post_config(struct device *);
130 
131 void	auixp_reset_aclink(struct auixp_softc *);
132 int	auixp_attach_codec(void *, struct ac97_codec_if *);
133 int	auixp_read_codec(void *, u_int8_t, u_int16_t *);
134 int	auixp_write_codec(void *, u_int8_t, u_int16_t);
135 int	auixp_wait_for_codecs(struct auixp_softc *, const char *);
136 void	auixp_reset_codec(void *);
137 enum ac97_host_flags	auixp_flags_codec(void *);
138 
139 void	auixp_enable_dma(struct auixp_softc *, struct auixp_dma *);
140 void	auixp_disable_dma(struct auixp_softc *, struct auixp_dma *);
141 void	auixp_enable_interrupts(struct auixp_softc *);
142 void	auixp_disable_interrupts(struct auixp_softc *);
143 
144 void	auixp_link_daisychain(struct auixp_softc *,
145     struct auixp_dma *, struct auixp_dma *, int, int);
146 int	auixp_allocate_dma_chain(struct auixp_softc *, struct auixp_dma **);
147 void	auixp_program_dma_chain(struct auixp_softc *, struct auixp_dma *);
148 void	auixp_dma_update(struct auixp_softc *, struct auixp_dma *);
149 void	auixp_update_busbusy(struct auixp_softc *);
150 
151 #ifdef DEBUG_AUIXP
152 #define DPRINTF(x)	printf x;
153 #else
154 #define DPRINTF(x)
155 #endif
156 
157 struct audio_hw_if auixp_hw_if = {
158 	auixp_open,
159 	auixp_close,
160 	auixp_set_params,
161 	auixp_round_blocksize,
162 	auixp_commit_settings,
163 	NULL,			/* init_output  */
164 	NULL,			/* init_input   */
165 	NULL,			/* start_output */
166 	NULL,			/* start_input  */
167 	auixp_halt_output,
168 	auixp_halt_input,
169 	NULL,			/* speaker_ctl */
170 	NULL,			/* getfd */
171 	auixp_set_port,
172 	auixp_get_port,
173 	auixp_query_devinfo,
174 	auixp_malloc,
175 	auixp_free,
176 	NULL,			/* round_buffersize */
177 	auixp_get_props,
178 	auixp_trigger_output,
179 	auixp_trigger_input
180 };
181 
182 int
183 auixp_open(void *v, int flags)
184 {
185 
186 	return 0;
187 }
188 
189 void
190 auixp_close(void *v)
191 {
192 }
193 
194 /* commit setting and program ATI IXP chip */
195 int
196 auixp_commit_settings(void *hdl)
197 {
198 	struct auixp_codec *co;
199 	struct auixp_softc *sc;
200 	bus_space_tag_t    iot;
201 	bus_space_handle_t ioh;
202 	struct audio_params *params;
203 	u_int32_t value;
204 
205 	/* XXX would it be better to stop interrupts first? XXX */
206 	co = (struct auixp_codec *) hdl;
207 	sc = co->sc;
208 	iot = sc->sc_iot;
209 	ioh = sc->sc_ioh;
210 
211 	/* process input settings */
212 	params = &sc->sc_play_params;
213 
214 	/* set input interleaving (precision) */
215 	value  =  bus_space_read_4(iot, ioh, ATI_REG_CMD);
216 	value &= ~ATI_REG_CMD_INTERLEAVE_IN;
217 	if (params->precision <= 16)
218 		value |= ATI_REG_CMD_INTERLEAVE_IN;
219 	bus_space_write_4(iot, ioh, ATI_REG_CMD, value);
220 
221 	/* process output settings */
222 	params = &sc->sc_play_params;
223 
224 	value  =  bus_space_read_4(iot, ioh, ATI_REG_OUT_DMA_SLOT);
225 	value &= ~ATI_REG_OUT_DMA_SLOT_MASK;
226 
227 	/* TODO SPDIF case for 8 channels */
228 	switch (params->channels) {
229 	case 6:
230 		value |= ATI_REG_OUT_DMA_SLOT_BIT(7) |
231 			 ATI_REG_OUT_DMA_SLOT_BIT(8);
232 		/* FALLTHROUGH */
233 	case 4:
234 		value |= ATI_REG_OUT_DMA_SLOT_BIT(6) |
235 			 ATI_REG_OUT_DMA_SLOT_BIT(9);
236 		/* FALLTHROUGH */
237 	default:
238 		value |= ATI_REG_OUT_DMA_SLOT_BIT(3) |
239 			 ATI_REG_OUT_DMA_SLOT_BIT(4);
240 		break;
241 	}
242 	/* set output threshold */
243 	value |= 0x04 << ATI_REG_OUT_DMA_THRESHOLD_SHIFT;
244 	bus_space_write_4(iot, ioh, ATI_REG_OUT_DMA_SLOT, value);
245 
246 	/* set output interleaving (precision) */
247 	value  =  bus_space_read_4(iot, ioh, ATI_REG_CMD);
248 	value &= ~ATI_REG_CMD_INTERLEAVE_OUT;
249 	if (params->precision <= 16)
250 		value |= ATI_REG_CMD_INTERLEAVE_OUT;
251 	bus_space_write_4(iot, ioh, ATI_REG_CMD, value);
252 
253 	/* enable 6 channel reordering */
254 	value  =  bus_space_read_4(iot, ioh, ATI_REG_6CH_REORDER);
255 	value &= ~ATI_REG_6CH_REORDER_EN;
256 	if (params->channels == 6)
257 		value |= ATI_REG_6CH_REORDER_EN;
258 	bus_space_write_4(iot, ioh, ATI_REG_6CH_REORDER, value);
259 
260 	if (sc->has_spdif) {
261 		/* set SPDIF (if present) */
262 		value  =  bus_space_read_4(iot, ioh, ATI_REG_CMD);
263 		value &= ~ATI_REG_CMD_SPDF_CONFIG_MASK;
264 		value |=  ATI_REG_CMD_SPDF_CONFIG_34; /* NetBSD AC'97 default */
265 
266 		/* XXX this is probably not necessary unless splitted XXX */
267 		value &= ~ATI_REG_CMD_INTERLEAVE_SPDF;
268 		if (params->precision <= 16)
269 			value |= ATI_REG_CMD_INTERLEAVE_SPDF;
270 		bus_space_write_4(iot, ioh, ATI_REG_CMD, value);
271 	}
272 
273 	return 0;
274 }
275 
276 
277 /* set audio properties in desired setting */
278 int
279 auixp_set_params(void *hdl, int setmode, int usemode,
280     struct audio_params *play, struct audio_params *rec)
281 {
282 	struct auixp_codec *co;
283 	int error;
284 	u_int temprate;
285 
286 	co = (struct auixp_codec *) hdl;
287 	if (setmode & AUMODE_PLAY) {
288 		play->channels = 2;
289 		play->precision = 16;
290 		switch(play->encoding) {
291 		case AUDIO_ENCODING_SLINEAR_LE:
292 			break;
293 		default:
294 			return (EINVAL);
295 		}
296 		play->bps = AUDIO_BPS(play->precision);
297 		play->msb = 1;
298 
299 		temprate = play->sample_rate;
300 		error = ac97_set_rate(co->codec_if,
301 		    AC97_REG_PCM_LFE_DAC_RATE, &play->sample_rate);
302 		if (error)
303 			return (error);
304 
305 		play->sample_rate = temprate;
306 		error = ac97_set_rate(co->codec_if,
307 		    AC97_REG_PCM_SURR_DAC_RATE, &play->sample_rate);
308 		if (error)
309 			return (error);
310 
311 		play->sample_rate = temprate;
312 		error = ac97_set_rate(co->codec_if,
313 		    AC97_REG_PCM_FRONT_DAC_RATE, &play->sample_rate);
314 		if (error)
315 			return (error);
316 
317 	}
318 
319 	if (setmode & AUMODE_RECORD) {
320 		rec->channels = 2;
321 		rec->precision = 16;
322 		switch(rec->encoding) {
323 		case AUDIO_ENCODING_SLINEAR_LE:
324 			break;
325 		default:
326 			return (EINVAL);
327 		}
328 		rec->bps = AUDIO_BPS(rec->precision);
329 		rec->msb = 1;
330 
331 		error = ac97_set_rate(co->codec_if, AC97_REG_PCM_LR_ADC_RATE,
332 		    &rec->sample_rate);
333 		if (error)
334 			return (error);
335 	}
336 
337 	return (0);
338 }
339 
340 
341 /* called to translate a requested blocksize to a hw-possible one */
342 int
343 auixp_round_blocksize(void *v, int blk)
344 {
345 
346 	blk = (blk + 0x1f) & ~0x1f;
347 	/* Be conservative; align to 32 bytes and maximise it to 64 kb */
348 	if (blk > 0x10000)
349 		blk = 0x10000;
350 
351 	return blk;
352 }
353 
354 
355 /*
356  * allocate dma capable memory and record its information for later retrieval
357  * when we program the dma chain itself. The trigger routines passes on the
358  * kernel virtual address we return here as a reference to the mapping.
359  */
360 void *
361 auixp_malloc(void *hdl, int direction, size_t size, int pool, int flags)
362 {
363 	struct auixp_codec *co;
364 	struct auixp_softc *sc;
365 	struct auixp_dma *dma;
366 	int error;
367 
368 	co = (struct auixp_codec *) hdl;
369 	sc = co->sc;
370 	/* get us a auixp_dma structure */
371 	dma = malloc(sizeof(*dma), pool, flags);
372 	if (!dma)
373 		return NULL;
374 
375 	/* get us a dma buffer itself */
376 	error = auixp_allocmem(sc, size, 16, dma);
377 	if (error) {
378 		free(dma, pool, sizeof(*dma));
379 		printf("%s: auixp_malloc: not enough memory\n",
380 		    sc->sc_dev.dv_xname);
381 		return NULL;
382 	}
383 	SLIST_INSERT_HEAD(&sc->sc_dma_list, dma, dma_chain);
384 
385 	DPRINTF(("auixp_malloc: returning kern %p,   hw 0x%08x for %d bytes "
386 	    "in %d segs\n", KERNADDR(dma), (u_int32_t) DMAADDR(dma), dma->size,
387 	    dma->nsegs)
388 	);
389 
390 	return KERNADDR(dma);
391 }
392 
393 /*
394  * free and release dma capable memory we allocated before and remove its
395  * recording
396  */
397 void
398 auixp_free(void *hdl, void *addr, int pool)
399 {
400 	struct auixp_codec *co;
401 	struct auixp_softc *sc;
402 	struct auixp_dma *dma;
403 
404 	co = (struct auixp_codec *) hdl;
405 	sc = co->sc;
406 	SLIST_FOREACH(dma, &sc->sc_dma_list, dma_chain) {
407 		if (KERNADDR(dma) == addr) {
408 			SLIST_REMOVE(&sc->sc_dma_list, dma, auixp_dma,
409 			    dma_chain);
410 			auixp_freemem(sc, dma);
411 			free(dma, pool, sizeof(*dma));
412 			return;
413 		}
414 	}
415 }
416 
417 /* pass request to AC'97 codec code */
418 int
419 auixp_set_port(void *hdl, mixer_ctrl_t *mc)
420 {
421 	struct auixp_codec *co;
422 
423 	co = (struct auixp_codec *) hdl;
424 	return co->codec_if->vtbl->mixer_set_port(co->codec_if, mc);
425 }
426 
427 
428 /* pass request to AC'97 codec code */
429 int
430 auixp_get_port(void *hdl, mixer_ctrl_t *mc)
431 {
432 	struct auixp_codec *co;
433 
434 	co = (struct auixp_codec *) hdl;
435 	return co->codec_if->vtbl->mixer_get_port(co->codec_if, mc);
436 }
437 
438 /* pass request to AC'97 codec code */
439 int
440 auixp_query_devinfo(void *hdl, mixer_devinfo_t *di)
441 {
442 	struct auixp_codec *co;
443 
444 	co = (struct auixp_codec *) hdl;
445 	return co->codec_if->vtbl->query_devinfo(co->codec_if, di);
446 }
447 
448 int
449 auixp_get_props(void *hdl)
450 {
451 
452 	return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
453 }
454 
455 
456 /*
457  * A dma descriptor has dma->nsegs segments defined in dma->segs set up when
458  * we claimed the memory.
459  *
460  * Due to our demand for one contiguous DMA area, we only have one segment. A
461  * c_dma structure is about 3 kb for the 256 entries we maximally program
462  * -arbitrary limit AFAIK- so all is most likely to be in one segment/page
463  * anyway.
464  *
465  * XXX ought to implement fragmented dma area XXX
466  *
467  * Note that _v variables depict kernel virtual addresses, _p variables depict
468  * physical addresses.
469  */
470 void
471 auixp_link_daisychain(struct auixp_softc *sc,
472 		struct auixp_dma *c_dma, struct auixp_dma *s_dma,
473 		int blksize, int blocks)
474 {
475 	atiixp_dma_desc_t *caddr_v, *next_caddr_v;
476 	u_int32_t caddr_p, next_caddr_p, saddr_p;
477 	int i;
478 
479 	/* just make sure we are not changing when its running */
480 	auixp_disable_dma(sc, c_dma);
481 
482 	/* setup dma chain start addresses */
483 	caddr_v = KERNADDR(c_dma);
484 	caddr_p = DMAADDR(c_dma);
485 	saddr_p = DMAADDR(s_dma);
486 
487 	/* program the requested number of blocks */
488 	for (i = 0; i < blocks; i++) {
489 		/* clear the block just in case */
490 		bzero(caddr_v, sizeof(atiixp_dma_desc_t));
491 
492 		/* round robin the chain dma addresses for its successor */
493 		next_caddr_v = caddr_v + 1;
494 		next_caddr_p = caddr_p + sizeof(atiixp_dma_desc_t);
495 
496 		if (i == blocks-1) {
497 			next_caddr_v = KERNADDR(c_dma);
498 			next_caddr_p = DMAADDR(c_dma);
499 		}
500 
501 		/* fill in the hardware dma chain descriptor in little-endian */
502 		caddr_v->addr   = htole32(saddr_p);
503 		caddr_v->status = htole16(0);
504 		caddr_v->size   = htole16((blksize >> 2)); /* in dwords (!!!) */
505 		caddr_v->next   = htole32(next_caddr_p);
506 
507 		/* advance slot */
508 		saddr_p += blksize;	/* XXX assuming contiguous XXX */
509 		caddr_v  = next_caddr_v;
510 		caddr_p  = next_caddr_p;
511 	}
512 }
513 
514 
515 int
516 auixp_allocate_dma_chain(struct auixp_softc *sc, struct auixp_dma **dmap)
517 {
518 	struct auixp_dma *dma;
519 	int error;
520 
521 	/* allocate keeper of dma area */
522 	*dmap = NULL;
523 	dma = malloc(sizeof(*dma), M_DEVBUF, M_NOWAIT | M_ZERO);
524 	if (!dma)
525 		return ENOMEM;
526 
527 	/* allocate for daisychain of IXP hardware-dma descriptors */
528 	error = auixp_allocmem(sc, DMA_DESC_CHAIN * sizeof(atiixp_dma_desc_t),
529 	    16, dma);
530 	if (error) {
531 		printf("%s: can't malloc dma descriptor chain\n",
532 		    sc->sc_dev.dv_xname);
533 		free(dma, M_DEVBUF, sizeof(*dma));
534 		return ENOMEM;
535 	}
536 
537 	/* return info and initialise structure */
538 	dma->intr    = NULL;
539 	dma->intrarg = NULL;
540 
541 	*dmap = dma;
542 	return 0;
543 }
544 
545 
546 /* program dma chain in its link address descriptor */
547 void
548 auixp_program_dma_chain(struct auixp_softc *sc, struct auixp_dma *dma)
549 {
550 	bus_space_tag_t    iot;
551 	bus_space_handle_t ioh;
552 	u_int32_t value;
553 
554 	iot = sc->sc_iot;
555 	ioh = sc->sc_ioh;
556 	/* get hardware start address of DMA chain and set valid-flag in it */
557 	/* XXX always at start? XXX */
558 	value = DMAADDR(dma);
559 	value = value | ATI_REG_LINKPTR_EN;
560 
561 	/* reset linkpointer */
562 	bus_space_write_4(iot, ioh, dma->linkptr, 0);
563 
564 	/* reset this DMA engine */
565 	auixp_disable_dma(sc, dma);
566 	auixp_enable_dma(sc, dma);
567 
568 	/* program new DMA linkpointer */
569 	bus_space_write_4(iot, ioh, dma->linkptr, value);
570 }
571 
572 
573 /* called from interrupt code to signal end of one dma-slot */
574 void
575 auixp_dma_update(struct auixp_softc *sc, struct auixp_dma *dma)
576 {
577 
578 	/* be very paranoid */
579 	if (!dma)
580 		panic("auixp: update: dma = NULL");
581 	if (!dma->intr)
582 		panic("auixp: update: dma->intr = NULL");
583 
584 	/* request more input from upper layer */
585 	(*dma->intr)(dma->intrarg);
586 }
587 
588 
589 /*
590  * The magic `busbusy' bit that needs to be set when dma is active; allowing
591  * busmastering?
592  */
593 void
594 auixp_update_busbusy(struct auixp_softc *sc)
595 {
596 	bus_space_tag_t    iot;
597 	bus_space_handle_t ioh;
598 	u_int32_t value;
599 	int running;
600 
601 	iot = sc->sc_iot;
602 	ioh = sc->sc_ioh;
603 	/* set bus-busy flag when either recording or playing is performed */
604 	value  = bus_space_read_4(iot, ioh, ATI_REG_IER);
605 	value &= ~ATI_REG_IER_SET_BUS_BUSY;
606 
607 	running = ((sc->sc_output_dma->running) || (sc->sc_input_dma->running));
608 	if (running)
609 		value |= ATI_REG_IER_SET_BUS_BUSY;
610 
611 	bus_space_write_4(iot, ioh, ATI_REG_IER, value);
612 
613 }
614 
615 
616 /*
617  * Called from upper audio layer to request playing audio, only called once;
618  * audio is refilled by calling the intr() function when space is available
619  * again.
620  */
621 /* XXX almost literally a copy of trigger-input; could be factorised XXX */
622 int
623 auixp_trigger_output(void *hdl, void *start, void *end, int blksize,
624     void (*intr)(void *), void *intrarg, struct audio_params *param)
625 {
626 	struct auixp_codec *co;
627 	struct auixp_softc *sc;
628 	struct auixp_dma   *chain_dma;
629 	struct auixp_dma   *sound_dma;
630 	u_int32_t blocks;
631 
632 	co = (struct auixp_codec *) hdl;
633 	sc = co->sc;
634 	chain_dma = sc->sc_output_dma;
635 	/* add functions to call back */
636 	chain_dma->intr    = intr;
637 	chain_dma->intrarg = intrarg;
638 
639 	/*
640 	 * Program output DMA chain with blocks from [start...end] with
641 	 * blksize fragments.
642 	 *
643 	 * NOTE, we can assume its in one block since we asked for it to be in
644 	 * one contiguous blob; XXX change this? XXX
645 	 */
646 	blocks = (size_t) (((caddr_t) end) - ((caddr_t) start)) / blksize;
647 
648 	/* lookup `start' address in our list of DMA area's */
649 	SLIST_FOREACH(sound_dma, &sc->sc_dma_list, dma_chain) {
650 		if (KERNADDR(sound_dma) == start)
651 			break;
652 	}
653 
654 	/* not ours ? then bail out */
655 	if (!sound_dma) {
656 		printf("%s: auixp_trigger_output: bad sound addr %p\n",
657 		    sc->sc_dev.dv_xname, start);
658 		return EINVAL;
659 	}
660 
661 	/* link round-robin daisychain and program hardware */
662 	auixp_link_daisychain(sc, chain_dma, sound_dma, blksize, blocks);
663 	auixp_program_dma_chain(sc, chain_dma);
664 
665 	/* mark we are now able to run now */
666 	mtx_enter(&audio_lock);
667 	chain_dma->running = 1;
668 
669 	/* update bus-flags; XXX programs more flags XXX */
670 	auixp_update_busbusy(sc);
671 	mtx_leave(&audio_lock);
672 
673 	/* callbacks happen in interrupt routine */
674 	return 0;
675 }
676 
677 
678 /* halt output of audio, just disable its dma and update bus state */
679 int
680 auixp_halt_output(void *hdl)
681 {
682 	struct auixp_codec *co;
683 	struct auixp_softc *sc;
684 	struct auixp_dma   *dma;
685 
686 	mtx_enter(&audio_lock);
687 	co  = (struct auixp_codec *) hdl;
688 	sc  = co->sc;
689 	dma = sc->sc_output_dma;
690 	auixp_disable_dma(sc, dma);
691 
692 	dma->running = 0;
693 	auixp_update_busbusy(sc);
694 	mtx_leave(&audio_lock);
695 	return 0;
696 }
697 
698 
699 /* XXX almost literally a copy of trigger-output; could be factorised XXX */
700 int
701 auixp_trigger_input(void *hdl, void *start, void *end, int blksize,
702     void (*intr)(void *), void *intrarg, struct audio_params *param)
703 {
704 	struct auixp_codec *co;
705 	struct auixp_softc *sc;
706 	struct auixp_dma   *chain_dma;
707 	struct auixp_dma   *sound_dma;
708 	u_int32_t blocks;
709 
710 	co = (struct auixp_codec *) hdl;
711 	sc = co->sc;
712 	chain_dma = sc->sc_input_dma;
713 	/* add functions to call back */
714 	chain_dma->intr    = intr;
715 	chain_dma->intrarg = intrarg;
716 
717 	/*
718 	 * Program output DMA chain with blocks from [start...end] with
719 	 * blksize fragments.
720 	 *
721 	 * NOTE, we can assume its in one block since we asked for it to be in
722 	 * one contiguous blob; XXX change this? XXX
723 	 */
724 	blocks = (size_t) (((caddr_t) end) - ((caddr_t) start)) / blksize;
725 
726 	/* lookup `start' address in our list of DMA area's */
727 	SLIST_FOREACH(sound_dma, &sc->sc_dma_list, dma_chain) {
728 		if (KERNADDR(sound_dma) == start)
729 			break;
730 	}
731 
732 	/* not ours ? then bail out */
733 	if (!sound_dma) {
734 		printf("%s: auixp_trigger_input: bad sound addr %p\n",
735 		    sc->sc_dev.dv_xname, start);
736 		return EINVAL;
737 	}
738 
739 	/* link round-robin daisychain and program hardware */
740 	auixp_link_daisychain(sc, chain_dma, sound_dma, blksize, blocks);
741 	auixp_program_dma_chain(sc, chain_dma);
742 
743 	/* mark we are now able to run now */
744 	mtx_enter(&audio_lock);
745 	chain_dma->running = 1;
746 
747 	/* update bus-flags; XXX programs more flags XXX */
748 	auixp_update_busbusy(sc);
749 	mtx_leave(&audio_lock);
750 
751 	/* callbacks happen in interrupt routine */
752 	return 0;
753 }
754 
755 
756 /* halt sampling audio, just disable its dma and update bus state */
757 int
758 auixp_halt_input(void *hdl)
759 {
760 	struct auixp_codec *co;
761 	struct auixp_softc *sc;
762 	struct auixp_dma   *dma;
763 
764 	mtx_enter(&audio_lock);
765 	co = (struct auixp_codec *) hdl;
766 	sc = co->sc;
767 	dma = sc->sc_input_dma;
768 	auixp_disable_dma(sc, dma);
769 
770 	dma->running = 0;
771 	auixp_update_busbusy(sc);
772 
773 	mtx_leave(&audio_lock);
774 	return 0;
775 }
776 
777 
778 /*
779  * IXP audio interrupt handler
780  *
781  * note that we return the number of bits handled; the return value is not
782  * documented but I saw it implemented in other drivers. Probably returning a
783  * value > 0 means "I've dealt with it"
784  *
785  */
786 int
787 auixp_intr(void *softc)
788 {
789 	struct auixp_softc *sc;
790 	bus_space_tag_t    iot;
791 	bus_space_handle_t ioh;
792 	u_int32_t status, enable, detected_codecs;
793 	int ret;
794 
795 	mtx_enter(&audio_lock);
796 	sc = softc;
797 	iot = sc->sc_iot;
798 	ioh = sc->sc_ioh;
799 	ret = 0;
800 	/* get status from the interrupt status register */
801 	status = bus_space_read_4(iot, ioh, ATI_REG_ISR);
802 
803 	if (status == 0) {
804 		mtx_leave(&audio_lock);
805 		return 0;
806 	}
807 
808 	DPRINTF(("%s: (status = %x)\n", sc->sc_dev.dv_xname, status));
809 
810 	/* check DMA UPDATE flags for input & output */
811 	if (status & ATI_REG_ISR_IN_STATUS) {
812 		ret++; DPRINTF(("IN_STATUS\n"));
813 		auixp_dma_update(sc, sc->sc_input_dma);
814 	}
815 	if (status & ATI_REG_ISR_OUT_STATUS) {
816 		ret++; DPRINTF(("OUT_STATUS\n"));
817 		auixp_dma_update(sc, sc->sc_output_dma);
818 	}
819 
820 	/* XXX XRUN flags not used/needed yet; should i implement it? XXX */
821 	/* acknowledge the interrupts nevertheless */
822 	if (status & ATI_REG_ISR_IN_XRUN) {
823 		ret++; DPRINTF(("IN_XRUN\n"));
824 		/* auixp_dma_xrun(sc, sc->sc_input_dma);  */
825 	}
826 	if (status & ATI_REG_ISR_OUT_XRUN) {
827 		ret++; DPRINTF(("OUT_XRUN\n"));
828 		/* auixp_dma_xrun(sc, sc->sc_output_dma); */
829 	}
830 
831 	/* check if we are looking for codec detection */
832 	if (status & CODEC_CHECK_BITS) {
833 		ret++;
834 		/* mark missing codecs as not ready */
835 		detected_codecs = status & CODEC_CHECK_BITS;
836 		sc->sc_codec_not_ready_bits |= detected_codecs;
837 
838 		/* disable detected interrupt sources */
839 		enable  = bus_space_read_4(iot, ioh, ATI_REG_IER);
840 		enable &= ~detected_codecs;
841 		bus_space_write_4(iot, ioh, ATI_REG_IER, enable);
842 	}
843 
844 	/* acknowledge interrupt sources */
845 	bus_space_write_4(iot, ioh, ATI_REG_ISR, status);
846 	mtx_leave(&audio_lock);
847 	return ret;
848 }
849 
850 
851 /* allocate memory for dma purposes; on failure of any of the steps, roll back */
852 int
853 auixp_allocmem(struct auixp_softc *sc, size_t size,
854 	       size_t align, struct auixp_dma *dma)
855 {
856 	int error;
857 
858 	/* remember size */
859 	dma->size = size;
860 
861 	/* allocate DMA safe memory but in just one segment for now :( */
862 	error = bus_dmamem_alloc(sc->sc_dmat, dma->size, align, 0,
863 	    dma->segs, sizeof(dma->segs) / sizeof(dma->segs[0]), &dma->nsegs,
864 	    BUS_DMA_NOWAIT);
865 	if (error)
866 		return error;
867 
868 	/*
869 	 * map allocated memory into kernel virtual address space and keep it
870 	 * coherent with the CPU.
871 	 */
872 	error = bus_dmamem_map(sc->sc_dmat, dma->segs, dma->nsegs, dma->size,
873 				&dma->addr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
874 	if (error)
875 		goto free;
876 
877 	/* allocate associated dma handle and initialize it. */
878 	error = bus_dmamap_create(sc->sc_dmat, dma->size, 1, dma->size, 0,
879 				  BUS_DMA_NOWAIT, &dma->map);
880 	if (error)
881 		goto unmap;
882 
883 	/*
884 	 * load the dma handle with mappings for a dma transfer; all pages
885 	 * need to be wired.
886 	 */
887 	error = bus_dmamap_load(sc->sc_dmat, dma->map, dma->addr, dma->size, NULL,
888 				BUS_DMA_NOWAIT);
889 	if (error)
890 		goto destroy;
891 
892 	return 0;
893 
894 destroy:
895 	bus_dmamap_destroy(sc->sc_dmat, dma->map);
896 unmap:
897 	bus_dmamem_unmap(sc->sc_dmat, dma->addr, dma->size);
898 free:
899 	bus_dmamem_free(sc->sc_dmat, dma->segs, dma->nsegs);
900 
901 	return error;
902 }
903 
904 
905 /* undo dma mapping and release memory allocated */
906 int
907 auixp_freemem(struct auixp_softc *sc, struct auixp_dma *p)
908 {
909 
910 	bus_dmamap_unload(sc->sc_dmat, p->map);
911 	bus_dmamap_destroy(sc->sc_dmat, p->map);
912 	bus_dmamem_unmap(sc->sc_dmat, p->addr, p->size);
913 	bus_dmamem_free(sc->sc_dmat, p->segs, p->nsegs);
914 
915 	return 0;
916 }
917 
918 int
919 auixp_match(struct device *dev, void *match, void *aux)
920 {
921 	return (pci_matchbyid((struct pci_attach_args *)aux, auixp_pci_devices,
922 	    sizeof(auixp_pci_devices)/sizeof(auixp_pci_devices[0])));
923 }
924 
925 int
926 auixp_activate(struct device *self, int act)
927 {
928 	struct auixp_softc *sc = (struct auixp_softc *)self;
929 	int rv = 0;
930 
931 	switch (act) {
932 	case DVACT_SUSPEND:
933 		auixp_disable_interrupts(sc);
934 		break;
935 	case DVACT_RESUME:
936 		auixp_init(sc);
937 		ac97_resume(&sc->sc_codec.host_if, sc->sc_codec.codec_if);
938 		rv = config_activate_children(self, act);
939 		break;
940 	default:
941 		rv = config_activate_children(self, act);
942 		break;
943 	}
944 	return (rv);
945 }
946 
947 void
948 auixp_attach(struct device *parent, struct device *self, void *aux)
949 {
950 	struct auixp_softc *sc;
951 	struct pci_attach_args *pa;
952 	pcitag_t tag;
953 	pci_chipset_tag_t pc;
954 	pci_intr_handle_t ih;
955 	const char *intrstr;
956 
957 	sc = (struct auixp_softc *)self;
958 	pa = (struct pci_attach_args *)aux;
959 	tag = pa->pa_tag;
960 	pc = pa->pa_pc;
961 
962 	/* map memory; its not sized -> what is the size? max PCI slot size? */
963 	if (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_MEM, 0,
964 	    &sc->sc_iot, &sc->sc_ioh, &sc->sc_iob, &sc->sc_ios, 0)) {
965 		printf(": can't map mem space\n");
966 		return;
967 	}
968 
969 	/* Initialize softc */
970 	sc->sc_tag = tag;
971 	sc->sc_pct = pc;
972 	sc->sc_dmat = pa->pa_dmat;
973 	SLIST_INIT(&sc->sc_dma_list);
974 
975 	/* get us the auixp_dma structures */
976 	auixp_allocate_dma_chain(sc, &sc->sc_output_dma);
977 	auixp_allocate_dma_chain(sc, &sc->sc_input_dma);
978 
979 	/* when that fails we are dead in the water */
980 	if (!sc->sc_output_dma || !sc->sc_input_dma)
981 		return;
982 
983 #if 0
984 	/* could preliminary program DMA chain */
985 	auixp_program_dma_chain(sc, sc->sc_output_dma);
986 	auixp_program_dma_chain(sc, sc->sc_input_dma);
987 #endif
988 
989 	if (pci_intr_map(pa, &ih)) {
990 		printf(": can't map interrupt\n");
991 		return;
992 	}
993 	intrstr = pci_intr_string(pc, ih);
994 	sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO | IPL_MPSAFE,
995 	    auixp_intr, sc, sc->sc_dev.dv_xname);
996 	if (sc->sc_ih == NULL) {
997 		printf(": can't establish interrupt");
998 		if (intrstr != NULL)
999 			printf(" at %s", intrstr);
1000 		printf("\n");
1001 		return;
1002 	}
1003 	printf(": %s\n", intrstr);
1004 
1005 	/* power up chip */
1006 	pci_set_powerstate(pc, tag, PCI_PMCSR_STATE_D0);
1007 
1008 	/* init chip */
1009 	if (auixp_init(sc) == -1) {
1010 		printf("%s: auixp_attach: unable to initialize the card\n",
1011 		    sc->sc_dev.dv_xname);
1012 		return;
1013 	}
1014 
1015 	/*
1016 	 * delay further configuration of codecs and audio after interrupts
1017 	 * are enabled.
1018 	 */
1019 	config_mountroot(self, auixp_post_config);
1020 }
1021 
1022 /* called from autoconfigure system when interrupts are enabled */
1023 void
1024 auixp_post_config(struct device *self)
1025 {
1026 	struct auixp_softc *sc = (struct auixp_softc *)self;
1027 
1028 	/* detect the AC97 codecs */
1029 	auixp_autodetect_codecs(sc);
1030 
1031 	/* Bail if no codecs attached. */
1032 	if (!sc->sc_codec.present) {
1033 		printf("%s: no codecs detected or initialised\n",
1034 		    sc->sc_dev.dv_xname);
1035 		return;
1036 	}
1037 
1038 	audio_attach_mi(&auixp_hw_if, &sc->sc_codec, &sc->sc_dev);
1039 
1040 	if (sc->has_spdif)
1041 		sc->has_spdif = 0;
1042 
1043 	/* fill in the missing details about the dma channels. */
1044 	/* for output */
1045 	sc->sc_output_dma->linkptr        = ATI_REG_OUT_DMA_LINKPTR;
1046 	sc->sc_output_dma->dma_enable_bit = ATI_REG_CMD_OUT_DMA_EN |
1047 					    ATI_REG_CMD_SEND_EN;
1048 	/* have spdif? then this too! XXX not seeing LED yet! XXX */
1049 	if (sc->has_spdif)
1050 		sc->sc_output_dma->dma_enable_bit |= ATI_REG_CMD_SPDF_OUT_EN;
1051 
1052 	/* and for input */
1053 	sc->sc_input_dma->linkptr         = ATI_REG_IN_DMA_LINKPTR;
1054 	sc->sc_input_dma->dma_enable_bit  = ATI_REG_CMD_IN_DMA_EN  |
1055 					    ATI_REG_CMD_RECEIVE_EN;
1056 
1057 	/* done! now enable all interrupts we can service */
1058 	auixp_enable_interrupts(sc);
1059 }
1060 
1061 void
1062 auixp_enable_interrupts(struct auixp_softc *sc)
1063 {
1064 	bus_space_tag_t     iot;
1065 	bus_space_handle_t  ioh;
1066 	u_int32_t value;
1067 
1068 	iot = sc->sc_iot;
1069 	ioh = sc->sc_ioh;
1070 	/* clear all pending */
1071 	bus_space_write_4(iot, ioh, ATI_REG_ISR, 0xffffffff);
1072 
1073 	/* enable all relevant interrupt sources we can handle */
1074 	value = bus_space_read_4(iot, ioh, ATI_REG_IER);
1075 
1076 	value |= ATI_REG_IER_IO_STATUS_EN;
1077 
1078 	bus_space_write_4(iot, ioh, ATI_REG_IER, value);
1079 }
1080 
1081 void
1082 auixp_disable_interrupts(struct auixp_softc *sc)
1083 {
1084 	bus_space_tag_t     iot;
1085 	bus_space_handle_t  ioh;
1086 
1087 	iot = sc->sc_iot;
1088 	ioh = sc->sc_ioh;
1089 	/* disable all interrupt sources */
1090 	bus_space_write_4(iot, ioh, ATI_REG_IER, 0);
1091 
1092 	/* clear all pending */
1093 	bus_space_write_4(iot, ioh, ATI_REG_ISR, 0xffffffff);
1094 }
1095 
1096 /* dismantle what we've set up by undoing setup */
1097 int
1098 auixp_detach(struct device *self, int flags)
1099 {
1100 	struct auixp_softc *sc;
1101 
1102 	sc = (struct auixp_softc *)self;
1103 	/* XXX shouldn't we just reset the chip? XXX */
1104 	/*
1105 	 * should we explicitly disable interrupt generation and acknowledge
1106 	 * what's left on? better be safe than sorry.
1107 	 */
1108 	auixp_disable_interrupts(sc);
1109 
1110 	/* tear down .... */
1111 	config_detach(&sc->sc_dev, flags);	/* XXX OK? XXX */
1112 
1113 	if (sc->sc_ih != NULL)
1114 		pci_intr_disestablish(sc->sc_pct, sc->sc_ih);
1115 	if (sc->sc_ios)
1116 		bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
1117 	return 0;
1118 }
1119 
1120 
1121 /*
1122  * codec handling
1123  *
1124  * IXP audio support can have upto 3 codecs! are they chained ? or
1125  * alternative outlets with the same audio feed i.e. with different mixer
1126  * settings? XXX does NetBSD support more than one audio codec? XXX
1127  */
1128 
1129 
1130 int
1131 auixp_attach_codec(void *aux, struct ac97_codec_if *codec_if)
1132 {
1133 	struct auixp_codec *ixp_codec;
1134 
1135 	ixp_codec = aux;
1136 	ixp_codec->codec_if = codec_if;
1137 
1138 	return 0;
1139 }
1140 
1141 int
1142 auixp_read_codec(void *aux, u_int8_t reg, u_int16_t *result)
1143 {
1144 	struct auixp_codec *co;
1145 	struct auixp_softc *sc;
1146 	bus_space_tag_t     iot;
1147 	bus_space_handle_t  ioh;
1148 	u_int32_t data;
1149 	int timeout;
1150 
1151 	co  = aux;
1152 	sc  = co->sc;
1153 	iot = sc->sc_iot;
1154 	ioh = sc->sc_ioh;
1155 	if (auixp_wait_for_codecs(sc, "read_codec"))
1156 		return 0xffff;
1157 
1158 	/* build up command for reading codec register */
1159 	data = (reg << ATI_REG_PHYS_OUT_ADDR_SHIFT) |
1160 		ATI_REG_PHYS_OUT_ADDR_EN |
1161 		ATI_REG_PHYS_OUT_RW |
1162 		co->codec_nr;
1163 
1164 	bus_space_write_4(iot, ioh, ATI_REG_PHYS_OUT_ADDR, data);
1165 
1166 	if (auixp_wait_for_codecs(sc, "read_codec"))
1167 		return 0xffff;
1168 
1169 	/* wait until codec info is clocked in */
1170 	timeout = 500;		/* 500*2 usec -> 0.001 sec */
1171 	do {
1172 		data = bus_space_read_4(iot, ioh, ATI_REG_PHYS_IN_ADDR);
1173 		if (data & ATI_REG_PHYS_IN_READ_FLAG) {
1174 			DPRINTF(("read ac'97 codec reg 0x%x = 0x%08x\n",
1175 				reg, data >> ATI_REG_PHYS_IN_DATA_SHIFT));
1176 			*result = data >> ATI_REG_PHYS_IN_DATA_SHIFT;
1177 			return 0;
1178 		}
1179 		DELAY(2);
1180 		timeout--;
1181 	} while (timeout > 0);
1182 
1183 	if (reg < 0x7c)
1184 		printf("%s: codec read timeout! (reg %x)\n",
1185 		    sc->sc_dev.dv_xname, reg);
1186 
1187 	return 0xffff;
1188 }
1189 
1190 int
1191 auixp_write_codec(void *aux, u_int8_t reg, u_int16_t data)
1192 {
1193 	struct auixp_codec *co;
1194 	struct auixp_softc *sc;
1195 	bus_space_tag_t     iot;
1196 	bus_space_handle_t  ioh;
1197 	u_int32_t value;
1198 
1199 	DPRINTF(("write ac'97 codec reg 0x%x = 0x%08x\n", reg, data));
1200 	co  = aux;
1201 	sc  = co->sc;
1202 	iot = sc->sc_iot;
1203 	ioh = sc->sc_ioh;
1204 	if (auixp_wait_for_codecs(sc, "write_codec"))
1205 		return -1;
1206 
1207 	/* build up command for writing codec register */
1208 	value = (((u_int32_t) data) << ATI_REG_PHYS_OUT_DATA_SHIFT) |
1209 		(((u_int32_t)  reg) << ATI_REG_PHYS_OUT_ADDR_SHIFT) |
1210 		ATI_REG_PHYS_OUT_ADDR_EN |
1211 		co->codec_nr;
1212 
1213 	bus_space_write_4(iot, ioh, ATI_REG_PHYS_OUT_ADDR, value);
1214 
1215 	return 0;
1216 }
1217 
1218 void
1219 auixp_reset_codec(void *aux)
1220 {
1221 
1222 	/* nothing to be done? */
1223 }
1224 
1225 enum ac97_host_flags
1226 auixp_flags_codec(void *aux)
1227 {
1228 	struct auixp_codec *ixp_codec;
1229 
1230 	ixp_codec = aux;
1231 	return ixp_codec->codec_flags;
1232 }
1233 
1234 int
1235 auixp_wait_for_codecs(struct auixp_softc *sc, const char *func)
1236 {
1237 	bus_space_tag_t      iot;
1238 	bus_space_handle_t   ioh;
1239 	u_int32_t value;
1240 	int timeout;
1241 
1242 	iot = sc->sc_iot;
1243 	ioh = sc->sc_ioh;
1244 	/* wait until all codec transfers are done */
1245 	timeout = 500;		/* 500*2 usec -> 0.001 sec */
1246 	do {
1247 		value = bus_space_read_4(iot, ioh, ATI_REG_PHYS_OUT_ADDR);
1248 		if ((value & ATI_REG_PHYS_OUT_ADDR_EN) == 0)
1249 			return 0;
1250 
1251 		DELAY(2);
1252 		timeout--;
1253 	} while (timeout > 0);
1254 
1255 	printf("%s: %s: timed out\n", func, sc->sc_dev.dv_xname);
1256 	return -1;
1257 }
1258 
1259 void
1260 auixp_autodetect_codecs(struct auixp_softc *sc)
1261 {
1262 	bus_space_tag_t      iot;
1263 	bus_space_handle_t   ioh;
1264 	pcireg_t subdev;
1265 	struct auixp_codec  *codec;
1266 	int timeout;
1267 
1268 	iot = sc->sc_iot;
1269 	ioh = sc->sc_ioh;
1270 	subdev = pci_conf_read(sc->sc_pct, sc->sc_tag, PCI_SUBSYS_ID_REG);
1271 
1272 	/* ATI IXP can have upto 3 codecs; mark all codecs as not existing */
1273 	sc->sc_codec_not_ready_bits = 0;
1274 
1275 	/* enable all codecs to interrupt as well as the new frame interrupt */
1276 	bus_space_write_4(iot, ioh, ATI_REG_IER, CODEC_CHECK_BITS);
1277 
1278 	/* wait for the interrupts to happen */
1279 	timeout = 100;		/* 100.000 usec -> 0.1 sec */
1280 
1281 	while (timeout > 0) {
1282 		DELAY(1000);
1283 		if (sc->sc_codec_not_ready_bits)
1284 			break;
1285 		timeout--;
1286 	}
1287 
1288 	if (timeout == 0)
1289 		printf("%s: WARNING: timeout during codec detection; "
1290 			"codecs might be present but haven't interrupted\n",
1291 			sc->sc_dev.dv_xname);
1292 
1293 	/* disable all interrupts for now */
1294 	auixp_disable_interrupts(sc);
1295 
1296 	/* Attach AC97 host interfaces */
1297 	codec = &sc->sc_codec;
1298 	bzero(codec, sizeof(struct auixp_codec));
1299 
1300 	codec->sc       = sc;
1301 
1302 	codec->host_if.arg    = codec;
1303 	codec->host_if.attach = auixp_attach_codec;
1304 	codec->host_if.read   = auixp_read_codec;
1305 	codec->host_if.write  = auixp_write_codec;
1306 	codec->host_if.reset  = auixp_reset_codec;
1307 	codec->host_if.flags  = auixp_flags_codec;
1308 	switch (subdev) {
1309 	case 0x1311462: /* MSI S270 */
1310 	case 0x1611462: /* LG K1 Express */
1311 	case 0x3511462: /* MSI L725 */
1312 	case 0x4711462: /* MSI L720 */
1313 	case 0x0611462: /* MSI S250 */
1314 		codec->codec_flags = AC97_HOST_ALC650_PIN47_IS_EAPD;
1315 		break;
1316 	}
1317 
1318 	if (!(sc->sc_codec_not_ready_bits & ATI_REG_ISR_CODEC0_NOT_READY)) {
1319 		/* codec 0 present */
1320 		DPRINTF(("auixp : YAY! codec 0 present!\n"));
1321 		if (ac97_attach(&sc->sc_codec.host_if) == 0) {
1322 			sc->sc_codec.codec_nr = 0;
1323 			sc->sc_codec.present = 1;
1324 			return;
1325 		}
1326 	}
1327 
1328 	if (!(sc->sc_codec_not_ready_bits & ATI_REG_ISR_CODEC1_NOT_READY)) {
1329 		/* codec 1 present */
1330 		DPRINTF(("auixp : YAY! codec 1 present!\n"));
1331 		if (ac97_attach(&sc->sc_codec.host_if) == 0) {
1332 			sc->sc_codec.codec_nr = 1;
1333 			sc->sc_codec.present = 1;
1334 			return;
1335 		}
1336 	}
1337 
1338 	if (!(sc->sc_codec_not_ready_bits & ATI_REG_ISR_CODEC2_NOT_READY)) {
1339 		/* codec 2 present */
1340 		DPRINTF(("auixp : YAY! codec 2 present!\n"));
1341 		if (ac97_attach(&sc->sc_codec.host_if) == 0) {
1342 			sc->sc_codec.codec_nr = 2;
1343 			sc->sc_codec.present = 1;
1344 			return;
1345 		}
1346 	}
1347 }
1348 
1349 void
1350 auixp_disable_dma(struct auixp_softc *sc, struct auixp_dma *dma)
1351 {
1352 	bus_space_tag_t      iot;
1353 	bus_space_handle_t   ioh;
1354 	u_int32_t value;
1355 
1356 	iot = sc->sc_iot;
1357 	ioh = sc->sc_ioh;
1358 	/* lets not stress the DMA engine more than necessary */
1359 	value = bus_space_read_4(iot, ioh, ATI_REG_CMD);
1360 	if (value & dma->dma_enable_bit) {
1361 		value &= ~dma->dma_enable_bit;
1362 		bus_space_write_4(iot, ioh, ATI_REG_CMD, value);
1363 	}
1364 }
1365 
1366 void
1367 auixp_enable_dma(struct auixp_softc *sc, struct auixp_dma *dma)
1368 {
1369 	bus_space_tag_t      iot;
1370 	bus_space_handle_t   ioh;
1371 	u_int32_t value;
1372 
1373 	iot = sc->sc_iot;
1374 	ioh = sc->sc_ioh;
1375 	/* lets not stress the DMA engine more than necesssary */
1376 	value = bus_space_read_4(iot, ioh, ATI_REG_CMD);
1377 	if (!(value & dma->dma_enable_bit)) {
1378 		value |= dma->dma_enable_bit;
1379 		bus_space_write_4(iot, ioh, ATI_REG_CMD, value);
1380 	}
1381 }
1382 
1383 void
1384 auixp_reset_aclink(struct auixp_softc *sc)
1385 {
1386 	bus_space_tag_t      iot;
1387 	bus_space_handle_t   ioh;
1388 	u_int32_t value, timeout;
1389 
1390 	iot = sc->sc_iot;
1391 	ioh = sc->sc_ioh;
1392 
1393 	/* if power is down, power it up */
1394 	value = bus_space_read_4(iot, ioh, ATI_REG_CMD);
1395 	if (value & ATI_REG_CMD_POWERDOWN) {
1396 		printf("%s: powering up\n", sc->sc_dev.dv_xname);
1397 
1398 		/* explicitly enable power */
1399 		value &= ~ATI_REG_CMD_POWERDOWN;
1400 		bus_space_write_4(iot, ioh, ATI_REG_CMD, value);
1401 
1402 		/* have to wait at least 10 usec for it to initialise */
1403 		DELAY(20);
1404 	};
1405 
1406 	printf("%s: soft resetting aclink\n", sc->sc_dev.dv_xname);
1407 
1408 	/* perform a soft reset */
1409 	value  = bus_space_read_4(iot, ioh, ATI_REG_CMD);
1410 	value |= ATI_REG_CMD_AC_SOFT_RESET;
1411 	bus_space_write_4(iot, ioh, ATI_REG_CMD, value);
1412 
1413 	/* need to read the CMD reg and wait aprox. 10 usec to init */
1414 	value  = bus_space_read_4(iot, ioh, ATI_REG_CMD);
1415 	DELAY(20);
1416 
1417 	/* clear soft reset flag again */
1418 	value  = bus_space_read_4(iot, ioh, ATI_REG_CMD);
1419 	value &= ~ATI_REG_CMD_AC_SOFT_RESET;
1420 	bus_space_write_4(iot, ioh, ATI_REG_CMD, value);
1421 
1422 	/* check if the ac-link is working; reset device otherwise */
1423 	timeout = 10;
1424 	value = bus_space_read_4(iot, ioh, ATI_REG_CMD);
1425 	while (!(value & ATI_REG_CMD_ACLINK_ACTIVE)) {
1426 		printf("%s: not up; resetting aclink hardware\n",
1427 				sc->sc_dev.dv_xname);
1428 
1429 		/* dip aclink reset but keep the acsync */
1430 		value &= ~ATI_REG_CMD_AC_RESET;
1431 		value |=  ATI_REG_CMD_AC_SYNC;
1432 		bus_space_write_4(iot, ioh, ATI_REG_CMD, value);
1433 
1434 		/* need to read CMD again and wait again (clocking in issue?) */
1435 		value = bus_space_read_4(iot, ioh, ATI_REG_CMD);
1436 		DELAY(20);
1437 
1438 		/* assert aclink reset again */
1439 		value = bus_space_read_4(iot, ioh, ATI_REG_CMD);
1440 		value |=  ATI_REG_CMD_AC_RESET;
1441 		bus_space_write_4(iot, ioh, ATI_REG_CMD, value);
1442 
1443 		/* check if its active now */
1444 		value = bus_space_read_4(iot, ioh, ATI_REG_CMD);
1445 
1446 		timeout--;
1447 		if (timeout == 0) break;
1448 	};
1449 
1450 	if (timeout == 0) {
1451 		printf("%s: giving up aclink reset\n", sc->sc_dev.dv_xname);
1452 	};
1453 	if (timeout != 10) {
1454 		printf("%s: aclink hardware reset successful\n",
1455 			sc->sc_dev.dv_xname);
1456 	};
1457 
1458 	/* assert reset and sync for safety */
1459 	value  = bus_space_read_4(iot, ioh, ATI_REG_CMD);
1460 	value |= ATI_REG_CMD_AC_SYNC | ATI_REG_CMD_AC_RESET;
1461 	bus_space_write_4(iot, ioh, ATI_REG_CMD, value);
1462 }
1463 
1464 /* chip hard init */
1465 int
1466 auixp_init(struct auixp_softc *sc)
1467 {
1468 	bus_space_tag_t      iot;
1469 	bus_space_handle_t   ioh;
1470 	u_int32_t value;
1471 
1472 	iot = sc->sc_iot;
1473 	ioh = sc->sc_ioh;
1474 	/* disable all interrupts and clear all sources */
1475 	auixp_disable_interrupts(sc);
1476 
1477 	/* clear all DMA enables (preserving rest of settings) */
1478 	value = bus_space_read_4(iot, ioh, ATI_REG_CMD);
1479 	value &= ~( ATI_REG_CMD_IN_DMA_EN  |
1480 		    ATI_REG_CMD_OUT_DMA_EN |
1481 		    ATI_REG_CMD_SPDF_OUT_EN );
1482 	bus_space_write_4(iot, ioh, ATI_REG_CMD, value);
1483 
1484 	/* Reset AC-link */
1485 	auixp_reset_aclink(sc);
1486 
1487 	/*
1488 	 * codecs get auto-detected later
1489 	 *
1490 	 * note: we are NOT enabling interrupts yet, no codecs have been
1491 	 * detected yet nor is anything else set up
1492 	 */
1493 
1494 	return 0;
1495 }
1496