xref: /openbsd-src/sys/dev/pci/auich.c (revision 8500990981f885cbe5e6a4958549cacc238b5ae6)
1 /*	$OpenBSD: auich.c,v 1.37 2003/10/10 04:38:56 jason Exp $	*/
2 
3 /*
4  * Copyright (c) 2000,2001 Michael Shalayeff
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
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 OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26  * THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /* #define	AUICH_DEBUG */
30 /*
31  * AC'97 audio found on Intel 810/815/820/440MX chipsets.
32  *	http://developer.intel.com/design/chipsets/datashts/290655.htm
33  *	http://developer.intel.com/design/chipsets/manuals/298028.htm
34  *	http://www.intel.com/design/chipsets/datashts/290716.htm
35  *	http://www.intel.com/design/chipsets/datashts/290744.htm
36  */
37 
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
41 #include <sys/malloc.h>
42 #include <sys/device.h>
43 
44 #include <dev/pci/pcidevs.h>
45 #include <dev/pci/pcivar.h>
46 
47 #include <sys/audioio.h>
48 #include <dev/audio_if.h>
49 #include <dev/mulaw.h>
50 #include <dev/auconv.h>
51 
52 #include <machine/bus.h>
53 
54 #include <dev/ic/ac97.h>
55 
56 /* 12.1.10 NAMBAR - native audio mixer base address register */
57 #define	AUICH_NAMBAR	0x10
58 /* 12.1.11 NABMBAR - native audio bus mastering base address register */
59 #define	AUICH_NABMBAR	0x14
60 
61 /* table 12-3. native audio bus master control registers */
62 #define	AUICH_BDBAR	0x00	/* 8-byte aligned address */
63 #define	AUICH_CIV		0x04	/* 5 bits current index value */
64 #define	AUICH_LVI		0x05	/* 5 bits last valid index value */
65 #define		AUICH_LVI_MASK	0x1f
66 #define	AUICH_STS		0x06	/* 16 bits status */
67 #define		AUICH_FIFOE	0x10	/* fifo error */
68 #define		AUICH_BCIS	0x08	/* r- buf cmplt int sts; wr ack */
69 #define		AUICH_LVBCI	0x04	/* r- last valid bci, wr ack */
70 #define		AUICH_CELV	0x02	/* current equals last valid */
71 #define		AUICH_DCH		0x01	/* dma halted */
72 #define		AUICH_ISTS_BITS	"\020\01dch\02celv\03lvbci\04bcis\05fifoe"
73 #define	AUICH_PICB	0x08	/* 16 bits */
74 #define	AUICH_PIV		0x0a	/* 5 bits prefetched index value */
75 #define	AUICH_CTRL	0x0b	/* control */
76 #define		AUICH_IOCE	0x10	/* int on completion enable */
77 #define		AUICH_FEIE	0x08	/* fifo error int enable */
78 #define		AUICH_LVBIE	0x04	/* last valid buf int enable */
79 #define		AUICH_RR		0x02	/* 1 - reset regs */
80 #define		AUICH_RPBM	0x01	/* 1 - run, 0 - pause */
81 
82 #define	AUICH_PCMI	0x00
83 #define	AUICH_PCMO	0x10
84 #define	AUICH_MICI	0x20
85 
86 #define	AUICH_GCTRL	0x2c
87 #define		AUICH_SSM_78	0x40000000	/* S/PDIF slots 7 and 8 */
88 #define		AUICH_SSM_69	0x80000000	/* S/PDIF slots 6 and 9 */
89 #define		AUICH_SSM_1011	0xc0000000	/* S/PDIF slots 10 and 11 */
90 #define		AUICH_POM16	0x000000	/* PCM out precision 16bit */
91 #define		AUICH_POM20	0x400000	/* PCM out precision 20bit */
92 #define		AUICH_PCM246_MASK 0x300000
93 #define		AUICH_PCM2	0x000000	/* 2ch output */
94 #define		AUICH_PCM4	0x100000	/* 4ch output */
95 #define		AUICH_PCM6	0x200000	/* 6ch output */
96 #define		AUICH_S2RIE	0x40	/* int when tertiary codec resume */
97 #define		AUICH_SRIE	0x20	/* int when 2ndary codec resume */
98 #define		AUICH_PRIE	0x10	/* int when primary codec resume */
99 #define		AUICH_ACLSO	0x08	/* aclink shut off */
100 #define		AUICH_WRESET	0x04	/* warm reset */
101 #define		AUICH_CRESET	0x02	/* cold reset */
102 #define		AUICH_GIE		0x01	/* gpi int enable */
103 #define	AUICH_GSTS	0x30
104 #define		AUICH_MD3		0x20000	/* pwr-dn semaphore for modem */
105 #define		AUICH_AD3		0x10000	/* pwr-dn semaphore for audio */
106 #define		AUICH_RCS		0x08000	/* read completion status */
107 #define		AUICH_B3S12	0x04000	/* bit 3 of slot 12 */
108 #define		AUICH_B2S12	0x02000	/* bit 2 of slot 12 */
109 #define		AUICH_B1S12	0x01000	/* bit 1 of slot 12 */
110 #define		AUICH_SRI		0x00800	/* secondary resume int */
111 #define		AUICH_PRI		0x00400	/* primary resume int */
112 #define		AUICH_SCR		0x00200	/* secondary codec ready */
113 #define		AUICH_PCR		0x00100	/* primary codec ready */
114 #define		AUICH_MINT	0x00080	/* mic in int */
115 #define		AUICH_POINT	0x00040	/* pcm out int */
116 #define		AUICH_PIINT	0x00020	/* pcm in int */
117 #define		AUICH_MOINT	0x00004	/* modem out int */
118 #define		AUICH_MIINT	0x00002	/* modem in int */
119 #define		AUICH_GSCI	0x00001	/* gpi status change */
120 #define		AUICH_GSTS_BITS	"\020\01gsci\02miict\03moint\06piint\07point\010mint\011pcr\012scr\013pri\014sri\015b1s12\016b2s12\017b3s12\020rcs\021ad3\022md3"
121 #define	AUICH_CAS		0x34	/* 1/8 bit */
122 #define	AUICH_SEMATIMO		1000	/* us */
123 #define	AUICH_RESETIMO		500000	/* us */
124 
125 /*
126  * according to the dev/audiovar.h AU_RING_SIZE is 2^16, what fits
127  * in our limits perfectly, i.e. setting it to higher value
128  * in your kernel config would improve perfomance, still 2^21 is the max
129  */
130 #define	AUICH_DMALIST_MAX	32
131 #define	AUICH_DMASEG_MAX	(65536*2)	/* 64k samples, 2x16 bit samples */
132 struct auich_dmalist {
133 	u_int32_t	base;
134 	u_int32_t	len;
135 #define	AUICH_DMAF_IOC	0x80000000	/* 1-int on complete */
136 #define	AUICH_DMAF_BUP	0x40000000	/* 0-retrans last, 1-transmit 0 */
137 };
138 
139 #define	AUICH_FIXED_RATE 48000
140 
141 struct auich_dma {
142 	bus_dmamap_t map;
143 	caddr_t addr;
144 	bus_dma_segment_t segs[AUICH_DMALIST_MAX];
145 	int nsegs;
146 	size_t size;
147 	struct auich_dma *next;
148 };
149 
150 struct auich_softc {
151 	struct device sc_dev;
152 	void *sc_ih;
153 
154 	audio_device_t sc_audev;
155 
156 	bus_space_tag_t iot;
157 	bus_space_handle_t mix_ioh;
158 	bus_space_handle_t aud_ioh;
159 	bus_dma_tag_t dmat;
160 
161 	struct ac97_codec_if *codec_if;
162 	struct ac97_host_if host_if;
163 
164 	/* dma scatter-gather buffer lists, aligned to 8 bytes */
165 	struct auich_dmalist *dmalist_pcmo, *dmap_pcmo,
166 	    dmasto_pcmo[AUICH_DMALIST_MAX+1];
167 	struct auich_dmalist *dmalist_pcmi, *dmap_pcmi,
168 	    dmasto_pcmi[AUICH_DMALIST_MAX+1];
169 	struct auich_dmalist *dmalist_mici, *dmap_mici,
170 	    dmasto_mici[AUICH_DMALIST_MAX+1];
171 	/* i/o buffer pointers */
172 	u_int32_t pcmo_start, pcmo_p, pcmo_end;
173 	int pcmo_blksize, pcmo_fifoe;
174 	u_int32_t pcmi_start, pcmi_p, pcmi_end;
175 	int pcmi_blksize, pcmi_fifoe;
176 	u_int32_t mici_start, mici_p, mici_end;
177 	int mici_blksize, mici_fifoe;
178 	struct auich_dma *sc_dmas;
179 
180 	void (*sc_pintr)(void *);
181 	void *sc_parg;
182 
183 	void (*sc_rintr)(void *);
184 	void *sc_rarg;
185 
186 	void *powerhook;
187 	int suspend;
188 	u_int16_t ext_ctrl;
189 	int sc_sample_size;
190 	int sc_sts_reg;
191 	int sc_ignore_codecready;
192 	int flags;
193 	int sc_ac97rate;
194 };
195 
196 #ifdef AUICH_DEBUG
197 #define	DPRINTF(l,x)	do { if (auich_debug & (l)) printf x; } while(0)
198 int auich_debug = 0xfffe;
199 #define	AUICH_DEBUG_CODECIO	0x0001
200 #define	AUICH_DEBUG_DMA		0x0002
201 #define	AUICH_DEBUG_PARAM	0x0004
202 #else
203 #define	DPRINTF(x,y)	/* nothing */
204 #endif
205 
206 struct cfdriver	auich_cd = {
207 	NULL, "auich", DV_DULL
208 };
209 
210 int  auich_match(struct device *, void *, void *);
211 void auich_attach(struct device *, struct device *, void *);
212 int  auich_intr(void *);
213 
214 struct cfattach auich_ca = {
215 	sizeof(struct auich_softc), auich_match, auich_attach
216 };
217 
218 static const struct auich_devtype {
219 	int	vendor;
220 	int	product;
221 	int	options;
222 	char	name[8];
223 } auich_devices[] = {
224 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82801AA_ACA,	0, "ICH" },
225 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82801AB_ACA,	0, "ICH0" },
226 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82801BA_ACA,	0, "ICH2" },
227 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82801CA_ACA,	0, "ICH3" },
228 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82801DB_ACA,	0, "ICH4" },
229 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82801EB_ACA,	0, "ICH5" },
230 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82440MX_ACA,	0, "440MX" },
231 	{ PCI_VENDOR_SIS,	PCI_PRODUCT_SIS_7012_ACA,	0, "SiS7012" },
232 	{ PCI_VENDOR_NVIDIA,	PCI_PRODUCT_NVIDIA_NFORCE_ACA,	0, "nForce" },
233 	{ PCI_VENDOR_NVIDIA,	PCI_PRODUCT_NVIDIA_NFORCE2_ACA,	0, "nForce2" },
234 	{ PCI_VENDOR_AMD,	PCI_PRODUCT_AMD_PBC768_ACA,	0, "AMD768" },
235 	{ PCI_VENDOR_AMD,	PCI_PRODUCT_AMD_8111_ACA,	0, "AMD8111" },
236 };
237 
238 int auich_open(void *, int);
239 void auich_close(void *);
240 int auich_query_encoding(void *, struct audio_encoding *);
241 int auich_set_params(void *, int, int, struct audio_params *,
242     struct audio_params *);
243 int auich_round_blocksize(void *, int);
244 int auich_halt_output(void *);
245 int auich_halt_input(void *);
246 int auich_getdev(void *, struct audio_device *);
247 int auich_set_port(void *, mixer_ctrl_t *);
248 int auich_get_port(void *, mixer_ctrl_t *);
249 int auich_query_devinfo(void *, mixer_devinfo_t *);
250 void *auich_allocm(void *, int, size_t, int, int);
251 void auich_freem(void *, void *, int);
252 size_t auich_round_buffersize(void *, int, size_t);
253 paddr_t auich_mappage(void *, void *, off_t, int);
254 int auich_get_props(void *);
255 int auich_trigger_output(void *, void *, void *, int, void (*)(void *),
256     void *, struct audio_params *);
257 int auich_trigger_input(void *, void *, void *, int, void (*)(void *),
258     void *, struct audio_params *);
259 
260 void auich_powerhook(int, void *);
261 
262 struct audio_hw_if auich_hw_if = {
263 	auich_open,
264 	auich_close,
265 	NULL,			/* drain */
266 	auich_query_encoding,
267 	auich_set_params,
268 	auich_round_blocksize,
269 	NULL,			/* commit_setting */
270 	NULL,			/* init_output */
271 	NULL,			/* init_input */
272 	NULL,			/* start_output */
273 	NULL,			/* start_input */
274 	auich_halt_output,
275 	auich_halt_input,
276 	NULL,			/* speaker_ctl */
277 	auich_getdev,
278 	NULL,			/* getfd */
279 	auich_set_port,
280 	auich_get_port,
281 	auich_query_devinfo,
282 	auich_allocm,
283 	auich_freem,
284 	auich_round_buffersize,
285 	auich_mappage,
286 	auich_get_props,
287 	auich_trigger_output,
288 	auich_trigger_input
289 };
290 
291 int  auich_attach_codec(void *, struct ac97_codec_if *);
292 int  auich_read_codec(void *, u_int8_t, u_int16_t *);
293 int  auich_write_codec(void *, u_int8_t, u_int16_t);
294 void auich_reset_codec(void *);
295 enum ac97_host_flags auich_flags_codec(void *);
296 unsigned int auich_calibrate(struct auich_softc *);
297 
298 int
299 auich_match(parent, match, aux)
300 	struct device *parent;
301 	void *match;
302 	void *aux;
303 {
304 	struct pci_attach_args *pa = aux;
305 	int i;
306 
307 	for (i = sizeof(auich_devices)/sizeof(auich_devices[0]); i--;)
308 		if (PCI_VENDOR(pa->pa_id) == auich_devices[i].vendor &&
309 		    PCI_PRODUCT(pa->pa_id) == auich_devices[i].product)
310 			return 1;
311 
312 	return 0;
313 }
314 
315 void
316 auich_attach(parent, self, aux)
317 	struct device *parent, *self;
318 	void *aux;
319 {
320 	struct auich_softc *sc = (struct auich_softc *)self;
321 	struct pci_attach_args *pa = aux;
322 	pci_intr_handle_t ih;
323 	bus_size_t mix_size, aud_size;
324 	pcireg_t csr;
325 	const char *intrstr;
326 	u_int32_t status;
327 	int i;
328 
329 	/* SiS 7012 needs special handling */
330 	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SIS &&
331 	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SIS_7012_ACA) {
332 		sc->sc_sts_reg = AUICH_PICB;
333 		sc->sc_sample_size = 1;
334 	} else {
335 		sc->sc_sts_reg = AUICH_STS;
336 		sc->sc_sample_size = 2;
337 	}
338 
339 	if (pci_mapreg_map(pa, AUICH_NAMBAR, PCI_MAPREG_TYPE_IO, 0,
340 			   &sc->iot, &sc->mix_ioh, NULL, &mix_size, 0)) {
341 		printf(": can't map codec i/o space\n");
342 		return;
343 	}
344 	if (pci_mapreg_map(pa, AUICH_NABMBAR, PCI_MAPREG_TYPE_IO, 0,
345 			   &sc->iot, &sc->aud_ioh, NULL, &aud_size, 0)) {
346 		printf(": can't map device i/o space\n");
347 		bus_space_unmap(sc->iot, sc->mix_ioh, mix_size);
348 		return;
349 	}
350 	sc->dmat = pa->pa_dmat;
351 
352 	/* enable bus mastering (should not it be mi?) */
353 	csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
354 	pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
355 	    csr | PCI_COMMAND_MASTER_ENABLE);
356 
357 	if (pci_intr_map(pa, &ih)) {
358 		printf(": can't map interrupt\n");
359 		bus_space_unmap(sc->iot, sc->aud_ioh, aud_size);
360 		bus_space_unmap(sc->iot, sc->mix_ioh, mix_size);
361 		return;
362 	}
363 	intrstr = pci_intr_string(pa->pa_pc, ih);
364 	sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, auich_intr,
365 				       sc, sc->sc_dev.dv_xname);
366 	if (!sc->sc_ih) {
367 		printf(": can't establish interrupt");
368 		if (intrstr)
369 			printf(" at %s", intrstr);
370 		printf("\n");
371 		bus_space_unmap(sc->iot, sc->aud_ioh, aud_size);
372 		bus_space_unmap(sc->iot, sc->mix_ioh, mix_size);
373 		return;
374 	}
375 
376 	for (i = sizeof(auich_devices)/sizeof(auich_devices[0]); i--;)
377 		if (PCI_PRODUCT(pa->pa_id) == auich_devices[i].product)
378 			break;
379 
380 	snprintf(sc->sc_audev.name, sizeof sc->sc_audev.name, "%s AC97",
381 		 auich_devices[i].name);
382 	snprintf(sc->sc_audev.version, sizeof sc->sc_audev.version, "0x%02x",
383 		 PCI_REVISION(pa->pa_class));
384 	strlcpy(sc->sc_audev.config, sc->sc_dev.dv_xname,
385 		sizeof sc->sc_audev.config);
386 
387 	printf(": %s, %s\n", intrstr, sc->sc_audev.name);
388 
389 	/* allocate dma lists */
390 #define	a(a)	(void *)(((u_long)(a) + sizeof(*(a)) - 1) & ~(sizeof(*(a))-1))
391 	sc->dmalist_pcmo = sc->dmap_pcmo = a(sc->dmasto_pcmo);
392 	sc->dmalist_pcmi = sc->dmap_pcmi = a(sc->dmasto_pcmi);
393 	sc->dmalist_mici = sc->dmap_mici = a(sc->dmasto_mici);
394 #undef a
395 	DPRINTF(AUICH_DEBUG_DMA, ("auich_attach: lists %p %p %p\n",
396 	    sc->dmalist_pcmo, sc->dmalist_pcmi, sc->dmalist_mici));
397 
398 	/* Reset codec and AC'97 */
399 	auich_reset_codec(sc);
400 	status = bus_space_read_4(sc->iot, sc->aud_ioh, AUICH_GSTS);
401 	if (!(status & AUICH_PCR)) {	/* reset failure */
402 		if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL &&
403 		    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801DB_ACA) {
404 			/* MSI 845G Max never return AUICH_PCR */
405 			sc->sc_ignore_codecready = 1;
406 		} else
407 			return;
408 	}
409 
410 	sc->host_if.arg = sc;
411 	sc->host_if.attach = auich_attach_codec;
412 	sc->host_if.read = auich_read_codec;
413 	sc->host_if.write = auich_write_codec;
414 	sc->host_if.reset = auich_reset_codec;
415 	sc->host_if.flags = auich_flags_codec;
416 	if (sc->sc_dev.dv_cfdata->cf_flags & 0x0001)
417 		sc->flags = AC97_HOST_SWAPPED_CHANNELS;
418 
419 	if (ac97_attach(&sc->host_if) != 0) {
420 		pci_intr_disestablish(pa->pa_pc, sc->sc_ih);
421 		bus_space_unmap(sc->iot, sc->aud_ioh, aud_size);
422 		bus_space_unmap(sc->iot, sc->mix_ioh, mix_size);
423 		return;
424 	}
425 
426 	audio_attach_mi(&auich_hw_if, sc, &sc->sc_dev);
427 
428 	/* Watch for power changes */
429 	sc->suspend = PWR_RESUME;
430 	sc->powerhook = powerhook_establish(auich_powerhook, sc);
431 
432 	sc->sc_ac97rate = auich_calibrate(sc);
433 }
434 
435 int
436 auich_read_codec(v, reg, val)
437 	void *v;
438 	u_int8_t reg;
439 	u_int16_t *val;
440 {
441 	struct auich_softc *sc = v;
442 	int i;
443 
444 	/* wait for an access semaphore */
445 	for (i = AUICH_SEMATIMO; i-- &&
446 	    bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_CAS) & 1; DELAY(1));
447 
448 	if (!sc->sc_ignore_codecready && i < 0) {
449 		DPRINTF(AUICH_DEBUG_CODECIO,
450 		    ("%s: read_codec timeout\n", sc->sc_dev.dv_xname));
451 		return (-1);
452 	}
453 
454 	*val = bus_space_read_2(sc->iot, sc->mix_ioh, reg);
455 	DPRINTF(AUICH_DEBUG_CODECIO, ("%s: read_codec(%x, %x)\n",
456 	    sc->sc_dev.dv_xname, reg, *val));
457 	return (0);
458 }
459 
460 int
461 auich_write_codec(v, reg, val)
462 	void *v;
463 	u_int8_t reg;
464 	u_int16_t val;
465 {
466 	struct auich_softc *sc = v;
467 	int i;
468 
469 	/* wait for an access semaphore */
470 	for (i = AUICH_SEMATIMO; i-- &&
471 	    bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_CAS) & 1; DELAY(1));
472 
473 	if (sc->sc_ignore_codecready || i >= 0) {
474 		DPRINTF(AUICH_DEBUG_CODECIO, ("%s: write_codec(%x, %x)\n",
475 		    sc->sc_dev.dv_xname, reg, val));
476 		bus_space_write_2(sc->iot, sc->mix_ioh, reg, val);
477 		return (0);
478 	} else {
479 		DPRINTF(AUICH_DEBUG_CODECIO,
480 		    ("%s: write_codec timeout\n", sc->sc_dev.dv_xname));
481 		return (-1);
482 	}
483 }
484 
485 int
486 auich_attach_codec(v, cif)
487 	void *v;
488 	struct ac97_codec_if *cif;
489 {
490 	struct auich_softc *sc = v;
491 
492 	sc->codec_if = cif;
493 	return 0;
494 }
495 
496 void
497 auich_reset_codec(v)
498 	void *v;
499 {
500 	struct auich_softc *sc = v;
501 	u_int32_t control;
502 	int i;
503 
504 	control = bus_space_read_4(sc->iot, sc->aud_ioh, AUICH_GCTRL);
505 	control &= ~(AUICH_ACLSO | AUICH_PCM246_MASK);
506 	control |= (control & AUICH_CRESET) ? AUICH_WRESET : AUICH_CRESET;
507 	bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_GCTRL, AUICH_CRESET);
508 
509 	for (i = AUICH_RESETIMO; i-- &&
510 	    !(bus_space_read_4(sc->iot, sc->aud_ioh, AUICH_GSTS) & AUICH_PCR);
511 	    DELAY(1));
512 
513 	if (i < 0)
514 		DPRINTF(AUICH_DEBUG_CODECIO,
515 		    ("%s: reset_codec timeout\n", sc->sc_dev.dv_xname));
516 }
517 
518 enum ac97_host_flags
519 auich_flags_codec(void *v)
520 {
521 	struct auich_softc *sc = v;
522 
523 	return (sc->flags);
524 }
525 
526 int
527 auich_open(v, flags)
528 	void *v;
529 	int flags;
530 {
531 	return 0;
532 }
533 
534 void
535 auich_close(v)
536 	void *v;
537 {
538 }
539 
540 int
541 auich_query_encoding(v, aep)
542 	void *v;
543 	struct audio_encoding *aep;
544 {
545 	switch (aep->index) {
546 	case 0:
547 		strlcpy(aep->name, AudioEulinear, sizeof aep->name);
548 		aep->encoding = AUDIO_ENCODING_ULINEAR;
549 		aep->precision = 8;
550 		aep->flags = 0;
551 		return (0);
552 	case 1:
553 		strlcpy(aep->name, AudioEmulaw, sizeof aep->name);
554 		aep->encoding = AUDIO_ENCODING_ULAW;
555 		aep->precision = 8;
556 		aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
557 		return (0);
558 	case 2:
559 		strlcpy(aep->name, AudioEalaw, sizeof aep->name);
560 		aep->encoding = AUDIO_ENCODING_ALAW;
561 		aep->precision = 8;
562 		aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
563 		return (0);
564 	case 3:
565 		strlcpy(aep->name, AudioEslinear, sizeof aep->name);
566 		aep->encoding = AUDIO_ENCODING_SLINEAR;
567 		aep->precision = 8;
568 		aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
569 		return (0);
570 	case 4:
571 		strlcpy(aep->name, AudioEslinear_le, sizeof aep->name);
572 		aep->encoding = AUDIO_ENCODING_SLINEAR_LE;
573 		aep->precision = 16;
574 		aep->flags = 0;
575 		return (0);
576 	case 5:
577 		strlcpy(aep->name, AudioEulinear_le, sizeof aep->name);
578 		aep->encoding = AUDIO_ENCODING_ULINEAR_LE;
579 		aep->precision = 16;
580 		aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
581 		return (0);
582 	case 6:
583 		strlcpy(aep->name, AudioEslinear_be, sizeof aep->name);
584 		aep->encoding = AUDIO_ENCODING_SLINEAR_BE;
585 		aep->precision = 16;
586 		aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
587 		return (0);
588 	case 7:
589 		strlcpy(aep->name, AudioEulinear_be, sizeof aep->name);
590 		aep->encoding = AUDIO_ENCODING_ULINEAR_BE;
591 		aep->precision = 16;
592 		aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
593 		return (0);
594 	default:
595 		return (EINVAL);
596 	}
597 }
598 
599 int
600 auich_set_params(v, setmode, usemode, play, rec)
601 	void *v;
602 	int setmode, usemode;
603 	struct audio_params *play, *rec;
604 {
605 	struct auich_softc *sc = v;
606 	int error;
607 	u_int orate;
608 
609 	if (setmode & AUMODE_PLAY) {
610 		play->factor = 1;
611 		play->sw_code = NULL;
612 		switch(play->encoding) {
613 		case AUDIO_ENCODING_ULAW:
614 			switch (play->channels) {
615 			case 1:
616 				play->factor = 4;
617 				play->sw_code = mulaw_to_slinear16_mts;
618 				break;
619 			case 2:
620 				play->factor = 2;
621 				play->sw_code = mulaw_to_slinear16;
622 				break;
623 			default:
624 				return (EINVAL);
625 			}
626 			break;
627 		case AUDIO_ENCODING_SLINEAR_LE:
628 			switch (play->precision) {
629 			case 8:
630 				switch (play->channels) {
631 				case 1:
632 					play->factor = 4;
633 					play->sw_code = linear8_to_linear16_mts;
634 					break;
635 				case 2:
636 					play->factor = 2;
637 					play->sw_code = linear8_to_linear16;
638 					break;
639 				default:
640 					return (EINVAL);
641 				}
642 				break;
643 			case 16:
644 				switch (play->channels) {
645 				case 1:
646 					play->factor = 2;
647 					play->sw_code = noswap_bytes_mts;
648 					break;
649 				case 2:
650 					break;
651 				default:
652 					return (EINVAL);
653 				}
654 				break;
655 			default:
656 				return (EINVAL);
657 			}
658 			break;
659 		case AUDIO_ENCODING_ULINEAR_LE:
660 			switch (play->precision) {
661 			case 8:
662 				switch (play->channels) {
663 				case 1:
664 					play->factor = 4;
665 					play->sw_code = ulinear8_to_linear16_mts;
666 					break;
667 				case 2:
668 					play->factor = 2;
669 					play->sw_code = ulinear8_to_linear16;
670 					break;
671 				default:
672 					return (EINVAL);
673 				}
674 				break;
675 			case 16:
676 				switch (play->channels) {
677 				case 1:
678 					play->factor = 2;
679 					play->sw_code = change_sign16_mts;
680 					break;
681 				case 2:
682 					play->sw_code = change_sign16;
683 					break;
684 				default:
685 					return (EINVAL);
686 				}
687 				break;
688 			default:
689 				return (EINVAL);
690 			}
691 			break;
692 		case AUDIO_ENCODING_ALAW:
693 			switch (play->channels) {
694 			case 1:
695 				play->factor = 4;
696 				play->sw_code = alaw_to_slinear16_mts;
697 			case 2:
698 				play->factor = 2;
699 				play->sw_code = alaw_to_slinear16;
700 			default:
701 				return (EINVAL);
702 			}
703 			break;
704 		case AUDIO_ENCODING_SLINEAR_BE:
705 			switch (play->precision) {
706 			case 8:
707 				switch (play->channels) {
708 				case 1:
709 					play->factor = 4;
710 					play->sw_code = linear8_to_linear16_mts;
711 					break;
712 				case 2:
713 					play->factor = 2;
714 					play->sw_code = linear8_to_linear16;
715 					break;
716 				default:
717 					return (EINVAL);
718 				}
719 				break;
720 			case 16:
721 				switch (play->channels) {
722 				case 1:
723 					play->factor = 2;
724 					play->sw_code = swap_bytes_mts;
725 					break;
726 				case 2:
727 					play->sw_code = swap_bytes;
728 					break;
729 				default:
730 					return (EINVAL);
731 				}
732 				break;
733 			default:
734 				return (EINVAL);
735 			}
736 			break;
737 		case AUDIO_ENCODING_ULINEAR_BE:
738 			switch (play->precision) {
739 			case 8:
740 				switch (play->channels) {
741 				case 1:
742 					play->factor = 4;
743 					play->sw_code = ulinear8_to_linear16_mts;
744 					break;
745 				case 2:
746 					play->factor = 2;
747 					play->sw_code = ulinear8_to_linear16;
748 					break;
749 				default:
750 					return (EINVAL);
751 				}
752 				break;
753 			case 16:
754 				switch (play->channels) {
755 				case 1:
756 					play->factor = 2;
757 					play->sw_code = change_sign16_swap_bytes_mts;
758 					break;
759 				case 2:
760 					play->sw_code = change_sign16_swap_bytes;
761 					break;
762 				default:
763 					return (EINVAL);
764 				}
765 				break;
766 			default:
767 				return (EINVAL);
768 			}
769 			break;
770 		default:
771 			return (EINVAL);
772 		}
773 
774 		orate = play->sample_rate;
775 		if (sc->sc_ac97rate != 0)
776 			play->sample_rate = orate * AUICH_FIXED_RATE /
777 			    sc->sc_ac97rate;
778 		error = ac97_set_rate(sc->codec_if, play, AUMODE_PLAY);
779 		play->sample_rate = orate;
780 		if (error)
781 			return (error);
782 	}
783 
784 	if (setmode & AUMODE_RECORD) {
785 		rec->factor = 1;
786 		rec->sw_code = 0;
787 		switch(rec->encoding) {
788 		case AUDIO_ENCODING_ULAW:
789 			rec->sw_code = ulinear8_to_mulaw;
790 			break;
791 		case AUDIO_ENCODING_SLINEAR_LE:
792 			if (rec->precision == 8)
793 				rec->sw_code = change_sign8;
794 			break;
795 		case AUDIO_ENCODING_ULINEAR_LE:
796 			if (rec->precision == 16)
797 				rec->sw_code = change_sign16;
798 			break;
799 		case AUDIO_ENCODING_ALAW:
800 			rec->sw_code = ulinear8_to_alaw;
801 			break;
802 		case AUDIO_ENCODING_SLINEAR_BE:
803 			if (rec->precision == 16)
804 				rec->sw_code = swap_bytes;
805 			else
806 				rec->sw_code = change_sign8;
807 			break;
808 		case AUDIO_ENCODING_ULINEAR_BE:
809 			if (rec->precision == 16)
810 				rec->sw_code = swap_bytes_change_sign16;
811 			break;
812 		default:
813 			return (EINVAL);
814 		}
815 
816 		orate = rec->sample_rate;
817 		if (sc->sc_ac97rate != 0)
818 			rec->sample_rate = orate * AUICH_FIXED_RATE /
819 			    sc->sc_ac97rate;
820 		error = ac97_set_rate(sc->codec_if, rec, AUMODE_RECORD);
821 		rec->sample_rate = orate;
822 		if (error)
823 			return (error);
824 	}
825 
826 	return (0);
827 }
828 
829 int
830 auich_round_blocksize(v, blk)
831 	void *v;
832 	int blk;
833 {
834 	return blk & ~0x3f;
835 }
836 
837 int
838 auich_halt_output(v)
839 	void *v;
840 {
841 	struct auich_softc *sc = v;
842 
843 	DPRINTF(AUICH_DEBUG_DMA, ("%s: halt_output\n", sc->sc_dev.dv_xname));
844 
845 	bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMO + AUICH_CTRL, AUICH_RR);
846 
847 	return 0;
848 }
849 
850 int
851 auich_halt_input(v)
852 	void *v;
853 {
854 	struct auich_softc *sc = v;
855 
856 	DPRINTF(AUICH_DEBUG_DMA,
857 	    ("%s: halt_input\n", sc->sc_dev.dv_xname));
858 
859 	/* XXX halt both unless known otherwise */
860 
861 	bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_CTRL, AUICH_RR);
862 	bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_MICI + AUICH_CTRL, AUICH_RR);
863 
864 	return 0;
865 }
866 
867 int
868 auich_getdev(v, adp)
869 	void *v;
870 	struct audio_device *adp;
871 {
872 	struct auich_softc *sc = v;
873 	*adp = sc->sc_audev;
874 	return 0;
875 }
876 
877 int
878 auich_set_port(v, cp)
879 	void *v;
880 	mixer_ctrl_t *cp;
881 {
882 	struct auich_softc *sc = v;
883 	return sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp);
884 }
885 
886 int
887 auich_get_port(v, cp)
888 	void *v;
889 	mixer_ctrl_t *cp;
890 {
891 	struct auich_softc *sc = v;
892 	return sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp);
893 }
894 
895 int
896 auich_query_devinfo(v, dp)
897 	void *v;
898 	mixer_devinfo_t *dp;
899 {
900 	struct auich_softc *sc = v;
901 	return sc->codec_if->vtbl->query_devinfo(sc->codec_if, dp);
902 }
903 
904 void *
905 auich_allocm(v, direction, size, pool, flags)
906 	void *v;
907 	int direction;
908 	size_t size;
909 	int pool, flags;
910 {
911 	struct auich_softc *sc = v;
912 	struct auich_dma *p;
913 	int error;
914 
915 	if (size > AUICH_DMALIST_MAX * AUICH_DMASEG_MAX)
916 		return NULL;
917 
918 	p = malloc(sizeof(*p), pool, flags);
919 	if (!p)
920 		return NULL;
921 	bzero(p, sizeof(*p));
922 
923 	p->size = size;
924 	if ((error = bus_dmamem_alloc(sc->dmat, p->size, NBPG, 0, p->segs,
925 	    1, &p->nsegs, BUS_DMA_NOWAIT)) != 0) {
926 		printf("%s: unable to allocate dma, error = %d\n",
927 		    sc->sc_dev.dv_xname, error);
928 		free(p, pool);
929 		return NULL;
930 	}
931 
932 	if ((error = bus_dmamem_map(sc->dmat, p->segs, p->nsegs, p->size,
933 	    &p->addr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) {
934 		printf("%s: unable to map dma, error = %d\n",
935 		    sc->sc_dev.dv_xname, error);
936 		bus_dmamem_free(sc->dmat, p->segs, p->nsegs);
937 		free(p, pool);
938 		return NULL;
939 	}
940 
941 	if ((error = bus_dmamap_create(sc->dmat, p->size, 1,
942 	    p->size, 0, BUS_DMA_NOWAIT, &p->map)) != 0) {
943 		printf("%s: unable to create dma map, error = %d\n",
944 		    sc->sc_dev.dv_xname, error);
945 		bus_dmamem_unmap(sc->dmat, p->addr, size);
946 		bus_dmamem_free(sc->dmat, p->segs, p->nsegs);
947 		free(p, pool);
948 		return NULL;
949 	}
950 
951 	if ((error = bus_dmamap_load(sc->dmat, p->map, p->addr, p->size,
952 	    NULL, BUS_DMA_NOWAIT)) != 0) {
953 		printf("%s: unable to load dma map, error = %d\n",
954 		    sc->sc_dev.dv_xname, error);
955 		bus_dmamap_destroy(sc->dmat, p->map);
956 		bus_dmamem_unmap(sc->dmat, p->addr, size);
957 		bus_dmamem_free(sc->dmat, p->segs, p->nsegs);
958 		free(p, pool);
959 		return NULL;
960 	}
961 
962 	p->next = sc->sc_dmas;
963 	sc->sc_dmas = p;
964 
965 	return p->addr;
966 }
967 
968 void
969 auich_freem(v, ptr, pool)
970 	void *v;
971 	void *ptr;
972 	int pool;
973 {
974 	struct auich_softc *sc = v;
975 	struct auich_dma *p;
976 
977 	for (p = sc->sc_dmas; p->addr != ptr; p = p->next)
978 		if (p->next == NULL) {
979 			printf("auich_freem: trying to free not allocated memory");
980 			return;
981 		}
982 
983 	bus_dmamap_unload(sc->dmat, p->map);
984 	bus_dmamap_destroy(sc->dmat, p->map);
985 	bus_dmamem_unmap(sc->dmat, p->addr, p->size);
986 	bus_dmamem_free(sc->dmat, p->segs, p->nsegs);
987 	free(p, pool);
988 }
989 
990 size_t
991 auich_round_buffersize(v, direction, size)
992 	void *v;
993 	int direction;
994 	size_t size;
995 {
996 	if (size > AUICH_DMALIST_MAX * AUICH_DMASEG_MAX)
997 		size = AUICH_DMALIST_MAX * AUICH_DMASEG_MAX;
998 
999 	return size;
1000 }
1001 
1002 paddr_t
1003 auich_mappage(v, mem, off, prot)
1004 	void *v;
1005 	void *mem;
1006 	off_t off;
1007 	int prot;
1008 {
1009 	struct auich_softc *sc = v;
1010 	struct auich_dma *p;
1011 
1012 	if (off < 0)
1013 		return -1;
1014 
1015 	for (p = sc->sc_dmas; p && p->addr != mem; p = p->next);
1016 	if (!p)
1017 		return -1;
1018 
1019 	return bus_dmamem_mmap(sc->dmat, p->segs, p->nsegs,
1020 	    off, prot, BUS_DMA_WAITOK);
1021 }
1022 
1023 int
1024 auich_get_props(v)
1025 	void *v;
1026 {
1027 	return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
1028 }
1029 
1030 int
1031 auich_intr(v)
1032 	void *v;
1033 {
1034 	struct auich_softc *sc = v;
1035 	int ret = 0, sts, gsts, i;
1036 
1037 	gsts = bus_space_read_2(sc->iot, sc->aud_ioh, AUICH_GSTS);
1038 	DPRINTF(AUICH_DEBUG_DMA, ("auich_intr: gsts=%b\n", gsts, AUICH_GSTS_BITS));
1039 
1040 	if (gsts & AUICH_POINT) {
1041 		sts = bus_space_read_2(sc->iot, sc->aud_ioh,
1042 		    AUICH_PCMO + sc->sc_sts_reg);
1043 		DPRINTF(AUICH_DEBUG_DMA,
1044 		    ("auich_intr: osts=%b\n", sts, AUICH_ISTS_BITS));
1045 
1046 		if (sts & AUICH_FIFOE) {
1047 			printf("%s: fifo underrun # %u\n",
1048 			    sc->sc_dev.dv_xname, ++sc->pcmo_fifoe);
1049 		}
1050 
1051 		i = bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_PCMO + AUICH_CIV);
1052 		if (sts & (AUICH_LVBCI | AUICH_CELV)) {
1053 			struct auich_dmalist *q, *qe;
1054 
1055 			q = sc->dmap_pcmo;
1056 			qe = &sc->dmalist_pcmo[i];
1057 
1058 			while (q != qe) {
1059 
1060 				q->base = sc->pcmo_p;
1061 				q->len = (sc->pcmo_blksize /
1062 				    sc->sc_sample_size) | AUICH_DMAF_IOC;
1063 				DPRINTF(AUICH_DEBUG_DMA,
1064 				    ("auich_intr: %p, %p = %x @ %p\n",
1065 				    qe, q, sc->pcmo_blksize /
1066 				    sc->sc_sample_size, sc->pcmo_p));
1067 
1068 				sc->pcmo_p += sc->pcmo_blksize;
1069 				if (sc->pcmo_p >= sc->pcmo_end)
1070 					sc->pcmo_p = sc->pcmo_start;
1071 
1072 				if (++q == &sc->dmalist_pcmo[AUICH_DMALIST_MAX])
1073 					q = sc->dmalist_pcmo;
1074 			}
1075 
1076 			sc->dmap_pcmo = q;
1077 			bus_space_write_1(sc->iot, sc->aud_ioh,
1078 			    AUICH_PCMO + AUICH_LVI,
1079 			    (sc->dmap_pcmo - sc->dmalist_pcmo - 1) &
1080 			    AUICH_LVI_MASK);
1081 		}
1082 
1083 		if (sts & AUICH_BCIS && sc->sc_pintr)
1084 			sc->sc_pintr(sc->sc_parg);
1085 
1086 		/* int ack */
1087 		bus_space_write_2(sc->iot, sc->aud_ioh,
1088 		    AUICH_PCMO + sc->sc_sts_reg, sts &
1089 		    (AUICH_LVBCI | AUICH_CELV | AUICH_BCIS | AUICH_FIFOE));
1090 		bus_space_write_2(sc->iot, sc->aud_ioh, AUICH_GSTS, AUICH_POINT);
1091 		ret++;
1092 	}
1093 
1094 	if (gsts & AUICH_PIINT) {
1095 		sts = bus_space_read_2(sc->iot, sc->aud_ioh,
1096 		    AUICH_PCMI + sc->sc_sts_reg);
1097 		DPRINTF(AUICH_DEBUG_DMA,
1098 		    ("auich_intr: ists=%b\n", sts, AUICH_ISTS_BITS));
1099 
1100 		if (sts & AUICH_FIFOE) {
1101 			printf("%s: in fifo overrun # %u\n",
1102 			    sc->sc_dev.dv_xname, ++sc->pcmi_fifoe);
1103 		}
1104 
1105 		i = bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_CIV);
1106 		if (sts & (AUICH_LVBCI | AUICH_CELV)) {
1107 			struct auich_dmalist *q, *qe;
1108 
1109 			q = sc->dmap_pcmi;
1110 			qe = &sc->dmalist_pcmi[i];
1111 
1112 			while (q != qe) {
1113 
1114 				q->base = sc->pcmi_p;
1115 				q->len = (sc->pcmi_blksize /
1116 				    sc->sc_sample_size) | AUICH_DMAF_IOC;
1117 				DPRINTF(AUICH_DEBUG_DMA,
1118 				    ("auich_intr: %p, %p = %x @ %p\n",
1119 				    qe, q, sc->pcmi_blksize /
1120 				    sc->sc_sample_size, sc->pcmi_p));
1121 
1122 				sc->pcmi_p += sc->pcmi_blksize;
1123 				if (sc->pcmi_p >= sc->pcmi_end)
1124 					sc->pcmi_p = sc->pcmi_start;
1125 
1126 				if (++q == &sc->dmalist_pcmi[AUICH_DMALIST_MAX])
1127 					q = sc->dmalist_pcmi;
1128 			}
1129 
1130 			sc->dmap_pcmi = q;
1131 			bus_space_write_1(sc->iot, sc->aud_ioh,
1132 			    AUICH_PCMI + AUICH_LVI,
1133 			    (sc->dmap_pcmi - sc->dmalist_pcmi - 1) &
1134 			    AUICH_LVI_MASK);
1135 		}
1136 
1137 		if (sts & AUICH_BCIS && sc->sc_rintr)
1138 			sc->sc_rintr(sc->sc_rarg);
1139 
1140 		/* int ack */
1141 		bus_space_write_2(sc->iot, sc->aud_ioh,
1142 		    AUICH_PCMI + sc->sc_sts_reg, sts &
1143 		    (AUICH_LVBCI | AUICH_CELV | AUICH_BCIS | AUICH_FIFOE));
1144 		bus_space_write_2(sc->iot, sc->aud_ioh, AUICH_GSTS, AUICH_POINT);
1145 		ret++;
1146 	}
1147 
1148 	if (gsts & AUICH_MIINT) {
1149 		sts = bus_space_read_2(sc->iot, sc->aud_ioh,
1150 		    AUICH_MICI + sc->sc_sts_reg);
1151 		DPRINTF(AUICH_DEBUG_DMA,
1152 		    ("auich_intr: ists=%b\n", sts, AUICH_ISTS_BITS));
1153 		if (sts & AUICH_FIFOE)
1154 			printf("%s: mic fifo overrun\n", sc->sc_dev.dv_xname);
1155 
1156 		/* TODO mic input dma */
1157 
1158 		bus_space_write_2(sc->iot, sc->aud_ioh, AUICH_GSTS, AUICH_MIINT);
1159 	}
1160 
1161 	return ret;
1162 }
1163 
1164 int
1165 auich_trigger_output(v, start, end, blksize, intr, arg, param)
1166 	void *v;
1167 	void *start, *end;
1168 	int blksize;
1169 	void (*intr)(void *);
1170 	void *arg;
1171 	struct audio_params *param;
1172 {
1173 	struct auich_softc *sc = v;
1174 	struct auich_dmalist *q;
1175 	struct auich_dma *p;
1176 
1177 	DPRINTF(AUICH_DEBUG_DMA,
1178 	    ("auich_trigger_output(%x, %x, %d, %p, %p, %p)\n",
1179 	    start, end, blksize, intr, arg, param));
1180 
1181 	for (p = sc->sc_dmas; p && p->addr != start; p = p->next);
1182 	if (!p)
1183 		return -1;
1184 
1185 	sc->sc_pintr = intr;
1186 	sc->sc_parg = arg;
1187 
1188 	/*
1189 	 * The logic behind this is:
1190 	 * setup one buffer to play, then LVI dump out the rest
1191 	 * to the scatter-gather chain.
1192 	 */
1193 	sc->pcmo_start = p->segs->ds_addr;
1194 	sc->pcmo_p = sc->pcmo_start + blksize;
1195 	sc->pcmo_end = sc->pcmo_start + (end - start);
1196 	sc->pcmo_blksize = blksize;
1197 
1198 	q = sc->dmap_pcmo = sc->dmalist_pcmo;
1199 	q->base = sc->pcmo_start;
1200 	q->len = (blksize / sc->sc_sample_size) | AUICH_DMAF_IOC;
1201 	if (++q == &sc->dmalist_pcmo[AUICH_DMALIST_MAX])
1202 		q = sc->dmalist_pcmo;
1203 	sc->dmap_pcmo = q;
1204 
1205 	bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_PCMO + AUICH_BDBAR,
1206 	    kvtop((caddr_t)sc->dmalist_pcmo));
1207 	bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMO + AUICH_CTRL,
1208 	    AUICH_IOCE | AUICH_FEIE | AUICH_LVBIE | AUICH_RPBM);
1209 	bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMO + AUICH_LVI,
1210 	    (sc->dmap_pcmo - 1 - sc->dmalist_pcmo) & AUICH_LVI_MASK);
1211 
1212 	return 0;
1213 }
1214 
1215 int
1216 auich_trigger_input(v, start, end, blksize, intr, arg, param)
1217 	void *v;
1218 	void *start, *end;
1219 	int blksize;
1220 	void (*intr)(void *);
1221 	void *arg;
1222 	struct audio_params *param;
1223 {
1224 	struct auich_softc *sc = v;
1225 	struct auich_dmalist *q;
1226 	struct auich_dma *p;
1227 
1228 	DPRINTF(AUICH_DEBUG_DMA,
1229 	    ("auich_trigger_input(%x, %x, %d, %p, %p, %p)\n",
1230 	    start, end, blksize, intr, arg, param));
1231 
1232 	for (p = sc->sc_dmas; p && p->addr != start; p = p->next);
1233 	if (!p)
1234 		return -1;
1235 
1236 	sc->sc_rintr = intr;
1237 	sc->sc_rarg = arg;
1238 
1239 	/*
1240 	 * The logic behind this is:
1241 	 * setup one buffer to play, then LVI dump out the rest
1242 	 * to the scatter-gather chain.
1243 	 */
1244 	sc->pcmi_start = p->segs->ds_addr;
1245 	sc->pcmi_p = sc->pcmi_start + blksize;
1246 	sc->pcmi_end = sc->pcmi_start + (end - start);
1247 	sc->pcmi_blksize = blksize;
1248 
1249 	q = sc->dmap_pcmi = sc->dmalist_pcmi;
1250 	q->base = sc->pcmi_start;
1251 	q->len = (blksize / sc->sc_sample_size) | AUICH_DMAF_IOC;
1252 	if (++q == &sc->dmalist_pcmi[AUICH_DMALIST_MAX])
1253 		q = sc->dmalist_pcmi;
1254 	sc->dmap_pcmi = q;
1255 
1256 	bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_BDBAR,
1257 	    kvtop((caddr_t)sc->dmalist_pcmi));
1258 	bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_CTRL,
1259 	    AUICH_IOCE | AUICH_FEIE | AUICH_LVBIE | AUICH_RPBM);
1260 	bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_LVI,
1261 	    (sc->dmap_pcmi - 1 - sc->dmalist_pcmi) & AUICH_LVI_MASK);
1262 
1263 	return 0;
1264 }
1265 
1266 void
1267 auich_powerhook(why, self)
1268        int why;
1269        void *self;
1270 {
1271 	struct auich_softc *sc = (struct auich_softc *)self;
1272 
1273 	if (why != PWR_RESUME) {
1274 		/* Power down */
1275 		DPRINTF(1, ("auich: power down\n"));
1276 		sc->suspend = why;
1277 		auich_read_codec(sc, AC97_REG_EXT_AUDIO_CTRL, &sc->ext_ctrl);
1278 
1279 	} else {
1280 		/* Wake up */
1281 		DPRINTF(1, ("auich: power resume\n"));
1282 		if (sc->suspend == PWR_RESUME) {
1283 			printf("%s: resume without suspend?\n",
1284 			    sc->sc_dev.dv_xname);
1285 			sc->suspend = why;
1286 			return;
1287 		}
1288 		sc->suspend = why;
1289 		auich_reset_codec(sc);
1290 		DELAY(1000);
1291 		(sc->codec_if->vtbl->restore_ports)(sc->codec_if);
1292 		auich_write_codec(sc, AC97_REG_EXT_AUDIO_CTRL, sc->ext_ctrl);
1293 	}
1294 }
1295 
1296 
1297 
1298 /* -------------------------------------------------------------------- */
1299 /* Calibrate card (some boards are overclocked and need scaling) */
1300 
1301 unsigned int
1302 auich_calibrate(struct auich_softc *sc)
1303 {
1304 	struct timeval t1, t2;
1305 	u_int8_t ociv, nciv;
1306 	u_int32_t wait_us, actual_48k_rate, bytes, ac97rate;
1307 	void *temp_buffer;
1308 	struct auich_dma *p;
1309 	int i;
1310 
1311 	ac97rate = AUICH_FIXED_RATE;
1312 	/*
1313 	 * Grab audio from input for fixed interval and compare how
1314 	 * much we actually get with what we expect.  Interval needs
1315 	 * to be sufficiently short that no interrupts are
1316 	 * generated.
1317 	 */
1318 
1319 	/* Setup a buffer */
1320 	bytes = 16000;
1321 	temp_buffer = auich_allocm(sc, AUMODE_RECORD, bytes, M_DEVBUF,
1322 	    M_NOWAIT);
1323 	if (temp_buffer == NULL)
1324 		return (ac97rate);
1325 	for (p = sc->sc_dmas; p && p->addr != temp_buffer; p = p->next)
1326 		;
1327 	if (p == NULL) {
1328 		printf("auich_calibrate: bad address %p\n", temp_buffer);
1329 		return (ac97rate);
1330 	}
1331 
1332 	for (i = 0; i < AUICH_DMALIST_MAX; i++) {
1333 		sc->dmalist_pcmi[i].base = p->map->dm_segs[0].ds_addr;
1334 		sc->dmalist_pcmi[i].len = bytes / sc->sc_sample_size;
1335 	}
1336 
1337 	/*
1338 	 * our data format is stereo, 16 bit so each sample is 4 bytes.
1339 	 * assuming we get 48000 samples per second, we get 192000 bytes/sec.
1340 	 * we're going to start recording with interrupts disabled and measure
1341 	 * the time taken for one block to complete.  we know the block size,
1342 	 * we know the time in microseconds, we calculate the sample rate:
1343 	 *
1344 	 * actual_rate [bps] = bytes / (time [s] * 4)
1345 	 * actual_rate [bps] = (bytes * 1000000) / (time [us] * 4)
1346 	 * actual_rate [Hz] = (bytes * 250000) / time [us]
1347 	 */
1348 
1349 	/* prepare */
1350 	ociv = bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_CIV);
1351 	nciv = ociv;
1352 	bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_BDBAR,
1353 	    kvtop((caddr_t)sc->dmalist_pcmi));
1354 	bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_LVI,
1355 			  (0 - 1) & AUICH_LVI_MASK);
1356 
1357 	/* start */
1358 	microtime(&t1);
1359 	bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_CTRL,
1360 	    AUICH_RPBM);
1361 
1362 	/* wait */
1363 	while (nciv == ociv) {
1364 		microtime(&t2);
1365 		if (t2.tv_sec - t1.tv_sec > 1)
1366 			break;
1367 		nciv = bus_space_read_1(sc->iot, sc->aud_ioh,
1368 					AUICH_PCMI + AUICH_CIV);
1369 	}
1370 	microtime(&t2);
1371 
1372 	/* reset */
1373 	bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_CTRL, AUICH_RR);
1374 	bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_MICI + AUICH_CTRL, AUICH_RR);
1375 	DELAY(100);
1376 
1377 	/* turn time delta into us */
1378 	wait_us = ((t2.tv_sec - t1.tv_sec) * 1000000) + t2.tv_usec - t1.tv_usec;
1379 
1380 #if 0
1381 	auich_freem(sc, temp_buffer, M_DEVBUF);
1382 #endif
1383 
1384 	if (nciv == ociv) {
1385 		printf("%s: ac97 link rate calibration timed out after %d us\n",
1386 		       sc->sc_dev.dv_xname, wait_us);
1387 		return (ac97rate);
1388 	}
1389 
1390 	actual_48k_rate = (bytes * 250000) / wait_us;
1391 
1392 	if (actual_48k_rate <= 48500)
1393 		ac97rate = AUICH_FIXED_RATE;
1394 	else
1395 		ac97rate = actual_48k_rate;
1396 
1397 	printf("%s: measured ac97 link rate at %d Hz",
1398 	       sc->sc_dev.dv_xname, actual_48k_rate);
1399 	if (ac97rate != actual_48k_rate)
1400 		printf(", will use %d Hz", ac97rate);
1401 	printf("\n");
1402 
1403 	return (ac97rate);
1404 }
1405