1139749Simp/*-
253553Stanimura * Copyright (c) 1999 Seigo Tanimura
353553Stanimura * All rights reserved.
453553Stanimura *
554377Stanimura * Portions of this source are based on cwcealdr.cpp and dhwiface.cpp in
654377Stanimura * cwcealdr1.zip, the sample sources by Crystal Semiconductor.
754377Stanimura * Copyright (c) 1996-1998 Crystal Semiconductor Corp.
854377Stanimura *
953553Stanimura * Redistribution and use in source and binary forms, with or without
1053553Stanimura * modification, are permitted provided that the following conditions
1153553Stanimura * are met:
1253553Stanimura * 1. Redistributions of source code must retain the above copyright
1353553Stanimura *    notice, this list of conditions and the following disclaimer.
1453553Stanimura * 2. Redistributions in binary form must reproduce the above copyright
1553553Stanimura *    notice, this list of conditions and the following disclaimer in the
1653553Stanimura *    documentation and/or other materials provided with the distribution.
1753553Stanimura *
1853553Stanimura * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1953553Stanimura * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2053553Stanimura * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2153553Stanimura * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2253553Stanimura * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2353553Stanimura * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2453553Stanimura * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2553553Stanimura * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2653553Stanimura * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2753553Stanimura * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2853553Stanimura * SUCH DAMAGE.
2953553Stanimura */
3053553Stanimura
3153553Stanimura#include <sys/param.h>
3253553Stanimura#include <sys/systm.h>
3353553Stanimura#include <sys/kernel.h>
3453553Stanimura#include <sys/bus.h>
3553553Stanimura#include <sys/malloc.h>
3653553Stanimura#include <sys/module.h>
3753553Stanimura#include <machine/resource.h>
3853553Stanimura#include <machine/bus.h>
3953553Stanimura#include <sys/rman.h>
40193640Sariff
41193640Sariff#ifdef HAVE_KERNEL_OPTION_HEADERS
42193640Sariff#include "opt_snd.h"
43193640Sariff#endif
44193640Sariff
4562483Scg#include <dev/sound/pcm/sound.h>
4653553Stanimura#include <dev/sound/chip.h>
4753553Stanimura#include <dev/sound/pci/csareg.h>
4853553Stanimura#include <dev/sound/pci/csavar.h>
4953553Stanimura
50119287Simp#include <dev/pci/pcireg.h>
51119287Simp#include <dev/pci/pcivar.h>
5253553Stanimura
53231047Spfg#include <dev/sound/pci/cs461x_dsp.h>
5453553Stanimura
5582180ScgSND_DECLARE_FILE("$FreeBSD$");
5682180Scg
5777504Scg/* This is the pci device id. */
5877504Scg#define CS4610_PCI_ID 0x60011013
5977504Scg#define CS4614_PCI_ID 0x60031013
6077504Scg#define CS4615_PCI_ID 0x60041013
6177504Scg
6253553Stanimura/* Here is the parameter structure per a device. */
6353553Stanimurastruct csa_softc {
6453553Stanimura	device_t dev; /* device */
6553553Stanimura	csa_res res; /* resources */
6653553Stanimura
6753553Stanimura	device_t pcm; /* pcm device */
6853553Stanimura	driver_intr_t* pcmintr; /* pcm intr */
6953553Stanimura	void *pcmintr_arg; /* pcm intr arg */
7053553Stanimura	device_t midi; /* midi device */
7153553Stanimura	driver_intr_t* midiintr; /* midi intr */
7253553Stanimura	void *midiintr_arg; /* midi intr arg */
7353553Stanimura	void *ih; /* cookie */
7455320Stanimura
7577504Scg	struct csa_card *card;
7655320Stanimura	struct csa_bridgeinfo binfo; /* The state of this bridge. */
7753553Stanimura};
7853553Stanimura
7953553Stanimuratypedef struct csa_softc *sc_p;
8053553Stanimura
8153553Stanimurastatic int csa_probe(device_t dev);
8253553Stanimurastatic int csa_attach(device_t dev);
8353553Stanimurastatic struct resource *csa_alloc_resource(device_t bus, device_t child, int type, int *rid,
8453553Stanimura					      u_long start, u_long end, u_long count, u_int flags);
8553553Stanimurastatic int csa_release_resource(device_t bus, device_t child, int type, int rid,
8653553Stanimura				   struct resource *r);
8755320Stanimurastatic int csa_setup_intr(device_t bus, device_t child,
8855320Stanimura			  struct resource *irq, int flags,
89166918Sariff#if __FreeBSD_version >= 700031
90166918Sariff			  driver_filter_t *filter,
91166918Sariff#endif
92166918Sariff			  driver_intr_t *intr,  void *arg, void **cookiep);
9355320Stanimurastatic int csa_teardown_intr(device_t bus, device_t child,
9455320Stanimura			     struct resource *irq, void *cookie);
9555320Stanimurastatic driver_intr_t csa_intr;
9653553Stanimurastatic int csa_initialize(sc_p scp);
9753553Stanimurastatic int csa_downloadimage(csa_res *resp);
98231047Spfgstatic int csa_transferimage(csa_res *resp, u_int32_t *src, u_long dest, u_long len);
9953553Stanimura
10053553Stanimurastatic devclass_t csa_devclass;
10153553Stanimura
10277504Scgstatic void
10377504Scgamp_none(void)
10477504Scg{
10577504Scg}
10677504Scg
10777504Scgstatic void
10877504Scgamp_voyetra(void)
10977504Scg{
11077504Scg}
11177504Scg
11253553Stanimurastatic int
11377504Scgclkrun_hack(int run)
11453553Stanimura{
11577504Scg#ifdef __i386__
11677504Scg	devclass_t		pci_devclass;
11777504Scg	device_t		*pci_devices, *pci_children, *busp, *childp;
11877504Scg	int			pci_count = 0, pci_childcount = 0;
11977504Scg	int			i, j, port;
12077504Scg	u_int16_t		control;
12177504Scg	bus_space_tag_t		btag;
12253553Stanimura
12377504Scg	if ((pci_devclass = devclass_find("pci")) == NULL) {
12477504Scg		return ENXIO;
12553553Stanimura	}
12653553Stanimura
12777504Scg	devclass_get_devices(pci_devclass, &pci_devices, &pci_count);
12877504Scg
12977504Scg	for (i = 0, busp = pci_devices; i < pci_count; i++, busp++) {
13077504Scg		pci_childcount = 0;
131182077Simp		if (device_get_children(*busp, &pci_children, &pci_childcount))
132182077Simp			continue;
13377504Scg		for (j = 0, childp = pci_children; j < pci_childcount; j++, childp++) {
13477504Scg			if (pci_get_vendor(*childp) == 0x8086 && pci_get_device(*childp) == 0x7113) {
13577504Scg				port = (pci_read_config(*childp, 0x41, 1) << 8) + 0x10;
13677504Scg				/* XXX */
137216592Stijl				btag = X86_BUS_SPACE_IO;
13877504Scg
13977504Scg				control = bus_space_read_2(btag, 0x0, port);
14077504Scg				control &= ~0x2000;
14177504Scg				control |= run? 0 : 0x2000;
14277504Scg				bus_space_write_2(btag, 0x0, port, control);
14378429Scg				free(pci_devices, M_TEMP);
14478429Scg				free(pci_children, M_TEMP);
14577504Scg				return 0;
14677504Scg			}
14777504Scg		}
14878429Scg		free(pci_children, M_TEMP);
14953553Stanimura	}
15053553Stanimura
15177504Scg	free(pci_devices, M_TEMP);
15277504Scg	return ENXIO;
15377504Scg#else
15477504Scg	return 0;
15577504Scg#endif
15653553Stanimura}
15753553Stanimura
15877504Scgstatic struct csa_card cards_4610[] = {
15978673Scg	{0, 0, "Unknown/invalid SSID (CS4610)", NULL, NULL, NULL, 0},
16077504Scg};
16177504Scg
16277504Scgstatic struct csa_card cards_4614[] = {
16378673Scg	{0x1489, 0x7001, "Genius Soundmaker 128 value", amp_none, NULL, NULL, 0},
16478673Scg	{0x5053, 0x3357, "Turtle Beach Santa Cruz", amp_voyetra, NULL, NULL, 1},
16578673Scg	{0x1071, 0x6003, "Mitac MI6020/21", amp_voyetra, NULL, NULL, 0},
16678673Scg	{0x14AF, 0x0050, "Hercules Game Theatre XP", NULL, NULL, NULL, 0},
16778673Scg	{0x1681, 0x0050, "Hercules Game Theatre XP", NULL, NULL, NULL, 0},
16886409Sasmodai	{0x1014, 0x0132, "Thinkpad 570", amp_none, NULL, NULL, 0},
16978673Scg	{0x1014, 0x0153, "Thinkpad 600X/A20/T20", amp_none, NULL, clkrun_hack, 0},
17078673Scg	{0x1014, 0x1010, "Thinkpad 600E (unsupported)", NULL, NULL, NULL, 0},
17178673Scg	{0, 0, "Unknown/invalid SSID (CS4614)", NULL, NULL, NULL, 0},
17277504Scg};
17377504Scg
17477504Scgstatic struct csa_card cards_4615[] = {
17578673Scg	{0, 0, "Unknown/invalid SSID (CS4615)", NULL, NULL, NULL, 0},
17677504Scg};
17777504Scg
17878673Scgstatic struct csa_card nocard = {0, 0, "unknown", NULL, NULL, NULL, 0};
17977504Scg
18077504Scgstruct card_type {
18177504Scg	u_int32_t devid;
18277504Scg	char *name;
18377504Scg	struct csa_card *cards;
18477504Scg};
18577504Scg
18677504Scgstatic struct card_type cards[] = {
18777504Scg	{CS4610_PCI_ID, "CS4610/CS4611", cards_4610},
18877504Scg	{CS4614_PCI_ID, "CS4280/CS4614/CS4622/CS4624/CS4630", cards_4614},
18977504Scg	{CS4615_PCI_ID, "CS4615", cards_4615},
19077504Scg	{0, NULL, NULL},
19177504Scg};
19277504Scg
19377504Scgstatic struct card_type *
19477504Scgcsa_findcard(device_t dev)
19577504Scg{
19677504Scg	int i;
19777504Scg
19877504Scg	i = 0;
19977504Scg	while (cards[i].devid != 0) {
20077504Scg		if (pci_get_devid(dev) == cards[i].devid)
20177504Scg			return &cards[i];
20277504Scg		i++;
20377504Scg	}
20477504Scg	return NULL;
20577504Scg}
20677504Scg
20777504Scgstruct csa_card *
20877504Scgcsa_findsubcard(device_t dev)
20977504Scg{
21077504Scg	int i;
21177504Scg	struct card_type *card;
21277504Scg	struct csa_card *subcard;
21377504Scg
21477504Scg	card = csa_findcard(dev);
21577504Scg	if (card == NULL)
21677504Scg		return &nocard;
21777504Scg	subcard = card->cards;
21877504Scg	i = 0;
21977504Scg	while (subcard[i].subvendor != 0) {
22077504Scg		if (pci_get_subvendor(dev) == subcard[i].subvendor
22177504Scg		    && pci_get_subdevice(dev) == subcard[i].subdevice) {
22277504Scg			return &subcard[i];
22377504Scg		}
22477504Scg		i++;
22577504Scg	}
22677504Scg	return &subcard[i];
22777504Scg}
22877504Scg
22953553Stanimurastatic int
23077504Scgcsa_probe(device_t dev)
23177504Scg{
23277504Scg	struct card_type *card;
23377504Scg
23477504Scg	card = csa_findcard(dev);
23577504Scg	if (card) {
23677504Scg		device_set_desc(dev, card->name);
237142890Simp		return BUS_PROBE_DEFAULT;
23877504Scg	}
23977504Scg	return ENXIO;
24077504Scg}
24177504Scg
24277504Scgstatic int
24353553Stanimuracsa_attach(device_t dev)
24453553Stanimura{
24553553Stanimura	sc_p scp;
24653553Stanimura	csa_res *resp;
24755320Stanimura	struct sndcard_func *func;
24878421Stmm	int error = ENXIO;
24953553Stanimura
25053553Stanimura	scp = device_get_softc(dev);
25153553Stanimura
25253553Stanimura	/* Fill in the softc. */
25353553Stanimura	bzero(scp, sizeof(*scp));
25453553Stanimura	scp->dev = dev;
25553553Stanimura
256254306Sscottl	pci_enable_busmaster(dev);
25753553Stanimura
25853553Stanimura	/* Allocate the resources. */
25953553Stanimura	resp = &scp->res;
26077504Scg	scp->card = csa_findsubcard(dev);
26177504Scg	scp->binfo.card = scp->card;
26277504Scg	printf("csa: card is %s\n", scp->card->name);
263119690Sjhb	resp->io_rid = PCIR_BAR(0);
264127135Snjl	resp->io = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
265127135Snjl		&resp->io_rid, RF_ACTIVE);
26653553Stanimura	if (resp->io == NULL)
26753553Stanimura		return (ENXIO);
268119690Sjhb	resp->mem_rid = PCIR_BAR(1);
269127135Snjl	resp->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
270127135Snjl		&resp->mem_rid, RF_ACTIVE);
27178421Stmm	if (resp->mem == NULL)
27278421Stmm		goto err_io;
27353553Stanimura	resp->irq_rid = 0;
274127135Snjl	resp->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
275127135Snjl		&resp->irq_rid, RF_ACTIVE | RF_SHAREABLE);
27678421Stmm	if (resp->irq == NULL)
27778421Stmm		goto err_mem;
27853553Stanimura
27955320Stanimura	/* Enable interrupt. */
280128232Sgreen	if (snd_setup_intr(dev, resp->irq, 0, csa_intr, scp, &scp->ih))
28178421Stmm		goto err_intr;
28277504Scg#if 0
28355320Stanimura	if ((csa_readio(resp, BA0_HISR) & HISR_INTENA) == 0)
28455320Stanimura		csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
28577504Scg#endif
28655320Stanimura
28753553Stanimura	/* Initialize the chip. */
28878421Stmm	if (csa_initialize(scp))
28978421Stmm		goto err_teardown;
29053553Stanimura
29153553Stanimura	/* Reset the Processor. */
29253553Stanimura	csa_resetdsp(resp);
29353553Stanimura
29453553Stanimura	/* Download the Processor Image to the processor. */
29578421Stmm	if (csa_downloadimage(resp))
29678421Stmm		goto err_teardown;
29753553Stanimura
29855320Stanimura	/* Attach the children. */
29955320Stanimura
30055320Stanimura	/* PCM Audio */
30178564Sgreid	func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
30278421Stmm	if (func == NULL) {
30378421Stmm		error = ENOMEM;
30478421Stmm		goto err_teardown;
30578421Stmm	}
30655320Stanimura	func->varinfo = &scp->binfo;
30755320Stanimura	func->func = SCF_PCM;
30855320Stanimura	scp->pcm = device_add_child(dev, "pcm", -1);
30955320Stanimura	device_set_ivars(scp->pcm, func);
31055320Stanimura
31155320Stanimura	/* Midi Interface */
31278564Sgreid	func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
31378421Stmm	if (func == NULL) {
31478421Stmm		error = ENOMEM;
31578421Stmm		goto err_teardown;
31678421Stmm	}
31755320Stanimura	func->varinfo = &scp->binfo;
31855320Stanimura	func->func = SCF_MIDI;
31955320Stanimura	scp->midi = device_add_child(dev, "midi", -1);
32055320Stanimura	device_set_ivars(scp->midi, func);
32155320Stanimura
32253553Stanimura	bus_generic_attach(dev);
32353553Stanimura
32453553Stanimura	return (0);
32578421Stmm
32678421Stmmerr_teardown:
32778421Stmm	bus_teardown_intr(dev, resp->irq, scp->ih);
32878421Stmmerr_intr:
32978421Stmm	bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq);
33078421Stmmerr_mem:
33178421Stmm	bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
33278421Stmmerr_io:
33378421Stmm	bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
33478421Stmm	return (error);
33553553Stanimura}
33653553Stanimura
33777504Scgstatic int
33877504Scgcsa_detach(device_t dev)
33977504Scg{
34082379Scg	csa_res *resp;
34177504Scg	sc_p scp;
342167667Sariff	struct sndcard_func *func;
34382379Scg	int err;
34477504Scg
34577504Scg	scp = device_get_softc(dev);
34682379Scg	resp = &scp->res;
34782379Scg
348167667Sariff	if (scp->midi != NULL) {
349167667Sariff		func = device_get_ivars(scp->midi);
35082379Scg		err = device_delete_child(dev, scp->midi);
351167667Sariff		if (err != 0)
352167667Sariff			return err;
353167667Sariff		if (func != NULL)
354167667Sariff			free(func, M_DEVBUF);
355167667Sariff		scp->midi = NULL;
356167667Sariff	}
35782379Scg
358167667Sariff	if (scp->pcm != NULL) {
359167667Sariff		func = device_get_ivars(scp->pcm);
36082379Scg		err = device_delete_child(dev, scp->pcm);
361167667Sariff		if (err != 0)
362167667Sariff			return err;
363167667Sariff		if (func != NULL)
364167667Sariff			free(func, M_DEVBUF);
365167667Sariff		scp->pcm = NULL;
366167667Sariff	}
36782379Scg
36882379Scg	bus_teardown_intr(dev, resp->irq, scp->ih);
36982379Scg	bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq);
37082379Scg	bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
37182379Scg	bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
37282379Scg
37377504Scg	return bus_generic_detach(dev);
37477504Scg}
37577504Scg
376100634Sambriskostatic int
377100634Sambriskocsa_resume(device_t dev)
378100634Sambrisko{
379147626Sglebius	csa_res *resp;
380147626Sglebius	sc_p scp;
381147626Sglebius
382147626Sglebius	scp = device_get_softc(dev);
383147626Sglebius	resp = &scp->res;
384147626Sglebius
385147626Sglebius	/* Initialize the chip. */
386147626Sglebius	if (csa_initialize(scp))
387147626Sglebius		return (ENXIO);
388147626Sglebius
389147626Sglebius	/* Reset the Processor. */
390147626Sglebius	csa_resetdsp(resp);
391147626Sglebius
392147626Sglebius	/* Download the Processor Image to the processor. */
393147626Sglebius	if (csa_downloadimage(resp))
394147626Sglebius		return (ENXIO);
395147626Sglebius
396147626Sglebius	return (bus_generic_resume(dev));
397100634Sambrisko}
398100634Sambrisko
39953553Stanimurastatic struct resource *
40053553Stanimuracsa_alloc_resource(device_t bus, device_t child, int type, int *rid,
40153553Stanimura		      u_long start, u_long end, u_long count, u_int flags)
40253553Stanimura{
40353553Stanimura	sc_p scp;
40453553Stanimura	csa_res *resp;
40553553Stanimura	struct resource *res;
40653553Stanimura
40753553Stanimura	scp = device_get_softc(bus);
40853553Stanimura	resp = &scp->res;
40953553Stanimura	switch (type) {
41053553Stanimura	case SYS_RES_IRQ:
41153553Stanimura		if (*rid != 0)
41253553Stanimura			return (NULL);
41353553Stanimura		res = resp->irq;
41453553Stanimura		break;
41553553Stanimura	case SYS_RES_MEMORY:
41653553Stanimura		switch (*rid) {
417119690Sjhb		case PCIR_BAR(0):
41853553Stanimura			res = resp->io;
41953553Stanimura			break;
420119690Sjhb		case PCIR_BAR(1):
42153553Stanimura			res = resp->mem;
42253553Stanimura			break;
42353553Stanimura		default:
42453553Stanimura			return (NULL);
42553553Stanimura		}
42653553Stanimura		break;
42753553Stanimura	default:
42853553Stanimura		return (NULL);
42953553Stanimura	}
43053553Stanimura
43153553Stanimura	return res;
43253553Stanimura}
43353553Stanimura
43453553Stanimurastatic int
43553553Stanimuracsa_release_resource(device_t bus, device_t child, int type, int rid,
43653553Stanimura			struct resource *r)
43753553Stanimura{
43853553Stanimura	return (0);
43953553Stanimura}
44053553Stanimura
44155320Stanimura/*
44255320Stanimura * The following three functions deal with interrupt handling.
44355320Stanimura * An interrupt is primarily handled by the bridge driver.
44455320Stanimura * The bridge driver then determines the child devices to pass
44555320Stanimura * the interrupt. Certain information of the device can be read
44655320Stanimura * only once(eg the value of HISR). The bridge driver is responsible
44755320Stanimura * to pass such the information to the children.
44855320Stanimura */
44955320Stanimura
45053553Stanimurastatic int
45155320Stanimuracsa_setup_intr(device_t bus, device_t child,
45255320Stanimura	       struct resource *irq, int flags,
453166918Sariff#if __FreeBSD_version >= 700031
454166918Sariff	       driver_filter_t *filter,
455166918Sariff#endif
456166918Sariff	       driver_intr_t *intr, void *arg, void **cookiep)
45755320Stanimura{
45855320Stanimura	sc_p scp;
45955320Stanimura	csa_res *resp;
46055320Stanimura	struct sndcard_func *func;
46155320Stanimura
462166918Sariff#if __FreeBSD_version >= 700031
463166901Spiso	if (filter != NULL) {
464166901Spiso		printf("ata-csa.c: we cannot use a filter here\n");
465166901Spiso		return (EINVAL);
466166901Spiso	}
467166918Sariff#endif
46855320Stanimura	scp = device_get_softc(bus);
46955320Stanimura	resp = &scp->res;
47055320Stanimura
47155320Stanimura	/*
47255320Stanimura	 * Look at the function code of the child to determine
47355320Stanimura	 * the appropriate hander for it.
47455320Stanimura	 */
47555320Stanimura	func = device_get_ivars(child);
47655320Stanimura	if (func == NULL || irq != resp->irq)
47755320Stanimura		return (EINVAL);
47855320Stanimura
47955320Stanimura	switch (func->func) {
48055320Stanimura	case SCF_PCM:
48155320Stanimura		scp->pcmintr = intr;
48255320Stanimura		scp->pcmintr_arg = arg;
48355320Stanimura		break;
48455320Stanimura
48555320Stanimura	case SCF_MIDI:
48655320Stanimura		scp->midiintr = intr;
48755320Stanimura		scp->midiintr_arg = arg;
48855320Stanimura		break;
48955320Stanimura
49055320Stanimura	default:
49155320Stanimura		return (EINVAL);
49255320Stanimura	}
49355320Stanimura	*cookiep = scp;
49455320Stanimura	if ((csa_readio(resp, BA0_HISR) & HISR_INTENA) == 0)
49555320Stanimura		csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
49655320Stanimura
49755320Stanimura	return (0);
49855320Stanimura}
49955320Stanimura
50055320Stanimurastatic int
50155320Stanimuracsa_teardown_intr(device_t bus, device_t child,
50255320Stanimura		  struct resource *irq, void *cookie)
50355320Stanimura{
50455320Stanimura	sc_p scp;
50555320Stanimura	csa_res *resp;
50655320Stanimura	struct sndcard_func *func;
50755320Stanimura
50855320Stanimura	scp = device_get_softc(bus);
50955320Stanimura	resp = &scp->res;
51055320Stanimura
51155320Stanimura	/*
51255320Stanimura	 * Look at the function code of the child to determine
51355320Stanimura	 * the appropriate hander for it.
51455320Stanimura	 */
51555320Stanimura	func = device_get_ivars(child);
51655320Stanimura	if (func == NULL || irq != resp->irq || cookie != scp)
51755320Stanimura		return (EINVAL);
51855320Stanimura
51955320Stanimura	switch (func->func) {
52055320Stanimura	case SCF_PCM:
52155320Stanimura		scp->pcmintr = NULL;
52255320Stanimura		scp->pcmintr_arg = NULL;
52355320Stanimura		break;
52455320Stanimura
52555320Stanimura	case SCF_MIDI:
52655320Stanimura		scp->midiintr = NULL;
52755320Stanimura		scp->midiintr_arg = NULL;
52855320Stanimura		break;
52955320Stanimura
53055320Stanimura	default:
53155320Stanimura		return (EINVAL);
53255320Stanimura	}
53355320Stanimura
53455320Stanimura	return (0);
53555320Stanimura}
53655320Stanimura
53755320Stanimura/* The interrupt handler */
53855320Stanimurastatic void
53955320Stanimuracsa_intr(void *arg)
54055320Stanimura{
54155320Stanimura	sc_p scp = arg;
54255320Stanimura	csa_res *resp;
54355320Stanimura	u_int32_t hisr;
54455320Stanimura
54555320Stanimura	resp = &scp->res;
54655320Stanimura
54755320Stanimura	/* Is this interrupt for us? */
54855320Stanimura	hisr = csa_readio(resp, BA0_HISR);
54977504Scg	if ((hisr & 0x7fffffff) == 0) {
55055320Stanimura		/* Throw an eoi. */
55155320Stanimura		csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
55255320Stanimura		return;
55355320Stanimura	}
55455320Stanimura
55555320Stanimura	/*
55655320Stanimura	 * Pass the value of HISR via struct csa_bridgeinfo.
55755320Stanimura	 * The children get access through their ivars.
55855320Stanimura	 */
55955320Stanimura	scp->binfo.hisr = hisr;
56055320Stanimura
56155320Stanimura	/* Invoke the handlers of the children. */
56277504Scg	if ((hisr & (HISR_VC0 | HISR_VC1)) != 0 && scp->pcmintr != NULL) {
56355320Stanimura		scp->pcmintr(scp->pcmintr_arg);
56477504Scg		hisr &= ~(HISR_VC0 | HISR_VC1);
56577504Scg	}
56677504Scg	if ((hisr & HISR_MIDI) != 0 && scp->midiintr != NULL) {
56755320Stanimura		scp->midiintr(scp->midiintr_arg);
56877504Scg		hisr &= ~HISR_MIDI;
56977504Scg	}
57055320Stanimura
57155320Stanimura	/* Throw an eoi. */
57255320Stanimura	csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
57355320Stanimura}
57455320Stanimura
57555320Stanimurastatic int
57653553Stanimuracsa_initialize(sc_p scp)
57753553Stanimura{
57853553Stanimura	int i;
57953553Stanimura	u_int32_t acsts, acisv;
58053553Stanimura	csa_res *resp;
58153553Stanimura
58253553Stanimura	resp = &scp->res;
58353553Stanimura
58453553Stanimura	/*
58553553Stanimura	 * First, blast the clock control register to zero so that the PLL starts
58653553Stanimura	 * out in a known state, and blast the master serial port control register
58753553Stanimura	 * to zero so that the serial ports also start out in a known state.
58853553Stanimura	 */
58953553Stanimura	csa_writeio(resp, BA0_CLKCR1, 0);
59053553Stanimura	csa_writeio(resp, BA0_SERMC1, 0);
59153553Stanimura
59253553Stanimura	/*
59353553Stanimura	 * If we are in AC97 mode, then we must set the part to a host controlled
59453553Stanimura	 * AC-link.  Otherwise, we won't be able to bring up the link.
59553553Stanimura	 */
59653553Stanimura#if 1
59753553Stanimura	csa_writeio(resp, BA0_SERACC, SERACC_HSP | SERACC_CODEC_TYPE_1_03); /* 1.03 codec */
59853553Stanimura#else
59953553Stanimura	csa_writeio(resp, BA0_SERACC, SERACC_HSP | SERACC_CODEC_TYPE_2_0); /* 2.0 codec */
60053553Stanimura#endif /* 1 */
60153553Stanimura
60253553Stanimura	/*
60353553Stanimura	 * Drive the ARST# pin low for a minimum of 1uS (as defined in the AC97
60453553Stanimura	 * spec) and then drive it high.  This is done for non AC97 modes since
60553553Stanimura	 * there might be logic external to the CS461x that uses the ARST# line
60653553Stanimura	 * for a reset.
60753553Stanimura	 */
60877504Scg	csa_writeio(resp, BA0_ACCTL, 1);
60977504Scg	DELAY(50);
61053553Stanimura	csa_writeio(resp, BA0_ACCTL, 0);
61177504Scg	DELAY(50);
61253553Stanimura	csa_writeio(resp, BA0_ACCTL, ACCTL_RSTN);
61353553Stanimura
61453553Stanimura	/*
61553553Stanimura	 * The first thing we do here is to enable sync generation.  As soon
61653553Stanimura	 * as we start receiving bit clock, we'll start producing the SYNC
61753553Stanimura	 * signal.
61853553Stanimura	 */
61953553Stanimura	csa_writeio(resp, BA0_ACCTL, ACCTL_ESYN | ACCTL_RSTN);
62053553Stanimura
62153553Stanimura	/*
62253553Stanimura	 * Now wait for a short while to allow the AC97 part to start
62353553Stanimura	 * generating bit clock (so we don't try to start the PLL without an
62453553Stanimura	 * input clock).
62553553Stanimura	 */
62653553Stanimura	DELAY(50000);
62753553Stanimura
62853553Stanimura	/*
62953553Stanimura	 * Set the serial port timing configuration, so that
63053553Stanimura	 * the clock control circuit gets its clock from the correct place.
63153553Stanimura	 */
63253553Stanimura	csa_writeio(resp, BA0_SERMC1, SERMC1_PTC_AC97);
63377504Scg	DELAY(700000);
63453553Stanimura
63553553Stanimura	/*
63653553Stanimura	 * Write the selected clock control setup to the hardware.  Do not turn on
63753553Stanimura	 * SWCE yet (if requested), so that the devices clocked by the output of
63853553Stanimura	 * PLL are not clocked until the PLL is stable.
63953553Stanimura	 */
64053553Stanimura	csa_writeio(resp, BA0_PLLCC, PLLCC_LPF_1050_2780_KHZ | PLLCC_CDR_73_104_MHZ);
64153553Stanimura	csa_writeio(resp, BA0_PLLM, 0x3a);
64253553Stanimura	csa_writeio(resp, BA0_CLKCR2, CLKCR2_PDIVS_8);
64353553Stanimura
64453553Stanimura	/*
64553553Stanimura	 * Power up the PLL.
64653553Stanimura	 */
64753553Stanimura	csa_writeio(resp, BA0_CLKCR1, CLKCR1_PLLP);
64853553Stanimura
64953553Stanimura	/*
65053553Stanimura	 * Wait until the PLL has stabilized.
65153553Stanimura	 */
65277504Scg	DELAY(5000);
65353553Stanimura
65453553Stanimura	/*
65553553Stanimura	 * Turn on clocking of the core so that we can setup the serial ports.
65653553Stanimura	 */
65753553Stanimura	csa_writeio(resp, BA0_CLKCR1, csa_readio(resp, BA0_CLKCR1) | CLKCR1_SWCE);
65853553Stanimura
65953553Stanimura	/*
66053553Stanimura	 * Fill the serial port FIFOs with silence.
66153553Stanimura	 */
66253553Stanimura	csa_clearserialfifos(resp);
66353553Stanimura
66453553Stanimura	/*
66553553Stanimura	 * Set the serial port FIFO pointer to the first sample in the FIFO.
66653553Stanimura	 */
667153084Sru#ifdef notdef
66853553Stanimura	csa_writeio(resp, BA0_SERBSP, 0);
66953553Stanimura#endif /* notdef */
67053553Stanimura
67153553Stanimura	/*
67253553Stanimura	 *  Write the serial port configuration to the part.  The master
67353553Stanimura	 *  enable bit is not set until all other values have been written.
67453553Stanimura	 */
67553553Stanimura	csa_writeio(resp, BA0_SERC1, SERC1_SO1F_AC97 | SERC1_SO1EN);
67653553Stanimura	csa_writeio(resp, BA0_SERC2, SERC2_SI1F_AC97 | SERC1_SO1EN);
67753553Stanimura	csa_writeio(resp, BA0_SERMC1, SERMC1_PTC_AC97 | SERMC1_MSPE);
67853553Stanimura
67953553Stanimura	/*
68053553Stanimura	 * Wait for the codec ready signal from the AC97 codec.
68153553Stanimura	 */
68253553Stanimura	acsts = 0;
68353553Stanimura	for (i = 0 ; i < 1000 ; i++) {
68453553Stanimura		/*
68553553Stanimura		 * First, lets wait a short while to let things settle out a bit,
68653553Stanimura		 * and to prevent retrying the read too quickly.
68753553Stanimura		 */
68855288Stanimura		DELAY(125);
68953553Stanimura
69053553Stanimura		/*
69153553Stanimura		 * Read the AC97 status register to see if we've seen a CODEC READY
69253553Stanimura		 * signal from the AC97 codec.
69353553Stanimura		 */
69453553Stanimura		acsts = csa_readio(resp, BA0_ACSTS);
69553553Stanimura		if ((acsts & ACSTS_CRDY) != 0)
69653553Stanimura			break;
69753553Stanimura	}
69853553Stanimura
69953553Stanimura	/*
70053553Stanimura	 * Make sure we sampled CODEC READY.
70153553Stanimura	 */
70253553Stanimura	if ((acsts & ACSTS_CRDY) == 0)
70353553Stanimura		return (ENXIO);
70453553Stanimura
70553553Stanimura	/*
70653553Stanimura	 * Assert the vaid frame signal so that we can start sending commands
70753553Stanimura	 * to the AC97 codec.
70853553Stanimura	 */
70953553Stanimura	csa_writeio(resp, BA0_ACCTL, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
71053553Stanimura
71153553Stanimura	/*
71253553Stanimura	 * Wait until we've sampled input slots 3 and 4 as valid, meaning that
71353553Stanimura	 * the codec is pumping ADC data across the AC-link.
71453553Stanimura	 */
71553553Stanimura	acisv = 0;
71653553Stanimura	for (i = 0 ; i < 1000 ; i++) {
71753553Stanimura		/*
71853553Stanimura		 * First, lets wait a short while to let things settle out a bit,
71953553Stanimura		 * and to prevent retrying the read too quickly.
72053553Stanimura		 */
721153084Sru#ifdef notdef
72253553Stanimura		DELAY(10000000L); /* clw */
72353553Stanimura#else
72455288Stanimura		DELAY(1000);
72553553Stanimura#endif /* notdef */
72653553Stanimura		/*
72753553Stanimura		 * Read the input slot valid register and see if input slots 3 and
72853553Stanimura		 * 4 are valid yet.
72953553Stanimura		 */
73053553Stanimura		acisv = csa_readio(resp, BA0_ACISV);
73153553Stanimura		if ((acisv & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4))
73253553Stanimura			break;
73353553Stanimura	}
73453553Stanimura	/*
73553553Stanimura	 * Make sure we sampled valid input slots 3 and 4.  If not, then return
73653553Stanimura	 * an error.
73753553Stanimura	 */
73853553Stanimura	if ((acisv & (ACISV_ISV3 | ACISV_ISV4)) != (ACISV_ISV3 | ACISV_ISV4))
73953553Stanimura		return (ENXIO);
74053553Stanimura
74153553Stanimura	/*
74253553Stanimura	 * Now, assert valid frame and the slot 3 and 4 valid bits.  This will
74353553Stanimura	 * commense the transfer of digital audio data to the AC97 codec.
74453553Stanimura	 */
74553553Stanimura	csa_writeio(resp, BA0_ACOSV, ACOSV_SLV3 | ACOSV_SLV4);
74653553Stanimura
74753553Stanimura	/*
74853553Stanimura	 * Power down the DAC and ADC.  We will power them up (if) when we need
74953553Stanimura	 * them.
75053553Stanimura	 */
751153084Sru#ifdef notdef
75253553Stanimura	csa_writeio(resp, BA0_AC97_POWERDOWN, 0x300);
75353553Stanimura#endif /* notdef */
75453553Stanimura
75553553Stanimura	/*
75661347Scg	 * Turn off the Processor by turning off the software clock enable flag in
75753553Stanimura	 * the clock control register.
75853553Stanimura	 */
759153084Sru#ifdef notdef
76053553Stanimura	clkcr1 = csa_readio(resp, BA0_CLKCR1) & ~CLKCR1_SWCE;
76153553Stanimura	csa_writeio(resp, BA0_CLKCR1, clkcr1);
76253553Stanimura#endif /* notdef */
76353553Stanimura
76453553Stanimura	/*
76553553Stanimura	 * Enable interrupts on the part.
76653553Stanimura	 */
76777504Scg#if 0
76853553Stanimura	csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
76953553Stanimura#endif /* notdef */
77053553Stanimura
77153553Stanimura	return (0);
77253553Stanimura}
77353553Stanimura
77455320Stanimuravoid
77553553Stanimuracsa_clearserialfifos(csa_res *resp)
77653553Stanimura{
77753553Stanimura	int i, j, pwr;
77853553Stanimura	u_int8_t clkcr1, serbst;
77953553Stanimura
78053553Stanimura	/*
78153553Stanimura	 * See if the devices are powered down.  If so, we must power them up first
78253553Stanimura	 * or they will not respond.
78353553Stanimura	 */
78453553Stanimura	pwr = 1;
78553553Stanimura	clkcr1 = csa_readio(resp, BA0_CLKCR1);
78653553Stanimura	if ((clkcr1 & CLKCR1_SWCE) == 0) {
78753553Stanimura		csa_writeio(resp, BA0_CLKCR1, clkcr1 | CLKCR1_SWCE);
78853553Stanimura		pwr = 0;
78953553Stanimura	}
79053553Stanimura
79153553Stanimura	/*
79253553Stanimura	 * We want to clear out the serial port FIFOs so we don't end up playing
79353553Stanimura	 * whatever random garbage happens to be in them.  We fill the sample FIFOs
79453553Stanimura	 * with zero (silence).
79553553Stanimura	 */
79653553Stanimura	csa_writeio(resp, BA0_SERBWP, 0);
79753553Stanimura
79853553Stanimura	/* Fill all 256 sample FIFO locations. */
79953553Stanimura	serbst = 0;
80053553Stanimura	for (i = 0 ; i < 256 ; i++) {
80153553Stanimura		/* Make sure the previous FIFO write operation has completed. */
80253553Stanimura		for (j = 0 ; j < 5 ; j++) {
80355288Stanimura			DELAY(100);
80453553Stanimura			serbst = csa_readio(resp, BA0_SERBST);
80553553Stanimura			if ((serbst & SERBST_WBSY) == 0)
80653553Stanimura				break;
80753553Stanimura		}
80853553Stanimura		if ((serbst & SERBST_WBSY) != 0) {
80953553Stanimura			if (!pwr)
81053553Stanimura				csa_writeio(resp, BA0_CLKCR1, clkcr1);
81153553Stanimura		}
81253553Stanimura		/* Write the serial port FIFO index. */
81353553Stanimura		csa_writeio(resp, BA0_SERBAD, i);
81453553Stanimura		/* Tell the serial port to load the new value into the FIFO location. */
81553553Stanimura		csa_writeio(resp, BA0_SERBCM, SERBCM_WRC);
81653553Stanimura	}
81753553Stanimura	/*
81853553Stanimura	 *  Now, if we powered up the devices, then power them back down again.
81953553Stanimura	 *  This is kinda ugly, but should never happen.
82053553Stanimura	 */
82153553Stanimura	if (!pwr)
82253553Stanimura		csa_writeio(resp, BA0_CLKCR1, clkcr1);
82353553Stanimura}
82453553Stanimura
825147626Sglebiusvoid
82653553Stanimuracsa_resetdsp(csa_res *resp)
82753553Stanimura{
82853553Stanimura	int i;
82953553Stanimura
83053553Stanimura	/*
83153553Stanimura	 * Write the reset bit of the SP control register.
83253553Stanimura	 */
83353553Stanimura	csa_writemem(resp, BA1_SPCR, SPCR_RSTSP);
83453553Stanimura
83553553Stanimura	/*
83653553Stanimura	 * Write the control register.
83753553Stanimura	 */
83853553Stanimura	csa_writemem(resp, BA1_SPCR, SPCR_DRQEN);
83953553Stanimura
84053553Stanimura	/*
84153553Stanimura	 * Clear the trap registers.
84253553Stanimura	 */
84353553Stanimura	for (i = 0 ; i < 8 ; i++) {
84453553Stanimura		csa_writemem(resp, BA1_DREG, DREG_REGID_TRAP_SELECT + i);
84553553Stanimura		csa_writemem(resp, BA1_TWPR, 0xffff);
84653553Stanimura	}
84753553Stanimura	csa_writemem(resp, BA1_DREG, 0);
84853553Stanimura
84953553Stanimura	/*
85053553Stanimura	 * Set the frame timer to reflect the number of cycles per frame.
85153553Stanimura	 */
85253553Stanimura	csa_writemem(resp, BA1_FRMT, 0xadf);
85353553Stanimura}
85453553Stanimura
85553553Stanimurastatic int
85653553Stanimuracsa_downloadimage(csa_res *resp)
85753553Stanimura{
858231047Spfg	int ret;
859231047Spfg	u_long ul, offset;
86053553Stanimura
861231047Spfg	for (ul = 0, offset = 0 ; ul < INKY_MEMORY_COUNT ; ul++) {
862231047Spfg	        /*
863231047Spfg	         * DMA this block from host memory to the appropriate
864231047Spfg	         * memory on the CSDevice.
865231047Spfg	         */
866231047Spfg		ret = csa_transferimage(resp,
867231047Spfg		    cs461x_firmware.BA1Array + offset,
868231047Spfg		    cs461x_firmware.MemoryStat[ul].ulDestAddr,
869231047Spfg		    cs461x_firmware.MemoryStat[ul].ulSourceSize);
870231047Spfg		if (ret)
871231047Spfg			return (ret);
872231047Spfg		offset += cs461x_firmware.MemoryStat[ul].ulSourceSize >> 2;
87353553Stanimura	}
874231047Spfg	return (0);
875231047Spfg}
87653553Stanimura
877231047Spfgstatic int
878231047Spfgcsa_transferimage(csa_res *resp, u_int32_t *src, u_long dest, u_long len)
879231047Spfg{
880231047Spfg	u_long ul;
881231047Spfg
882231047Spfg	/*
883231047Spfg	 * We do not allow DMAs from host memory to host memory (although the DMA
884231047Spfg	 * can do it) and we do not allow DMAs which are not a multiple of 4 bytes
885231047Spfg	 * in size (because that DMA can not do that).  Return an error if either
886231047Spfg	 * of these conditions exist.
887231047Spfg	 */
888231047Spfg	if ((len & 0x3) != 0)
889231047Spfg		return (EINVAL);
89053553Stanimura
891231047Spfg	/* Check the destination address that it is a multiple of 4 */
892231047Spfg	if ((dest & 0x3) != 0)
893231047Spfg		return (EINVAL);
894231047Spfg
895231047Spfg	/* Write the buffer out. */
896231047Spfg	for (ul = 0 ; ul < len ; ul += 4)
897231047Spfg		csa_writemem(resp, dest + ul, src[ul >> 2]);
89853553Stanimura	return (0);
89953553Stanimura}
90053553Stanimura
90153553Stanimuraint
90253553Stanimuracsa_readcodec(csa_res *resp, u_long offset, u_int32_t *data)
90353553Stanimura{
90453553Stanimura	int i;
905193640Sariff	u_int32_t acctl, acsts;
90653553Stanimura
90753553Stanimura	/*
90853553Stanimura	 * Make sure that there is not data sitting around from a previous
90953553Stanimura	 * uncompleted access. ACSDA = Status Data Register = 47Ch
91053553Stanimura	 */
911193640Sariff	csa_readio(resp, BA0_ACSDA);
91253553Stanimura
91353553Stanimura	/*
91453553Stanimura	 * Setup the AC97 control registers on the CS461x to send the
91553553Stanimura	 * appropriate command to the AC97 to perform the read.
91653553Stanimura	 * ACCAD = Command Address Register = 46Ch
91753553Stanimura	 * ACCDA = Command Data Register = 470h
91853553Stanimura	 * ACCTL = Control Register = 460h
91953553Stanimura	 * set DCV - will clear when process completed
92053553Stanimura	 * set CRW - Read command
92153553Stanimura	 * set VFRM - valid frame enabled
92253553Stanimura	 * set ESYN - ASYNC generation enabled
92353553Stanimura	 * set RSTN - ARST# inactive, AC97 codec not reset
92453553Stanimura	 */
92553553Stanimura
92653553Stanimura	/*
92753553Stanimura	 * Get the actual AC97 register from the offset
92853553Stanimura	 */
92953553Stanimura	csa_writeio(resp, BA0_ACCAD, offset - BA0_AC97_RESET);
93053553Stanimura	csa_writeio(resp, BA0_ACCDA, 0);
93153553Stanimura	csa_writeio(resp, BA0_ACCTL, ACCTL_DCV | ACCTL_CRW | ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
93253553Stanimura
93353553Stanimura	/*
93453553Stanimura	 * Wait for the read to occur.
93553553Stanimura	 */
93653553Stanimura	acctl = 0;
93753553Stanimura	for (i = 0 ; i < 10 ; i++) {
93853553Stanimura		/*
93953553Stanimura		 * First, we want to wait for a short time.
94053553Stanimura		 */
94153553Stanimura		DELAY(25);
94253553Stanimura
94353553Stanimura		/*
94453553Stanimura		 * Now, check to see if the read has completed.
94553553Stanimura		 * ACCTL = 460h, DCV should be reset by now and 460h = 17h
94653553Stanimura		 */
94753553Stanimura		acctl = csa_readio(resp, BA0_ACCTL);
94853553Stanimura		if ((acctl & ACCTL_DCV) == 0)
94953553Stanimura			break;
95053553Stanimura	}
95153553Stanimura
95253553Stanimura	/*
95353553Stanimura	 * Make sure the read completed.
95453553Stanimura	 */
95553553Stanimura	if ((acctl & ACCTL_DCV) != 0)
95653553Stanimura		return (EAGAIN);
95753553Stanimura
95853553Stanimura	/*
95953553Stanimura	 * Wait for the valid status bit to go active.
96053553Stanimura	 */
96153553Stanimura	acsts = 0;
96253553Stanimura	for (i = 0 ; i < 10 ; i++) {
96353553Stanimura		/*
96453553Stanimura		 * Read the AC97 status register.
96553553Stanimura		 * ACSTS = Status Register = 464h
96653553Stanimura		 */
96753553Stanimura		acsts = csa_readio(resp, BA0_ACSTS);
96853553Stanimura		/*
96953553Stanimura		 * See if we have valid status.
97053553Stanimura		 * VSTS - Valid Status
97153553Stanimura		 */
97253553Stanimura		if ((acsts & ACSTS_VSTS) != 0)
97353553Stanimura			break;
97453553Stanimura		/*
97553553Stanimura		 * Wait for a short while.
97653553Stanimura		 */
97753553Stanimura		 DELAY(25);
97853553Stanimura	}
97953553Stanimura
98053553Stanimura	/*
98153553Stanimura	 * Make sure we got valid status.
98253553Stanimura	 */
98353553Stanimura	if ((acsts & ACSTS_VSTS) == 0)
98453553Stanimura		return (EAGAIN);
98553553Stanimura
98653553Stanimura	/*
98753553Stanimura	 * Read the data returned from the AC97 register.
98862483Scg	 * ACSDA = Status Data Register = 474h
98953553Stanimura	 */
99062483Scg	*data = csa_readio(resp, BA0_ACSDA);
99153553Stanimura
99253553Stanimura	return (0);
99353553Stanimura}
99453553Stanimura
99553553Stanimuraint
99653553Stanimuracsa_writecodec(csa_res *resp, u_long offset, u_int32_t data)
99753553Stanimura{
99853553Stanimura	int i;
99953553Stanimura	u_int32_t acctl;
100053553Stanimura
100153553Stanimura	/*
100253553Stanimura	 * Setup the AC97 control registers on the CS461x to send the
100353553Stanimura	 * appropriate command to the AC97 to perform the write.
100453553Stanimura	 * ACCAD = Command Address Register = 46Ch
100553553Stanimura	 * ACCDA = Command Data Register = 470h
100653553Stanimura	 * ACCTL = Control Register = 460h
100753553Stanimura	 * set DCV - will clear when process completed
100853553Stanimura	 * set VFRM - valid frame enabled
100953553Stanimura	 * set ESYN - ASYNC generation enabled
101053553Stanimura	 * set RSTN - ARST# inactive, AC97 codec not reset
101153553Stanimura	 */
101253553Stanimura
101353553Stanimura	/*
101453553Stanimura	 * Get the actual AC97 register from the offset
101553553Stanimura	 */
101653553Stanimura	csa_writeio(resp, BA0_ACCAD, offset - BA0_AC97_RESET);
101753553Stanimura	csa_writeio(resp, BA0_ACCDA, data);
101853553Stanimura	csa_writeio(resp, BA0_ACCTL, ACCTL_DCV | ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
101953553Stanimura
102053553Stanimura	/*
102153553Stanimura	 * Wait for the write to occur.
102253553Stanimura	 */
102353553Stanimura	acctl = 0;
102453553Stanimura	for (i = 0 ; i < 10 ; i++) {
102553553Stanimura		/*
102653553Stanimura		 * First, we want to wait for a short time.
102753553Stanimura		 */
102853553Stanimura		DELAY(25);
102953553Stanimura
103053553Stanimura		/*
103153553Stanimura		 * Now, check to see if the read has completed.
103253553Stanimura		 * ACCTL = 460h, DCV should be reset by now and 460h = 17h
103353553Stanimura		 */
103453553Stanimura		acctl = csa_readio(resp, BA0_ACCTL);
103553553Stanimura		if ((acctl & ACCTL_DCV) == 0)
103653553Stanimura			break;
103753553Stanimura	}
103853553Stanimura
103953553Stanimura	/*
104053553Stanimura	 * Make sure the write completed.
104153553Stanimura	 */
104253553Stanimura	if ((acctl & ACCTL_DCV) != 0)
104353553Stanimura		return (EAGAIN);
104453553Stanimura
104553553Stanimura	return (0);
104653553Stanimura}
104753553Stanimura
104853553Stanimurau_int32_t
104953553Stanimuracsa_readio(csa_res *resp, u_long offset)
105053553Stanimura{
105153553Stanimura	u_int32_t ul;
105253553Stanimura
105353553Stanimura	if (offset < BA0_AC97_RESET)
105453553Stanimura		return bus_space_read_4(rman_get_bustag(resp->io), rman_get_bushandle(resp->io), offset) & 0xffffffff;
105553553Stanimura	else {
105653553Stanimura		if (csa_readcodec(resp, offset, &ul))
105753553Stanimura			ul = 0;
105853553Stanimura		return (ul);
105953553Stanimura	}
106053553Stanimura}
106153553Stanimura
106253553Stanimuravoid
106353553Stanimuracsa_writeio(csa_res *resp, u_long offset, u_int32_t data)
106453553Stanimura{
106553553Stanimura	if (offset < BA0_AC97_RESET)
106653553Stanimura		bus_space_write_4(rman_get_bustag(resp->io), rman_get_bushandle(resp->io), offset, data);
106753553Stanimura	else
106853553Stanimura		csa_writecodec(resp, offset, data);
106953553Stanimura}
107053553Stanimura
107153553Stanimurau_int32_t
107253553Stanimuracsa_readmem(csa_res *resp, u_long offset)
107353553Stanimura{
107477504Scg	return bus_space_read_4(rman_get_bustag(resp->mem), rman_get_bushandle(resp->mem), offset);
107553553Stanimura}
107653553Stanimura
107753553Stanimuravoid
107853553Stanimuracsa_writemem(csa_res *resp, u_long offset, u_int32_t data)
107953553Stanimura{
108053553Stanimura	bus_space_write_4(rman_get_bustag(resp->mem), rman_get_bushandle(resp->mem), offset, data);
108153553Stanimura}
108253553Stanimura
108353553Stanimurastatic device_method_t csa_methods[] = {
108453553Stanimura	/* Device interface */
108553553Stanimura	DEVMETHOD(device_probe,		csa_probe),
108653553Stanimura	DEVMETHOD(device_attach,	csa_attach),
108777504Scg	DEVMETHOD(device_detach,	csa_detach),
108853553Stanimura	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
108953553Stanimura	DEVMETHOD(device_suspend,	bus_generic_suspend),
1090100634Sambrisko	DEVMETHOD(device_resume,	csa_resume),
109153553Stanimura
109253553Stanimura	/* Bus interface */
109353553Stanimura	DEVMETHOD(bus_alloc_resource,	csa_alloc_resource),
109453553Stanimura	DEVMETHOD(bus_release_resource,	csa_release_resource),
109553553Stanimura	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
109653553Stanimura	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
109755320Stanimura	DEVMETHOD(bus_setup_intr,	csa_setup_intr),
109855320Stanimura	DEVMETHOD(bus_teardown_intr,	csa_teardown_intr),
109953553Stanimura
1100229093Shselasky	DEVMETHOD_END
110153553Stanimura};
110253553Stanimura
110353553Stanimurastatic driver_t csa_driver = {
110453553Stanimura	"csa",
110553553Stanimura	csa_methods,
110653553Stanimura	sizeof(struct csa_softc),
110753553Stanimura};
110853553Stanimura
110953553Stanimura/*
111053553Stanimura * csa can be attached to a pci bus.
111153553Stanimura */
111262483ScgDRIVER_MODULE(snd_csa, pci, csa_driver, csa_devclass, 0, 0);
1113132236StanimuraMODULE_DEPEND(snd_csa, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
111462483ScgMODULE_VERSION(snd_csa, 1);
1115