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