xref: /freebsd/sys/dev/sound/pci/csa.c (revision 7012990a735976e1431d85b0320ad3796bce5059)
1fe1a5d1cSSeigo 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 "pci.h"
34fe1a5d1cSSeigo Tanimura 
35fe1a5d1cSSeigo Tanimura #include <sys/param.h>
36fe1a5d1cSSeigo Tanimura #include <sys/systm.h>
37fe1a5d1cSSeigo Tanimura #include <sys/kernel.h>
38fe1a5d1cSSeigo Tanimura #include <sys/bus.h>
39fe1a5d1cSSeigo Tanimura #include <sys/malloc.h>
40fe1a5d1cSSeigo Tanimura #include <sys/module.h>
41fe1a5d1cSSeigo Tanimura #include <machine/resource.h>
42fe1a5d1cSSeigo Tanimura #include <machine/bus.h>
43fe1a5d1cSSeigo Tanimura #include <machine/clock.h>
44fe1a5d1cSSeigo Tanimura #include <sys/rman.h>
45fe1a5d1cSSeigo Tanimura #include <sys/soundcard.h>
46fe1a5d1cSSeigo Tanimura #include <dev/sound/chip.h>
47fe1a5d1cSSeigo Tanimura #include <dev/sound/pci/csareg.h>
48fe1a5d1cSSeigo Tanimura #include <dev/sound/pci/csavar.h>
49fe1a5d1cSSeigo Tanimura 
50fe1a5d1cSSeigo Tanimura #if NPCI > 0
51fe1a5d1cSSeigo Tanimura #include <pci/pcireg.h>
52fe1a5d1cSSeigo Tanimura #include <pci/pcivar.h>
53fe1a5d1cSSeigo Tanimura #endif /* NPCI > 0 */
54fe1a5d1cSSeigo Tanimura 
55fe1a5d1cSSeigo Tanimura #include <dev/sound/pci/csaimg.h>
56fe1a5d1cSSeigo Tanimura 
57fe1a5d1cSSeigo Tanimura /* Here is the parameter structure per a device. */
58fe1a5d1cSSeigo Tanimura struct csa_softc {
59fe1a5d1cSSeigo Tanimura 	device_t dev; /* device */
60fe1a5d1cSSeigo Tanimura 	csa_res res; /* resources */
61fe1a5d1cSSeigo Tanimura 
62fe1a5d1cSSeigo Tanimura 	device_t pcm; /* pcm device */
63fe1a5d1cSSeigo Tanimura 	driver_intr_t* pcmintr; /* pcm intr */
64fe1a5d1cSSeigo Tanimura 	void *pcmintr_arg; /* pcm intr arg */
65125fdb98SSeigo Tanimura #if notyet
66fe1a5d1cSSeigo Tanimura 	device_t midi; /* midi device */
67fe1a5d1cSSeigo Tanimura 	driver_intr_t* midiintr; /* midi intr */
68fe1a5d1cSSeigo Tanimura 	void *midiintr_arg; /* midi intr arg */
69125fdb98SSeigo Tanimura #endif /* notyet */
70fe1a5d1cSSeigo Tanimura 	void *ih; /* cookie */
71fe1a5d1cSSeigo Tanimura };
72fe1a5d1cSSeigo Tanimura 
73fe1a5d1cSSeigo Tanimura typedef struct csa_softc *sc_p;
74fe1a5d1cSSeigo Tanimura 
75fe1a5d1cSSeigo Tanimura #if NPCI > 0
76fe1a5d1cSSeigo Tanimura static int csa_probe(device_t dev);
77fe1a5d1cSSeigo Tanimura static int csa_attach(device_t dev);
78fe1a5d1cSSeigo Tanimura #endif /* NPCI > 0 */
79fe1a5d1cSSeigo Tanimura static struct resource *csa_alloc_resource(device_t bus, device_t child, int type, int *rid,
80fe1a5d1cSSeigo Tanimura 					      u_long start, u_long end, u_long count, u_int flags);
81fe1a5d1cSSeigo Tanimura static int csa_release_resource(device_t bus, device_t child, int type, int rid,
82fe1a5d1cSSeigo Tanimura 				   struct resource *r);
83fe1a5d1cSSeigo Tanimura static int csa_initialize(sc_p scp);
84fe1a5d1cSSeigo Tanimura static void csa_clearserialfifos(csa_res *resp);
85fe1a5d1cSSeigo Tanimura static void csa_resetdsp(csa_res *resp);
86fe1a5d1cSSeigo Tanimura static int csa_downloadimage(csa_res *resp);
87fe1a5d1cSSeigo Tanimura static int csa_transferimage(csa_res *resp, u_long *src, u_long dest, u_long len);
88fe1a5d1cSSeigo Tanimura 
89fe1a5d1cSSeigo Tanimura static devclass_t csa_devclass;
90fe1a5d1cSSeigo Tanimura 
91fe1a5d1cSSeigo Tanimura #if NPCI > 0
92fe1a5d1cSSeigo Tanimura static int
93fe1a5d1cSSeigo Tanimura csa_probe(device_t dev)
94fe1a5d1cSSeigo Tanimura {
95fe0d4089SMatthew N. Dodd 	device_t child;
96fe1a5d1cSSeigo Tanimura 	char *s;
97fe1a5d1cSSeigo Tanimura 	struct sndcard_func *func;
98fe1a5d1cSSeigo Tanimura 
99fe1a5d1cSSeigo Tanimura 	s = NULL;
100fe1a5d1cSSeigo Tanimura 	switch (pci_get_devid(dev)) {
101fe1a5d1cSSeigo Tanimura 	case CS4610_PCI_ID:
102fe1a5d1cSSeigo Tanimura 		s = "Crystal Semiconductor CS4610/4611 Audio accelerator";
103fe1a5d1cSSeigo Tanimura 		break;
104fe1a5d1cSSeigo Tanimura 	case CS4614_PCI_ID:
105fe1a5d1cSSeigo Tanimura 		s = "Crystal Semiconductor CS4614/4622/4624 Audio accelerator/4280 Audio controller";
106fe1a5d1cSSeigo Tanimura 		break;
107fe1a5d1cSSeigo Tanimura 	case CS4615_PCI_ID:
108fe1a5d1cSSeigo Tanimura 		s = "Crystal Semiconductor CS4615 Audio accelerator";
109fe1a5d1cSSeigo Tanimura 		break;
110fe1a5d1cSSeigo Tanimura 	case CS4281_PCI_ID:
111fe1a5d1cSSeigo Tanimura 		s = "Crystal Semiconductor CS4281 Audio controller";
112fe1a5d1cSSeigo Tanimura 		break;
113fe1a5d1cSSeigo Tanimura 	}
114fe1a5d1cSSeigo Tanimura 
115fe1a5d1cSSeigo Tanimura 	if (s != NULL) {
116fe1a5d1cSSeigo Tanimura 		device_set_desc(dev, s);
117fe1a5d1cSSeigo Tanimura 
118fe1a5d1cSSeigo Tanimura 		/* PCM Audio */
119fe1a5d1cSSeigo Tanimura 		func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT);
120fe1a5d1cSSeigo Tanimura 		if (func == NULL)
121fe1a5d1cSSeigo Tanimura 			return (ENOMEM);
122fe1a5d1cSSeigo Tanimura 		bzero(func, sizeof(*func));
123fe1a5d1cSSeigo Tanimura 		func->func = SCF_PCM;
124fe0d4089SMatthew N. Dodd 		child = device_add_child(dev, "pcm", -1);
125fe0d4089SMatthew N. Dodd 		device_set_ivars(child, func);
126fe1a5d1cSSeigo Tanimura 
127125fdb98SSeigo Tanimura #if notyet
128fe1a5d1cSSeigo Tanimura 		/* Midi Interface */
129fe1a5d1cSSeigo Tanimura 		func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT);
130fe1a5d1cSSeigo Tanimura 		if (func == NULL)
131fe1a5d1cSSeigo Tanimura 			return (ENOMEM);
132fe1a5d1cSSeigo Tanimura 		bzero(func, sizeof(*func));
133fe1a5d1cSSeigo Tanimura 		func->func = SCF_MIDI;
134fe0d4089SMatthew N. Dodd 		child = device_add_child(dev, "midi", -1);
135fe0d4089SMatthew N. Dodd 		device_set_ivars(child, func);
136125fdb98SSeigo Tanimura #endif /* notyet */
137fe1a5d1cSSeigo Tanimura 
138fe1a5d1cSSeigo Tanimura 		return (0);
139fe1a5d1cSSeigo Tanimura 	}
140fe1a5d1cSSeigo Tanimura 
141fe1a5d1cSSeigo Tanimura 	return (ENXIO);
142fe1a5d1cSSeigo Tanimura }
143fe1a5d1cSSeigo Tanimura 
144fe1a5d1cSSeigo Tanimura static int
145fe1a5d1cSSeigo Tanimura csa_attach(device_t dev)
146fe1a5d1cSSeigo Tanimura {
147fe1a5d1cSSeigo Tanimura 	u_int32_t stcmd;
148fe1a5d1cSSeigo Tanimura 	sc_p scp;
149fe1a5d1cSSeigo Tanimura 	csa_res *resp;
150fe1a5d1cSSeigo Tanimura 
151fe1a5d1cSSeigo Tanimura 	scp = device_get_softc(dev);
152fe1a5d1cSSeigo Tanimura 
153fe1a5d1cSSeigo Tanimura 	/* Fill in the softc. */
154fe1a5d1cSSeigo Tanimura 	bzero(scp, sizeof(*scp));
155fe1a5d1cSSeigo Tanimura 	scp->dev = dev;
156fe1a5d1cSSeigo Tanimura 
157fe1a5d1cSSeigo Tanimura 	/* Wake up the device. */
158fe1a5d1cSSeigo Tanimura 	stcmd = pci_read_config(dev, PCIR_COMMAND, 4);
159fe1a5d1cSSeigo Tanimura 	if ((stcmd & PCIM_CMD_MEMEN) == 0 || (stcmd & PCIM_CMD_BUSMASTEREN) == 0) {
160fe1a5d1cSSeigo Tanimura 		stcmd |= (PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
161fe1a5d1cSSeigo Tanimura 		pci_write_config(dev, PCIR_COMMAND, 4, stcmd);
162fe1a5d1cSSeigo Tanimura 	}
163fe1a5d1cSSeigo Tanimura 	stcmd = pci_read_config(dev, PCIR_LATTIMER, 4);
164fe1a5d1cSSeigo Tanimura 	if (stcmd < 32)
165fe1a5d1cSSeigo Tanimura 		stcmd = 32;
166fe1a5d1cSSeigo Tanimura 	pci_write_config(dev, PCIR_LATTIMER, 4, stcmd);
167fe1a5d1cSSeigo Tanimura 
168fe1a5d1cSSeigo Tanimura 	/* Allocate the resources. */
169fe1a5d1cSSeigo Tanimura 	resp = &scp->res;
170fe1a5d1cSSeigo Tanimura 	resp->io_rid = CS461x_IO_OFFSET;
171fe1a5d1cSSeigo Tanimura 	resp->io = bus_alloc_resource(dev, SYS_RES_MEMORY, &resp->io_rid, 0, ~0, CS461x_IO_SIZE, RF_ACTIVE);
172fe1a5d1cSSeigo Tanimura 	if (resp->io == NULL)
173fe1a5d1cSSeigo Tanimura 		return (ENXIO);
174fe1a5d1cSSeigo Tanimura 	resp->mem_rid = CS461x_MEM_OFFSET;
175fe1a5d1cSSeigo Tanimura 	resp->mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &resp->mem_rid, 0, ~0, CS461x_MEM_SIZE, RF_ACTIVE);
176fe1a5d1cSSeigo Tanimura 	if (resp->mem == NULL) {
177fe1a5d1cSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
178fe1a5d1cSSeigo Tanimura 		return (ENXIO);
179fe1a5d1cSSeigo Tanimura 	}
180fe1a5d1cSSeigo Tanimura 	resp->irq_rid = 0;
181fe1a5d1cSSeigo Tanimura 	resp->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &resp->irq_rid, 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
182fe1a5d1cSSeigo Tanimura 	if (resp->irq == NULL) {
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 		return (ENXIO);
186fe1a5d1cSSeigo Tanimura 	}
187fe1a5d1cSSeigo Tanimura 
188fe1a5d1cSSeigo Tanimura 	/* Initialize the chip. */
189fe1a5d1cSSeigo Tanimura 	if (csa_initialize(scp)) {
190fe1a5d1cSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
191fe1a5d1cSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
192fe1a5d1cSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq);
193fe1a5d1cSSeigo Tanimura 		return (ENXIO);
194fe1a5d1cSSeigo Tanimura 	}
195fe1a5d1cSSeigo Tanimura 
196fe1a5d1cSSeigo Tanimura 	/* Reset the Processor. */
197fe1a5d1cSSeigo Tanimura 	csa_resetdsp(resp);
198fe1a5d1cSSeigo Tanimura 
199fe1a5d1cSSeigo Tanimura 	/* Download the Processor Image to the processor. */
200fe1a5d1cSSeigo Tanimura 	if (csa_downloadimage(resp)) {
201fe1a5d1cSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
202fe1a5d1cSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
203fe1a5d1cSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq);
204fe1a5d1cSSeigo Tanimura 		return (ENXIO);
205fe1a5d1cSSeigo Tanimura 	}
206fe1a5d1cSSeigo Tanimura 
207fe1a5d1cSSeigo Tanimura 	bus_generic_attach(dev);
208fe1a5d1cSSeigo Tanimura 
209fe1a5d1cSSeigo Tanimura 	return (0);
210fe1a5d1cSSeigo Tanimura }
211fe1a5d1cSSeigo Tanimura #endif /* NPCI > 0 */
212fe1a5d1cSSeigo Tanimura 
213fe1a5d1cSSeigo Tanimura static struct resource *
214fe1a5d1cSSeigo Tanimura csa_alloc_resource(device_t bus, device_t child, int type, int *rid,
215fe1a5d1cSSeigo Tanimura 		      u_long start, u_long end, u_long count, u_int flags)
216fe1a5d1cSSeigo Tanimura {
217fe1a5d1cSSeigo Tanimura 	sc_p scp;
218fe1a5d1cSSeigo Tanimura 	csa_res *resp;
219fe1a5d1cSSeigo Tanimura 	struct resource *res;
220fe1a5d1cSSeigo Tanimura 
221fe1a5d1cSSeigo Tanimura 	scp = device_get_softc(bus);
222fe1a5d1cSSeigo Tanimura 	resp = &scp->res;
223fe1a5d1cSSeigo Tanimura 	switch (type) {
224fe1a5d1cSSeigo Tanimura 	case SYS_RES_IRQ:
225fe1a5d1cSSeigo Tanimura 		if (*rid != 0)
226fe1a5d1cSSeigo Tanimura 			return (NULL);
227fe1a5d1cSSeigo Tanimura 		res = resp->irq;
228fe1a5d1cSSeigo Tanimura 		break;
229fe1a5d1cSSeigo Tanimura 	case SYS_RES_MEMORY:
230fe1a5d1cSSeigo Tanimura 		switch (*rid) {
231fe1a5d1cSSeigo Tanimura 		case CS461x_IO_OFFSET:
232fe1a5d1cSSeigo Tanimura 			res = resp->io;
233fe1a5d1cSSeigo Tanimura 			break;
234fe1a5d1cSSeigo Tanimura 		case CS461x_MEM_OFFSET:
235fe1a5d1cSSeigo Tanimura 			res = resp->mem;
236fe1a5d1cSSeigo Tanimura 			break;
237fe1a5d1cSSeigo Tanimura 		default:
238fe1a5d1cSSeigo Tanimura 			return (NULL);
239fe1a5d1cSSeigo Tanimura 		}
240fe1a5d1cSSeigo Tanimura 		break;
241fe1a5d1cSSeigo Tanimura 	default:
242fe1a5d1cSSeigo Tanimura 		return (NULL);
243fe1a5d1cSSeigo Tanimura 	}
244fe1a5d1cSSeigo Tanimura 
245fe1a5d1cSSeigo Tanimura 	return res;
246fe1a5d1cSSeigo Tanimura }
247fe1a5d1cSSeigo Tanimura 
248fe1a5d1cSSeigo Tanimura static int
249fe1a5d1cSSeigo Tanimura csa_release_resource(device_t bus, device_t child, int type, int rid,
250fe1a5d1cSSeigo Tanimura 			struct resource *r)
251fe1a5d1cSSeigo Tanimura {
252fe1a5d1cSSeigo Tanimura 	return (0);
253fe1a5d1cSSeigo Tanimura }
254fe1a5d1cSSeigo Tanimura 
255fe1a5d1cSSeigo Tanimura static int
256fe1a5d1cSSeigo Tanimura csa_initialize(sc_p scp)
257fe1a5d1cSSeigo Tanimura {
258fe1a5d1cSSeigo Tanimura 	int i;
259fe1a5d1cSSeigo Tanimura 	u_int32_t acsts, acisv;
260fe1a5d1cSSeigo Tanimura 	csa_res *resp;
261fe1a5d1cSSeigo Tanimura 
262fe1a5d1cSSeigo Tanimura 	resp = &scp->res;
263fe1a5d1cSSeigo Tanimura 
264fe1a5d1cSSeigo Tanimura 	/*
265fe1a5d1cSSeigo Tanimura 	 * First, blast the clock control register to zero so that the PLL starts
266fe1a5d1cSSeigo Tanimura 	 * out in a known state, and blast the master serial port control register
267fe1a5d1cSSeigo Tanimura 	 * to zero so that the serial ports also start out in a known state.
268fe1a5d1cSSeigo Tanimura 	 */
269fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_CLKCR1, 0);
270fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_SERMC1, 0);
271fe1a5d1cSSeigo Tanimura 
272fe1a5d1cSSeigo Tanimura 	/*
273fe1a5d1cSSeigo Tanimura 	 * If we are in AC97 mode, then we must set the part to a host controlled
274fe1a5d1cSSeigo Tanimura 	 * AC-link.  Otherwise, we won't be able to bring up the link.
275fe1a5d1cSSeigo Tanimura 	 */
276fe1a5d1cSSeigo Tanimura #if 1
277fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_SERACC, SERACC_HSP | SERACC_CODEC_TYPE_1_03); /* 1.03 codec */
278fe1a5d1cSSeigo Tanimura #else
279fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_SERACC, SERACC_HSP | SERACC_CODEC_TYPE_2_0); /* 2.0 codec */
280fe1a5d1cSSeigo Tanimura #endif /* 1 */
281fe1a5d1cSSeigo Tanimura 
282fe1a5d1cSSeigo Tanimura 	/*
283fe1a5d1cSSeigo Tanimura 	 * Drive the ARST# pin low for a minimum of 1uS (as defined in the AC97
284fe1a5d1cSSeigo Tanimura 	 * spec) and then drive it high.  This is done for non AC97 modes since
285fe1a5d1cSSeigo Tanimura 	 * there might be logic external to the CS461x that uses the ARST# line
286fe1a5d1cSSeigo Tanimura 	 * for a reset.
287fe1a5d1cSSeigo Tanimura 	 */
288fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCTL, 0);
289fe1a5d1cSSeigo Tanimura 	DELAY(250);
290fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCTL, ACCTL_RSTN);
291fe1a5d1cSSeigo Tanimura 
292fe1a5d1cSSeigo Tanimura 	/*
293fe1a5d1cSSeigo Tanimura 	 * The first thing we do here is to enable sync generation.  As soon
294fe1a5d1cSSeigo Tanimura 	 * as we start receiving bit clock, we'll start producing the SYNC
295fe1a5d1cSSeigo Tanimura 	 * signal.
296fe1a5d1cSSeigo Tanimura 	 */
297fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCTL, ACCTL_ESYN | ACCTL_RSTN);
298fe1a5d1cSSeigo Tanimura 
299fe1a5d1cSSeigo Tanimura 	/*
300fe1a5d1cSSeigo Tanimura 	 * Now wait for a short while to allow the AC97 part to start
301fe1a5d1cSSeigo Tanimura 	 * generating bit clock (so we don't try to start the PLL without an
302fe1a5d1cSSeigo Tanimura 	 * input clock).
303fe1a5d1cSSeigo Tanimura 	 */
304fe1a5d1cSSeigo Tanimura 	DELAY(50000);
305fe1a5d1cSSeigo Tanimura 
306fe1a5d1cSSeigo Tanimura 	/*
307fe1a5d1cSSeigo Tanimura 	 * Set the serial port timing configuration, so that
308fe1a5d1cSSeigo Tanimura 	 * the clock control circuit gets its clock from the correct place.
309fe1a5d1cSSeigo Tanimura 	 */
310fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_SERMC1, SERMC1_PTC_AC97);
311fe1a5d1cSSeigo Tanimura 
312fe1a5d1cSSeigo Tanimura 	/*
313fe1a5d1cSSeigo Tanimura 	 * Write the selected clock control setup to the hardware.  Do not turn on
314fe1a5d1cSSeigo Tanimura 	 * SWCE yet (if requested), so that the devices clocked by the output of
315fe1a5d1cSSeigo Tanimura 	 * PLL are not clocked until the PLL is stable.
316fe1a5d1cSSeigo Tanimura 	 */
317fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_PLLCC, PLLCC_LPF_1050_2780_KHZ | PLLCC_CDR_73_104_MHZ);
318fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_PLLM, 0x3a);
319fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_CLKCR2, CLKCR2_PDIVS_8);
320fe1a5d1cSSeigo Tanimura 
321fe1a5d1cSSeigo Tanimura 	/*
322fe1a5d1cSSeigo Tanimura 	 * Power up the PLL.
323fe1a5d1cSSeigo Tanimura 	 */
324fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_CLKCR1, CLKCR1_PLLP);
325fe1a5d1cSSeigo Tanimura 
326fe1a5d1cSSeigo Tanimura 	/*
327fe1a5d1cSSeigo Tanimura 	 * Wait until the PLL has stabilized.
328fe1a5d1cSSeigo Tanimura 	 */
329fe1a5d1cSSeigo Tanimura 	DELAY(50000);
330fe1a5d1cSSeigo Tanimura 
331fe1a5d1cSSeigo Tanimura 	/*
332fe1a5d1cSSeigo Tanimura 	 * Turn on clocking of the core so that we can setup the serial ports.
333fe1a5d1cSSeigo Tanimura 	 */
334fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_CLKCR1, csa_readio(resp, BA0_CLKCR1) | CLKCR1_SWCE);
335fe1a5d1cSSeigo Tanimura 
336fe1a5d1cSSeigo Tanimura 	/*
337fe1a5d1cSSeigo Tanimura 	 * Fill the serial port FIFOs with silence.
338fe1a5d1cSSeigo Tanimura 	 */
339fe1a5d1cSSeigo Tanimura 	csa_clearserialfifos(resp);
340fe1a5d1cSSeigo Tanimura 
341fe1a5d1cSSeigo Tanimura 	/*
342fe1a5d1cSSeigo Tanimura 	 * Set the serial port FIFO pointer to the first sample in the FIFO.
343fe1a5d1cSSeigo Tanimura 	 */
344fe1a5d1cSSeigo Tanimura #if notdef
345fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_SERBSP, 0);
346fe1a5d1cSSeigo Tanimura #endif /* notdef */
347fe1a5d1cSSeigo Tanimura 
348fe1a5d1cSSeigo Tanimura 	/*
349fe1a5d1cSSeigo Tanimura 	 *  Write the serial port configuration to the part.  The master
350fe1a5d1cSSeigo Tanimura 	 *  enable bit is not set until all other values have been written.
351fe1a5d1cSSeigo Tanimura 	 */
352fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_SERC1, SERC1_SO1F_AC97 | SERC1_SO1EN);
353fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_SERC2, SERC2_SI1F_AC97 | SERC1_SO1EN);
354fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_SERMC1, SERMC1_PTC_AC97 | SERMC1_MSPE);
355fe1a5d1cSSeigo Tanimura 
356fe1a5d1cSSeigo Tanimura 	/*
357fe1a5d1cSSeigo Tanimura 	 * Wait for the codec ready signal from the AC97 codec.
358fe1a5d1cSSeigo Tanimura 	 */
359fe1a5d1cSSeigo Tanimura 	acsts = 0;
360fe1a5d1cSSeigo Tanimura 	for (i = 0 ; i < 1000 ; i++) {
361fe1a5d1cSSeigo Tanimura 		/*
362fe1a5d1cSSeigo Tanimura 		 * First, lets wait a short while to let things settle out a bit,
363fe1a5d1cSSeigo Tanimura 		 * and to prevent retrying the read too quickly.
364fe1a5d1cSSeigo Tanimura 		 */
365fe1a5d1cSSeigo Tanimura 		DELAY(250);
366fe1a5d1cSSeigo Tanimura 
367fe1a5d1cSSeigo Tanimura 		/*
368fe1a5d1cSSeigo Tanimura 		 * Read the AC97 status register to see if we've seen a CODEC READY
369fe1a5d1cSSeigo Tanimura 		 * signal from the AC97 codec.
370fe1a5d1cSSeigo Tanimura 		 */
371fe1a5d1cSSeigo Tanimura 		acsts = csa_readio(resp, BA0_ACSTS);
372fe1a5d1cSSeigo Tanimura 		if ((acsts & ACSTS_CRDY) != 0)
373fe1a5d1cSSeigo Tanimura 			break;
374fe1a5d1cSSeigo Tanimura 	}
375fe1a5d1cSSeigo Tanimura 
376fe1a5d1cSSeigo Tanimura 	/*
377fe1a5d1cSSeigo Tanimura 	 * Make sure we sampled CODEC READY.
378fe1a5d1cSSeigo Tanimura 	 */
379fe1a5d1cSSeigo Tanimura 	if ((acsts & ACSTS_CRDY) == 0)
380fe1a5d1cSSeigo Tanimura 		return (ENXIO);
381fe1a5d1cSSeigo Tanimura 
382fe1a5d1cSSeigo Tanimura 	/*
383fe1a5d1cSSeigo Tanimura 	 * Assert the vaid frame signal so that we can start sending commands
384fe1a5d1cSSeigo Tanimura 	 * to the AC97 codec.
385fe1a5d1cSSeigo Tanimura 	 */
386fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCTL, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
387fe1a5d1cSSeigo Tanimura 
388fe1a5d1cSSeigo Tanimura 	/*
389fe1a5d1cSSeigo Tanimura 	 * Wait until we've sampled input slots 3 and 4 as valid, meaning that
390fe1a5d1cSSeigo Tanimura 	 * the codec is pumping ADC data across the AC-link.
391fe1a5d1cSSeigo Tanimura 	 */
392fe1a5d1cSSeigo Tanimura 	acisv = 0;
393fe1a5d1cSSeigo Tanimura 	for (i = 0 ; i < 1000 ; i++) {
394fe1a5d1cSSeigo Tanimura 		/*
395fe1a5d1cSSeigo Tanimura 		 * First, lets wait a short while to let things settle out a bit,
396fe1a5d1cSSeigo Tanimura 		 * and to prevent retrying the read too quickly.
397fe1a5d1cSSeigo Tanimura 		 */
398fe1a5d1cSSeigo Tanimura #if notdef
399fe1a5d1cSSeigo Tanimura 		DELAY(10000000L); /* clw */
400fe1a5d1cSSeigo Tanimura #else
401fe1a5d1cSSeigo Tanimura 		DELAY(2500);
402fe1a5d1cSSeigo Tanimura #endif /* notdef */
403fe1a5d1cSSeigo Tanimura 		/*
404fe1a5d1cSSeigo Tanimura 		 * Read the input slot valid register and see if input slots 3 and
405fe1a5d1cSSeigo Tanimura 		 * 4 are valid yet.
406fe1a5d1cSSeigo Tanimura 		 */
407fe1a5d1cSSeigo Tanimura 		acisv = csa_readio(resp, BA0_ACISV);
408fe1a5d1cSSeigo Tanimura 		if ((acisv & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4))
409fe1a5d1cSSeigo Tanimura 			break;
410fe1a5d1cSSeigo Tanimura 	}
411fe1a5d1cSSeigo Tanimura 	/*
412fe1a5d1cSSeigo Tanimura 	 * Make sure we sampled valid input slots 3 and 4.  If not, then return
413fe1a5d1cSSeigo Tanimura 	 * an error.
414fe1a5d1cSSeigo Tanimura 	 */
415fe1a5d1cSSeigo Tanimura 	if ((acisv & (ACISV_ISV3 | ACISV_ISV4)) != (ACISV_ISV3 | ACISV_ISV4))
416fe1a5d1cSSeigo Tanimura 		return (ENXIO);
417fe1a5d1cSSeigo Tanimura 
418fe1a5d1cSSeigo Tanimura 	/*
419fe1a5d1cSSeigo Tanimura 	 * Now, assert valid frame and the slot 3 and 4 valid bits.  This will
420fe1a5d1cSSeigo Tanimura 	 * commense the transfer of digital audio data to the AC97 codec.
421fe1a5d1cSSeigo Tanimura 	 */
422fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACOSV, ACOSV_SLV3 | ACOSV_SLV4);
423fe1a5d1cSSeigo Tanimura 
424fe1a5d1cSSeigo Tanimura 	/*
425fe1a5d1cSSeigo Tanimura 	 * Power down the DAC and ADC.  We will power them up (if) when we need
426fe1a5d1cSSeigo Tanimura 	 * them.
427fe1a5d1cSSeigo Tanimura 	 */
428fe1a5d1cSSeigo Tanimura #if notdef
429fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_AC97_POWERDOWN, 0x300);
430fe1a5d1cSSeigo Tanimura #endif /* notdef */
431fe1a5d1cSSeigo Tanimura 
432fe1a5d1cSSeigo Tanimura 	/*
433fe1a5d1cSSeigo Tanimura 	 * Turn off the Processor by turning off the software clock enable flag in
434fe1a5d1cSSeigo Tanimura 	 * the clock control register.
435fe1a5d1cSSeigo Tanimura 	 */
436fe1a5d1cSSeigo Tanimura #if notdef
437fe1a5d1cSSeigo Tanimura 	clkcr1 = csa_readio(resp, BA0_CLKCR1) & ~CLKCR1_SWCE;
438fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_CLKCR1, clkcr1);
439fe1a5d1cSSeigo Tanimura #endif /* notdef */
440fe1a5d1cSSeigo Tanimura 
441fe1a5d1cSSeigo Tanimura 	/*
442fe1a5d1cSSeigo Tanimura 	 * Enable interrupts on the part.
443fe1a5d1cSSeigo Tanimura 	 */
444fe1a5d1cSSeigo Tanimura #if notdef
445fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
446fe1a5d1cSSeigo Tanimura #endif /* notdef */
447fe1a5d1cSSeigo Tanimura 
448fe1a5d1cSSeigo Tanimura 	return (0);
449fe1a5d1cSSeigo Tanimura }
450fe1a5d1cSSeigo Tanimura 
451fe1a5d1cSSeigo Tanimura static void
452fe1a5d1cSSeigo Tanimura csa_clearserialfifos(csa_res *resp)
453fe1a5d1cSSeigo Tanimura {
454fe1a5d1cSSeigo Tanimura 	int i, j, pwr;
455fe1a5d1cSSeigo Tanimura 	u_int8_t clkcr1, serbst;
456fe1a5d1cSSeigo Tanimura 
457fe1a5d1cSSeigo Tanimura 	/*
458fe1a5d1cSSeigo Tanimura 	 * See if the devices are powered down.  If so, we must power them up first
459fe1a5d1cSSeigo Tanimura 	 * or they will not respond.
460fe1a5d1cSSeigo Tanimura 	 */
461fe1a5d1cSSeigo Tanimura 	pwr = 1;
462fe1a5d1cSSeigo Tanimura 	clkcr1 = csa_readio(resp, BA0_CLKCR1);
463fe1a5d1cSSeigo Tanimura 	if ((clkcr1 & CLKCR1_SWCE) == 0) {
464fe1a5d1cSSeigo Tanimura 		csa_writeio(resp, BA0_CLKCR1, clkcr1 | CLKCR1_SWCE);
465fe1a5d1cSSeigo Tanimura 		pwr = 0;
466fe1a5d1cSSeigo Tanimura 	}
467fe1a5d1cSSeigo Tanimura 
468fe1a5d1cSSeigo Tanimura 	/*
469fe1a5d1cSSeigo Tanimura 	 * We want to clear out the serial port FIFOs so we don't end up playing
470fe1a5d1cSSeigo Tanimura 	 * whatever random garbage happens to be in them.  We fill the sample FIFOs
471fe1a5d1cSSeigo Tanimura 	 * with zero (silence).
472fe1a5d1cSSeigo Tanimura 	 */
473fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_SERBWP, 0);
474fe1a5d1cSSeigo Tanimura 
475fe1a5d1cSSeigo Tanimura 	/* Fill all 256 sample FIFO locations. */
476fe1a5d1cSSeigo Tanimura 	serbst = 0;
477fe1a5d1cSSeigo Tanimura 	for (i = 0 ; i < 256 ; i++) {
478fe1a5d1cSSeigo Tanimura 		/* Make sure the previous FIFO write operation has completed. */
479fe1a5d1cSSeigo Tanimura 		for (j = 0 ; j < 5 ; j++) {
480fe1a5d1cSSeigo Tanimura 			DELAY(250);
481fe1a5d1cSSeigo Tanimura 			serbst = csa_readio(resp, BA0_SERBST);
482fe1a5d1cSSeigo Tanimura 			if ((serbst & SERBST_WBSY) == 0)
483fe1a5d1cSSeigo Tanimura 				break;
484fe1a5d1cSSeigo Tanimura 		}
485fe1a5d1cSSeigo Tanimura 		if ((serbst & SERBST_WBSY) != 0) {
486fe1a5d1cSSeigo Tanimura 			if (!pwr)
487fe1a5d1cSSeigo Tanimura 				csa_writeio(resp, BA0_CLKCR1, clkcr1);
488fe1a5d1cSSeigo Tanimura 		}
489fe1a5d1cSSeigo Tanimura 		/* Write the serial port FIFO index. */
490fe1a5d1cSSeigo Tanimura 		csa_writeio(resp, BA0_SERBAD, i);
491fe1a5d1cSSeigo Tanimura 		/* Tell the serial port to load the new value into the FIFO location. */
492fe1a5d1cSSeigo Tanimura 		csa_writeio(resp, BA0_SERBCM, SERBCM_WRC);
493fe1a5d1cSSeigo Tanimura 	}
494fe1a5d1cSSeigo Tanimura 	/*
495fe1a5d1cSSeigo Tanimura 	 *  Now, if we powered up the devices, then power them back down again.
496fe1a5d1cSSeigo Tanimura 	 *  This is kinda ugly, but should never happen.
497fe1a5d1cSSeigo Tanimura 	 */
498fe1a5d1cSSeigo Tanimura 	if (!pwr)
499fe1a5d1cSSeigo Tanimura 		csa_writeio(resp, BA0_CLKCR1, clkcr1);
500fe1a5d1cSSeigo Tanimura }
501fe1a5d1cSSeigo Tanimura 
502fe1a5d1cSSeigo Tanimura static void
503fe1a5d1cSSeigo Tanimura csa_resetdsp(csa_res *resp)
504fe1a5d1cSSeigo Tanimura {
505fe1a5d1cSSeigo Tanimura 	int i;
506fe1a5d1cSSeigo Tanimura 
507fe1a5d1cSSeigo Tanimura 	/*
508fe1a5d1cSSeigo Tanimura 	 * Write the reset bit of the SP control register.
509fe1a5d1cSSeigo Tanimura 	 */
510fe1a5d1cSSeigo Tanimura 	csa_writemem(resp, BA1_SPCR, SPCR_RSTSP);
511fe1a5d1cSSeigo Tanimura 
512fe1a5d1cSSeigo Tanimura 	/*
513fe1a5d1cSSeigo Tanimura 	 * Write the control register.
514fe1a5d1cSSeigo Tanimura 	 */
515fe1a5d1cSSeigo Tanimura 	csa_writemem(resp, BA1_SPCR, SPCR_DRQEN);
516fe1a5d1cSSeigo Tanimura 
517fe1a5d1cSSeigo Tanimura 	/*
518fe1a5d1cSSeigo Tanimura 	 * Clear the trap registers.
519fe1a5d1cSSeigo Tanimura 	 */
520fe1a5d1cSSeigo Tanimura 	for (i = 0 ; i < 8 ; i++) {
521fe1a5d1cSSeigo Tanimura 		csa_writemem(resp, BA1_DREG, DREG_REGID_TRAP_SELECT + i);
522fe1a5d1cSSeigo Tanimura 		csa_writemem(resp, BA1_TWPR, 0xffff);
523fe1a5d1cSSeigo Tanimura 	}
524fe1a5d1cSSeigo Tanimura 	csa_writemem(resp, BA1_DREG, 0);
525fe1a5d1cSSeigo Tanimura 
526fe1a5d1cSSeigo Tanimura 	/*
527fe1a5d1cSSeigo Tanimura 	 * Set the frame timer to reflect the number of cycles per frame.
528fe1a5d1cSSeigo Tanimura 	 */
529fe1a5d1cSSeigo Tanimura 	csa_writemem(resp, BA1_FRMT, 0xadf);
530fe1a5d1cSSeigo Tanimura }
531fe1a5d1cSSeigo Tanimura 
532fe1a5d1cSSeigo Tanimura static int
533fe1a5d1cSSeigo Tanimura csa_downloadimage(csa_res *resp)
534fe1a5d1cSSeigo Tanimura {
535fe1a5d1cSSeigo Tanimura 	int ret;
536fe1a5d1cSSeigo Tanimura 	u_long ul, offset;
537fe1a5d1cSSeigo Tanimura 
538fe1a5d1cSSeigo Tanimura 	for (ul = 0, offset = 0 ; ul < INKY_MEMORY_COUNT ; ul++) {
539fe1a5d1cSSeigo Tanimura 		/*
540fe1a5d1cSSeigo Tanimura 		 * DMA this block from host memory to the appropriate
541fe1a5d1cSSeigo Tanimura 		 * memory on the CSDevice.
542fe1a5d1cSSeigo Tanimura 		 */
543fe1a5d1cSSeigo Tanimura 		ret = csa_transferimage(
544fe1a5d1cSSeigo Tanimura 			resp,
545fe1a5d1cSSeigo Tanimura 			BA1Struct.BA1Array + offset,
546fe1a5d1cSSeigo Tanimura 			BA1Struct.MemoryStat[ul].ulDestByteOffset,
547fe1a5d1cSSeigo Tanimura 			BA1Struct.MemoryStat[ul].ulSourceByteSize);
548fe1a5d1cSSeigo Tanimura 		if (ret)
549fe1a5d1cSSeigo Tanimura 			return (ret);
550fe1a5d1cSSeigo Tanimura 		offset += BA1Struct.MemoryStat[ul].ulSourceByteSize >> 2;
551fe1a5d1cSSeigo Tanimura 	}
552fe1a5d1cSSeigo Tanimura 
553fe1a5d1cSSeigo Tanimura 	return (0);
554fe1a5d1cSSeigo Tanimura }
555fe1a5d1cSSeigo Tanimura 
556fe1a5d1cSSeigo Tanimura static int
557fe1a5d1cSSeigo Tanimura csa_transferimage(csa_res *resp, u_long *src, u_long dest, u_long len)
558fe1a5d1cSSeigo Tanimura {
559fe1a5d1cSSeigo Tanimura 	u_long ul;
560fe1a5d1cSSeigo Tanimura 
561fe1a5d1cSSeigo Tanimura 	/*
562fe1a5d1cSSeigo Tanimura 	 * We do not allow DMAs from host memory to host memory (although the DMA
563fe1a5d1cSSeigo Tanimura 	 * can do it) and we do not allow DMAs which are not a multiple of 4 bytes
564fe1a5d1cSSeigo Tanimura 	 * in size (because that DMA can not do that).  Return an error if either
565fe1a5d1cSSeigo Tanimura 	 * of these conditions exist.
566fe1a5d1cSSeigo Tanimura 	 */
567fe1a5d1cSSeigo Tanimura 	if ((len & 0x3) != 0)
568fe1a5d1cSSeigo Tanimura 		return (EINVAL);
569fe1a5d1cSSeigo Tanimura 
570fe1a5d1cSSeigo Tanimura 	/* Check the destination address that it is a multiple of 4 */
571fe1a5d1cSSeigo Tanimura 	if ((dest & 0x3) != 0)
572fe1a5d1cSSeigo Tanimura 		return (EINVAL);
573fe1a5d1cSSeigo Tanimura 
574fe1a5d1cSSeigo Tanimura 	/* Write the buffer out. */
575fe1a5d1cSSeigo Tanimura 	for (ul = 0 ; ul < len ; ul += 4)
576fe1a5d1cSSeigo Tanimura 		csa_writemem(resp, dest + ul, src[ul >> 2]);
577fe1a5d1cSSeigo Tanimura 
578fe1a5d1cSSeigo Tanimura 	return (0);
579fe1a5d1cSSeigo Tanimura }
580fe1a5d1cSSeigo Tanimura 
581fe1a5d1cSSeigo Tanimura int
582fe1a5d1cSSeigo Tanimura csa_readcodec(csa_res *resp, u_long offset, u_int32_t *data)
583fe1a5d1cSSeigo Tanimura {
584fe1a5d1cSSeigo Tanimura 	int i;
585fe1a5d1cSSeigo Tanimura 	u_int32_t acsda, acctl, acsts;
586fe1a5d1cSSeigo Tanimura 
587fe1a5d1cSSeigo Tanimura 	/*
588fe1a5d1cSSeigo Tanimura 	 * Make sure that there is not data sitting around from a previous
589fe1a5d1cSSeigo Tanimura 	 * uncompleted access. ACSDA = Status Data Register = 47Ch
590fe1a5d1cSSeigo Tanimura 	 */
591fe1a5d1cSSeigo Tanimura 	acsda = csa_readio(resp, BA0_ACSDA);
592fe1a5d1cSSeigo Tanimura 
593fe1a5d1cSSeigo Tanimura 	/*
594fe1a5d1cSSeigo Tanimura 	 * Setup the AC97 control registers on the CS461x to send the
595fe1a5d1cSSeigo Tanimura 	 * appropriate command to the AC97 to perform the read.
596fe1a5d1cSSeigo Tanimura 	 * ACCAD = Command Address Register = 46Ch
597fe1a5d1cSSeigo Tanimura 	 * ACCDA = Command Data Register = 470h
598fe1a5d1cSSeigo Tanimura 	 * ACCTL = Control Register = 460h
599fe1a5d1cSSeigo Tanimura 	 * set DCV - will clear when process completed
600fe1a5d1cSSeigo Tanimura 	 * set CRW - Read command
601fe1a5d1cSSeigo Tanimura 	 * set VFRM - valid frame enabled
602fe1a5d1cSSeigo Tanimura 	 * set ESYN - ASYNC generation enabled
603fe1a5d1cSSeigo Tanimura 	 * set RSTN - ARST# inactive, AC97 codec not reset
604fe1a5d1cSSeigo Tanimura 	 */
605fe1a5d1cSSeigo Tanimura 
606fe1a5d1cSSeigo Tanimura 	/*
607fe1a5d1cSSeigo Tanimura 	 * Get the actual AC97 register from the offset
608fe1a5d1cSSeigo Tanimura 	 */
609fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCAD, offset - BA0_AC97_RESET);
610fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCDA, 0);
611fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCTL, ACCTL_DCV | ACCTL_CRW | ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
612fe1a5d1cSSeigo Tanimura 
613fe1a5d1cSSeigo Tanimura 	/*
614fe1a5d1cSSeigo Tanimura 	 * Wait for the read to occur.
615fe1a5d1cSSeigo Tanimura 	 */
616fe1a5d1cSSeigo Tanimura 	acctl = 0;
617fe1a5d1cSSeigo Tanimura 	for (i = 0 ; i < 10 ; i++) {
618fe1a5d1cSSeigo Tanimura 		/*
619fe1a5d1cSSeigo Tanimura 		 * First, we want to wait for a short time.
620fe1a5d1cSSeigo Tanimura 		 */
621fe1a5d1cSSeigo Tanimura 		DELAY(25);
622fe1a5d1cSSeigo Tanimura 
623fe1a5d1cSSeigo Tanimura 		/*
624fe1a5d1cSSeigo Tanimura 		 * Now, check to see if the read has completed.
625fe1a5d1cSSeigo Tanimura 		 * ACCTL = 460h, DCV should be reset by now and 460h = 17h
626fe1a5d1cSSeigo Tanimura 		 */
627fe1a5d1cSSeigo Tanimura 		acctl = csa_readio(resp, BA0_ACCTL);
628fe1a5d1cSSeigo Tanimura 		if ((acctl & ACCTL_DCV) == 0)
629fe1a5d1cSSeigo Tanimura 			break;
630fe1a5d1cSSeigo Tanimura 	}
631fe1a5d1cSSeigo Tanimura 
632fe1a5d1cSSeigo Tanimura 	/*
633fe1a5d1cSSeigo Tanimura 	 * Make sure the read completed.
634fe1a5d1cSSeigo Tanimura 	 */
635fe1a5d1cSSeigo Tanimura 	if ((acctl & ACCTL_DCV) != 0)
636fe1a5d1cSSeigo Tanimura 		return (EAGAIN);
637fe1a5d1cSSeigo Tanimura 
638fe1a5d1cSSeigo Tanimura 	/*
639fe1a5d1cSSeigo Tanimura 	 * Wait for the valid status bit to go active.
640fe1a5d1cSSeigo Tanimura 	 */
641fe1a5d1cSSeigo Tanimura 	acsts = 0;
642fe1a5d1cSSeigo Tanimura 	for (i = 0 ; i < 10 ; i++) {
643fe1a5d1cSSeigo Tanimura 		/*
644fe1a5d1cSSeigo Tanimura 		 * Read the AC97 status register.
645fe1a5d1cSSeigo Tanimura 		 * ACSTS = Status Register = 464h
646fe1a5d1cSSeigo Tanimura 		 */
647fe1a5d1cSSeigo Tanimura 		acsts = csa_readio(resp, BA0_ACSTS);
648fe1a5d1cSSeigo Tanimura 		/*
649fe1a5d1cSSeigo Tanimura 		 * See if we have valid status.
650fe1a5d1cSSeigo Tanimura 		 * VSTS - Valid Status
651fe1a5d1cSSeigo Tanimura 		 */
652fe1a5d1cSSeigo Tanimura 		if ((acsts & ACSTS_VSTS) != 0)
653fe1a5d1cSSeigo Tanimura 			break;
654fe1a5d1cSSeigo Tanimura 		/*
655fe1a5d1cSSeigo Tanimura 		 * Wait for a short while.
656fe1a5d1cSSeigo Tanimura 		 */
657fe1a5d1cSSeigo Tanimura 		 DELAY(25);
658fe1a5d1cSSeigo Tanimura 	}
659fe1a5d1cSSeigo Tanimura 
660fe1a5d1cSSeigo Tanimura 	/*
661fe1a5d1cSSeigo Tanimura 	 * Make sure we got valid status.
662fe1a5d1cSSeigo Tanimura 	 */
663fe1a5d1cSSeigo Tanimura 	if ((acsts & ACSTS_VSTS) == 0)
664fe1a5d1cSSeigo Tanimura 		return (EAGAIN);
665fe1a5d1cSSeigo Tanimura 
666fe1a5d1cSSeigo Tanimura 	/*
667fe1a5d1cSSeigo Tanimura 	 * Read the data returned from the AC97 register.
668fe1a5d1cSSeigo Tanimura 	 * ACSDA = Status Data Register = 474h
669fe1a5d1cSSeigo Tanimura 	 */
670fe1a5d1cSSeigo Tanimura 	*data = csa_readio(resp, BA0_ACSDA);
671fe1a5d1cSSeigo Tanimura 
672fe1a5d1cSSeigo Tanimura 	return (0);
673fe1a5d1cSSeigo Tanimura }
674fe1a5d1cSSeigo Tanimura 
675fe1a5d1cSSeigo Tanimura int
676fe1a5d1cSSeigo Tanimura csa_writecodec(csa_res *resp, u_long offset, u_int32_t data)
677fe1a5d1cSSeigo Tanimura {
678fe1a5d1cSSeigo Tanimura 	int i;
679fe1a5d1cSSeigo Tanimura 	u_int32_t acctl;
680fe1a5d1cSSeigo Tanimura 
681fe1a5d1cSSeigo Tanimura 	/*
682fe1a5d1cSSeigo Tanimura 	 * Setup the AC97 control registers on the CS461x to send the
683fe1a5d1cSSeigo Tanimura 	 * appropriate command to the AC97 to perform the write.
684fe1a5d1cSSeigo Tanimura 	 * ACCAD = Command Address Register = 46Ch
685fe1a5d1cSSeigo Tanimura 	 * ACCDA = Command Data Register = 470h
686fe1a5d1cSSeigo Tanimura 	 * ACCTL = Control Register = 460h
687fe1a5d1cSSeigo Tanimura 	 * set DCV - will clear when process completed
688fe1a5d1cSSeigo Tanimura 	 * set VFRM - valid frame enabled
689fe1a5d1cSSeigo Tanimura 	 * set ESYN - ASYNC generation enabled
690fe1a5d1cSSeigo Tanimura 	 * set RSTN - ARST# inactive, AC97 codec not reset
691fe1a5d1cSSeigo Tanimura 	 */
692fe1a5d1cSSeigo Tanimura 
693fe1a5d1cSSeigo Tanimura 	/*
694fe1a5d1cSSeigo Tanimura 	 * Get the actual AC97 register from the offset
695fe1a5d1cSSeigo Tanimura 	 */
696fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCAD, offset - BA0_AC97_RESET);
697fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCDA, data);
698fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCTL, ACCTL_DCV | ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
699fe1a5d1cSSeigo Tanimura 
700fe1a5d1cSSeigo Tanimura 	/*
701fe1a5d1cSSeigo Tanimura 	 * Wait for the write to occur.
702fe1a5d1cSSeigo Tanimura 	 */
703fe1a5d1cSSeigo Tanimura 	acctl = 0;
704fe1a5d1cSSeigo Tanimura 	for (i = 0 ; i < 10 ; i++) {
705fe1a5d1cSSeigo Tanimura 		/*
706fe1a5d1cSSeigo Tanimura 		 * First, we want to wait for a short time.
707fe1a5d1cSSeigo Tanimura 		 */
708fe1a5d1cSSeigo Tanimura 		DELAY(25);
709fe1a5d1cSSeigo Tanimura 
710fe1a5d1cSSeigo Tanimura 		/*
711fe1a5d1cSSeigo Tanimura 		 * Now, check to see if the read has completed.
712fe1a5d1cSSeigo Tanimura 		 * ACCTL = 460h, DCV should be reset by now and 460h = 17h
713fe1a5d1cSSeigo Tanimura 		 */
714fe1a5d1cSSeigo Tanimura 		acctl = csa_readio(resp, BA0_ACCTL);
715fe1a5d1cSSeigo Tanimura 		if ((acctl & ACCTL_DCV) == 0)
716fe1a5d1cSSeigo Tanimura 			break;
717fe1a5d1cSSeigo Tanimura 	}
718fe1a5d1cSSeigo Tanimura 
719fe1a5d1cSSeigo Tanimura 	/*
720fe1a5d1cSSeigo Tanimura 	 * Make sure the write completed.
721fe1a5d1cSSeigo Tanimura 	 */
722fe1a5d1cSSeigo Tanimura 	if ((acctl & ACCTL_DCV) != 0)
723fe1a5d1cSSeigo Tanimura 		return (EAGAIN);
724fe1a5d1cSSeigo Tanimura 
725fe1a5d1cSSeigo Tanimura 	return (0);
726fe1a5d1cSSeigo Tanimura }
727fe1a5d1cSSeigo Tanimura 
728fe1a5d1cSSeigo Tanimura u_int32_t
729fe1a5d1cSSeigo Tanimura csa_readio(csa_res *resp, u_long offset)
730fe1a5d1cSSeigo Tanimura {
731fe1a5d1cSSeigo Tanimura 	u_int32_t ul;
732fe1a5d1cSSeigo Tanimura 
733fe1a5d1cSSeigo Tanimura 	if (offset < BA0_AC97_RESET)
734fe1a5d1cSSeigo Tanimura 		return bus_space_read_4(rman_get_bustag(resp->io), rman_get_bushandle(resp->io), offset) & 0xffffffff;
735fe1a5d1cSSeigo Tanimura 	else {
736fe1a5d1cSSeigo Tanimura 		if (csa_readcodec(resp, offset, &ul))
737fe1a5d1cSSeigo Tanimura 			ul = 0;
738fe1a5d1cSSeigo Tanimura 		return (ul);
739fe1a5d1cSSeigo Tanimura 	}
740fe1a5d1cSSeigo Tanimura }
741fe1a5d1cSSeigo Tanimura 
742fe1a5d1cSSeigo Tanimura void
743fe1a5d1cSSeigo Tanimura csa_writeio(csa_res *resp, u_long offset, u_int32_t data)
744fe1a5d1cSSeigo Tanimura {
745fe1a5d1cSSeigo Tanimura 	if (offset < BA0_AC97_RESET)
746fe1a5d1cSSeigo Tanimura 		bus_space_write_4(rman_get_bustag(resp->io), rman_get_bushandle(resp->io), offset, data);
747fe1a5d1cSSeigo Tanimura 	else
748fe1a5d1cSSeigo Tanimura 		csa_writecodec(resp, offset, data);
749fe1a5d1cSSeigo Tanimura }
750fe1a5d1cSSeigo Tanimura 
751fe1a5d1cSSeigo Tanimura u_int32_t
752fe1a5d1cSSeigo Tanimura csa_readmem(csa_res *resp, u_long offset)
753fe1a5d1cSSeigo Tanimura {
754fe1a5d1cSSeigo Tanimura 	return bus_space_read_4(rman_get_bustag(resp->mem), rman_get_bushandle(resp->mem), offset) & 0xffffffff;
755fe1a5d1cSSeigo Tanimura }
756fe1a5d1cSSeigo Tanimura 
757fe1a5d1cSSeigo Tanimura void
758fe1a5d1cSSeigo Tanimura csa_writemem(csa_res *resp, u_long offset, u_int32_t data)
759fe1a5d1cSSeigo Tanimura {
760fe1a5d1cSSeigo Tanimura 	bus_space_write_4(rman_get_bustag(resp->mem), rman_get_bushandle(resp->mem), offset, data);
761fe1a5d1cSSeigo Tanimura }
762fe1a5d1cSSeigo Tanimura 
763fe1a5d1cSSeigo Tanimura #if NPCI > 0
764fe1a5d1cSSeigo Tanimura static device_method_t csa_methods[] = {
765fe1a5d1cSSeigo Tanimura 	/* Device interface */
766fe1a5d1cSSeigo Tanimura 	DEVMETHOD(device_probe,		csa_probe),
767fe1a5d1cSSeigo Tanimura 	DEVMETHOD(device_attach,	csa_attach),
768fe1a5d1cSSeigo Tanimura 	DEVMETHOD(device_detach,	bus_generic_detach),
769fe1a5d1cSSeigo Tanimura 	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
770fe1a5d1cSSeigo Tanimura 	DEVMETHOD(device_suspend,	bus_generic_suspend),
771fe1a5d1cSSeigo Tanimura 	DEVMETHOD(device_resume,	bus_generic_resume),
772fe1a5d1cSSeigo Tanimura 
773fe1a5d1cSSeigo Tanimura 	/* Bus interface */
774fe1a5d1cSSeigo Tanimura 	DEVMETHOD(bus_print_child,	bus_generic_print_child),
775fe1a5d1cSSeigo Tanimura 	DEVMETHOD(bus_alloc_resource,	csa_alloc_resource),
776fe1a5d1cSSeigo Tanimura 	DEVMETHOD(bus_release_resource,	csa_release_resource),
777fe1a5d1cSSeigo Tanimura 	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
778fe1a5d1cSSeigo Tanimura 	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
779fe1a5d1cSSeigo Tanimura 	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
780fe1a5d1cSSeigo Tanimura 	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
781fe1a5d1cSSeigo Tanimura 
782fe1a5d1cSSeigo Tanimura 	{ 0, 0 }
783fe1a5d1cSSeigo Tanimura };
784fe1a5d1cSSeigo Tanimura 
785fe1a5d1cSSeigo Tanimura static driver_t csa_driver = {
786fe1a5d1cSSeigo Tanimura 	"csa",
787fe1a5d1cSSeigo Tanimura 	csa_methods,
788fe1a5d1cSSeigo Tanimura 	sizeof(struct csa_softc),
789fe1a5d1cSSeigo Tanimura };
790fe1a5d1cSSeigo Tanimura 
791fe1a5d1cSSeigo Tanimura /*
792fe1a5d1cSSeigo Tanimura  * csa can be attached to a pci bus.
793fe1a5d1cSSeigo Tanimura  */
794fe1a5d1cSSeigo Tanimura DRIVER_MODULE(csa, pci, csa_driver, csa_devclass, 0, 0);
795fe1a5d1cSSeigo Tanimura #endif /* NPCI > 0 */
796