xref: /freebsd/sys/dev/sound/pci/csa.c (revision f314f3dad2574f8edc41c7aa1f125b83ab7af60a)
1f259d7eeSSeigo Tanimura /*
2fe1a5d1cSSeigo Tanimura  * Copyright (c) 1999 Seigo Tanimura
3fe1a5d1cSSeigo Tanimura  * All rights reserved.
4fe1a5d1cSSeigo Tanimura  *
57012990aSSeigo Tanimura  * Portions of this source are based on cwcealdr.cpp and dhwiface.cpp in
67012990aSSeigo Tanimura  * cwcealdr1.zip, the sample sources by Crystal Semiconductor.
77012990aSSeigo Tanimura  * Copyright (c) 1996-1998 Crystal Semiconductor Corp.
87012990aSSeigo Tanimura  *
9fe1a5d1cSSeigo Tanimura  * Redistribution and use in source and binary forms, with or without
10fe1a5d1cSSeigo Tanimura  * modification, are permitted provided that the following conditions
11fe1a5d1cSSeigo Tanimura  * are met:
12fe1a5d1cSSeigo Tanimura  * 1. Redistributions of source code must retain the above copyright
13fe1a5d1cSSeigo Tanimura  *    notice, this list of conditions and the following disclaimer.
14fe1a5d1cSSeigo Tanimura  * 2. Redistributions in binary form must reproduce the above copyright
15fe1a5d1cSSeigo Tanimura  *    notice, this list of conditions and the following disclaimer in the
16fe1a5d1cSSeigo Tanimura  *    documentation and/or other materials provided with the distribution.
17fe1a5d1cSSeigo Tanimura  *
18fe1a5d1cSSeigo Tanimura  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19fe1a5d1cSSeigo Tanimura  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20fe1a5d1cSSeigo Tanimura  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21fe1a5d1cSSeigo Tanimura  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22fe1a5d1cSSeigo Tanimura  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23fe1a5d1cSSeigo Tanimura  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24fe1a5d1cSSeigo Tanimura  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25fe1a5d1cSSeigo Tanimura  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26fe1a5d1cSSeigo Tanimura  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27fe1a5d1cSSeigo Tanimura  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28fe1a5d1cSSeigo Tanimura  * SUCH DAMAGE.
29fe1a5d1cSSeigo Tanimura  *
30fe1a5d1cSSeigo Tanimura  * $FreeBSD$
31fe1a5d1cSSeigo Tanimura  */
32fe1a5d1cSSeigo Tanimura 
33fe1a5d1cSSeigo Tanimura #include <sys/param.h>
34fe1a5d1cSSeigo Tanimura #include <sys/systm.h>
35fe1a5d1cSSeigo Tanimura #include <sys/kernel.h>
36fe1a5d1cSSeigo Tanimura #include <sys/bus.h>
37fe1a5d1cSSeigo Tanimura #include <sys/malloc.h>
38fe1a5d1cSSeigo Tanimura #include <sys/module.h>
39fe1a5d1cSSeigo Tanimura #include <machine/resource.h>
40fe1a5d1cSSeigo Tanimura #include <machine/bus.h>
41fe1a5d1cSSeigo Tanimura #include <machine/clock.h>
42fe1a5d1cSSeigo Tanimura #include <sys/rman.h>
43fe1a5d1cSSeigo Tanimura #include <sys/soundcard.h>
44f314f3daSCameron Grant #include <dev/sound/pcm/sound.h>
45fe1a5d1cSSeigo Tanimura #include <dev/sound/chip.h>
46fe1a5d1cSSeigo Tanimura #include <dev/sound/pci/csareg.h>
47fe1a5d1cSSeigo Tanimura #include <dev/sound/pci/csavar.h>
48fe1a5d1cSSeigo Tanimura 
49fe1a5d1cSSeigo Tanimura #include <pci/pcireg.h>
50fe1a5d1cSSeigo Tanimura #include <pci/pcivar.h>
51fe1a5d1cSSeigo Tanimura 
52fe1a5d1cSSeigo Tanimura #include <dev/sound/pci/csaimg.h>
53fe1a5d1cSSeigo Tanimura 
54fe1a5d1cSSeigo Tanimura /* Here is the parameter structure per a device. */
55fe1a5d1cSSeigo Tanimura struct csa_softc {
56fe1a5d1cSSeigo Tanimura 	device_t dev; /* device */
57fe1a5d1cSSeigo Tanimura 	csa_res res; /* resources */
58fe1a5d1cSSeigo Tanimura 
59fe1a5d1cSSeigo Tanimura 	device_t pcm; /* pcm device */
60fe1a5d1cSSeigo Tanimura 	driver_intr_t* pcmintr; /* pcm intr */
61fe1a5d1cSSeigo Tanimura 	void *pcmintr_arg; /* pcm intr arg */
62125fdb98SSeigo Tanimura #if notyet
63fe1a5d1cSSeigo Tanimura 	device_t midi; /* midi device */
64fe1a5d1cSSeigo Tanimura 	driver_intr_t* midiintr; /* midi intr */
65fe1a5d1cSSeigo Tanimura 	void *midiintr_arg; /* midi intr arg */
66125fdb98SSeigo Tanimura #endif /* notyet */
67fe1a5d1cSSeigo Tanimura 	void *ih; /* cookie */
68f259d7eeSSeigo Tanimura 
69f259d7eeSSeigo Tanimura 	struct csa_bridgeinfo binfo; /* The state of this bridge. */
70fe1a5d1cSSeigo Tanimura };
71fe1a5d1cSSeigo Tanimura 
72fe1a5d1cSSeigo Tanimura typedef struct csa_softc *sc_p;
73fe1a5d1cSSeigo Tanimura 
74fe1a5d1cSSeigo Tanimura static int csa_probe(device_t dev);
75fe1a5d1cSSeigo Tanimura static int csa_attach(device_t dev);
76fe1a5d1cSSeigo Tanimura static struct resource *csa_alloc_resource(device_t bus, device_t child, int type, int *rid,
77fe1a5d1cSSeigo Tanimura 					      u_long start, u_long end, u_long count, u_int flags);
78fe1a5d1cSSeigo Tanimura static int csa_release_resource(device_t bus, device_t child, int type, int rid,
79fe1a5d1cSSeigo Tanimura 				   struct resource *r);
80f259d7eeSSeigo Tanimura static int csa_setup_intr(device_t bus, device_t child,
81f259d7eeSSeigo Tanimura 			  struct resource *irq, int flags,
82f259d7eeSSeigo Tanimura 			  driver_intr_t *intr, void *arg, void **cookiep);
83f259d7eeSSeigo Tanimura static int csa_teardown_intr(device_t bus, device_t child,
84f259d7eeSSeigo Tanimura 			     struct resource *irq, void *cookie);
85f259d7eeSSeigo Tanimura static driver_intr_t csa_intr;
86fe1a5d1cSSeigo Tanimura static int csa_initialize(sc_p scp);
87fe1a5d1cSSeigo Tanimura static void csa_resetdsp(csa_res *resp);
88fe1a5d1cSSeigo Tanimura static int csa_downloadimage(csa_res *resp);
89fe1a5d1cSSeigo Tanimura static int csa_transferimage(csa_res *resp, u_long *src, u_long dest, u_long len);
90fe1a5d1cSSeigo Tanimura 
91fe1a5d1cSSeigo Tanimura static devclass_t csa_devclass;
92fe1a5d1cSSeigo Tanimura 
93fe1a5d1cSSeigo Tanimura static int
94fe1a5d1cSSeigo Tanimura csa_probe(device_t dev)
95fe1a5d1cSSeigo Tanimura {
96fe1a5d1cSSeigo Tanimura 	char *s;
97fe1a5d1cSSeigo Tanimura 
98fe1a5d1cSSeigo Tanimura 	s = NULL;
99fe1a5d1cSSeigo Tanimura 	switch (pci_get_devid(dev)) {
100fe1a5d1cSSeigo Tanimura 	case CS4610_PCI_ID:
101fe1a5d1cSSeigo Tanimura 		s = "Crystal Semiconductor CS4610/4611 Audio accelerator";
102fe1a5d1cSSeigo Tanimura 		break;
103fe1a5d1cSSeigo Tanimura 	case CS4614_PCI_ID:
104fe1a5d1cSSeigo Tanimura 		s = "Crystal Semiconductor CS4614/4622/4624 Audio accelerator/4280 Audio controller";
105fe1a5d1cSSeigo Tanimura 		break;
106fe1a5d1cSSeigo Tanimura 	case CS4615_PCI_ID:
107fe1a5d1cSSeigo Tanimura 		s = "Crystal Semiconductor CS4615 Audio accelerator";
108fe1a5d1cSSeigo Tanimura 		break;
109fe1a5d1cSSeigo Tanimura 	}
110fe1a5d1cSSeigo Tanimura 
111fe1a5d1cSSeigo Tanimura 	if (s != NULL) {
112fe1a5d1cSSeigo Tanimura 		device_set_desc(dev, s);
113fe1a5d1cSSeigo Tanimura 		return (0);
114fe1a5d1cSSeigo Tanimura 	}
115fe1a5d1cSSeigo Tanimura 
116fe1a5d1cSSeigo Tanimura 	return (ENXIO);
117fe1a5d1cSSeigo Tanimura }
118fe1a5d1cSSeigo Tanimura 
119fe1a5d1cSSeigo Tanimura static int
120fe1a5d1cSSeigo Tanimura csa_attach(device_t dev)
121fe1a5d1cSSeigo Tanimura {
122fe1a5d1cSSeigo Tanimura 	u_int32_t stcmd;
123fe1a5d1cSSeigo Tanimura 	sc_p scp;
124fe1a5d1cSSeigo Tanimura 	csa_res *resp;
125f259d7eeSSeigo Tanimura 	struct sndcard_func *func;
126fe1a5d1cSSeigo Tanimura 
127fe1a5d1cSSeigo Tanimura 	scp = device_get_softc(dev);
128fe1a5d1cSSeigo Tanimura 
129fe1a5d1cSSeigo Tanimura 	/* Fill in the softc. */
130fe1a5d1cSSeigo Tanimura 	bzero(scp, sizeof(*scp));
131fe1a5d1cSSeigo Tanimura 	scp->dev = dev;
132fe1a5d1cSSeigo Tanimura 
133fe1a5d1cSSeigo Tanimura 	/* Wake up the device. */
134fe1a5d1cSSeigo Tanimura 	stcmd = pci_read_config(dev, PCIR_COMMAND, 4);
135fe1a5d1cSSeigo Tanimura 	if ((stcmd & PCIM_CMD_MEMEN) == 0 || (stcmd & PCIM_CMD_BUSMASTEREN) == 0) {
136fe1a5d1cSSeigo Tanimura 		stcmd |= (PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
137fe1a5d1cSSeigo Tanimura 		pci_write_config(dev, PCIR_COMMAND, 4, stcmd);
138fe1a5d1cSSeigo Tanimura 	}
139fe1a5d1cSSeigo Tanimura 
140fe1a5d1cSSeigo Tanimura 	/* Allocate the resources. */
141fe1a5d1cSSeigo Tanimura 	resp = &scp->res;
142fe1a5d1cSSeigo Tanimura 	resp->io_rid = CS461x_IO_OFFSET;
143fe1a5d1cSSeigo Tanimura 	resp->io = bus_alloc_resource(dev, SYS_RES_MEMORY, &resp->io_rid, 0, ~0, CS461x_IO_SIZE, RF_ACTIVE);
144fe1a5d1cSSeigo Tanimura 	if (resp->io == NULL)
145fe1a5d1cSSeigo Tanimura 		return (ENXIO);
146fe1a5d1cSSeigo Tanimura 	resp->mem_rid = CS461x_MEM_OFFSET;
147fe1a5d1cSSeigo Tanimura 	resp->mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &resp->mem_rid, 0, ~0, CS461x_MEM_SIZE, RF_ACTIVE);
148fe1a5d1cSSeigo Tanimura 	if (resp->mem == NULL) {
149fe1a5d1cSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
150fe1a5d1cSSeigo Tanimura 		return (ENXIO);
151fe1a5d1cSSeigo Tanimura 	}
152fe1a5d1cSSeigo Tanimura 	resp->irq_rid = 0;
153fe1a5d1cSSeigo Tanimura 	resp->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &resp->irq_rid, 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
154fe1a5d1cSSeigo Tanimura 	if (resp->irq == NULL) {
155fe1a5d1cSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
156fe1a5d1cSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
157fe1a5d1cSSeigo Tanimura 		return (ENXIO);
158fe1a5d1cSSeigo Tanimura 	}
159fe1a5d1cSSeigo Tanimura 
160f259d7eeSSeigo Tanimura 	/* Enable interrupt. */
161f259d7eeSSeigo Tanimura 	if (bus_setup_intr(dev, resp->irq, INTR_TYPE_TTY, csa_intr, scp, &scp->ih)) {
162f259d7eeSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
163f259d7eeSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
164f259d7eeSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq);
165f259d7eeSSeigo Tanimura 		return (ENXIO);
166f259d7eeSSeigo Tanimura 	}
167f259d7eeSSeigo Tanimura 	if ((csa_readio(resp, BA0_HISR) & HISR_INTENA) == 0)
168f259d7eeSSeigo Tanimura 		csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
169f259d7eeSSeigo Tanimura 
170fe1a5d1cSSeigo Tanimura 	/* Initialize the chip. */
171fe1a5d1cSSeigo Tanimura 	if (csa_initialize(scp)) {
172fe1a5d1cSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
173fe1a5d1cSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
174fe1a5d1cSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq);
175fe1a5d1cSSeigo Tanimura 		return (ENXIO);
176fe1a5d1cSSeigo Tanimura 	}
177fe1a5d1cSSeigo Tanimura 
178fe1a5d1cSSeigo Tanimura 	/* Reset the Processor. */
179fe1a5d1cSSeigo Tanimura 	csa_resetdsp(resp);
180fe1a5d1cSSeigo Tanimura 
181fe1a5d1cSSeigo Tanimura 	/* Download the Processor Image to the processor. */
182fe1a5d1cSSeigo Tanimura 	if (csa_downloadimage(resp)) {
183fe1a5d1cSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
184fe1a5d1cSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
185fe1a5d1cSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq);
186fe1a5d1cSSeigo Tanimura 		return (ENXIO);
187fe1a5d1cSSeigo Tanimura 	}
188fe1a5d1cSSeigo Tanimura 
189f259d7eeSSeigo Tanimura 	/* Attach the children. */
190f259d7eeSSeigo Tanimura 
191f259d7eeSSeigo Tanimura 	/* PCM Audio */
192f259d7eeSSeigo Tanimura 	func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT);
193f259d7eeSSeigo Tanimura 	if (func == NULL)
194f259d7eeSSeigo Tanimura 		return (ENOMEM);
195f259d7eeSSeigo Tanimura 	bzero(func, sizeof(*func));
196f259d7eeSSeigo Tanimura 	func->varinfo = &scp->binfo;
197f259d7eeSSeigo Tanimura 	func->func = SCF_PCM;
198f259d7eeSSeigo Tanimura 	scp->pcm = device_add_child(dev, "pcm", -1);
199f259d7eeSSeigo Tanimura 	device_set_ivars(scp->pcm, func);
200f259d7eeSSeigo Tanimura 
201f259d7eeSSeigo Tanimura #if notyet
202f259d7eeSSeigo Tanimura 	/* Midi Interface */
203f259d7eeSSeigo Tanimura 	func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT);
204f259d7eeSSeigo Tanimura 	if (func == NULL)
205f259d7eeSSeigo Tanimura 		return (ENOMEM);
206f259d7eeSSeigo Tanimura 	bzero(func, sizeof(*func));
207f259d7eeSSeigo Tanimura 	func->varinfo = &scp->binfo;
208f259d7eeSSeigo Tanimura 	func->func = SCF_MIDI;
209f259d7eeSSeigo Tanimura 	scp->midi = device_add_child(dev, "midi", -1);
210f259d7eeSSeigo Tanimura 	device_set_ivars(scp->midi, func);
211f259d7eeSSeigo Tanimura #endif /* notyet */
212f259d7eeSSeigo Tanimura 
213fe1a5d1cSSeigo Tanimura 	bus_generic_attach(dev);
214fe1a5d1cSSeigo Tanimura 
215fe1a5d1cSSeigo Tanimura 	return (0);
216fe1a5d1cSSeigo Tanimura }
217fe1a5d1cSSeigo Tanimura 
218fe1a5d1cSSeigo Tanimura static struct resource *
219fe1a5d1cSSeigo Tanimura csa_alloc_resource(device_t bus, device_t child, int type, int *rid,
220fe1a5d1cSSeigo Tanimura 		      u_long start, u_long end, u_long count, u_int flags)
221fe1a5d1cSSeigo Tanimura {
222fe1a5d1cSSeigo Tanimura 	sc_p scp;
223fe1a5d1cSSeigo Tanimura 	csa_res *resp;
224fe1a5d1cSSeigo Tanimura 	struct resource *res;
225fe1a5d1cSSeigo Tanimura 
226fe1a5d1cSSeigo Tanimura 	scp = device_get_softc(bus);
227fe1a5d1cSSeigo Tanimura 	resp = &scp->res;
228fe1a5d1cSSeigo Tanimura 	switch (type) {
229fe1a5d1cSSeigo Tanimura 	case SYS_RES_IRQ:
230fe1a5d1cSSeigo Tanimura 		if (*rid != 0)
231fe1a5d1cSSeigo Tanimura 			return (NULL);
232fe1a5d1cSSeigo Tanimura 		res = resp->irq;
233fe1a5d1cSSeigo Tanimura 		break;
234fe1a5d1cSSeigo Tanimura 	case SYS_RES_MEMORY:
235fe1a5d1cSSeigo Tanimura 		switch (*rid) {
236fe1a5d1cSSeigo Tanimura 		case CS461x_IO_OFFSET:
237fe1a5d1cSSeigo Tanimura 			res = resp->io;
238fe1a5d1cSSeigo Tanimura 			break;
239fe1a5d1cSSeigo Tanimura 		case CS461x_MEM_OFFSET:
240fe1a5d1cSSeigo Tanimura 			res = resp->mem;
241fe1a5d1cSSeigo Tanimura 			break;
242fe1a5d1cSSeigo Tanimura 		default:
243fe1a5d1cSSeigo Tanimura 			return (NULL);
244fe1a5d1cSSeigo Tanimura 		}
245fe1a5d1cSSeigo Tanimura 		break;
246fe1a5d1cSSeigo Tanimura 	default:
247fe1a5d1cSSeigo Tanimura 		return (NULL);
248fe1a5d1cSSeigo Tanimura 	}
249fe1a5d1cSSeigo Tanimura 
250fe1a5d1cSSeigo Tanimura 	return res;
251fe1a5d1cSSeigo Tanimura }
252fe1a5d1cSSeigo Tanimura 
253fe1a5d1cSSeigo Tanimura static int
254fe1a5d1cSSeigo Tanimura csa_release_resource(device_t bus, device_t child, int type, int rid,
255fe1a5d1cSSeigo Tanimura 			struct resource *r)
256fe1a5d1cSSeigo Tanimura {
257fe1a5d1cSSeigo Tanimura 	return (0);
258fe1a5d1cSSeigo Tanimura }
259fe1a5d1cSSeigo Tanimura 
260f259d7eeSSeigo Tanimura /*
261f259d7eeSSeigo Tanimura  * The following three functions deal with interrupt handling.
262f259d7eeSSeigo Tanimura  * An interrupt is primarily handled by the bridge driver.
263f259d7eeSSeigo Tanimura  * The bridge driver then determines the child devices to pass
264f259d7eeSSeigo Tanimura  * the interrupt. Certain information of the device can be read
265f259d7eeSSeigo Tanimura  * only once(eg the value of HISR). The bridge driver is responsible
266f259d7eeSSeigo Tanimura  * to pass such the information to the children.
267f259d7eeSSeigo Tanimura  */
268f259d7eeSSeigo Tanimura 
269f259d7eeSSeigo Tanimura static int
270f259d7eeSSeigo Tanimura csa_setup_intr(device_t bus, device_t child,
271f259d7eeSSeigo Tanimura 	       struct resource *irq, int flags,
272f259d7eeSSeigo Tanimura 	       driver_intr_t *intr, void *arg, void **cookiep)
273f259d7eeSSeigo Tanimura {
274f259d7eeSSeigo Tanimura 	sc_p scp;
275f259d7eeSSeigo Tanimura 	csa_res *resp;
276f259d7eeSSeigo Tanimura 	struct sndcard_func *func;
277f259d7eeSSeigo Tanimura 
278f259d7eeSSeigo Tanimura 	scp = device_get_softc(bus);
279f259d7eeSSeigo Tanimura 	resp = &scp->res;
280f259d7eeSSeigo Tanimura 
281f259d7eeSSeigo Tanimura 	/*
282f259d7eeSSeigo Tanimura 	 * Look at the function code of the child to determine
283f259d7eeSSeigo Tanimura 	 * the appropriate hander for it.
284f259d7eeSSeigo Tanimura 	 */
285f259d7eeSSeigo Tanimura 	func = device_get_ivars(child);
286f259d7eeSSeigo Tanimura 	if (func == NULL || irq != resp->irq)
287f259d7eeSSeigo Tanimura 		return (EINVAL);
288f259d7eeSSeigo Tanimura 
289f259d7eeSSeigo Tanimura 	switch (func->func) {
290f259d7eeSSeigo Tanimura 	case SCF_PCM:
291f259d7eeSSeigo Tanimura 		scp->pcmintr = intr;
292f259d7eeSSeigo Tanimura 		scp->pcmintr_arg = arg;
293f259d7eeSSeigo Tanimura 		break;
294f259d7eeSSeigo Tanimura 
295f259d7eeSSeigo Tanimura #if notyet
296f259d7eeSSeigo Tanimura 	case SCF_MIDI:
297f259d7eeSSeigo Tanimura 		scp->midiintr = intr;
298f259d7eeSSeigo Tanimura 		scp->midiintr_arg = arg;
299f259d7eeSSeigo Tanimura 		break;
300f259d7eeSSeigo Tanimura #endif /* notyet */
301f259d7eeSSeigo Tanimura 
302f259d7eeSSeigo Tanimura 	default:
303f259d7eeSSeigo Tanimura 		return (EINVAL);
304f259d7eeSSeigo Tanimura 	}
305f259d7eeSSeigo Tanimura 	*cookiep = scp;
306f259d7eeSSeigo Tanimura 	if ((csa_readio(resp, BA0_HISR) & HISR_INTENA) == 0)
307f259d7eeSSeigo Tanimura 		csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
308f259d7eeSSeigo Tanimura 
309f259d7eeSSeigo Tanimura 	return (0);
310f259d7eeSSeigo Tanimura }
311f259d7eeSSeigo Tanimura 
312f259d7eeSSeigo Tanimura static int
313f259d7eeSSeigo Tanimura csa_teardown_intr(device_t bus, device_t child,
314f259d7eeSSeigo Tanimura 		  struct resource *irq, void *cookie)
315f259d7eeSSeigo Tanimura {
316f259d7eeSSeigo Tanimura 	sc_p scp;
317f259d7eeSSeigo Tanimura 	csa_res *resp;
318f259d7eeSSeigo Tanimura 	struct sndcard_func *func;
319f259d7eeSSeigo Tanimura 
320f259d7eeSSeigo Tanimura 	scp = device_get_softc(bus);
321f259d7eeSSeigo Tanimura 	resp = &scp->res;
322f259d7eeSSeigo Tanimura 
323f259d7eeSSeigo Tanimura 	/*
324f259d7eeSSeigo Tanimura 	 * Look at the function code of the child to determine
325f259d7eeSSeigo Tanimura 	 * the appropriate hander for it.
326f259d7eeSSeigo Tanimura 	 */
327f259d7eeSSeigo Tanimura 	func = device_get_ivars(child);
328f259d7eeSSeigo Tanimura 	if (func == NULL || irq != resp->irq || cookie != scp)
329f259d7eeSSeigo Tanimura 		return (EINVAL);
330f259d7eeSSeigo Tanimura 
331f259d7eeSSeigo Tanimura 	switch (func->func) {
332f259d7eeSSeigo Tanimura 	case SCF_PCM:
333f259d7eeSSeigo Tanimura 		scp->pcmintr = NULL;
334f259d7eeSSeigo Tanimura 		scp->pcmintr_arg = NULL;
335f259d7eeSSeigo Tanimura 		break;
336f259d7eeSSeigo Tanimura 
337f259d7eeSSeigo Tanimura #if notyet
338f259d7eeSSeigo Tanimura 	case SCF_MIDI:
339f259d7eeSSeigo Tanimura 		scp->midiintr = NULL;
340f259d7eeSSeigo Tanimura 		scp->midiintr_arg = NULL;
341f259d7eeSSeigo Tanimura 		break;
342f259d7eeSSeigo Tanimura #endif /* notyet */
343f259d7eeSSeigo Tanimura 
344f259d7eeSSeigo Tanimura 	default:
345f259d7eeSSeigo Tanimura 		return (EINVAL);
346f259d7eeSSeigo Tanimura 	}
347f259d7eeSSeigo Tanimura 
348f259d7eeSSeigo Tanimura 	return (0);
349f259d7eeSSeigo Tanimura }
350f259d7eeSSeigo Tanimura 
351f259d7eeSSeigo Tanimura /* The interrupt handler */
352f259d7eeSSeigo Tanimura static void
353f259d7eeSSeigo Tanimura csa_intr(void *arg)
354f259d7eeSSeigo Tanimura {
355f259d7eeSSeigo Tanimura 	sc_p scp = arg;
356f259d7eeSSeigo Tanimura 	csa_res *resp;
357f259d7eeSSeigo Tanimura 	u_int32_t hisr;
358f259d7eeSSeigo Tanimura 
359f259d7eeSSeigo Tanimura 	resp = &scp->res;
360f259d7eeSSeigo Tanimura 
361f259d7eeSSeigo Tanimura 	/* Is this interrupt for us? */
362f259d7eeSSeigo Tanimura 	hisr = csa_readio(resp, BA0_HISR);
363f259d7eeSSeigo Tanimura 	if ((hisr & ~HISR_INTENA) == 0) {
364f259d7eeSSeigo Tanimura 		/* Throw an eoi. */
365f259d7eeSSeigo Tanimura 		csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
366f259d7eeSSeigo Tanimura 		return;
367f259d7eeSSeigo Tanimura 	}
368f259d7eeSSeigo Tanimura 
369f259d7eeSSeigo Tanimura 	/*
370f259d7eeSSeigo Tanimura 	 * Pass the value of HISR via struct csa_bridgeinfo.
371f259d7eeSSeigo Tanimura 	 * The children get access through their ivars.
372f259d7eeSSeigo Tanimura 	 */
373f259d7eeSSeigo Tanimura 	scp->binfo.hisr = hisr;
374f259d7eeSSeigo Tanimura 
375f259d7eeSSeigo Tanimura 	/* Invoke the handlers of the children. */
376f259d7eeSSeigo Tanimura 	if ((hisr & (HISR_VC0 | HISR_VC1)) != 0 && scp->pcmintr != NULL)
377f259d7eeSSeigo Tanimura 		scp->pcmintr(scp->pcmintr_arg);
378f259d7eeSSeigo Tanimura #if notyet
379f259d7eeSSeigo Tanimura 	if ((hisr & HISR_MIDI) != 0 && scp->midiintr != NULL)
380f259d7eeSSeigo Tanimura 		scp->midiintr(scp->midiintr_arg);
381f259d7eeSSeigo Tanimura #endif /* notyet */
382f259d7eeSSeigo Tanimura 
383f259d7eeSSeigo Tanimura 	/* Throw an eoi. */
384f259d7eeSSeigo Tanimura 	csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
385f259d7eeSSeigo Tanimura }
386f259d7eeSSeigo Tanimura 
387fe1a5d1cSSeigo Tanimura static int
388fe1a5d1cSSeigo Tanimura csa_initialize(sc_p scp)
389fe1a5d1cSSeigo Tanimura {
390fe1a5d1cSSeigo Tanimura 	int i;
391fe1a5d1cSSeigo Tanimura 	u_int32_t acsts, acisv;
392fe1a5d1cSSeigo Tanimura 	csa_res *resp;
393fe1a5d1cSSeigo Tanimura 
394fe1a5d1cSSeigo Tanimura 	resp = &scp->res;
395fe1a5d1cSSeigo Tanimura 
396fe1a5d1cSSeigo Tanimura 	/*
397fe1a5d1cSSeigo Tanimura 	 * First, blast the clock control register to zero so that the PLL starts
398fe1a5d1cSSeigo Tanimura 	 * out in a known state, and blast the master serial port control register
399fe1a5d1cSSeigo Tanimura 	 * to zero so that the serial ports also start out in a known state.
400fe1a5d1cSSeigo Tanimura 	 */
401fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_CLKCR1, 0);
402fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_SERMC1, 0);
403fe1a5d1cSSeigo Tanimura 
404fe1a5d1cSSeigo Tanimura 	/*
405fe1a5d1cSSeigo Tanimura 	 * If we are in AC97 mode, then we must set the part to a host controlled
406fe1a5d1cSSeigo Tanimura 	 * AC-link.  Otherwise, we won't be able to bring up the link.
407fe1a5d1cSSeigo Tanimura 	 */
408fe1a5d1cSSeigo Tanimura #if 1
409fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_SERACC, SERACC_HSP | SERACC_CODEC_TYPE_1_03); /* 1.03 codec */
410fe1a5d1cSSeigo Tanimura #else
411fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_SERACC, SERACC_HSP | SERACC_CODEC_TYPE_2_0); /* 2.0 codec */
412fe1a5d1cSSeigo Tanimura #endif /* 1 */
413fe1a5d1cSSeigo Tanimura 
414fe1a5d1cSSeigo Tanimura 	/*
415fe1a5d1cSSeigo Tanimura 	 * Drive the ARST# pin low for a minimum of 1uS (as defined in the AC97
416fe1a5d1cSSeigo Tanimura 	 * spec) and then drive it high.  This is done for non AC97 modes since
417fe1a5d1cSSeigo Tanimura 	 * there might be logic external to the CS461x that uses the ARST# line
418fe1a5d1cSSeigo Tanimura 	 * for a reset.
419fe1a5d1cSSeigo Tanimura 	 */
420fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCTL, 0);
421f7e00c54SSeigo Tanimura 	DELAY(100);
422fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCTL, ACCTL_RSTN);
423fe1a5d1cSSeigo Tanimura 
424fe1a5d1cSSeigo Tanimura 	/*
425fe1a5d1cSSeigo Tanimura 	 * The first thing we do here is to enable sync generation.  As soon
426fe1a5d1cSSeigo Tanimura 	 * as we start receiving bit clock, we'll start producing the SYNC
427fe1a5d1cSSeigo Tanimura 	 * signal.
428fe1a5d1cSSeigo Tanimura 	 */
429fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCTL, ACCTL_ESYN | ACCTL_RSTN);
430fe1a5d1cSSeigo Tanimura 
431fe1a5d1cSSeigo Tanimura 	/*
432fe1a5d1cSSeigo Tanimura 	 * Now wait for a short while to allow the AC97 part to start
433fe1a5d1cSSeigo Tanimura 	 * generating bit clock (so we don't try to start the PLL without an
434fe1a5d1cSSeigo Tanimura 	 * input clock).
435fe1a5d1cSSeigo Tanimura 	 */
436fe1a5d1cSSeigo Tanimura 	DELAY(50000);
437fe1a5d1cSSeigo Tanimura 
438fe1a5d1cSSeigo Tanimura 	/*
439fe1a5d1cSSeigo Tanimura 	 * Set the serial port timing configuration, so that
440fe1a5d1cSSeigo Tanimura 	 * the clock control circuit gets its clock from the correct place.
441fe1a5d1cSSeigo Tanimura 	 */
442fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_SERMC1, SERMC1_PTC_AC97);
443fe1a5d1cSSeigo Tanimura 
444fe1a5d1cSSeigo Tanimura 	/*
445fe1a5d1cSSeigo Tanimura 	 * Write the selected clock control setup to the hardware.  Do not turn on
446fe1a5d1cSSeigo Tanimura 	 * SWCE yet (if requested), so that the devices clocked by the output of
447fe1a5d1cSSeigo Tanimura 	 * PLL are not clocked until the PLL is stable.
448fe1a5d1cSSeigo Tanimura 	 */
449fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_PLLCC, PLLCC_LPF_1050_2780_KHZ | PLLCC_CDR_73_104_MHZ);
450fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_PLLM, 0x3a);
451fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_CLKCR2, CLKCR2_PDIVS_8);
452fe1a5d1cSSeigo Tanimura 
453fe1a5d1cSSeigo Tanimura 	/*
454fe1a5d1cSSeigo Tanimura 	 * Power up the PLL.
455fe1a5d1cSSeigo Tanimura 	 */
456fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_CLKCR1, CLKCR1_PLLP);
457fe1a5d1cSSeigo Tanimura 
458fe1a5d1cSSeigo Tanimura 	/*
459fe1a5d1cSSeigo Tanimura 	 * Wait until the PLL has stabilized.
460fe1a5d1cSSeigo Tanimura 	 */
461fe1a5d1cSSeigo Tanimura 	DELAY(50000);
462fe1a5d1cSSeigo Tanimura 
463fe1a5d1cSSeigo Tanimura 	/*
464fe1a5d1cSSeigo Tanimura 	 * Turn on clocking of the core so that we can setup the serial ports.
465fe1a5d1cSSeigo Tanimura 	 */
466fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_CLKCR1, csa_readio(resp, BA0_CLKCR1) | CLKCR1_SWCE);
467fe1a5d1cSSeigo Tanimura 
468fe1a5d1cSSeigo Tanimura 	/*
469fe1a5d1cSSeigo Tanimura 	 * Fill the serial port FIFOs with silence.
470fe1a5d1cSSeigo Tanimura 	 */
471fe1a5d1cSSeigo Tanimura 	csa_clearserialfifos(resp);
472fe1a5d1cSSeigo Tanimura 
473fe1a5d1cSSeigo Tanimura 	/*
474fe1a5d1cSSeigo Tanimura 	 * Set the serial port FIFO pointer to the first sample in the FIFO.
475fe1a5d1cSSeigo Tanimura 	 */
476fe1a5d1cSSeigo Tanimura #if notdef
477fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_SERBSP, 0);
478fe1a5d1cSSeigo Tanimura #endif /* notdef */
479fe1a5d1cSSeigo Tanimura 
480fe1a5d1cSSeigo Tanimura 	/*
481fe1a5d1cSSeigo Tanimura 	 *  Write the serial port configuration to the part.  The master
482fe1a5d1cSSeigo Tanimura 	 *  enable bit is not set until all other values have been written.
483fe1a5d1cSSeigo Tanimura 	 */
484fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_SERC1, SERC1_SO1F_AC97 | SERC1_SO1EN);
485fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_SERC2, SERC2_SI1F_AC97 | SERC1_SO1EN);
486fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_SERMC1, SERMC1_PTC_AC97 | SERMC1_MSPE);
487fe1a5d1cSSeigo Tanimura 
488fe1a5d1cSSeigo Tanimura 	/*
489fe1a5d1cSSeigo Tanimura 	 * Wait for the codec ready signal from the AC97 codec.
490fe1a5d1cSSeigo Tanimura 	 */
491fe1a5d1cSSeigo Tanimura 	acsts = 0;
492fe1a5d1cSSeigo Tanimura 	for (i = 0 ; i < 1000 ; i++) {
493fe1a5d1cSSeigo Tanimura 		/*
494fe1a5d1cSSeigo Tanimura 		 * First, lets wait a short while to let things settle out a bit,
495fe1a5d1cSSeigo Tanimura 		 * and to prevent retrying the read too quickly.
496fe1a5d1cSSeigo Tanimura 		 */
497f7e00c54SSeigo Tanimura 		DELAY(125);
498fe1a5d1cSSeigo Tanimura 
499fe1a5d1cSSeigo Tanimura 		/*
500fe1a5d1cSSeigo Tanimura 		 * Read the AC97 status register to see if we've seen a CODEC READY
501fe1a5d1cSSeigo Tanimura 		 * signal from the AC97 codec.
502fe1a5d1cSSeigo Tanimura 		 */
503fe1a5d1cSSeigo Tanimura 		acsts = csa_readio(resp, BA0_ACSTS);
504fe1a5d1cSSeigo Tanimura 		if ((acsts & ACSTS_CRDY) != 0)
505fe1a5d1cSSeigo Tanimura 			break;
506fe1a5d1cSSeigo Tanimura 	}
507fe1a5d1cSSeigo Tanimura 
508fe1a5d1cSSeigo Tanimura 	/*
509fe1a5d1cSSeigo Tanimura 	 * Make sure we sampled CODEC READY.
510fe1a5d1cSSeigo Tanimura 	 */
511fe1a5d1cSSeigo Tanimura 	if ((acsts & ACSTS_CRDY) == 0)
512fe1a5d1cSSeigo Tanimura 		return (ENXIO);
513fe1a5d1cSSeigo Tanimura 
514fe1a5d1cSSeigo Tanimura 	/*
515fe1a5d1cSSeigo Tanimura 	 * Assert the vaid frame signal so that we can start sending commands
516fe1a5d1cSSeigo Tanimura 	 * to the AC97 codec.
517fe1a5d1cSSeigo Tanimura 	 */
518fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCTL, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
519fe1a5d1cSSeigo Tanimura 
520fe1a5d1cSSeigo Tanimura 	/*
521fe1a5d1cSSeigo Tanimura 	 * Wait until we've sampled input slots 3 and 4 as valid, meaning that
522fe1a5d1cSSeigo Tanimura 	 * the codec is pumping ADC data across the AC-link.
523fe1a5d1cSSeigo Tanimura 	 */
524fe1a5d1cSSeigo Tanimura 	acisv = 0;
525fe1a5d1cSSeigo Tanimura 	for (i = 0 ; i < 1000 ; i++) {
526fe1a5d1cSSeigo Tanimura 		/*
527fe1a5d1cSSeigo Tanimura 		 * First, lets wait a short while to let things settle out a bit,
528fe1a5d1cSSeigo Tanimura 		 * and to prevent retrying the read too quickly.
529fe1a5d1cSSeigo Tanimura 		 */
530fe1a5d1cSSeigo Tanimura #if notdef
531fe1a5d1cSSeigo Tanimura 		DELAY(10000000L); /* clw */
532fe1a5d1cSSeigo Tanimura #else
533f7e00c54SSeigo Tanimura 		DELAY(1000);
534fe1a5d1cSSeigo Tanimura #endif /* notdef */
535fe1a5d1cSSeigo Tanimura 		/*
536fe1a5d1cSSeigo Tanimura 		 * Read the input slot valid register and see if input slots 3 and
537fe1a5d1cSSeigo Tanimura 		 * 4 are valid yet.
538fe1a5d1cSSeigo Tanimura 		 */
539fe1a5d1cSSeigo Tanimura 		acisv = csa_readio(resp, BA0_ACISV);
540fe1a5d1cSSeigo Tanimura 		if ((acisv & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4))
541fe1a5d1cSSeigo Tanimura 			break;
542fe1a5d1cSSeigo Tanimura 	}
543fe1a5d1cSSeigo Tanimura 	/*
544fe1a5d1cSSeigo Tanimura 	 * Make sure we sampled valid input slots 3 and 4.  If not, then return
545fe1a5d1cSSeigo Tanimura 	 * an error.
546fe1a5d1cSSeigo Tanimura 	 */
547fe1a5d1cSSeigo Tanimura 	if ((acisv & (ACISV_ISV3 | ACISV_ISV4)) != (ACISV_ISV3 | ACISV_ISV4))
548fe1a5d1cSSeigo Tanimura 		return (ENXIO);
549fe1a5d1cSSeigo Tanimura 
550fe1a5d1cSSeigo Tanimura 	/*
551fe1a5d1cSSeigo Tanimura 	 * Now, assert valid frame and the slot 3 and 4 valid bits.  This will
552fe1a5d1cSSeigo Tanimura 	 * commense the transfer of digital audio data to the AC97 codec.
553fe1a5d1cSSeigo Tanimura 	 */
554fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACOSV, ACOSV_SLV3 | ACOSV_SLV4);
555fe1a5d1cSSeigo Tanimura 
556fe1a5d1cSSeigo Tanimura 	/*
557fe1a5d1cSSeigo Tanimura 	 * Power down the DAC and ADC.  We will power them up (if) when we need
558fe1a5d1cSSeigo Tanimura 	 * them.
559fe1a5d1cSSeigo Tanimura 	 */
560fe1a5d1cSSeigo Tanimura #if notdef
561fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_AC97_POWERDOWN, 0x300);
562fe1a5d1cSSeigo Tanimura #endif /* notdef */
563fe1a5d1cSSeigo Tanimura 
564fe1a5d1cSSeigo Tanimura 	/*
565fe1a5d1cSSeigo Tanimura 	 * Turn off the Processor by turning off the software clock enable flag in
566fe1a5d1cSSeigo Tanimura 	 * the clock control register.
567fe1a5d1cSSeigo Tanimura 	 */
568fe1a5d1cSSeigo Tanimura #if notdef
569fe1a5d1cSSeigo Tanimura 	clkcr1 = csa_readio(resp, BA0_CLKCR1) & ~CLKCR1_SWCE;
570fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_CLKCR1, clkcr1);
571fe1a5d1cSSeigo Tanimura #endif /* notdef */
572fe1a5d1cSSeigo Tanimura 
573fe1a5d1cSSeigo Tanimura 	/*
574fe1a5d1cSSeigo Tanimura 	 * Enable interrupts on the part.
575fe1a5d1cSSeigo Tanimura 	 */
576fe1a5d1cSSeigo Tanimura #if notdef
577fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
578fe1a5d1cSSeigo Tanimura #endif /* notdef */
579fe1a5d1cSSeigo Tanimura 
580fe1a5d1cSSeigo Tanimura 	return (0);
581fe1a5d1cSSeigo Tanimura }
582fe1a5d1cSSeigo Tanimura 
583f259d7eeSSeigo Tanimura void
584fe1a5d1cSSeigo Tanimura csa_clearserialfifos(csa_res *resp)
585fe1a5d1cSSeigo Tanimura {
586fe1a5d1cSSeigo Tanimura 	int i, j, pwr;
587fe1a5d1cSSeigo Tanimura 	u_int8_t clkcr1, serbst;
588fe1a5d1cSSeigo Tanimura 
589fe1a5d1cSSeigo Tanimura 	/*
590fe1a5d1cSSeigo Tanimura 	 * See if the devices are powered down.  If so, we must power them up first
591fe1a5d1cSSeigo Tanimura 	 * or they will not respond.
592fe1a5d1cSSeigo Tanimura 	 */
593fe1a5d1cSSeigo Tanimura 	pwr = 1;
594fe1a5d1cSSeigo Tanimura 	clkcr1 = csa_readio(resp, BA0_CLKCR1);
595fe1a5d1cSSeigo Tanimura 	if ((clkcr1 & CLKCR1_SWCE) == 0) {
596fe1a5d1cSSeigo Tanimura 		csa_writeio(resp, BA0_CLKCR1, clkcr1 | CLKCR1_SWCE);
597fe1a5d1cSSeigo Tanimura 		pwr = 0;
598fe1a5d1cSSeigo Tanimura 	}
599fe1a5d1cSSeigo Tanimura 
600fe1a5d1cSSeigo Tanimura 	/*
601fe1a5d1cSSeigo Tanimura 	 * We want to clear out the serial port FIFOs so we don't end up playing
602fe1a5d1cSSeigo Tanimura 	 * whatever random garbage happens to be in them.  We fill the sample FIFOs
603fe1a5d1cSSeigo Tanimura 	 * with zero (silence).
604fe1a5d1cSSeigo Tanimura 	 */
605fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_SERBWP, 0);
606fe1a5d1cSSeigo Tanimura 
607fe1a5d1cSSeigo Tanimura 	/* Fill all 256 sample FIFO locations. */
608fe1a5d1cSSeigo Tanimura 	serbst = 0;
609fe1a5d1cSSeigo Tanimura 	for (i = 0 ; i < 256 ; i++) {
610fe1a5d1cSSeigo Tanimura 		/* Make sure the previous FIFO write operation has completed. */
611fe1a5d1cSSeigo Tanimura 		for (j = 0 ; j < 5 ; j++) {
612f7e00c54SSeigo Tanimura 			DELAY(100);
613fe1a5d1cSSeigo Tanimura 			serbst = csa_readio(resp, BA0_SERBST);
614fe1a5d1cSSeigo Tanimura 			if ((serbst & SERBST_WBSY) == 0)
615fe1a5d1cSSeigo Tanimura 				break;
616fe1a5d1cSSeigo Tanimura 		}
617fe1a5d1cSSeigo Tanimura 		if ((serbst & SERBST_WBSY) != 0) {
618fe1a5d1cSSeigo Tanimura 			if (!pwr)
619fe1a5d1cSSeigo Tanimura 				csa_writeio(resp, BA0_CLKCR1, clkcr1);
620fe1a5d1cSSeigo Tanimura 		}
621fe1a5d1cSSeigo Tanimura 		/* Write the serial port FIFO index. */
622fe1a5d1cSSeigo Tanimura 		csa_writeio(resp, BA0_SERBAD, i);
623fe1a5d1cSSeigo Tanimura 		/* Tell the serial port to load the new value into the FIFO location. */
624fe1a5d1cSSeigo Tanimura 		csa_writeio(resp, BA0_SERBCM, SERBCM_WRC);
625fe1a5d1cSSeigo Tanimura 	}
626fe1a5d1cSSeigo Tanimura 	/*
627fe1a5d1cSSeigo Tanimura 	 *  Now, if we powered up the devices, then power them back down again.
628fe1a5d1cSSeigo Tanimura 	 *  This is kinda ugly, but should never happen.
629fe1a5d1cSSeigo Tanimura 	 */
630fe1a5d1cSSeigo Tanimura 	if (!pwr)
631fe1a5d1cSSeigo Tanimura 		csa_writeio(resp, BA0_CLKCR1, clkcr1);
632fe1a5d1cSSeigo Tanimura }
633fe1a5d1cSSeigo Tanimura 
634fe1a5d1cSSeigo Tanimura static void
635fe1a5d1cSSeigo Tanimura csa_resetdsp(csa_res *resp)
636fe1a5d1cSSeigo Tanimura {
637fe1a5d1cSSeigo Tanimura 	int i;
638fe1a5d1cSSeigo Tanimura 
639fe1a5d1cSSeigo Tanimura 	/*
640fe1a5d1cSSeigo Tanimura 	 * Write the reset bit of the SP control register.
641fe1a5d1cSSeigo Tanimura 	 */
642fe1a5d1cSSeigo Tanimura 	csa_writemem(resp, BA1_SPCR, SPCR_RSTSP);
643fe1a5d1cSSeigo Tanimura 
644fe1a5d1cSSeigo Tanimura 	/*
645fe1a5d1cSSeigo Tanimura 	 * Write the control register.
646fe1a5d1cSSeigo Tanimura 	 */
647fe1a5d1cSSeigo Tanimura 	csa_writemem(resp, BA1_SPCR, SPCR_DRQEN);
648fe1a5d1cSSeigo Tanimura 
649fe1a5d1cSSeigo Tanimura 	/*
650fe1a5d1cSSeigo Tanimura 	 * Clear the trap registers.
651fe1a5d1cSSeigo Tanimura 	 */
652fe1a5d1cSSeigo Tanimura 	for (i = 0 ; i < 8 ; i++) {
653fe1a5d1cSSeigo Tanimura 		csa_writemem(resp, BA1_DREG, DREG_REGID_TRAP_SELECT + i);
654fe1a5d1cSSeigo Tanimura 		csa_writemem(resp, BA1_TWPR, 0xffff);
655fe1a5d1cSSeigo Tanimura 	}
656fe1a5d1cSSeigo Tanimura 	csa_writemem(resp, BA1_DREG, 0);
657fe1a5d1cSSeigo Tanimura 
658fe1a5d1cSSeigo Tanimura 	/*
659fe1a5d1cSSeigo Tanimura 	 * Set the frame timer to reflect the number of cycles per frame.
660fe1a5d1cSSeigo Tanimura 	 */
661fe1a5d1cSSeigo Tanimura 	csa_writemem(resp, BA1_FRMT, 0xadf);
662fe1a5d1cSSeigo Tanimura }
663fe1a5d1cSSeigo Tanimura 
664fe1a5d1cSSeigo Tanimura static int
665fe1a5d1cSSeigo Tanimura csa_downloadimage(csa_res *resp)
666fe1a5d1cSSeigo Tanimura {
667fe1a5d1cSSeigo Tanimura 	int ret;
668fe1a5d1cSSeigo Tanimura 	u_long ul, offset;
669fe1a5d1cSSeigo Tanimura 
670fe1a5d1cSSeigo Tanimura 	for (ul = 0, offset = 0 ; ul < INKY_MEMORY_COUNT ; ul++) {
671fe1a5d1cSSeigo Tanimura 		/*
672fe1a5d1cSSeigo Tanimura 		 * DMA this block from host memory to the appropriate
673fe1a5d1cSSeigo Tanimura 		 * memory on the CSDevice.
674fe1a5d1cSSeigo Tanimura 		 */
675fe1a5d1cSSeigo Tanimura 		ret = csa_transferimage(
676fe1a5d1cSSeigo Tanimura 			resp,
677fe1a5d1cSSeigo Tanimura 			BA1Struct.BA1Array + offset,
678fe1a5d1cSSeigo Tanimura 			BA1Struct.MemoryStat[ul].ulDestByteOffset,
679fe1a5d1cSSeigo Tanimura 			BA1Struct.MemoryStat[ul].ulSourceByteSize);
680fe1a5d1cSSeigo Tanimura 		if (ret)
681fe1a5d1cSSeigo Tanimura 			return (ret);
682fe1a5d1cSSeigo Tanimura 		offset += BA1Struct.MemoryStat[ul].ulSourceByteSize >> 2;
683fe1a5d1cSSeigo Tanimura 	}
684fe1a5d1cSSeigo Tanimura 
685fe1a5d1cSSeigo Tanimura 	return (0);
686fe1a5d1cSSeigo Tanimura }
687fe1a5d1cSSeigo Tanimura 
688fe1a5d1cSSeigo Tanimura static int
689fe1a5d1cSSeigo Tanimura csa_transferimage(csa_res *resp, u_long *src, u_long dest, u_long len)
690fe1a5d1cSSeigo Tanimura {
691fe1a5d1cSSeigo Tanimura 	u_long ul;
692fe1a5d1cSSeigo Tanimura 
693fe1a5d1cSSeigo Tanimura 	/*
694fe1a5d1cSSeigo Tanimura 	 * We do not allow DMAs from host memory to host memory (although the DMA
695fe1a5d1cSSeigo Tanimura 	 * can do it) and we do not allow DMAs which are not a multiple of 4 bytes
696fe1a5d1cSSeigo Tanimura 	 * in size (because that DMA can not do that).  Return an error if either
697fe1a5d1cSSeigo Tanimura 	 * of these conditions exist.
698fe1a5d1cSSeigo Tanimura 	 */
699fe1a5d1cSSeigo Tanimura 	if ((len & 0x3) != 0)
700fe1a5d1cSSeigo Tanimura 		return (EINVAL);
701fe1a5d1cSSeigo Tanimura 
702fe1a5d1cSSeigo Tanimura 	/* Check the destination address that it is a multiple of 4 */
703fe1a5d1cSSeigo Tanimura 	if ((dest & 0x3) != 0)
704fe1a5d1cSSeigo Tanimura 		return (EINVAL);
705fe1a5d1cSSeigo Tanimura 
706fe1a5d1cSSeigo Tanimura 	/* Write the buffer out. */
707fe1a5d1cSSeigo Tanimura 	for (ul = 0 ; ul < len ; ul += 4)
708fe1a5d1cSSeigo Tanimura 		csa_writemem(resp, dest + ul, src[ul >> 2]);
709fe1a5d1cSSeigo Tanimura 
710fe1a5d1cSSeigo Tanimura 	return (0);
711fe1a5d1cSSeigo Tanimura }
712fe1a5d1cSSeigo Tanimura 
713fe1a5d1cSSeigo Tanimura int
714fe1a5d1cSSeigo Tanimura csa_readcodec(csa_res *resp, u_long offset, u_int32_t *data)
715fe1a5d1cSSeigo Tanimura {
716fe1a5d1cSSeigo Tanimura 	int i;
717fe1a5d1cSSeigo Tanimura 	u_int32_t acsda, acctl, acsts;
718fe1a5d1cSSeigo Tanimura 
719fe1a5d1cSSeigo Tanimura 	/*
720fe1a5d1cSSeigo Tanimura 	 * Make sure that there is not data sitting around from a previous
721fe1a5d1cSSeigo Tanimura 	 * uncompleted access. ACSDA = Status Data Register = 47Ch
722fe1a5d1cSSeigo Tanimura 	 */
723fe1a5d1cSSeigo Tanimura 	acsda = csa_readio(resp, BA0_ACSDA);
724fe1a5d1cSSeigo Tanimura 
725fe1a5d1cSSeigo Tanimura 	/*
726fe1a5d1cSSeigo Tanimura 	 * Setup the AC97 control registers on the CS461x to send the
727fe1a5d1cSSeigo Tanimura 	 * appropriate command to the AC97 to perform the read.
728fe1a5d1cSSeigo Tanimura 	 * ACCAD = Command Address Register = 46Ch
729fe1a5d1cSSeigo Tanimura 	 * ACCDA = Command Data Register = 470h
730fe1a5d1cSSeigo Tanimura 	 * ACCTL = Control Register = 460h
731fe1a5d1cSSeigo Tanimura 	 * set DCV - will clear when process completed
732fe1a5d1cSSeigo Tanimura 	 * set CRW - Read command
733fe1a5d1cSSeigo Tanimura 	 * set VFRM - valid frame enabled
734fe1a5d1cSSeigo Tanimura 	 * set ESYN - ASYNC generation enabled
735fe1a5d1cSSeigo Tanimura 	 * set RSTN - ARST# inactive, AC97 codec not reset
736fe1a5d1cSSeigo Tanimura 	 */
737fe1a5d1cSSeigo Tanimura 
738fe1a5d1cSSeigo Tanimura 	/*
739fe1a5d1cSSeigo Tanimura 	 * Get the actual AC97 register from the offset
740fe1a5d1cSSeigo Tanimura 	 */
741fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCAD, offset - BA0_AC97_RESET);
742fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCDA, 0);
743fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCTL, ACCTL_DCV | ACCTL_CRW | ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
744fe1a5d1cSSeigo Tanimura 
745fe1a5d1cSSeigo Tanimura 	/*
746fe1a5d1cSSeigo Tanimura 	 * Wait for the read to occur.
747fe1a5d1cSSeigo Tanimura 	 */
748fe1a5d1cSSeigo Tanimura 	acctl = 0;
749fe1a5d1cSSeigo Tanimura 	for (i = 0 ; i < 10 ; i++) {
750fe1a5d1cSSeigo Tanimura 		/*
751fe1a5d1cSSeigo Tanimura 		 * First, we want to wait for a short time.
752fe1a5d1cSSeigo Tanimura 		 */
753fe1a5d1cSSeigo Tanimura 		DELAY(25);
754fe1a5d1cSSeigo Tanimura 
755fe1a5d1cSSeigo Tanimura 		/*
756fe1a5d1cSSeigo Tanimura 		 * Now, check to see if the read has completed.
757fe1a5d1cSSeigo Tanimura 		 * ACCTL = 460h, DCV should be reset by now and 460h = 17h
758fe1a5d1cSSeigo Tanimura 		 */
759fe1a5d1cSSeigo Tanimura 		acctl = csa_readio(resp, BA0_ACCTL);
760fe1a5d1cSSeigo Tanimura 		if ((acctl & ACCTL_DCV) == 0)
761fe1a5d1cSSeigo Tanimura 			break;
762fe1a5d1cSSeigo Tanimura 	}
763fe1a5d1cSSeigo Tanimura 
764fe1a5d1cSSeigo Tanimura 	/*
765fe1a5d1cSSeigo Tanimura 	 * Make sure the read completed.
766fe1a5d1cSSeigo Tanimura 	 */
767fe1a5d1cSSeigo Tanimura 	if ((acctl & ACCTL_DCV) != 0)
768fe1a5d1cSSeigo Tanimura 		return (EAGAIN);
769fe1a5d1cSSeigo Tanimura 
770fe1a5d1cSSeigo Tanimura 	/*
771fe1a5d1cSSeigo Tanimura 	 * Wait for the valid status bit to go active.
772fe1a5d1cSSeigo Tanimura 	 */
773fe1a5d1cSSeigo Tanimura 	acsts = 0;
774fe1a5d1cSSeigo Tanimura 	for (i = 0 ; i < 10 ; i++) {
775fe1a5d1cSSeigo Tanimura 		/*
776fe1a5d1cSSeigo Tanimura 		 * Read the AC97 status register.
777fe1a5d1cSSeigo Tanimura 		 * ACSTS = Status Register = 464h
778fe1a5d1cSSeigo Tanimura 		 */
779fe1a5d1cSSeigo Tanimura 		acsts = csa_readio(resp, BA0_ACSTS);
780fe1a5d1cSSeigo Tanimura 		/*
781fe1a5d1cSSeigo Tanimura 		 * See if we have valid status.
782fe1a5d1cSSeigo Tanimura 		 * VSTS - Valid Status
783fe1a5d1cSSeigo Tanimura 		 */
784fe1a5d1cSSeigo Tanimura 		if ((acsts & ACSTS_VSTS) != 0)
785fe1a5d1cSSeigo Tanimura 			break;
786fe1a5d1cSSeigo Tanimura 		/*
787fe1a5d1cSSeigo Tanimura 		 * Wait for a short while.
788fe1a5d1cSSeigo Tanimura 		 */
789fe1a5d1cSSeigo Tanimura 		 DELAY(25);
790fe1a5d1cSSeigo Tanimura 	}
791fe1a5d1cSSeigo Tanimura 
792fe1a5d1cSSeigo Tanimura 	/*
793fe1a5d1cSSeigo Tanimura 	 * Make sure we got valid status.
794fe1a5d1cSSeigo Tanimura 	 */
795fe1a5d1cSSeigo Tanimura 	if ((acsts & ACSTS_VSTS) == 0)
796fe1a5d1cSSeigo Tanimura 		return (EAGAIN);
797fe1a5d1cSSeigo Tanimura 
798fe1a5d1cSSeigo Tanimura 	/*
799fe1a5d1cSSeigo Tanimura 	 * Read the data returned from the AC97 register.
800fe1a5d1cSSeigo Tanimura 	 * ACSDA = Status Data Register = 474h
801fe1a5d1cSSeigo Tanimura 	 */
802fe1a5d1cSSeigo Tanimura 	*data = csa_readio(resp, BA0_ACSDA);
803fe1a5d1cSSeigo Tanimura 
804fe1a5d1cSSeigo Tanimura 	return (0);
805fe1a5d1cSSeigo Tanimura }
806fe1a5d1cSSeigo Tanimura 
807fe1a5d1cSSeigo Tanimura int
808fe1a5d1cSSeigo Tanimura csa_writecodec(csa_res *resp, u_long offset, u_int32_t data)
809fe1a5d1cSSeigo Tanimura {
810fe1a5d1cSSeigo Tanimura 	int i;
811fe1a5d1cSSeigo Tanimura 	u_int32_t acctl;
812fe1a5d1cSSeigo Tanimura 
813fe1a5d1cSSeigo Tanimura 	/*
814fe1a5d1cSSeigo Tanimura 	 * Setup the AC97 control registers on the CS461x to send the
815fe1a5d1cSSeigo Tanimura 	 * appropriate command to the AC97 to perform the write.
816fe1a5d1cSSeigo Tanimura 	 * ACCAD = Command Address Register = 46Ch
817fe1a5d1cSSeigo Tanimura 	 * ACCDA = Command Data Register = 470h
818fe1a5d1cSSeigo Tanimura 	 * ACCTL = Control Register = 460h
819fe1a5d1cSSeigo Tanimura 	 * set DCV - will clear when process completed
820fe1a5d1cSSeigo Tanimura 	 * set VFRM - valid frame enabled
821fe1a5d1cSSeigo Tanimura 	 * set ESYN - ASYNC generation enabled
822fe1a5d1cSSeigo Tanimura 	 * set RSTN - ARST# inactive, AC97 codec not reset
823fe1a5d1cSSeigo Tanimura 	 */
824fe1a5d1cSSeigo Tanimura 
825fe1a5d1cSSeigo Tanimura 	/*
826fe1a5d1cSSeigo Tanimura 	 * Get the actual AC97 register from the offset
827fe1a5d1cSSeigo Tanimura 	 */
828fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCAD, offset - BA0_AC97_RESET);
829fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCDA, data);
830fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCTL, ACCTL_DCV | ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
831fe1a5d1cSSeigo Tanimura 
832fe1a5d1cSSeigo Tanimura 	/*
833fe1a5d1cSSeigo Tanimura 	 * Wait for the write to occur.
834fe1a5d1cSSeigo Tanimura 	 */
835fe1a5d1cSSeigo Tanimura 	acctl = 0;
836fe1a5d1cSSeigo Tanimura 	for (i = 0 ; i < 10 ; i++) {
837fe1a5d1cSSeigo Tanimura 		/*
838fe1a5d1cSSeigo Tanimura 		 * First, we want to wait for a short time.
839fe1a5d1cSSeigo Tanimura 		 */
840fe1a5d1cSSeigo Tanimura 		DELAY(25);
841fe1a5d1cSSeigo Tanimura 
842fe1a5d1cSSeigo Tanimura 		/*
843fe1a5d1cSSeigo Tanimura 		 * Now, check to see if the read has completed.
844fe1a5d1cSSeigo Tanimura 		 * ACCTL = 460h, DCV should be reset by now and 460h = 17h
845fe1a5d1cSSeigo Tanimura 		 */
846fe1a5d1cSSeigo Tanimura 		acctl = csa_readio(resp, BA0_ACCTL);
847fe1a5d1cSSeigo Tanimura 		if ((acctl & ACCTL_DCV) == 0)
848fe1a5d1cSSeigo Tanimura 			break;
849fe1a5d1cSSeigo Tanimura 	}
850fe1a5d1cSSeigo Tanimura 
851fe1a5d1cSSeigo Tanimura 	/*
852fe1a5d1cSSeigo Tanimura 	 * Make sure the write completed.
853fe1a5d1cSSeigo Tanimura 	 */
854fe1a5d1cSSeigo Tanimura 	if ((acctl & ACCTL_DCV) != 0)
855fe1a5d1cSSeigo Tanimura 		return (EAGAIN);
856fe1a5d1cSSeigo Tanimura 
857fe1a5d1cSSeigo Tanimura 	return (0);
858fe1a5d1cSSeigo Tanimura }
859fe1a5d1cSSeigo Tanimura 
860fe1a5d1cSSeigo Tanimura u_int32_t
861fe1a5d1cSSeigo Tanimura csa_readio(csa_res *resp, u_long offset)
862fe1a5d1cSSeigo Tanimura {
863fe1a5d1cSSeigo Tanimura 	u_int32_t ul;
864fe1a5d1cSSeigo Tanimura 
865fe1a5d1cSSeigo Tanimura 	if (offset < BA0_AC97_RESET)
866fe1a5d1cSSeigo Tanimura 		return bus_space_read_4(rman_get_bustag(resp->io), rman_get_bushandle(resp->io), offset) & 0xffffffff;
867fe1a5d1cSSeigo Tanimura 	else {
868fe1a5d1cSSeigo Tanimura 		if (csa_readcodec(resp, offset, &ul))
869fe1a5d1cSSeigo Tanimura 			ul = 0;
870fe1a5d1cSSeigo Tanimura 		return (ul);
871fe1a5d1cSSeigo Tanimura 	}
872fe1a5d1cSSeigo Tanimura }
873fe1a5d1cSSeigo Tanimura 
874fe1a5d1cSSeigo Tanimura void
875fe1a5d1cSSeigo Tanimura csa_writeio(csa_res *resp, u_long offset, u_int32_t data)
876fe1a5d1cSSeigo Tanimura {
877fe1a5d1cSSeigo Tanimura 	if (offset < BA0_AC97_RESET)
878fe1a5d1cSSeigo Tanimura 		bus_space_write_4(rman_get_bustag(resp->io), rman_get_bushandle(resp->io), offset, data);
879fe1a5d1cSSeigo Tanimura 	else
880fe1a5d1cSSeigo Tanimura 		csa_writecodec(resp, offset, data);
881fe1a5d1cSSeigo Tanimura }
882fe1a5d1cSSeigo Tanimura 
883fe1a5d1cSSeigo Tanimura u_int32_t
884fe1a5d1cSSeigo Tanimura csa_readmem(csa_res *resp, u_long offset)
885fe1a5d1cSSeigo Tanimura {
886fe1a5d1cSSeigo Tanimura 	return bus_space_read_4(rman_get_bustag(resp->mem), rman_get_bushandle(resp->mem), offset) & 0xffffffff;
887fe1a5d1cSSeigo Tanimura }
888fe1a5d1cSSeigo Tanimura 
889fe1a5d1cSSeigo Tanimura void
890fe1a5d1cSSeigo Tanimura csa_writemem(csa_res *resp, u_long offset, u_int32_t data)
891fe1a5d1cSSeigo Tanimura {
892fe1a5d1cSSeigo Tanimura 	bus_space_write_4(rman_get_bustag(resp->mem), rman_get_bushandle(resp->mem), offset, data);
893fe1a5d1cSSeigo Tanimura }
894fe1a5d1cSSeigo Tanimura 
895fe1a5d1cSSeigo Tanimura static device_method_t csa_methods[] = {
896fe1a5d1cSSeigo Tanimura 	/* Device interface */
897fe1a5d1cSSeigo Tanimura 	DEVMETHOD(device_probe,		csa_probe),
898fe1a5d1cSSeigo Tanimura 	DEVMETHOD(device_attach,	csa_attach),
899fe1a5d1cSSeigo Tanimura 	DEVMETHOD(device_detach,	bus_generic_detach),
900fe1a5d1cSSeigo Tanimura 	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
901fe1a5d1cSSeigo Tanimura 	DEVMETHOD(device_suspend,	bus_generic_suspend),
902fe1a5d1cSSeigo Tanimura 	DEVMETHOD(device_resume,	bus_generic_resume),
903fe1a5d1cSSeigo Tanimura 
904fe1a5d1cSSeigo Tanimura 	/* Bus interface */
905fe1a5d1cSSeigo Tanimura 	DEVMETHOD(bus_print_child,	bus_generic_print_child),
906fe1a5d1cSSeigo Tanimura 	DEVMETHOD(bus_alloc_resource,	csa_alloc_resource),
907fe1a5d1cSSeigo Tanimura 	DEVMETHOD(bus_release_resource,	csa_release_resource),
908fe1a5d1cSSeigo Tanimura 	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
909fe1a5d1cSSeigo Tanimura 	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
910f259d7eeSSeigo Tanimura 	DEVMETHOD(bus_setup_intr,	csa_setup_intr),
911f259d7eeSSeigo Tanimura 	DEVMETHOD(bus_teardown_intr,	csa_teardown_intr),
912fe1a5d1cSSeigo Tanimura 
913fe1a5d1cSSeigo Tanimura 	{ 0, 0 }
914fe1a5d1cSSeigo Tanimura };
915fe1a5d1cSSeigo Tanimura 
916fe1a5d1cSSeigo Tanimura static driver_t csa_driver = {
917fe1a5d1cSSeigo Tanimura 	"csa",
918fe1a5d1cSSeigo Tanimura 	csa_methods,
919fe1a5d1cSSeigo Tanimura 	sizeof(struct csa_softc),
920fe1a5d1cSSeigo Tanimura };
921fe1a5d1cSSeigo Tanimura 
922fe1a5d1cSSeigo Tanimura /*
923fe1a5d1cSSeigo Tanimura  * csa can be attached to a pci bus.
924fe1a5d1cSSeigo Tanimura  */
925f314f3daSCameron Grant DRIVER_MODULE(snd_csa, pci, csa_driver, csa_devclass, 0, 0);
926f314f3daSCameron Grant MODULE_DEPEND(snd_csa, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER);
927f314f3daSCameron Grant MODULE_VERSION(snd_csa, 1);
928