1/*	$NetBSD: auich.c,v 1.161 2023/05/10 00:11:24 riastradh Exp $	*/
2
3/*-
4 * Copyright (c) 2000, 2004, 2005, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe and by Charles M. Hannum.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32/*
33 * Copyright (c) 2000 Michael Shalayeff
34 * All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 *    notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 *    notice, this list of conditions and the following disclaimer in the
43 *    documentation and/or other materials provided with the distribution.
44 * 3. The name of the author may not be used to endorse or promote products
45 *    derived from this software without specific prior written permission.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
48 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
49 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
50 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
51 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
52 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
53 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
55 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
56 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
57 * THE POSSIBILITY OF SUCH DAMAGE.
58 *
59 *	from OpenBSD: ich.c,v 1.3 2000/08/11 06:17:18 mickey Exp
60 */
61
62/*
63 * Copyright (c) 2000 Katsurajima Naoto <raven@katsurajima.seya.yokohama.jp>
64 * Copyright (c) 2001 Cameron Grant <cg@freebsd.org>
65 * All rights reserved.
66 *
67 * Redistribution and use in source and binary forms, with or without
68 * modification, are permitted provided that the following conditions
69 * are met:
70 * 1. Redistributions of source code must retain the above copyright
71 *    notice, this list of conditions and the following disclaimer.
72 * 2. Redistributions in binary form must reproduce the above copyright
73 *    notice, this list of conditions and the following disclaimer in the
74 *    documentation and/or other materials provided with the distribution.
75 *
76 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
77 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
78 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
79 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
80 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
81 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
82 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
83 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
84 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
85 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
86 * SUCH DAMAGE.
87 *
88 * auich_calibrate() was from FreeBSD: ich.c,v 1.22 2002/06/27 22:36:01 scottl Exp
89 */
90
91
92/* #define	AUICH_DEBUG */
93/*
94 * AC'97 audio found on Intel 810/820/440MX chipsets.
95 *	http://developer.intel.com/design/chipsets/datashts/290655.htm
96 *	http://developer.intel.com/design/chipsets/manuals/298028.htm
97 * ICH3:http://www.intel.com/design/chipsets/datashts/290716.htm
98 * ICH4:http://www.intel.com/design/chipsets/datashts/290744.htm
99 * ICH5:http://www.intel.com/design/chipsets/datashts/252516.htm
100 * AMD8111:
101 *	http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/24674.pdf
102 *	http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/25720.pdf
103 *
104 * TODO:
105 *	- Add support for the dedicated microphone input.
106 *
107 * NOTE:
108 *      - The 440MX B-stepping at running 100MHz has a hardware erratum.
109 *        It causes PCI master abort and hangups until cold reboot.
110 *        http://www.intel.com/design/chipsets/specupdt/245051.htm
111 */
112
113#include <sys/cdefs.h>
114__KERNEL_RCSID(0, "$NetBSD: auich.c,v 1.161 2023/05/10 00:11:24 riastradh Exp $");
115
116#include <sys/param.h>
117#include <sys/systm.h>
118#include <sys/kernel.h>
119#include <sys/kmem.h>
120#include <sys/device.h>
121#include <sys/fcntl.h>
122#include <sys/proc.h>
123#include <sys/sysctl.h>
124#include <sys/audioio.h>
125#include <sys/bus.h>
126#include <sys/rndsource.h>
127
128#include <dev/pci/pcidevs.h>
129#include <dev/pci/pcivar.h>
130#include <dev/pci/auichreg.h>
131
132#include <dev/audio/audio_if.h>
133
134#include <dev/ic/ac97reg.h>
135#include <dev/ic/ac97var.h>
136
137struct auich_dma {
138	bus_dmamap_t map;
139	void *addr;
140	bus_dma_segment_t segs[1];
141	int nsegs;
142	size_t size;
143	struct auich_dma *next;
144};
145
146#define	DMAADDR(p)	((p)->map->dm_segs[0].ds_addr)
147#define	KERNADDR(p)	((void *)((p)->addr))
148
149struct auich_cdata {
150	struct auich_dmalist ic_dmalist_pcmo[ICH_DMALIST_MAX];
151	struct auich_dmalist ic_dmalist_pcmi[ICH_DMALIST_MAX];
152	struct auich_dmalist ic_dmalist_mici[ICH_DMALIST_MAX];
153};
154
155#define	ICH_CDOFF(x)		offsetof(struct auich_cdata, x)
156#define	ICH_PCMO_OFF(x)		ICH_CDOFF(ic_dmalist_pcmo[(x)])
157#define	ICH_PCMI_OFF(x)		ICH_CDOFF(ic_dmalist_pcmi[(x)])
158#define	ICH_MICI_OFF(x)		ICH_CDOFF(ic_dmalist_mici[(x)])
159
160struct auich_softc {
161	device_t sc_dev;
162	void *sc_ih;
163	kmutex_t sc_lock;
164	kmutex_t sc_intr_lock;
165
166	device_t sc_audiodev;
167	audio_device_t sc_audev;
168
169	pci_chipset_tag_t sc_pc;
170	pcitag_t sc_pt;
171	bus_space_tag_t iot;
172	bus_space_handle_t mix_ioh;
173	bus_size_t mix_size;
174	bus_space_handle_t aud_ioh;
175	bus_size_t aud_size;
176	bus_dma_tag_t dmat;
177	pci_intr_handle_t intrh;
178
179	struct ac97_codec_if *codec_if;
180	struct ac97_host_if host_if;
181	int sc_codecnum;
182	int sc_codectype;
183	int sc_fixedrate;
184	enum ac97_host_flags sc_codecflags;
185	bool sc_spdif;
186
187	/* multi-channel control bits */
188	int sc_pcm246_mask;
189	int sc_pcm2;
190	int sc_pcm4;
191	int sc_pcm6;
192
193	/* DMA scatter-gather lists. */
194	bus_dmamap_t sc_cddmamap;
195#define	sc_cddma	sc_cddmamap->dm_segs[0].ds_addr
196
197	struct auich_cdata *sc_cdata;
198
199	struct auich_ring {
200		int qptr;
201		struct auich_dmalist *dmalist;
202
203		uint32_t start, p, end;
204		int blksize;
205
206		void (*intr)(void *);
207		void *arg;
208	} pcmo, pcmi, mici;
209
210	struct auich_dma *sc_dmas;
211
212	/* SiS 7012 hack */
213	int  sc_sample_shift;
214	int  sc_sts_reg;
215	/* 440MX workaround */
216	int  sc_dmamap_flags;
217	/* flags */
218	u_int  sc_iose	:1,
219		     	:31;
220
221	/* sysctl */
222	struct sysctllog *sc_log;
223	uint32_t sc_ac97_clock;
224	int sc_ac97_clock_mib;
225
226	int	sc_modem_offset;
227
228#define AUICH_AUDIO_NFORMATS	3
229#define AUICH_MODEM_NFORMATS	1
230	struct audio_format sc_audio_formats[AUICH_AUDIO_NFORMATS];
231	struct audio_format sc_modem_formats[AUICH_MODEM_NFORMATS];
232
233	int sc_cas_been_used;
234};
235
236/* Debug */
237#ifdef AUICH_DEBUG
238#define	DPRINTF(l,x)	do { if (auich_debug & (l)) aprint_normal_dev x; } while(0)
239int auich_debug = 0xfffe;
240#define	ICH_DEBUG_CODECIO	0x0001
241#define	ICH_DEBUG_DMA		0x0002
242#define	ICH_DEBUG_INTR		0x0004
243#else
244#define	DPRINTF(x,y)	/* nothing */
245#endif
246
247static int	auich_match(device_t, cfdata_t, void *);
248static void	auich_attach(device_t, device_t, void *);
249static int	auich_detach(device_t, int);
250static void	auich_childdet(device_t, device_t);
251static int	auich_intr(void *);
252
253CFATTACH_DECL2_NEW(auich, sizeof(struct auich_softc),
254    auich_match, auich_attach, auich_detach, NULL, NULL, auich_childdet);
255
256static int	auich_open(void *, int);
257static void	auich_close(void *);
258static int	auich_query_format(void *, struct audio_format_query *);
259static int	auich_set_format(void *, int,
260		    const audio_params_t *, const audio_params_t *,
261		    audio_filter_reg_t *, audio_filter_reg_t *);
262static void	auich_halt_pipe(struct auich_softc *, int);
263static int	auich_halt_output(void *);
264static int	auich_halt_input(void *);
265static int	auich_getdev(void *, struct audio_device *);
266static int	auich_set_port(void *, mixer_ctrl_t *);
267static int	auich_get_port(void *, mixer_ctrl_t *);
268static int	auich_query_devinfo(void *, mixer_devinfo_t *);
269static void	*auich_allocm(void *, int, size_t);
270static void	auich_freem(void *, void *, size_t);
271static size_t	auich_round_buffersize(void *, int, size_t);
272static int	auich_get_props(void *);
273static void	auich_trigger_pipe(struct auich_softc *, int, struct auich_ring *);
274static void	auich_intr_pipe(struct auich_softc *, int, struct auich_ring *);
275static int	auich_trigger_output(void *, void *, void *, int,
276		    void (*)(void *), void *, const audio_params_t *);
277static int	auich_trigger_input(void *, void *, void *, int,
278		    void (*)(void *), void *, const audio_params_t *);
279static void	auich_get_locks(void *, kmutex_t **, kmutex_t **);
280
281static int	auich_alloc_cdata(struct auich_softc *);
282
283static int	auich_allocmem(struct auich_softc *, size_t, size_t,
284		    struct auich_dma *);
285static int	auich_freemem(struct auich_softc *, struct auich_dma *);
286
287static bool	auich_resume(device_t, const pmf_qual_t *);
288static int	auich_set_rate(struct auich_softc *, int, u_long);
289static int	auich_sysctl_verify(SYSCTLFN_ARGS);
290static void	auich_finish_attach(device_t);
291static void	auich_calibrate(struct auich_softc *);
292static void	auich_clear_cas(struct auich_softc *);
293
294static int	auich_attach_codec(void *, struct ac97_codec_if *);
295static int	auich_read_codec(void *, uint8_t, uint16_t *);
296static int	auich_write_codec(void *, uint8_t, uint16_t);
297static int	auich_reset_codec(void *);
298static enum ac97_host_flags	auich_flags_codec(void *);
299static void	auich_spdif_event(void *, bool);
300
301static const struct audio_hw_if auich_hw_if = {
302	.open			= auich_open,
303	.close			= auich_close,
304	.query_format		= auich_query_format,
305	.set_format		= auich_set_format,
306	.halt_output		= auich_halt_output,
307	.halt_input		= auich_halt_input,
308	.getdev			= auich_getdev,
309	.set_port		= auich_set_port,
310	.get_port		= auich_get_port,
311	.query_devinfo		= auich_query_devinfo,
312	.allocm			= auich_allocm,
313	.freem			= auich_freem,
314	.round_buffersize	= auich_round_buffersize,
315	.get_props		= auich_get_props,
316	.trigger_output		= auich_trigger_output,
317	.trigger_input		= auich_trigger_input,
318	.get_locks		= auich_get_locks,
319};
320
321#define AUICH_FORMATS_1CH	0
322#define AUICH_FORMATS_4CH	1
323#define AUICH_FORMATS_6CH	2
324#define AUICH_FORMAT(aumode, ch, chmask) \
325	{ \
326		.mode		= (aumode), \
327		.encoding	= AUDIO_ENCODING_SLINEAR_LE, \
328		.validbits	= 16, \
329		.precision	= 16, \
330		.channels	= (ch), \
331		.channel_mask	= (chmask), \
332		.frequency_type	= 0, \
333		.frequency	= { 8000, 48000 }, \
334	}
335static const struct audio_format auich_audio_formats[AUICH_AUDIO_NFORMATS] = {
336	AUICH_FORMAT(AUMODE_PLAY | AUMODE_RECORD, 2, AUFMT_STEREO),
337	AUICH_FORMAT(AUMODE_PLAY                , 4, AUFMT_SURROUND4),
338	AUICH_FORMAT(AUMODE_PLAY                , 6, AUFMT_DOLBY_5_1),
339};
340
341#define AUICH_SPDIF_NFORMATS	1
342static const struct audio_format auich_spdif_formats[AUICH_SPDIF_NFORMATS] = {
343	{
344		.mode		= AUMODE_PLAY | AUMODE_RECORD,
345		.encoding	= AUDIO_ENCODING_SLINEAR_LE,
346		.validbits	= 16,
347		.precision	= 16,
348		.channels	= 2,
349		.channel_mask	= AUFMT_STEREO,
350		.frequency_type	= 1,
351		.frequency	= { 48000 },
352	},
353};
354
355static const struct audio_format auich_modem_formats[AUICH_MODEM_NFORMATS] = {
356	{
357		.mode		= AUMODE_PLAY | AUMODE_RECORD,
358		.encoding	= AUDIO_ENCODING_SLINEAR_LE,
359		.validbits	= 16,
360		.precision	= 16,
361		.channels	= 1,
362		.channel_mask	= AUFMT_MONAURAL,
363		.frequency_type	= 2,
364		.frequency	= { 8000, 16000 },
365	},
366};
367
368#define PCI_ID_CODE0(v, p)	PCI_ID_CODE(PCI_VENDOR_##v, PCI_PRODUCT_##v##_##p)
369#define PCIID_ICH		PCI_ID_CODE0(INTEL, 82801AA_ACA)
370#define PCIID_ICH0		PCI_ID_CODE0(INTEL, 82801AB_ACA)
371#define PCIID_ICH2		PCI_ID_CODE0(INTEL, 82801BA_ACA)
372#define PCIID_440MX		PCI_ID_CODE0(INTEL, 82440MX_ACA)
373#define PCIID_ICH3		PCI_ID_CODE0(INTEL, 82801CA_AC)
374#define PCIID_ICH4		PCI_ID_CODE0(INTEL, 82801DB_AC)
375#define PCIID_ICH5		PCI_ID_CODE0(INTEL, 82801EB_AC)
376#define PCIID_ICH6		PCI_ID_CODE0(INTEL, 82801FB_AC)
377#define PCIID_ICH7		PCI_ID_CODE0(INTEL, 82801G_ACA)
378#define PCIID_I6300ESB		PCI_ID_CODE0(INTEL, 6300ESB_ACA)
379#define PCIID_SIS7012		PCI_ID_CODE0(SIS, 7012_AC)
380#define PCIID_NFORCE		PCI_ID_CODE0(NVIDIA, NFORCE_MCP_AC)
381#define PCIID_NFORCE2		PCI_ID_CODE0(NVIDIA, NFORCE2_MCPT_AC)
382#define PCIID_NFORCE2_400	PCI_ID_CODE0(NVIDIA, NFORCE2_400_MCPT_AC)
383#define PCIID_NFORCE3		PCI_ID_CODE0(NVIDIA, NFORCE3_MCPT_AC)
384#define PCIID_NFORCE3_250	PCI_ID_CODE0(NVIDIA, NFORCE3_250_MCPT_AC)
385#define PCIID_NFORCE4		PCI_ID_CODE0(NVIDIA, NFORCE4_AC)
386#define	PCIID_NFORCE430 	PCI_ID_CODE0(NVIDIA, NFORCE430_AC)
387#define PCIID_AMD768		PCI_ID_CODE0(AMD, PBC768_AC)
388#define PCIID_AMD8111		PCI_ID_CODE0(AMD, PBC8111_AC)
389
390#define	PCIID_ICH3MODEM		PCI_ID_CODE0(INTEL, 82801CA_MOD)
391#define PCIID_ICH4MODEM		PCI_ID_CODE0(INTEL, 82801DB_MOD)
392#define PCIID_ICH6MODEM 	PCI_ID_CODE0(INTEL, 82801FB_ACM)
393
394struct auich_devtype {
395	pcireg_t	id;
396	const char	*name;
397	const char	*shortname;	/* must be less than 11 characters */
398};
399
400static const struct auich_devtype auich_audio_devices[] = {
401	{ PCIID_ICH,	"i82801AA (ICH) AC-97 Audio",	"ICH" },
402	{ PCIID_ICH0,	"i82801AB (ICH0) AC-97 Audio",	"ICH0" },
403	{ PCIID_ICH2,	"i82801BA (ICH2) AC-97 Audio",	"ICH2" },
404	{ PCIID_440MX,	"i82440MX AC-97 Audio",		"440MX" },
405	{ PCIID_ICH3,	"i82801CA (ICH3) AC-97 Audio",	"ICH3" },
406	{ PCIID_ICH4,	"i82801DB/DBM (ICH4/ICH4M) AC-97 Audio", "ICH4" },
407	{ PCIID_ICH5,	"i82801EB (ICH5) AC-97 Audio",	"ICH5" },
408	{ PCIID_ICH6,	"i82801FB (ICH6) AC-97 Audio",	"ICH6" },
409	{ PCIID_ICH7,	"i82801GB/GR (ICH7) AC-97 Audio",	"ICH7" },
410	{ PCIID_I6300ESB,	"Intel 6300ESB AC-97 Audio",	"I6300ESB" },
411	{ PCIID_SIS7012, "SiS 7012 AC-97 Audio",	"SiS7012" },
412	{ PCIID_NFORCE,	"nForce MCP AC-97 Audio",	"nForce" },
413	{ PCIID_NFORCE2, "nForce2 MCP-T AC-97 Audio",	"nForce2" },
414	{ PCIID_NFORCE2_400, "nForce2 400 MCP-T AC-97 Audio",	"nForce2" },
415	{ PCIID_NFORCE3, "nForce3 MCP-T AC-97 Audio",	"nForce3" },
416	{ PCIID_NFORCE3_250, "nForce3 250 MCP-T AC-97 Audio", "nForce3" },
417	{ PCIID_NFORCE4, "nForce4 AC-97 Audio",		"nForce4" },
418	{ PCIID_NFORCE430, "nForce430 (MCP51) AC-97 Audio", "nForce430" },
419	{ PCIID_AMD768,	"AMD768 AC-97 Audio",		"AMD768" },
420	{ PCIID_AMD8111,"AMD8111 AC-97 Audio",		"AMD8111" },
421	{ 0,		NULL,				NULL },
422};
423
424static const struct auich_devtype auich_modem_devices[] = {
425#ifdef AUICH_ATTACH_MODEM
426	{ PCIID_ICH3MODEM, "i82801CA (ICH3) AC-97 Modem", "ICH3MODEM" },
427	{ PCIID_ICH4MODEM, "i82801DB (ICH4) AC-97 Modem", "ICH4MODEM" },
428	{ PCIID_ICH6MODEM, "i82801FB (ICH6) AC-97 Modem", "ICH6MODEM" },
429#endif
430	{ 0,		NULL,				NULL },
431};
432
433static const struct auich_devtype *
434auich_lookup(struct pci_attach_args *pa, const struct auich_devtype *auich_devices)
435{
436	const struct auich_devtype *d;
437
438	for (d = auich_devices; d->name != NULL; d++) {
439		if (pa->pa_id == d->id)
440			return d;
441	}
442
443	return NULL;
444}
445
446static int
447auich_match(device_t parent, cfdata_t match, void *aux)
448{
449	struct pci_attach_args *pa;
450
451	pa = aux;
452	if (auich_lookup(pa, auich_audio_devices) != NULL)
453		return 1;
454	if (auich_lookup(pa, auich_modem_devices) != NULL)
455		return 1;
456
457	return 0;
458}
459
460static void
461auich_attach(device_t parent, device_t self, void *aux)
462{
463	struct auich_softc *sc = device_private(self);
464	struct pci_attach_args *pa;
465	pcireg_t v, subdev;
466	const char *intrstr;
467	const struct auich_devtype *d;
468	const struct sysctlnode *node, *node_ac97clock;
469	int err, node_mib, i;
470	char intrbuf[PCI_INTRSTR_LEN];
471
472	sc->sc_dev = self;
473	pa = aux;
474
475	if ((d = auich_lookup(pa, auich_modem_devices)) != NULL) {
476		sc->sc_modem_offset = 0x10;
477		sc->sc_codectype = AC97_CODEC_TYPE_MODEM;
478	} else if ((d = auich_lookup(pa, auich_audio_devices)) != NULL) {
479		sc->sc_modem_offset = 0;
480		sc->sc_codectype = AC97_CODEC_TYPE_AUDIO;
481	} else
482		panic("auich_attach: impossible");
483
484	if (sc->sc_codectype == AC97_CODEC_TYPE_AUDIO)
485		aprint_naive(": Audio controller\n");
486	else
487		aprint_naive(": Modem controller\n");
488
489	sc->sc_pc = pa->pa_pc;
490	sc->sc_pt = pa->pa_tag;
491
492	aprint_normal(": %s\n", d->name);
493
494	if (d->id == PCIID_ICH4 || d->id == PCIID_ICH5 || d->id == PCIID_ICH6
495	    || d->id == PCIID_ICH7 || d->id == PCIID_I6300ESB
496	    || d->id == PCIID_ICH4MODEM) {
497		/*
498		 * Use native mode for Intel 6300ESB and ICH4/ICH5/ICH6/ICH7
499		 */
500
501		if (pci_mapreg_map(pa, ICH_MMBAR, PCI_MAPREG_TYPE_MEM, 0,
502		    &sc->iot, &sc->mix_ioh, NULL, &sc->mix_size)) {
503			goto retry_map;
504		}
505		if (pci_mapreg_map(pa, ICH_MBBAR, PCI_MAPREG_TYPE_MEM, 0,
506		    &sc->iot, &sc->aud_ioh, NULL, &sc->aud_size)) {
507			goto retry_map;
508		}
509		goto map_done;
510	} else
511		goto non_native_map;
512
513retry_map:
514	sc->sc_iose = 1;
515	v = pci_conf_read(pa->pa_pc, pa->pa_tag, ICH_CFG);
516	pci_conf_write(pa->pa_pc, pa->pa_tag, ICH_CFG,
517		       v | ICH_CFG_IOSE);
518
519non_native_map:
520	if (pci_mapreg_map(pa, ICH_NAMBAR, PCI_MAPREG_TYPE_IO, 0,
521			   &sc->iot, &sc->mix_ioh, NULL, &sc->mix_size)) {
522		aprint_error_dev(self, "can't map codec i/o space\n");
523		return;
524	}
525	if (pci_mapreg_map(pa, ICH_NABMBAR, PCI_MAPREG_TYPE_IO, 0,
526			   &sc->iot, &sc->aud_ioh, NULL, &sc->aud_size)) {
527		aprint_error_dev(self, "can't map device i/o space\n");
528		return;
529	}
530
531map_done:
532	sc->dmat = pa->pa_dmat;
533
534	/* enable bus mastering */
535	v = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
536	pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
537	    v | PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_BACKTOBACK_ENABLE);
538
539	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
540	mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO);
541
542	/* Map and establish the interrupt. */
543	if (pci_intr_map(pa, &sc->intrh)) {
544		aprint_error_dev(self, "can't map interrupt\n");
545		return;
546	}
547	intrstr = pci_intr_string(pa->pa_pc, sc->intrh, intrbuf, sizeof(intrbuf));
548	sc->sc_ih = pci_intr_establish_xname(pa->pa_pc, sc->intrh, IPL_AUDIO,
549	    auich_intr, sc, device_xname(sc->sc_dev));
550	if (sc->sc_ih == NULL) {
551		aprint_error_dev(self, "can't establish interrupt");
552		if (intrstr != NULL)
553			aprint_error(" at %s", intrstr);
554		aprint_error("\n");
555		return;
556	}
557	aprint_normal_dev(self, "interrupting at %s\n", intrstr);
558
559	snprintf(sc->sc_audev.name, MAX_AUDIO_DEV_LEN, "%s AC97", d->shortname);
560	snprintf(sc->sc_audev.version, MAX_AUDIO_DEV_LEN,
561		 "0x%02x", PCI_REVISION(pa->pa_class));
562	strlcpy(sc->sc_audev.config, device_xname(self), MAX_AUDIO_DEV_LEN);
563
564	/* SiS 7012 needs special handling */
565	if (d->id == PCIID_SIS7012) {
566		sc->sc_sts_reg = ICH_PICB;
567		sc->sc_sample_shift = 0;
568		sc->sc_pcm246_mask = ICH_SIS_PCM246_MASK;
569		sc->sc_pcm2 = ICH_SIS_PCM2;
570		sc->sc_pcm4 = ICH_SIS_PCM4;
571		sc->sc_pcm6 = ICH_SIS_PCM6;
572		/* Un-mute output. From Linux. */
573		bus_space_write_4(sc->iot, sc->aud_ioh, ICH_SIS_NV_CTL,
574		    bus_space_read_4(sc->iot, sc->aud_ioh, ICH_SIS_NV_CTL) |
575		    ICH_SIS_CTL_UNMUTE);
576	} else {
577		sc->sc_sts_reg = ICH_STS;
578		sc->sc_sample_shift = 1;
579		sc->sc_pcm246_mask = ICH_PCM246_MASK;
580		sc->sc_pcm2 = ICH_PCM2;
581		sc->sc_pcm4 = ICH_PCM4;
582		sc->sc_pcm6 = ICH_PCM6;
583	}
584
585	/* Workaround for a 440MX B-stepping erratum */
586	sc->sc_dmamap_flags = BUS_DMA_COHERENT;
587	if (d->id == PCIID_440MX) {
588		sc->sc_dmamap_flags |= BUS_DMA_NOCACHE;
589		aprint_normal_dev(self, "DMA bug workaround enabled\n");
590	}
591
592	/* Set up DMA lists. */
593	sc->pcmo.qptr = sc->pcmi.qptr = sc->mici.qptr = 0;
594	auich_alloc_cdata(sc);
595
596	DPRINTF(ICH_DEBUG_DMA, (sc->sc_dev, "%s: lists %p %p %p\n",
597	    __func__, sc->pcmo.dmalist, sc->pcmi.dmalist, sc->mici.dmalist));
598
599	/* Modem codecs are always the secondary codec on ICH */
600	sc->sc_codecnum = sc->sc_codectype == AC97_CODEC_TYPE_MODEM ? 1 : 0;
601
602	sc->host_if.arg = sc;
603	sc->host_if.attach = auich_attach_codec;
604	sc->host_if.read = auich_read_codec;
605	sc->host_if.write = auich_write_codec;
606	sc->host_if.reset = auich_reset_codec;
607	sc->host_if.flags = auich_flags_codec;
608	sc->host_if.spdif_event = auich_spdif_event;
609
610	subdev = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
611	switch (subdev) {
612	case 0x202f161f:	/* Gateway 7326GZ */
613	case 0x203a161f:	/* Gateway 4028GZ */
614	case 0x204c161f:	/* Kvazar-Micro Senator 3592XT */
615	case 0x8144104d:	/* Sony VAIO PCG-TR* */
616	case 0x8197104d:	/* Sony S1XP */
617	case 0x81c0104d:	/* Sony VAIO type T */
618	case 0x81c5104d:	/* Sony VAIO VGN-B1XP */
619		sc->sc_codecflags = AC97_HOST_INVERTED_EAMP;
620		break;
621	default:
622		sc->sc_codecflags = 0;
623		break;
624	}
625
626	if (ac97_attach_type(&sc->host_if, self, sc->sc_codectype,
627	    &sc->sc_lock) != 0)
628		return;
629
630	mutex_enter(&sc->sc_lock);
631	sc->codec_if->vtbl->unlock(sc->codec_if);
632	sc->sc_fixedrate = AC97_IS_FIXED_RATE(sc->codec_if);
633
634	/* setup audio_format */
635	if (sc->sc_codectype == AC97_CODEC_TYPE_AUDIO) {
636		memcpy(sc->sc_audio_formats, auich_audio_formats,
637		    sizeof(auich_audio_formats));
638		if (!AC97_IS_4CH(sc->codec_if))
639			AUFMT_INVALIDATE(&sc->sc_audio_formats[AUICH_FORMATS_4CH]);
640		if (!AC97_IS_6CH(sc->codec_if))
641			AUFMT_INVALIDATE(&sc->sc_audio_formats[AUICH_FORMATS_6CH]);
642		if (AC97_IS_FIXED_RATE(sc->codec_if)) {
643			for (i = 0; i < AUICH_AUDIO_NFORMATS; i++) {
644				sc->sc_audio_formats[i].frequency_type = 1;
645				sc->sc_audio_formats[i].frequency[0] = 48000;
646			}
647		}
648		mutex_exit(&sc->sc_lock);
649	} else {
650		mutex_exit(&sc->sc_lock);
651		memcpy(sc->sc_modem_formats, auich_modem_formats,
652		    sizeof(auich_modem_formats));
653	}
654
655	/* Watch for power change */
656	if (!pmf_device_register(self, NULL, auich_resume))
657		aprint_error_dev(self, "couldn't establish power handler\n");
658
659	config_interrupts(self, auich_finish_attach);
660
661	/* sysctl setup */
662	if (sc->sc_fixedrate && sc->sc_codectype == AC97_CODEC_TYPE_AUDIO)
663		return;
664
665	err = sysctl_createv(&sc->sc_log, 0, NULL, &node, 0,
666			     CTLTYPE_NODE, device_xname(self), NULL, NULL, 0,
667			     NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL);
668	if (err != 0)
669		goto sysctl_err;
670	node_mib = node->sysctl_num;
671
672	if (!sc->sc_fixedrate) {
673		/* passing the sc address instead of &sc->sc_ac97_clock */
674		err = sysctl_createv(&sc->sc_log, 0, NULL, &node_ac97clock,
675				     CTLFLAG_READWRITE,
676				     CTLTYPE_INT, "ac97rate",
677				     SYSCTL_DESCR("AC'97 codec link rate"),
678				     auich_sysctl_verify, 0, (void *)sc, 0,
679				     CTL_HW, node_mib, CTL_CREATE, CTL_EOL);
680		if (err != 0)
681			goto sysctl_err;
682		sc->sc_ac97_clock_mib = node_ac97clock->sysctl_num;
683	}
684
685	return;
686
687 sysctl_err:
688	aprint_error_dev(self, "failed to add sysctl nodes. (%d)\n", err);
689	return;			/* failure of sysctl is not fatal. */
690}
691
692static void
693auich_childdet(device_t self, device_t child)
694{
695	struct auich_softc *sc = device_private(self);
696
697	KASSERT(sc->sc_audiodev == child);
698	sc->sc_audiodev = NULL;
699}
700
701static int
702auich_detach(device_t self, int flags)
703{
704	struct auich_softc *sc = device_private(self);
705	int error;
706
707	/* audio */
708	error = config_detach_children(self, flags);
709	if (error)
710		return error;
711
712	/* sysctl */
713	sysctl_teardown(&sc->sc_log);
714
715	mutex_enter(&sc->sc_lock);
716
717	/* ac97 */
718	if (sc->codec_if != NULL)
719		sc->codec_if->vtbl->detach(sc->codec_if);
720
721	mutex_exit(&sc->sc_lock);
722	mutex_destroy(&sc->sc_lock);
723	mutex_destroy(&sc->sc_intr_lock);
724
725	/* PCI */
726	if (sc->sc_ih != NULL)
727		pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
728	if (sc->mix_size != 0)
729		bus_space_unmap(sc->iot, sc->mix_ioh, sc->mix_size);
730	if (sc->aud_size != 0)
731		bus_space_unmap(sc->iot, sc->aud_ioh, sc->aud_size);
732	return 0;
733}
734
735static int
736auich_sysctl_verify(SYSCTLFN_ARGS)
737{
738	int error, tmp;
739	struct sysctlnode node;
740	struct auich_softc *sc;
741
742	node = *rnode;
743	sc = rnode->sysctl_data;
744	if (node.sysctl_num == sc->sc_ac97_clock_mib) {
745		tmp = sc->sc_ac97_clock;
746		node.sysctl_data = &tmp;
747		error = sysctl_lookup(SYSCTLFN_CALL(&node));
748		if (error || newp == NULL)
749			return error;
750
751		if (tmp < 48000 || tmp > 96000)
752			return EINVAL;
753		mutex_enter(&sc->sc_lock);
754		sc->sc_ac97_clock = tmp;
755		mutex_exit(&sc->sc_lock);
756	}
757
758	return 0;
759}
760
761static void
762auich_finish_attach(device_t self)
763{
764	struct auich_softc *sc = device_private(self);
765
766	mutex_enter(&sc->sc_lock);
767	if (!AC97_IS_FIXED_RATE(sc->codec_if))
768		auich_calibrate(sc);
769	mutex_exit(&sc->sc_lock);
770
771	sc->sc_audiodev = audio_attach_mi(&auich_hw_if, sc, sc->sc_dev);
772
773	return;
774}
775
776#define ICH_CODECIO_INTERVAL	10
777static int
778auich_read_codec(void *v, uint8_t reg, uint16_t *val)
779{
780	struct auich_softc *sc;
781	int i;
782	uint32_t status;
783
784	sc = v;
785	/* wait for an access semaphore */
786	for (i = ICH_SEMATIMO / ICH_CODECIO_INTERVAL; i-- &&
787	    bus_space_read_1(sc->iot, sc->aud_ioh,
788		ICH_CAS + sc->sc_modem_offset) & 1;
789	    DELAY(ICH_CODECIO_INTERVAL));
790
791	/*
792	 * Be permissive in first attempt. If previous instances of
793	 * this routine were interrupted precisely at this point (after
794	 * access is granted by CAS but before a command is sent),
795	 * they could have left hardware in an inconsistent state where
796	 * a command is expected and therefore semaphore wait would hit
797	 * the timeout.
798	 */
799	if (!sc->sc_cas_been_used && i <= 0)
800		i = 1;
801	sc->sc_cas_been_used = 1;
802
803	if (i > 0) {
804		*val = bus_space_read_2(sc->iot, sc->mix_ioh,
805		    reg + (sc->sc_codecnum * ICH_CODEC_OFFSET));
806		DPRINTF(ICH_DEBUG_CODECIO,
807		    (sc->sc_dev, "%s(%x, %x)\n", __func__, reg, *val));
808		status = bus_space_read_4(sc->iot, sc->aud_ioh,
809		    ICH_GSTS + sc->sc_modem_offset);
810		if (status & ICH_RCS) {
811			bus_space_write_4(sc->iot, sc->aud_ioh,
812					  ICH_GSTS + sc->sc_modem_offset,
813					  status & ~(ICH_SRI|ICH_PRI|ICH_GSCI));
814			*val = 0xffff;
815			DPRINTF(ICH_DEBUG_CODECIO,
816			    (sc->sc_dev, "%s: read_codec error\n", __func__));
817			if (reg == AC97_REG_GPIO_STATUS)
818				auich_clear_cas(sc);
819			return -1;
820		}
821		if (reg == AC97_REG_GPIO_STATUS)
822			auich_clear_cas(sc);
823		return 0;
824	} else {
825		aprint_normal_dev(sc->sc_dev, "read_codec timeout\n");
826		if (reg == AC97_REG_GPIO_STATUS)
827			auich_clear_cas(sc);
828		return -1;
829	}
830}
831
832static int
833auich_write_codec(void *v, uint8_t reg, uint16_t val)
834{
835	struct auich_softc *sc;
836	int i;
837
838	sc = v;
839	DPRINTF(ICH_DEBUG_CODECIO, (sc->sc_dev, "%s(%x, %x)\n",
840	    __func__, reg, val));
841	/* wait for an access semaphore */
842	for (i = ICH_SEMATIMO / ICH_CODECIO_INTERVAL; i-- &&
843	    bus_space_read_1(sc->iot, sc->aud_ioh,
844		ICH_CAS + sc->sc_modem_offset) & 1;
845	    DELAY(ICH_CODECIO_INTERVAL));
846
847	/* Be permissive in first attempt (see comments in auich_read_codec) */
848	if (!sc->sc_cas_been_used && i <= 0)
849		i = 1;
850	sc->sc_cas_been_used = 1;
851
852	if (i > 0) {
853		bus_space_write_2(sc->iot, sc->mix_ioh,
854		    reg + (sc->sc_codecnum * ICH_CODEC_OFFSET), val);
855		return 0;
856	} else {
857		aprint_normal_dev(sc->sc_dev, "write_codec timeout\n");
858		return -1;
859	}
860}
861
862static int
863auich_attach_codec(void *v, struct ac97_codec_if *cif)
864{
865	struct auich_softc *sc;
866
867	sc = v;
868	sc->codec_if = cif;
869
870	return 0;
871}
872
873static int
874auich_reset_codec(void *v)
875{
876	struct auich_softc *sc;
877	int i;
878	uint32_t control, status;
879
880	sc = v;
881	control = bus_space_read_4(sc->iot, sc->aud_ioh,
882	    ICH_GCTRL + sc->sc_modem_offset);
883	if (sc->sc_codectype == AC97_CODEC_TYPE_AUDIO) {
884		control &= ~(ICH_ACLSO | sc->sc_pcm246_mask);
885	} else {
886		control &= ~ICH_ACLSO;
887		control |= ICH_GIE;
888	}
889	control |= (control & ICH_CRESET) ? ICH_WRESET : ICH_CRESET;
890	bus_space_write_4(sc->iot, sc->aud_ioh,
891	    ICH_GCTRL + sc->sc_modem_offset, control);
892
893	for (i = 500000; i >= 0; i--) {
894		status = bus_space_read_4(sc->iot, sc->aud_ioh,
895		    ICH_GSTS + sc->sc_modem_offset);
896		if (status & (ICH_PCR | ICH_SCR | ICH_S2CR))
897			break;
898		DELAY(1);
899	}
900	if (i <= 0) {
901		aprint_error_dev(sc->sc_dev, "auich_reset_codec: time out\n");
902		return ETIMEDOUT;
903	}
904#ifdef AUICH_DEBUG
905	if (status & ICH_SCR)
906		aprint_normal_dev(sc->sc_dev, "The 2nd codec is ready.\n");
907	if (status & ICH_S2CR)
908		aprint_normal_dev(sc->sc_dev, "The 3rd codec is ready.\n");
909#endif
910	return 0;
911}
912
913static enum ac97_host_flags
914auich_flags_codec(void *v)
915{
916	struct auich_softc *sc = v;
917	return sc->sc_codecflags;
918}
919
920static void
921auich_spdif_event(void *addr, bool flag)
922{
923	struct auich_softc *sc;
924
925	sc = addr;
926	sc->sc_spdif = flag;
927}
928
929static int
930auich_open(void *addr, int flags)
931{
932	struct auich_softc *sc;
933
934	sc = (struct auich_softc *)addr;
935	sc->codec_if->vtbl->lock(sc->codec_if);
936	return 0;
937}
938
939static void
940auich_close(void *addr)
941{
942	struct auich_softc *sc;
943
944	sc = (struct auich_softc *)addr;
945	sc->codec_if->vtbl->unlock(sc->codec_if);
946}
947
948static int
949auich_query_format(void *v, struct audio_format_query *afp)
950{
951	struct auich_softc *sc;
952
953	sc = (struct auich_softc *)v;
954	if (sc->sc_spdif) {
955		return audio_query_format(auich_spdif_formats,
956		    AUICH_SPDIF_NFORMATS, afp);
957	} else {
958		return audio_query_format(sc->sc_audio_formats,
959		    AUICH_AUDIO_NFORMATS, afp);
960	}
961}
962
963static int
964auich_set_rate(struct auich_softc *sc, int mode, u_long srate)
965{
966	int ret;
967	u_int ratetmp;
968
969	sc->codec_if->vtbl->set_clock(sc->codec_if, sc->sc_ac97_clock);
970	ratetmp = srate;
971	if (mode == AUMODE_RECORD)
972		return sc->codec_if->vtbl->set_rate(sc->codec_if,
973		    AC97_REG_PCM_LR_ADC_RATE, &ratetmp);
974	ret = sc->codec_if->vtbl->set_rate(sc->codec_if,
975	    AC97_REG_PCM_FRONT_DAC_RATE, &ratetmp);
976	if (ret)
977		return ret;
978	ratetmp = srate;
979	ret = sc->codec_if->vtbl->set_rate(sc->codec_if,
980	    AC97_REG_PCM_SURR_DAC_RATE, &ratetmp);
981	if (ret)
982		return ret;
983	ratetmp = srate;
984	ret = sc->codec_if->vtbl->set_rate(sc->codec_if,
985	    AC97_REG_PCM_LFE_DAC_RATE, &ratetmp);
986	return ret;
987}
988
989static int
990auich_set_format(void *v, int setmode,
991    const audio_params_t *play, const audio_params_t *rec,
992    audio_filter_reg_t *pfil, audio_filter_reg_t *rfil)
993{
994	struct auich_softc *sc;
995	const audio_params_t *p;
996	int mode, index;
997	uint32_t control;
998
999	sc = v;
1000	for (mode = AUMODE_RECORD; mode != -1;
1001	     mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
1002		if ((setmode & mode) == 0)
1003			continue;
1004
1005		p = mode == AUMODE_PLAY ? play : rec;
1006
1007		if (sc->sc_codectype == AC97_CODEC_TYPE_AUDIO) {
1008			if (!sc->sc_spdif)
1009				index = audio_indexof_format(
1010				    sc->sc_audio_formats, AUICH_AUDIO_NFORMATS,
1011				    mode, p);
1012			else
1013				index = audio_indexof_format(
1014				    auich_spdif_formats, AUICH_SPDIF_NFORMATS,
1015				    mode, p);
1016		} else {
1017			index = audio_indexof_format(sc->sc_modem_formats,
1018			    AUICH_MODEM_NFORMATS, mode, p);
1019		}
1020
1021		/* p represents HW encoding */
1022		if (sc->sc_codectype == AC97_CODEC_TYPE_AUDIO) {
1023			if (sc->sc_audio_formats[index].frequency_type != 1
1024			    && auich_set_rate(sc, mode, p->sample_rate))
1025				return EINVAL;
1026		} else {
1027			if (sc->sc_modem_formats[index].frequency_type != 1
1028			    && auich_set_rate(sc, mode, p->sample_rate))
1029				return EINVAL;
1030			auich_write_codec(sc, AC97_REG_LINE1_RATE,
1031					  p->sample_rate);
1032			auich_write_codec(sc, AC97_REG_LINE1_LEVEL, 0);
1033		}
1034		if (mode == AUMODE_PLAY &&
1035		    sc->sc_codectype == AC97_CODEC_TYPE_AUDIO) {
1036			control = bus_space_read_4(sc->iot, sc->aud_ioh,
1037			    ICH_GCTRL + sc->sc_modem_offset);
1038			control &= ~sc->sc_pcm246_mask;
1039			if (p->channels == 4) {
1040				control |= sc->sc_pcm4;
1041			} else if (p->channels == 6) {
1042				control |= sc->sc_pcm6;
1043			}
1044			bus_space_write_4(sc->iot, sc->aud_ioh,
1045			    ICH_GCTRL + sc->sc_modem_offset, control);
1046		}
1047	}
1048
1049	return 0;
1050}
1051
1052static void
1053auich_halt_pipe(struct auich_softc *sc, int pipe)
1054{
1055	int i;
1056	uint32_t status;
1057
1058	bus_space_write_1(sc->iot, sc->aud_ioh, pipe + ICH_CTRL, 0);
1059	for (i = 0; i < 100; i++) {
1060		status = bus_space_read_4(sc->iot, sc->aud_ioh, pipe + ICH_STS);
1061		if (status & ICH_DCH)
1062			break;
1063		DELAY(1);
1064	}
1065	bus_space_write_1(sc->iot, sc->aud_ioh, pipe + ICH_CTRL, ICH_RR);
1066
1067#if AUICH_DEBUG
1068	if (i > 0)
1069		aprint_normal_dev(sc->sc_dev, "%s: halt took %d cycles\n",
1070		    __func__, i);
1071#endif
1072}
1073
1074static int
1075auich_halt_output(void *v)
1076{
1077	struct auich_softc *sc;
1078
1079	sc = v;
1080	DPRINTF(ICH_DEBUG_DMA, (sc->sc_dev, "%s\n", __func__));
1081
1082	auich_halt_pipe(sc, ICH_PCMO);
1083	sc->pcmo.intr = NULL;
1084
1085	return 0;
1086}
1087
1088static int
1089auich_halt_input(void *v)
1090{
1091	struct auich_softc *sc;
1092
1093	sc = v;
1094	DPRINTF(ICH_DEBUG_DMA, (sc->sc_dev, "%s\n", __func__));
1095
1096	auich_halt_pipe(sc, ICH_PCMI);
1097	sc->pcmi.intr = NULL;
1098
1099	return 0;
1100}
1101
1102static int
1103auich_getdev(void *v, struct audio_device *adp)
1104{
1105	struct auich_softc *sc;
1106
1107	sc = v;
1108	*adp = sc->sc_audev;
1109	return 0;
1110}
1111
1112static int
1113auich_set_port(void *v, mixer_ctrl_t *cp)
1114{
1115	struct auich_softc *sc;
1116
1117	sc = v;
1118	return sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp);
1119}
1120
1121static int
1122auich_get_port(void *v, mixer_ctrl_t *cp)
1123{
1124	struct auich_softc *sc;
1125
1126	sc = v;
1127	return sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp);
1128}
1129
1130static int
1131auich_query_devinfo(void *v, mixer_devinfo_t *dp)
1132{
1133	struct auich_softc *sc;
1134
1135	sc = v;
1136	return sc->codec_if->vtbl->query_devinfo(sc->codec_if, dp);
1137}
1138
1139static void *
1140auich_allocm(void *v, int direction, size_t size)
1141{
1142	struct auich_softc *sc;
1143	struct auich_dma *p;
1144	int error;
1145
1146	if (size > (ICH_DMALIST_MAX * ICH_DMASEG_MAX))
1147		return NULL;
1148
1149	p = kmem_alloc(sizeof(*p), KM_SLEEP);
1150
1151	sc = v;
1152	error = auich_allocmem(sc, size, 0, p);
1153	if (error) {
1154		kmem_free(p, sizeof(*p));
1155		return NULL;
1156	}
1157
1158	p->next = sc->sc_dmas;
1159	sc->sc_dmas = p;
1160
1161	return KERNADDR(p);
1162}
1163
1164static void
1165auich_freem(void *v, void *ptr, size_t size)
1166{
1167	struct auich_softc *sc;
1168	struct auich_dma *p, **pp;
1169
1170	sc = v;
1171	for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) {
1172		if (KERNADDR(p) == ptr) {
1173			auich_freemem(sc, p);
1174			*pp = p->next;
1175			kmem_free(p, sizeof(*p));
1176			return;
1177		}
1178	}
1179}
1180
1181static size_t
1182auich_round_buffersize(void *v, int direction, size_t size)
1183{
1184
1185	if (size > (ICH_DMALIST_MAX * ICH_DMASEG_MAX))
1186		size = ICH_DMALIST_MAX * ICH_DMASEG_MAX;
1187
1188	return size;
1189}
1190
1191static int
1192auich_get_props(void *v)
1193{
1194
1195	return AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE |
1196	    AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
1197}
1198
1199static int
1200auich_intr(void *v)
1201{
1202	struct auich_softc *sc;
1203	int ret, gsts;
1204#ifdef DIAGNOSTIC
1205	int csts;
1206#endif
1207
1208	sc = v;
1209
1210	if (!device_has_power(sc->sc_dev))
1211		return (0);
1212
1213	mutex_spin_enter(&sc->sc_intr_lock);
1214
1215	ret = 0;
1216#ifdef DIAGNOSTIC
1217	csts = pci_conf_read(sc->sc_pc, sc->sc_pt, PCI_COMMAND_STATUS_REG);
1218	if (csts & PCI_STATUS_MASTER_ABORT) {
1219		aprint_error_dev(sc->sc_dev, "%s: PCI master abort\n",
1220		    __func__);
1221	}
1222#endif
1223
1224	gsts = bus_space_read_4(sc->iot, sc->aud_ioh,
1225	    ICH_GSTS + sc->sc_modem_offset);
1226	DPRINTF(ICH_DEBUG_INTR, (sc->sc_dev, "%s: gsts=0x%x\n",
1227	    __func__, gsts));
1228
1229	if ((sc->sc_codectype == AC97_CODEC_TYPE_AUDIO && gsts & ICH_POINT) ||
1230	    (sc->sc_codectype == AC97_CODEC_TYPE_MODEM && gsts & ICH_MOINT)) {
1231		int sts;
1232
1233		sts = bus_space_read_2(sc->iot, sc->aud_ioh,
1234		    ICH_PCMO + sc->sc_sts_reg);
1235		DPRINTF(ICH_DEBUG_INTR,
1236		    (sc->sc_dev, "%s: osts=0x%x\n", __func__, sts));
1237
1238		if (sts & ICH_FIFOE)
1239			aprint_error_dev(sc->sc_dev, "%s: fifo underrun\n",
1240			    __func__);
1241
1242		if (sts & ICH_BCIS)
1243			auich_intr_pipe(sc, ICH_PCMO, &sc->pcmo);
1244
1245		/* int ack */
1246		bus_space_write_2(sc->iot, sc->aud_ioh, ICH_PCMO +
1247		    sc->sc_sts_reg, sts & (ICH_BCIS | ICH_FIFOE));
1248		if (sc->sc_codectype == AC97_CODEC_TYPE_AUDIO)
1249			bus_space_write_4(sc->iot, sc->aud_ioh,
1250			    ICH_GSTS + sc->sc_modem_offset, ICH_POINT);
1251		else
1252			bus_space_write_4(sc->iot, sc->aud_ioh,
1253			    ICH_GSTS + sc->sc_modem_offset, ICH_MOINT);
1254		ret++;
1255	}
1256
1257	if ((sc->sc_codectype == AC97_CODEC_TYPE_AUDIO && gsts & ICH_PIINT) ||
1258	    (sc->sc_codectype == AC97_CODEC_TYPE_MODEM && gsts & ICH_MIINT)) {
1259		int sts;
1260
1261		sts = bus_space_read_2(sc->iot, sc->aud_ioh,
1262		    ICH_PCMI + sc->sc_sts_reg);
1263		DPRINTF(ICH_DEBUG_INTR,
1264		    (sc->sc_dev, "%s: ists=0x%x\n", __func__, sts));
1265
1266		if (sts & ICH_FIFOE)
1267			aprint_error_dev(sc->sc_dev, "%s: fifo overrun\n",
1268			    __func__);
1269
1270		if (sts & ICH_BCIS)
1271			auich_intr_pipe(sc, ICH_PCMI, &sc->pcmi);
1272
1273		/* int ack */
1274		bus_space_write_2(sc->iot, sc->aud_ioh, ICH_PCMI +
1275		    sc->sc_sts_reg, sts & (ICH_BCIS | ICH_FIFOE));
1276		if (sc->sc_codectype == AC97_CODEC_TYPE_AUDIO)
1277			bus_space_write_4(sc->iot, sc->aud_ioh,
1278			    ICH_GSTS + sc->sc_modem_offset, ICH_PIINT);
1279		else
1280			bus_space_write_4(sc->iot, sc->aud_ioh,
1281			    ICH_GSTS + sc->sc_modem_offset, ICH_MIINT);
1282		ret++;
1283	}
1284
1285	if (sc->sc_codectype == AC97_CODEC_TYPE_AUDIO && gsts & ICH_MINT) {
1286		int sts;
1287
1288		sts = bus_space_read_2(sc->iot, sc->aud_ioh,
1289		    ICH_MICI + sc->sc_sts_reg);
1290		DPRINTF(ICH_DEBUG_INTR,
1291		    (sc->sc_dev, "%s: ists=0x%x\n", __func__, sts));
1292
1293		if (sts & ICH_FIFOE)
1294			aprint_error_dev(sc->sc_dev, "%s: fifo overrun\n",
1295			    __func__);
1296
1297		if (sts & ICH_BCIS)
1298			auich_intr_pipe(sc, ICH_MICI, &sc->mici);
1299
1300		/* int ack */
1301		bus_space_write_2(sc->iot, sc->aud_ioh, ICH_MICI +
1302		    sc->sc_sts_reg, sts & (ICH_BCIS | ICH_FIFOE));
1303		bus_space_write_4(sc->iot, sc->aud_ioh,
1304		    ICH_GSTS + sc->sc_modem_offset, ICH_MINT);
1305		ret++;
1306	}
1307
1308#ifdef AUICH_MODEM_DEBUG
1309	if (sc->sc_codectype == AC97_CODEC_TYPE_MODEM && gsts & ICH_GSCI) {
1310		aprint_normal_dev(sc->sc_dev, "gsts=0x%x\n", gsts);
1311		/* int ack */
1312		bus_space_write_4(sc->iot, sc->aud_ioh,
1313		    ICH_GSTS + sc->sc_modem_offset, ICH_GSCI);
1314		ret++;
1315	}
1316#endif
1317
1318	mutex_spin_exit(&sc->sc_intr_lock);
1319
1320	return ret;
1321}
1322
1323static void
1324auich_trigger_pipe(struct auich_softc *sc, int pipe, struct auich_ring *ring)
1325{
1326	int blksize, qptr;
1327	struct auich_dmalist *q;
1328
1329	blksize = ring->blksize;
1330
1331	for (qptr = 0; qptr < ICH_DMALIST_MAX; qptr++) {
1332		q = &ring->dmalist[qptr];
1333		q->base = ring->p;
1334		q->len = (blksize >> sc->sc_sample_shift) | ICH_DMAF_IOC;
1335
1336		ring->p += blksize;
1337		if (ring->p >= ring->end)
1338			ring->p = ring->start;
1339	}
1340	ring->qptr = 0;
1341
1342	bus_space_write_1(sc->iot, sc->aud_ioh, pipe + ICH_LVI,
1343	    (qptr - 1) & ICH_LVI_MASK);
1344	bus_space_write_1(sc->iot, sc->aud_ioh, pipe + ICH_CTRL,
1345	    ICH_IOCE | ICH_FEIE | ICH_RPBM);
1346}
1347
1348static void
1349auich_intr_pipe(struct auich_softc *sc, int pipe, struct auich_ring *ring)
1350{
1351	int blksize, qptr, nqptr;
1352	struct auich_dmalist *q;
1353
1354	blksize = ring->blksize;
1355	qptr = ring->qptr;
1356	nqptr = bus_space_read_1(sc->iot, sc->aud_ioh, pipe + ICH_CIV);
1357
1358	while (qptr != nqptr) {
1359		q = &ring->dmalist[qptr];
1360		q->base = ring->p;
1361		q->len = (blksize >> sc->sc_sample_shift) | ICH_DMAF_IOC;
1362
1363		DPRINTF(ICH_DEBUG_INTR,
1364		    (sc->sc_dev, "%s: %p, %p = %x @ 0x%x\n", __func__,
1365		    &ring->dmalist[qptr], q, q->len, q->base));
1366
1367		ring->p += blksize;
1368		if (ring->p >= ring->end)
1369			ring->p = ring->start;
1370
1371		qptr = (qptr + 1) & ICH_LVI_MASK;
1372		if (ring->intr)
1373			ring->intr(ring->arg);
1374	}
1375	ring->qptr = qptr;
1376
1377	bus_space_write_1(sc->iot, sc->aud_ioh, pipe + ICH_LVI,
1378	    (qptr - 1) & ICH_LVI_MASK);
1379}
1380
1381static int
1382auich_trigger_output(void *v, void *start, void *end, int blksize,
1383    void (*intr)(void *), void *arg, const audio_params_t *param)
1384{
1385	struct auich_softc *sc;
1386	struct auich_dma *p;
1387	size_t size;
1388
1389	sc = v;
1390	DPRINTF(ICH_DEBUG_DMA,
1391	    (sc->sc_dev, "%s(%p, %p, %d, %p, %p, %p)\n", __func__,
1392	    start, end, blksize, intr, arg, param));
1393
1394	for (p = sc->sc_dmas; p && KERNADDR(p) != start; p = p->next)
1395		continue;
1396	if (!p) {
1397		aprint_error_dev(sc->sc_dev, "%s: bad addr %p\n", __func__,
1398		    start);
1399		return EINVAL;
1400	}
1401
1402	size = (size_t)((char *)end - (char *)start);
1403
1404	sc->pcmo.intr = intr;
1405	sc->pcmo.arg = arg;
1406	sc->pcmo.start = DMAADDR(p);
1407	sc->pcmo.p = sc->pcmo.start;
1408	sc->pcmo.end = sc->pcmo.start + size;
1409	sc->pcmo.blksize = blksize;
1410
1411	bus_space_write_4(sc->iot, sc->aud_ioh, ICH_PCMO + ICH_BDBAR,
1412	    sc->sc_cddma + ICH_PCMO_OFF(0));
1413	auich_trigger_pipe(sc, ICH_PCMO, &sc->pcmo);
1414
1415	return 0;
1416}
1417
1418static int
1419auich_trigger_input(void *v, void *start, void *end, int blksize,
1420    void (*intr)(void *), void *arg, const audio_params_t *param)
1421{
1422	struct auich_softc *sc;
1423	struct auich_dma *p;
1424	size_t size;
1425
1426	sc = v;
1427	DPRINTF(ICH_DEBUG_DMA,
1428	    (sc->sc_dev, "%s(%p, %p, %d, %p, %p, %p)\n", __func__,
1429	    start, end, blksize, intr, arg, param));
1430
1431	for (p = sc->sc_dmas; p && KERNADDR(p) != start; p = p->next)
1432		continue;
1433	if (!p) {
1434		aprint_error_dev(sc->sc_dev, "%s: bad addr %p\n", __func__,
1435		    start);
1436		return EINVAL;
1437	}
1438
1439	size = (size_t)((char *)end - (char *)start);
1440
1441	sc->pcmi.intr = intr;
1442	sc->pcmi.arg = arg;
1443	sc->pcmi.start = DMAADDR(p);
1444	sc->pcmi.p = sc->pcmi.start;
1445	sc->pcmi.end = sc->pcmi.start + size;
1446	sc->pcmi.blksize = blksize;
1447
1448	bus_space_write_4(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_BDBAR,
1449	    sc->sc_cddma + ICH_PCMI_OFF(0));
1450	auich_trigger_pipe(sc, ICH_PCMI, &sc->pcmi);
1451
1452	return 0;
1453}
1454
1455static int
1456auich_allocmem(struct auich_softc *sc, size_t size, size_t align,
1457    struct auich_dma *p)
1458{
1459	int error;
1460
1461	p->size = size;
1462	error = bus_dmamem_alloc(sc->dmat, p->size, align, 0,
1463				 p->segs, sizeof(p->segs)/sizeof(p->segs[0]),
1464				 &p->nsegs, BUS_DMA_WAITOK);
1465	if (error)
1466		return error;
1467
1468	error = bus_dmamem_map(sc->dmat, p->segs, p->nsegs, p->size,
1469			       &p->addr, BUS_DMA_WAITOK|sc->sc_dmamap_flags);
1470	if (error)
1471		goto free;
1472
1473	error = bus_dmamap_create(sc->dmat, p->size, 1, p->size,
1474				  0, BUS_DMA_WAITOK, &p->map);
1475	if (error)
1476		goto unmap;
1477
1478	error = bus_dmamap_load(sc->dmat, p->map, p->addr, p->size, NULL,
1479				BUS_DMA_WAITOK);
1480	if (error)
1481		goto destroy;
1482	return 0;
1483
1484 destroy:
1485	bus_dmamap_destroy(sc->dmat, p->map);
1486 unmap:
1487	bus_dmamem_unmap(sc->dmat, p->addr, p->size);
1488 free:
1489	bus_dmamem_free(sc->dmat, p->segs, p->nsegs);
1490	return error;
1491}
1492
1493static int
1494auich_freemem(struct auich_softc *sc, struct auich_dma *p)
1495{
1496
1497	bus_dmamap_unload(sc->dmat, p->map);
1498	bus_dmamap_destroy(sc->dmat, p->map);
1499	bus_dmamem_unmap(sc->dmat, p->addr, p->size);
1500	bus_dmamem_free(sc->dmat, p->segs, p->nsegs);
1501	return 0;
1502}
1503
1504static int
1505auich_alloc_cdata(struct auich_softc *sc)
1506{
1507	bus_dma_segment_t seg;
1508	int error, rseg;
1509
1510	/*
1511	 * Allocate the control data structure, and create and load the
1512	 * DMA map for it.
1513	 */
1514	if ((error = bus_dmamem_alloc(sc->dmat,
1515				      sizeof(struct auich_cdata),
1516				      PAGE_SIZE, 0, &seg, 1, &rseg, 0)) != 0) {
1517		aprint_error_dev(sc->sc_dev, "unable to allocate control data, error = %d\n", error);
1518		goto fail_0;
1519	}
1520
1521	if ((error = bus_dmamem_map(sc->dmat, &seg, rseg,
1522				    sizeof(struct auich_cdata),
1523				    (void **) &sc->sc_cdata,
1524				    sc->sc_dmamap_flags)) != 0) {
1525		aprint_error_dev(sc->sc_dev, "unable to map control data, error = %d\n", error);
1526		goto fail_1;
1527	}
1528
1529	if ((error = bus_dmamap_create(sc->dmat, sizeof(struct auich_cdata), 1,
1530				       sizeof(struct auich_cdata), 0, 0,
1531				       &sc->sc_cddmamap)) != 0) {
1532		aprint_error_dev(sc->sc_dev, "unable to create control data DMA map, "
1533		    "error = %d\n", error);
1534		goto fail_2;
1535	}
1536
1537	if ((error = bus_dmamap_load(sc->dmat, sc->sc_cddmamap,
1538				     sc->sc_cdata, sizeof(struct auich_cdata),
1539				     NULL, 0)) != 0) {
1540		aprint_error_dev(sc->sc_dev, "unable tp load control data DMA map, "
1541		    "error = %d\n", error);
1542		goto fail_3;
1543	}
1544
1545	sc->pcmo.dmalist = sc->sc_cdata->ic_dmalist_pcmo;
1546	sc->pcmi.dmalist = sc->sc_cdata->ic_dmalist_pcmi;
1547	sc->mici.dmalist = sc->sc_cdata->ic_dmalist_mici;
1548
1549	return 0;
1550
1551 fail_3:
1552	bus_dmamap_destroy(sc->dmat, sc->sc_cddmamap);
1553 fail_2:
1554	bus_dmamem_unmap(sc->dmat, (void *) sc->sc_cdata,
1555	    sizeof(struct auich_cdata));
1556 fail_1:
1557	bus_dmamem_free(sc->dmat, &seg, rseg);
1558 fail_0:
1559	return error;
1560}
1561
1562static bool
1563auich_resume(device_t dv, const pmf_qual_t *qual)
1564{
1565	struct auich_softc *sc = device_private(dv);
1566	pcireg_t v;
1567
1568	mutex_enter(&sc->sc_lock);
1569	mutex_spin_enter(&sc->sc_intr_lock);
1570
1571	if (sc->sc_iose) {
1572		v = pci_conf_read(sc->sc_pc, sc->sc_pt, ICH_CFG);
1573		pci_conf_write(sc->sc_pc, sc->sc_pt, ICH_CFG,
1574			       v | ICH_CFG_IOSE);
1575	}
1576
1577	auich_reset_codec(sc);
1578	mutex_spin_exit(&sc->sc_intr_lock);
1579	DELAY(1000);
1580	(sc->codec_if->vtbl->restore_ports)(sc->codec_if);
1581	mutex_exit(&sc->sc_lock);
1582
1583	return true;
1584}
1585
1586/*
1587 * Calibrate card (some boards are overclocked and need scaling)
1588 */
1589static void
1590auich_calibrate(struct auich_softc *sc)
1591{
1592	struct timeval t1, t2;
1593	uint8_t ociv, nciv;
1594	uint64_t wait_us;
1595	uint32_t actual_48k_rate, bytes, ac97rate;
1596	void *temp_buffer;
1597	struct auich_dma *p;
1598	u_int rate;
1599
1600	/*
1601	 * Grab audio from input for fixed interval and compare how
1602	 * much we actually get with what we expect.  Interval needs
1603	 * to be sufficiently short that no interrupts are
1604	 * generated.
1605	 */
1606
1607	/* Force the codec to a known state first. */
1608	sc->codec_if->vtbl->set_clock(sc->codec_if, 48000);
1609	rate = sc->sc_ac97_clock = 48000;
1610	sc->codec_if->vtbl->set_rate(sc->codec_if, AC97_REG_PCM_LR_ADC_RATE,
1611	    &rate);
1612
1613	/* Setup a buffer */
1614	bytes = 64000;
1615	temp_buffer = auich_allocm(sc, AUMODE_RECORD, bytes);
1616
1617	for (p = sc->sc_dmas; p && KERNADDR(p) != temp_buffer; p = p->next)
1618		continue;
1619	if (p == NULL) {
1620		aprint_error_dev(sc->sc_dev, "%s: bad address %p\n",
1621		    __func__, temp_buffer);
1622		return;
1623	}
1624	sc->pcmi.dmalist[0].base = DMAADDR(p);
1625	sc->pcmi.dmalist[0].len = (bytes >> sc->sc_sample_shift);
1626
1627	/*
1628	 * our data format is stereo, 16 bit so each sample is 4 bytes.
1629	 * assuming we get 48000 samples per second, we get 192000 bytes/sec.
1630	 * we're going to start recording with interrupts disabled and measure
1631	 * the time taken for one block to complete.  we know the block size,
1632	 * we know the time in microseconds, we calculate the sample rate:
1633	 *
1634	 * actual_rate [bps] = bytes / (time [s] * 4)
1635	 * actual_rate [bps] = (bytes * 1000000) / (time [us] * 4)
1636	 * actual_rate [Hz] = (bytes * 250000) / time [us]
1637	 */
1638
1639	/* prepare */
1640	ociv = bus_space_read_1(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_CIV);
1641	bus_space_write_4(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_BDBAR,
1642			  sc->sc_cddma + ICH_PCMI_OFF(0));
1643	bus_space_write_1(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_LVI,
1644			  (0 - 1) & ICH_LVI_MASK);
1645
1646	/* start */
1647	kpreempt_disable();
1648	microtime(&t1);
1649	bus_space_write_1(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_CTRL, ICH_RPBM);
1650
1651	/* wait */
1652	nciv = ociv;
1653	do {
1654		microtime(&t2);
1655		if (t2.tv_sec - t1.tv_sec > 1)
1656			break;
1657		nciv = bus_space_read_1(sc->iot, sc->aud_ioh,
1658					ICH_PCMI + ICH_CIV);
1659	} while (nciv == ociv);
1660	microtime(&t2);
1661
1662	/* stop */
1663	bus_space_write_1(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_CTRL, 0);
1664	kpreempt_enable();
1665
1666	/* reset */
1667	DELAY(100);
1668	bus_space_write_1(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_CTRL, ICH_RR);
1669
1670	/* turn time delta into us */
1671	wait_us = ((t2.tv_sec - t1.tv_sec) * 1000000) + t2.tv_usec - t1.tv_usec;
1672
1673	auich_freem(sc, temp_buffer, bytes);
1674
1675	if (nciv == ociv) {
1676		aprint_error_dev(sc->sc_dev, "ac97 link rate calibration "
1677		    "timed out after %" PRIu64 " us\n", wait_us);
1678		return;
1679	}
1680
1681	if (wait_us == 0) {
1682		/* Can happen with emulated hardware */
1683		aprint_error_dev(sc->sc_dev, "abnormal zero delay during "
1684		    "calibration\n");
1685		return;
1686	}
1687
1688	rnd_add_data(NULL, &wait_us, sizeof(wait_us), 1);
1689
1690	actual_48k_rate = (bytes * UINT64_C(250000)) / wait_us;
1691
1692	if (actual_48k_rate < 50000)
1693		ac97rate = 48000;
1694	else
1695		ac97rate = ((actual_48k_rate + 500) / 1000) * 1000;
1696
1697	aprint_verbose_dev(sc->sc_dev, "measured ac97 link rate at %d Hz",
1698	       actual_48k_rate);
1699	if (ac97rate != actual_48k_rate)
1700		aprint_verbose(", will use %d Hz", ac97rate);
1701	aprint_verbose("\n");
1702
1703	sc->sc_ac97_clock = ac97rate;
1704}
1705
1706static void
1707auich_clear_cas(struct auich_softc *sc)
1708{
1709	/* Clear the codec access semaphore */
1710	(void)bus_space_read_2(sc->iot, sc->mix_ioh,
1711	    AC97_REG_RESET * (sc->sc_codecnum * ICH_CODEC_OFFSET));
1712
1713	return;
1714}
1715
1716static void
1717auich_get_locks(void *addr, kmutex_t **intr, kmutex_t **thread)
1718{
1719	struct auich_softc *sc;
1720
1721	sc = addr;
1722	*intr = &sc->sc_intr_lock;
1723	*thread = &sc->sc_lock;
1724}
1725