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