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 53230897Spfg#include <dev/sound/pci/cs461x_dsp.h> 5453553Stanimura 5582180ScgSND_DECLARE_FILE("$FreeBSD: stable/10/sys/dev/sound/pci/csa.c 339297 2018-10-10 22:51:45Z avatar $"); 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); 98230897Spfgstatic 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}, 171339297Savatar {0x153b, 0x1136, "Terratec SiXPack 5.1+", NULL, NULL, NULL, 0}, 17278673Scg {0, 0, "Unknown/invalid SSID (CS4614)", NULL, NULL, NULL, 0}, 17377504Scg}; 17477504Scg 17577504Scgstatic struct csa_card cards_4615[] = { 17678673Scg {0, 0, "Unknown/invalid SSID (CS4615)", NULL, NULL, NULL, 0}, 17777504Scg}; 17877504Scg 17978673Scgstatic struct csa_card nocard = {0, 0, "unknown", NULL, NULL, NULL, 0}; 18077504Scg 18177504Scgstruct card_type { 18277504Scg u_int32_t devid; 18377504Scg char *name; 18477504Scg struct csa_card *cards; 18577504Scg}; 18677504Scg 18777504Scgstatic struct card_type cards[] = { 18877504Scg {CS4610_PCI_ID, "CS4610/CS4611", cards_4610}, 18977504Scg {CS4614_PCI_ID, "CS4280/CS4614/CS4622/CS4624/CS4630", cards_4614}, 19077504Scg {CS4615_PCI_ID, "CS4615", cards_4615}, 19177504Scg {0, NULL, NULL}, 19277504Scg}; 19377504Scg 19477504Scgstatic struct card_type * 19577504Scgcsa_findcard(device_t dev) 19677504Scg{ 19777504Scg int i; 19877504Scg 19977504Scg i = 0; 20077504Scg while (cards[i].devid != 0) { 20177504Scg if (pci_get_devid(dev) == cards[i].devid) 20277504Scg return &cards[i]; 20377504Scg i++; 20477504Scg } 20577504Scg return NULL; 20677504Scg} 20777504Scg 20877504Scgstruct csa_card * 20977504Scgcsa_findsubcard(device_t dev) 21077504Scg{ 21177504Scg int i; 21277504Scg struct card_type *card; 21377504Scg struct csa_card *subcard; 21477504Scg 21577504Scg card = csa_findcard(dev); 21677504Scg if (card == NULL) 21777504Scg return &nocard; 21877504Scg subcard = card->cards; 21977504Scg i = 0; 22077504Scg while (subcard[i].subvendor != 0) { 22177504Scg if (pci_get_subvendor(dev) == subcard[i].subvendor 22277504Scg && pci_get_subdevice(dev) == subcard[i].subdevice) { 22377504Scg return &subcard[i]; 22477504Scg } 22577504Scg i++; 22677504Scg } 22777504Scg return &subcard[i]; 22877504Scg} 22977504Scg 23053553Stanimurastatic int 23177504Scgcsa_probe(device_t dev) 23277504Scg{ 23377504Scg struct card_type *card; 23477504Scg 23577504Scg card = csa_findcard(dev); 23677504Scg if (card) { 23777504Scg device_set_desc(dev, card->name); 238142890Simp return BUS_PROBE_DEFAULT; 23977504Scg } 24077504Scg return ENXIO; 24177504Scg} 24277504Scg 24377504Scgstatic int 24453553Stanimuracsa_attach(device_t dev) 24553553Stanimura{ 24653553Stanimura sc_p scp; 24753553Stanimura csa_res *resp; 24855320Stanimura struct sndcard_func *func; 24978421Stmm int error = ENXIO; 25053553Stanimura 25153553Stanimura scp = device_get_softc(dev); 25253553Stanimura 25353553Stanimura /* Fill in the softc. */ 25453553Stanimura bzero(scp, sizeof(*scp)); 25553553Stanimura scp->dev = dev; 25653553Stanimura 257254263Sscottl pci_enable_busmaster(dev); 25853553Stanimura 25953553Stanimura /* Allocate the resources. */ 26053553Stanimura resp = &scp->res; 26177504Scg scp->card = csa_findsubcard(dev); 26277504Scg scp->binfo.card = scp->card; 26377504Scg printf("csa: card is %s\n", scp->card->name); 264119690Sjhb resp->io_rid = PCIR_BAR(0); 265127135Snjl resp->io = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 266127135Snjl &resp->io_rid, RF_ACTIVE); 26753553Stanimura if (resp->io == NULL) 26853553Stanimura return (ENXIO); 269119690Sjhb resp->mem_rid = PCIR_BAR(1); 270127135Snjl resp->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 271127135Snjl &resp->mem_rid, RF_ACTIVE); 27278421Stmm if (resp->mem == NULL) 27378421Stmm goto err_io; 27453553Stanimura resp->irq_rid = 0; 275127135Snjl resp->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, 276127135Snjl &resp->irq_rid, RF_ACTIVE | RF_SHAREABLE); 27778421Stmm if (resp->irq == NULL) 27878421Stmm goto err_mem; 27953553Stanimura 28055320Stanimura /* Enable interrupt. */ 281128232Sgreen if (snd_setup_intr(dev, resp->irq, 0, csa_intr, scp, &scp->ih)) 28278421Stmm goto err_intr; 28377504Scg#if 0 28455320Stanimura if ((csa_readio(resp, BA0_HISR) & HISR_INTENA) == 0) 28555320Stanimura csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM); 28677504Scg#endif 28755320Stanimura 28853553Stanimura /* Initialize the chip. */ 28978421Stmm if (csa_initialize(scp)) 29078421Stmm goto err_teardown; 29153553Stanimura 29253553Stanimura /* Reset the Processor. */ 29353553Stanimura csa_resetdsp(resp); 29453553Stanimura 29553553Stanimura /* Download the Processor Image to the processor. */ 29678421Stmm if (csa_downloadimage(resp)) 29778421Stmm goto err_teardown; 29853553Stanimura 29955320Stanimura /* Attach the children. */ 30055320Stanimura 30155320Stanimura /* PCM Audio */ 30278564Sgreid func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO); 30378421Stmm if (func == NULL) { 30478421Stmm error = ENOMEM; 30578421Stmm goto err_teardown; 30678421Stmm } 30755320Stanimura func->varinfo = &scp->binfo; 30855320Stanimura func->func = SCF_PCM; 30955320Stanimura scp->pcm = device_add_child(dev, "pcm", -1); 31055320Stanimura device_set_ivars(scp->pcm, func); 31155320Stanimura 31255320Stanimura /* Midi Interface */ 31378564Sgreid func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO); 31478421Stmm if (func == NULL) { 31578421Stmm error = ENOMEM; 31678421Stmm goto err_teardown; 31778421Stmm } 31855320Stanimura func->varinfo = &scp->binfo; 31955320Stanimura func->func = SCF_MIDI; 32055320Stanimura scp->midi = device_add_child(dev, "midi", -1); 32155320Stanimura device_set_ivars(scp->midi, func); 32255320Stanimura 32353553Stanimura bus_generic_attach(dev); 32453553Stanimura 32553553Stanimura return (0); 32678421Stmm 32778421Stmmerr_teardown: 32878421Stmm bus_teardown_intr(dev, resp->irq, scp->ih); 32978421Stmmerr_intr: 33078421Stmm bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq); 33178421Stmmerr_mem: 33278421Stmm bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem); 33378421Stmmerr_io: 33478421Stmm bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io); 33578421Stmm return (error); 33653553Stanimura} 33753553Stanimura 33877504Scgstatic int 33977504Scgcsa_detach(device_t dev) 34077504Scg{ 34182379Scg csa_res *resp; 34277504Scg sc_p scp; 343167667Sariff struct sndcard_func *func; 34482379Scg int err; 34577504Scg 34677504Scg scp = device_get_softc(dev); 34782379Scg resp = &scp->res; 34882379Scg 349167667Sariff if (scp->midi != NULL) { 350167667Sariff func = device_get_ivars(scp->midi); 35182379Scg err = device_delete_child(dev, scp->midi); 352167667Sariff if (err != 0) 353167667Sariff return err; 354167667Sariff if (func != NULL) 355167667Sariff free(func, M_DEVBUF); 356167667Sariff scp->midi = NULL; 357167667Sariff } 35882379Scg 359167667Sariff if (scp->pcm != NULL) { 360167667Sariff func = device_get_ivars(scp->pcm); 36182379Scg err = device_delete_child(dev, scp->pcm); 362167667Sariff if (err != 0) 363167667Sariff return err; 364167667Sariff if (func != NULL) 365167667Sariff free(func, M_DEVBUF); 366167667Sariff scp->pcm = NULL; 367167667Sariff } 36882379Scg 36982379Scg bus_teardown_intr(dev, resp->irq, scp->ih); 37082379Scg bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq); 37182379Scg bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem); 37282379Scg bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io); 37382379Scg 37477504Scg return bus_generic_detach(dev); 37577504Scg} 37677504Scg 377100634Sambriskostatic int 378100634Sambriskocsa_resume(device_t dev) 379100634Sambrisko{ 380147626Sglebius csa_res *resp; 381147626Sglebius sc_p scp; 382147626Sglebius 383147626Sglebius scp = device_get_softc(dev); 384147626Sglebius resp = &scp->res; 385147626Sglebius 386147626Sglebius /* Initialize the chip. */ 387147626Sglebius if (csa_initialize(scp)) 388147626Sglebius return (ENXIO); 389147626Sglebius 390147626Sglebius /* Reset the Processor. */ 391147626Sglebius csa_resetdsp(resp); 392147626Sglebius 393147626Sglebius /* Download the Processor Image to the processor. */ 394147626Sglebius if (csa_downloadimage(resp)) 395147626Sglebius return (ENXIO); 396147626Sglebius 397147626Sglebius return (bus_generic_resume(dev)); 398100634Sambrisko} 399100634Sambrisko 40053553Stanimurastatic struct resource * 40153553Stanimuracsa_alloc_resource(device_t bus, device_t child, int type, int *rid, 40253553Stanimura u_long start, u_long end, u_long count, u_int flags) 40353553Stanimura{ 40453553Stanimura sc_p scp; 40553553Stanimura csa_res *resp; 40653553Stanimura struct resource *res; 40753553Stanimura 40853553Stanimura scp = device_get_softc(bus); 40953553Stanimura resp = &scp->res; 41053553Stanimura switch (type) { 41153553Stanimura case SYS_RES_IRQ: 41253553Stanimura if (*rid != 0) 41353553Stanimura return (NULL); 41453553Stanimura res = resp->irq; 41553553Stanimura break; 41653553Stanimura case SYS_RES_MEMORY: 41753553Stanimura switch (*rid) { 418119690Sjhb case PCIR_BAR(0): 41953553Stanimura res = resp->io; 42053553Stanimura break; 421119690Sjhb case PCIR_BAR(1): 42253553Stanimura res = resp->mem; 42353553Stanimura break; 42453553Stanimura default: 42553553Stanimura return (NULL); 42653553Stanimura } 42753553Stanimura break; 42853553Stanimura default: 42953553Stanimura return (NULL); 43053553Stanimura } 43153553Stanimura 43253553Stanimura return res; 43353553Stanimura} 43453553Stanimura 43553553Stanimurastatic int 43653553Stanimuracsa_release_resource(device_t bus, device_t child, int type, int rid, 43753553Stanimura struct resource *r) 43853553Stanimura{ 43953553Stanimura return (0); 44053553Stanimura} 44153553Stanimura 44255320Stanimura/* 44355320Stanimura * The following three functions deal with interrupt handling. 44455320Stanimura * An interrupt is primarily handled by the bridge driver. 44555320Stanimura * The bridge driver then determines the child devices to pass 44655320Stanimura * the interrupt. Certain information of the device can be read 44755320Stanimura * only once(eg the value of HISR). The bridge driver is responsible 44855320Stanimura * to pass such the information to the children. 44955320Stanimura */ 45055320Stanimura 45153553Stanimurastatic int 45255320Stanimuracsa_setup_intr(device_t bus, device_t child, 45355320Stanimura struct resource *irq, int flags, 454166918Sariff#if __FreeBSD_version >= 700031 455166918Sariff driver_filter_t *filter, 456166918Sariff#endif 457166918Sariff driver_intr_t *intr, void *arg, void **cookiep) 45855320Stanimura{ 45955320Stanimura sc_p scp; 46055320Stanimura csa_res *resp; 46155320Stanimura struct sndcard_func *func; 46255320Stanimura 463166918Sariff#if __FreeBSD_version >= 700031 464166901Spiso if (filter != NULL) { 465166901Spiso printf("ata-csa.c: we cannot use a filter here\n"); 466166901Spiso return (EINVAL); 467166901Spiso } 468166918Sariff#endif 46955320Stanimura scp = device_get_softc(bus); 47055320Stanimura resp = &scp->res; 47155320Stanimura 47255320Stanimura /* 47355320Stanimura * Look at the function code of the child to determine 47455320Stanimura * the appropriate hander for it. 47555320Stanimura */ 47655320Stanimura func = device_get_ivars(child); 47755320Stanimura if (func == NULL || irq != resp->irq) 47855320Stanimura return (EINVAL); 47955320Stanimura 48055320Stanimura switch (func->func) { 48155320Stanimura case SCF_PCM: 48255320Stanimura scp->pcmintr = intr; 48355320Stanimura scp->pcmintr_arg = arg; 48455320Stanimura break; 48555320Stanimura 48655320Stanimura case SCF_MIDI: 48755320Stanimura scp->midiintr = intr; 48855320Stanimura scp->midiintr_arg = arg; 48955320Stanimura break; 49055320Stanimura 49155320Stanimura default: 49255320Stanimura return (EINVAL); 49355320Stanimura } 49455320Stanimura *cookiep = scp; 49555320Stanimura if ((csa_readio(resp, BA0_HISR) & HISR_INTENA) == 0) 49655320Stanimura csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM); 49755320Stanimura 49855320Stanimura return (0); 49955320Stanimura} 50055320Stanimura 50155320Stanimurastatic int 50255320Stanimuracsa_teardown_intr(device_t bus, device_t child, 50355320Stanimura struct resource *irq, void *cookie) 50455320Stanimura{ 50555320Stanimura sc_p scp; 50655320Stanimura csa_res *resp; 50755320Stanimura struct sndcard_func *func; 50855320Stanimura 50955320Stanimura scp = device_get_softc(bus); 51055320Stanimura resp = &scp->res; 51155320Stanimura 51255320Stanimura /* 51355320Stanimura * Look at the function code of the child to determine 51455320Stanimura * the appropriate hander for it. 51555320Stanimura */ 51655320Stanimura func = device_get_ivars(child); 51755320Stanimura if (func == NULL || irq != resp->irq || cookie != scp) 51855320Stanimura return (EINVAL); 51955320Stanimura 52055320Stanimura switch (func->func) { 52155320Stanimura case SCF_PCM: 52255320Stanimura scp->pcmintr = NULL; 52355320Stanimura scp->pcmintr_arg = NULL; 52455320Stanimura break; 52555320Stanimura 52655320Stanimura case SCF_MIDI: 52755320Stanimura scp->midiintr = NULL; 52855320Stanimura scp->midiintr_arg = NULL; 52955320Stanimura break; 53055320Stanimura 53155320Stanimura default: 53255320Stanimura return (EINVAL); 53355320Stanimura } 53455320Stanimura 53555320Stanimura return (0); 53655320Stanimura} 53755320Stanimura 53855320Stanimura/* The interrupt handler */ 53955320Stanimurastatic void 54055320Stanimuracsa_intr(void *arg) 54155320Stanimura{ 54255320Stanimura sc_p scp = arg; 54355320Stanimura csa_res *resp; 54455320Stanimura u_int32_t hisr; 54555320Stanimura 54655320Stanimura resp = &scp->res; 54755320Stanimura 54855320Stanimura /* Is this interrupt for us? */ 54955320Stanimura hisr = csa_readio(resp, BA0_HISR); 55077504Scg if ((hisr & 0x7fffffff) == 0) { 55155320Stanimura /* Throw an eoi. */ 55255320Stanimura csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM); 55355320Stanimura return; 55455320Stanimura } 55555320Stanimura 55655320Stanimura /* 55755320Stanimura * Pass the value of HISR via struct csa_bridgeinfo. 55855320Stanimura * The children get access through their ivars. 55955320Stanimura */ 56055320Stanimura scp->binfo.hisr = hisr; 56155320Stanimura 56255320Stanimura /* Invoke the handlers of the children. */ 56377504Scg if ((hisr & (HISR_VC0 | HISR_VC1)) != 0 && scp->pcmintr != NULL) { 56455320Stanimura scp->pcmintr(scp->pcmintr_arg); 56577504Scg hisr &= ~(HISR_VC0 | HISR_VC1); 56677504Scg } 56777504Scg if ((hisr & HISR_MIDI) != 0 && scp->midiintr != NULL) { 56855320Stanimura scp->midiintr(scp->midiintr_arg); 56977504Scg hisr &= ~HISR_MIDI; 57077504Scg } 57155320Stanimura 57255320Stanimura /* Throw an eoi. */ 57355320Stanimura csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM); 57455320Stanimura} 57555320Stanimura 57655320Stanimurastatic int 57753553Stanimuracsa_initialize(sc_p scp) 57853553Stanimura{ 57953553Stanimura int i; 58053553Stanimura u_int32_t acsts, acisv; 58153553Stanimura csa_res *resp; 58253553Stanimura 58353553Stanimura resp = &scp->res; 58453553Stanimura 58553553Stanimura /* 58653553Stanimura * First, blast the clock control register to zero so that the PLL starts 58753553Stanimura * out in a known state, and blast the master serial port control register 58853553Stanimura * to zero so that the serial ports also start out in a known state. 58953553Stanimura */ 59053553Stanimura csa_writeio(resp, BA0_CLKCR1, 0); 59153553Stanimura csa_writeio(resp, BA0_SERMC1, 0); 59253553Stanimura 59353553Stanimura /* 59453553Stanimura * If we are in AC97 mode, then we must set the part to a host controlled 59553553Stanimura * AC-link. Otherwise, we won't be able to bring up the link. 59653553Stanimura */ 59753553Stanimura#if 1 59853553Stanimura csa_writeio(resp, BA0_SERACC, SERACC_HSP | SERACC_CODEC_TYPE_1_03); /* 1.03 codec */ 59953553Stanimura#else 60053553Stanimura csa_writeio(resp, BA0_SERACC, SERACC_HSP | SERACC_CODEC_TYPE_2_0); /* 2.0 codec */ 60153553Stanimura#endif /* 1 */ 60253553Stanimura 60353553Stanimura /* 60453553Stanimura * Drive the ARST# pin low for a minimum of 1uS (as defined in the AC97 60553553Stanimura * spec) and then drive it high. This is done for non AC97 modes since 60653553Stanimura * there might be logic external to the CS461x that uses the ARST# line 60753553Stanimura * for a reset. 60853553Stanimura */ 60977504Scg csa_writeio(resp, BA0_ACCTL, 1); 61077504Scg DELAY(50); 61153553Stanimura csa_writeio(resp, BA0_ACCTL, 0); 61277504Scg DELAY(50); 61353553Stanimura csa_writeio(resp, BA0_ACCTL, ACCTL_RSTN); 61453553Stanimura 61553553Stanimura /* 61653553Stanimura * The first thing we do here is to enable sync generation. As soon 61753553Stanimura * as we start receiving bit clock, we'll start producing the SYNC 61853553Stanimura * signal. 61953553Stanimura */ 62053553Stanimura csa_writeio(resp, BA0_ACCTL, ACCTL_ESYN | ACCTL_RSTN); 62153553Stanimura 62253553Stanimura /* 62353553Stanimura * Now wait for a short while to allow the AC97 part to start 62453553Stanimura * generating bit clock (so we don't try to start the PLL without an 62553553Stanimura * input clock). 62653553Stanimura */ 62753553Stanimura DELAY(50000); 62853553Stanimura 62953553Stanimura /* 63053553Stanimura * Set the serial port timing configuration, so that 63153553Stanimura * the clock control circuit gets its clock from the correct place. 63253553Stanimura */ 63353553Stanimura csa_writeio(resp, BA0_SERMC1, SERMC1_PTC_AC97); 63477504Scg DELAY(700000); 63553553Stanimura 63653553Stanimura /* 63753553Stanimura * Write the selected clock control setup to the hardware. Do not turn on 63853553Stanimura * SWCE yet (if requested), so that the devices clocked by the output of 63953553Stanimura * PLL are not clocked until the PLL is stable. 64053553Stanimura */ 64153553Stanimura csa_writeio(resp, BA0_PLLCC, PLLCC_LPF_1050_2780_KHZ | PLLCC_CDR_73_104_MHZ); 64253553Stanimura csa_writeio(resp, BA0_PLLM, 0x3a); 64353553Stanimura csa_writeio(resp, BA0_CLKCR2, CLKCR2_PDIVS_8); 64453553Stanimura 64553553Stanimura /* 64653553Stanimura * Power up the PLL. 64753553Stanimura */ 64853553Stanimura csa_writeio(resp, BA0_CLKCR1, CLKCR1_PLLP); 64953553Stanimura 65053553Stanimura /* 65153553Stanimura * Wait until the PLL has stabilized. 65253553Stanimura */ 65377504Scg DELAY(5000); 65453553Stanimura 65553553Stanimura /* 65653553Stanimura * Turn on clocking of the core so that we can setup the serial ports. 65753553Stanimura */ 65853553Stanimura csa_writeio(resp, BA0_CLKCR1, csa_readio(resp, BA0_CLKCR1) | CLKCR1_SWCE); 65953553Stanimura 66053553Stanimura /* 66153553Stanimura * Fill the serial port FIFOs with silence. 66253553Stanimura */ 66353553Stanimura csa_clearserialfifos(resp); 66453553Stanimura 66553553Stanimura /* 66653553Stanimura * Set the serial port FIFO pointer to the first sample in the FIFO. 66753553Stanimura */ 668153084Sru#ifdef notdef 66953553Stanimura csa_writeio(resp, BA0_SERBSP, 0); 67053553Stanimura#endif /* notdef */ 67153553Stanimura 67253553Stanimura /* 67353553Stanimura * Write the serial port configuration to the part. The master 67453553Stanimura * enable bit is not set until all other values have been written. 67553553Stanimura */ 67653553Stanimura csa_writeio(resp, BA0_SERC1, SERC1_SO1F_AC97 | SERC1_SO1EN); 67753553Stanimura csa_writeio(resp, BA0_SERC2, SERC2_SI1F_AC97 | SERC1_SO1EN); 67853553Stanimura csa_writeio(resp, BA0_SERMC1, SERMC1_PTC_AC97 | SERMC1_MSPE); 67953553Stanimura 68053553Stanimura /* 68153553Stanimura * Wait for the codec ready signal from the AC97 codec. 68253553Stanimura */ 68353553Stanimura acsts = 0; 68453553Stanimura for (i = 0 ; i < 1000 ; i++) { 68553553Stanimura /* 68653553Stanimura * First, lets wait a short while to let things settle out a bit, 68753553Stanimura * and to prevent retrying the read too quickly. 68853553Stanimura */ 68955288Stanimura DELAY(125); 69053553Stanimura 69153553Stanimura /* 69253553Stanimura * Read the AC97 status register to see if we've seen a CODEC READY 69353553Stanimura * signal from the AC97 codec. 69453553Stanimura */ 69553553Stanimura acsts = csa_readio(resp, BA0_ACSTS); 69653553Stanimura if ((acsts & ACSTS_CRDY) != 0) 69753553Stanimura break; 69853553Stanimura } 69953553Stanimura 70053553Stanimura /* 70153553Stanimura * Make sure we sampled CODEC READY. 70253553Stanimura */ 70353553Stanimura if ((acsts & ACSTS_CRDY) == 0) 70453553Stanimura return (ENXIO); 70553553Stanimura 70653553Stanimura /* 70753553Stanimura * Assert the vaid frame signal so that we can start sending commands 70853553Stanimura * to the AC97 codec. 70953553Stanimura */ 71053553Stanimura csa_writeio(resp, BA0_ACCTL, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN); 71153553Stanimura 71253553Stanimura /* 71353553Stanimura * Wait until we've sampled input slots 3 and 4 as valid, meaning that 71453553Stanimura * the codec is pumping ADC data across the AC-link. 71553553Stanimura */ 71653553Stanimura acisv = 0; 717338326Savatar for (i = 0 ; i < 2000 ; i++) { 71853553Stanimura /* 71953553Stanimura * First, lets wait a short while to let things settle out a bit, 72053553Stanimura * and to prevent retrying the read too quickly. 72153553Stanimura */ 722153084Sru#ifdef notdef 72353553Stanimura DELAY(10000000L); /* clw */ 72453553Stanimura#else 72555288Stanimura DELAY(1000); 72653553Stanimura#endif /* notdef */ 72753553Stanimura /* 72853553Stanimura * Read the input slot valid register and see if input slots 3 and 72953553Stanimura * 4 are valid yet. 73053553Stanimura */ 73153553Stanimura acisv = csa_readio(resp, BA0_ACISV); 73253553Stanimura if ((acisv & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4)) 73353553Stanimura break; 73453553Stanimura } 73553553Stanimura /* 73653553Stanimura * Make sure we sampled valid input slots 3 and 4. If not, then return 73753553Stanimura * an error. 73853553Stanimura */ 73953553Stanimura if ((acisv & (ACISV_ISV3 | ACISV_ISV4)) != (ACISV_ISV3 | ACISV_ISV4)) 74053553Stanimura return (ENXIO); 74153553Stanimura 74253553Stanimura /* 74353553Stanimura * Now, assert valid frame and the slot 3 and 4 valid bits. This will 74453553Stanimura * commense the transfer of digital audio data to the AC97 codec. 74553553Stanimura */ 74653553Stanimura csa_writeio(resp, BA0_ACOSV, ACOSV_SLV3 | ACOSV_SLV4); 74753553Stanimura 74853553Stanimura /* 74953553Stanimura * Power down the DAC and ADC. We will power them up (if) when we need 75053553Stanimura * them. 75153553Stanimura */ 752153084Sru#ifdef notdef 75353553Stanimura csa_writeio(resp, BA0_AC97_POWERDOWN, 0x300); 75453553Stanimura#endif /* notdef */ 75553553Stanimura 75653553Stanimura /* 75761347Scg * Turn off the Processor by turning off the software clock enable flag in 75853553Stanimura * the clock control register. 75953553Stanimura */ 760153084Sru#ifdef notdef 76153553Stanimura clkcr1 = csa_readio(resp, BA0_CLKCR1) & ~CLKCR1_SWCE; 76253553Stanimura csa_writeio(resp, BA0_CLKCR1, clkcr1); 76353553Stanimura#endif /* notdef */ 76453553Stanimura 76553553Stanimura /* 76653553Stanimura * Enable interrupts on the part. 76753553Stanimura */ 76877504Scg#if 0 76953553Stanimura csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM); 77053553Stanimura#endif /* notdef */ 77153553Stanimura 77253553Stanimura return (0); 77353553Stanimura} 77453553Stanimura 77555320Stanimuravoid 77653553Stanimuracsa_clearserialfifos(csa_res *resp) 77753553Stanimura{ 77853553Stanimura int i, j, pwr; 77953553Stanimura u_int8_t clkcr1, serbst; 78053553Stanimura 78153553Stanimura /* 78253553Stanimura * See if the devices are powered down. If so, we must power them up first 78353553Stanimura * or they will not respond. 78453553Stanimura */ 78553553Stanimura pwr = 1; 78653553Stanimura clkcr1 = csa_readio(resp, BA0_CLKCR1); 78753553Stanimura if ((clkcr1 & CLKCR1_SWCE) == 0) { 78853553Stanimura csa_writeio(resp, BA0_CLKCR1, clkcr1 | CLKCR1_SWCE); 78953553Stanimura pwr = 0; 79053553Stanimura } 79153553Stanimura 79253553Stanimura /* 79353553Stanimura * We want to clear out the serial port FIFOs so we don't end up playing 79453553Stanimura * whatever random garbage happens to be in them. We fill the sample FIFOs 79553553Stanimura * with zero (silence). 79653553Stanimura */ 79753553Stanimura csa_writeio(resp, BA0_SERBWP, 0); 79853553Stanimura 79953553Stanimura /* Fill all 256 sample FIFO locations. */ 80053553Stanimura serbst = 0; 80153553Stanimura for (i = 0 ; i < 256 ; i++) { 80253553Stanimura /* Make sure the previous FIFO write operation has completed. */ 80353553Stanimura for (j = 0 ; j < 5 ; j++) { 80455288Stanimura DELAY(100); 80553553Stanimura serbst = csa_readio(resp, BA0_SERBST); 80653553Stanimura if ((serbst & SERBST_WBSY) == 0) 80753553Stanimura break; 80853553Stanimura } 80953553Stanimura if ((serbst & SERBST_WBSY) != 0) { 81053553Stanimura if (!pwr) 81153553Stanimura csa_writeio(resp, BA0_CLKCR1, clkcr1); 81253553Stanimura } 81353553Stanimura /* Write the serial port FIFO index. */ 81453553Stanimura csa_writeio(resp, BA0_SERBAD, i); 81553553Stanimura /* Tell the serial port to load the new value into the FIFO location. */ 81653553Stanimura csa_writeio(resp, BA0_SERBCM, SERBCM_WRC); 81753553Stanimura } 81853553Stanimura /* 81953553Stanimura * Now, if we powered up the devices, then power them back down again. 82053553Stanimura * This is kinda ugly, but should never happen. 82153553Stanimura */ 82253553Stanimura if (!pwr) 82353553Stanimura csa_writeio(resp, BA0_CLKCR1, clkcr1); 82453553Stanimura} 82553553Stanimura 826147626Sglebiusvoid 82753553Stanimuracsa_resetdsp(csa_res *resp) 82853553Stanimura{ 82953553Stanimura int i; 83053553Stanimura 83153553Stanimura /* 83253553Stanimura * Write the reset bit of the SP control register. 83353553Stanimura */ 83453553Stanimura csa_writemem(resp, BA1_SPCR, SPCR_RSTSP); 83553553Stanimura 83653553Stanimura /* 83753553Stanimura * Write the control register. 83853553Stanimura */ 83953553Stanimura csa_writemem(resp, BA1_SPCR, SPCR_DRQEN); 84053553Stanimura 84153553Stanimura /* 84253553Stanimura * Clear the trap registers. 84353553Stanimura */ 84453553Stanimura for (i = 0 ; i < 8 ; i++) { 84553553Stanimura csa_writemem(resp, BA1_DREG, DREG_REGID_TRAP_SELECT + i); 84653553Stanimura csa_writemem(resp, BA1_TWPR, 0xffff); 84753553Stanimura } 84853553Stanimura csa_writemem(resp, BA1_DREG, 0); 84953553Stanimura 85053553Stanimura /* 85153553Stanimura * Set the frame timer to reflect the number of cycles per frame. 85253553Stanimura */ 85353553Stanimura csa_writemem(resp, BA1_FRMT, 0xadf); 85453553Stanimura} 85553553Stanimura 85653553Stanimurastatic int 85753553Stanimuracsa_downloadimage(csa_res *resp) 85853553Stanimura{ 859230897Spfg int ret; 860230897Spfg u_long ul, offset; 86153553Stanimura 862230897Spfg for (ul = 0, offset = 0 ; ul < INKY_MEMORY_COUNT ; ul++) { 863230897Spfg /* 864230897Spfg * DMA this block from host memory to the appropriate 865230897Spfg * memory on the CSDevice. 866230897Spfg */ 867230897Spfg ret = csa_transferimage(resp, 868230897Spfg cs461x_firmware.BA1Array + offset, 869230897Spfg cs461x_firmware.MemoryStat[ul].ulDestAddr, 870230897Spfg cs461x_firmware.MemoryStat[ul].ulSourceSize); 871230897Spfg if (ret) 872230897Spfg return (ret); 873230897Spfg offset += cs461x_firmware.MemoryStat[ul].ulSourceSize >> 2; 87453553Stanimura } 875230897Spfg return (0); 876230897Spfg} 87753553Stanimura 878230897Spfgstatic int 879230897Spfgcsa_transferimage(csa_res *resp, u_int32_t *src, u_long dest, u_long len) 880230897Spfg{ 881230897Spfg u_long ul; 882230897Spfg 883230897Spfg /* 884230897Spfg * We do not allow DMAs from host memory to host memory (although the DMA 885230897Spfg * can do it) and we do not allow DMAs which are not a multiple of 4 bytes 886230897Spfg * in size (because that DMA can not do that). Return an error if either 887230897Spfg * of these conditions exist. 888230897Spfg */ 889230897Spfg if ((len & 0x3) != 0) 890230897Spfg return (EINVAL); 89153553Stanimura 892230897Spfg /* Check the destination address that it is a multiple of 4 */ 893230897Spfg if ((dest & 0x3) != 0) 894230897Spfg return (EINVAL); 895230897Spfg 896230897Spfg /* Write the buffer out. */ 897230897Spfg for (ul = 0 ; ul < len ; ul += 4) 898230897Spfg csa_writemem(resp, dest + ul, src[ul >> 2]); 89953553Stanimura return (0); 90053553Stanimura} 90153553Stanimura 90253553Stanimuraint 90353553Stanimuracsa_readcodec(csa_res *resp, u_long offset, u_int32_t *data) 90453553Stanimura{ 90553553Stanimura int i; 906193640Sariff u_int32_t acctl, acsts; 90753553Stanimura 90853553Stanimura /* 90953553Stanimura * Make sure that there is not data sitting around from a previous 91053553Stanimura * uncompleted access. ACSDA = Status Data Register = 47Ch 91153553Stanimura */ 912193640Sariff csa_readio(resp, BA0_ACSDA); 91353553Stanimura 91453553Stanimura /* 91553553Stanimura * Setup the AC97 control registers on the CS461x to send the 91653553Stanimura * appropriate command to the AC97 to perform the read. 91753553Stanimura * ACCAD = Command Address Register = 46Ch 91853553Stanimura * ACCDA = Command Data Register = 470h 91953553Stanimura * ACCTL = Control Register = 460h 92053553Stanimura * set DCV - will clear when process completed 92153553Stanimura * set CRW - Read command 92253553Stanimura * set VFRM - valid frame enabled 92353553Stanimura * set ESYN - ASYNC generation enabled 92453553Stanimura * set RSTN - ARST# inactive, AC97 codec not reset 92553553Stanimura */ 92653553Stanimura 92753553Stanimura /* 92853553Stanimura * Get the actual AC97 register from the offset 92953553Stanimura */ 93053553Stanimura csa_writeio(resp, BA0_ACCAD, offset - BA0_AC97_RESET); 93153553Stanimura csa_writeio(resp, BA0_ACCDA, 0); 93253553Stanimura csa_writeio(resp, BA0_ACCTL, ACCTL_DCV | ACCTL_CRW | ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN); 93353553Stanimura 93453553Stanimura /* 93553553Stanimura * Wait for the read to occur. 93653553Stanimura */ 93753553Stanimura acctl = 0; 93853553Stanimura for (i = 0 ; i < 10 ; i++) { 93953553Stanimura /* 94053553Stanimura * First, we want to wait for a short time. 94153553Stanimura */ 94253553Stanimura DELAY(25); 94353553Stanimura 94453553Stanimura /* 94553553Stanimura * Now, check to see if the read has completed. 94653553Stanimura * ACCTL = 460h, DCV should be reset by now and 460h = 17h 94753553Stanimura */ 94853553Stanimura acctl = csa_readio(resp, BA0_ACCTL); 94953553Stanimura if ((acctl & ACCTL_DCV) == 0) 95053553Stanimura break; 95153553Stanimura } 95253553Stanimura 95353553Stanimura /* 95453553Stanimura * Make sure the read completed. 95553553Stanimura */ 95653553Stanimura if ((acctl & ACCTL_DCV) != 0) 95753553Stanimura return (EAGAIN); 95853553Stanimura 95953553Stanimura /* 96053553Stanimura * Wait for the valid status bit to go active. 96153553Stanimura */ 96253553Stanimura acsts = 0; 96353553Stanimura for (i = 0 ; i < 10 ; i++) { 96453553Stanimura /* 96553553Stanimura * Read the AC97 status register. 96653553Stanimura * ACSTS = Status Register = 464h 96753553Stanimura */ 96853553Stanimura acsts = csa_readio(resp, BA0_ACSTS); 96953553Stanimura /* 97053553Stanimura * See if we have valid status. 97153553Stanimura * VSTS - Valid Status 97253553Stanimura */ 97353553Stanimura if ((acsts & ACSTS_VSTS) != 0) 97453553Stanimura break; 97553553Stanimura /* 97653553Stanimura * Wait for a short while. 97753553Stanimura */ 97853553Stanimura DELAY(25); 97953553Stanimura } 98053553Stanimura 98153553Stanimura /* 98253553Stanimura * Make sure we got valid status. 98353553Stanimura */ 98453553Stanimura if ((acsts & ACSTS_VSTS) == 0) 98553553Stanimura return (EAGAIN); 98653553Stanimura 98753553Stanimura /* 98853553Stanimura * Read the data returned from the AC97 register. 98962483Scg * ACSDA = Status Data Register = 474h 99053553Stanimura */ 99162483Scg *data = csa_readio(resp, BA0_ACSDA); 99253553Stanimura 99353553Stanimura return (0); 99453553Stanimura} 99553553Stanimura 99653553Stanimuraint 99753553Stanimuracsa_writecodec(csa_res *resp, u_long offset, u_int32_t data) 99853553Stanimura{ 99953553Stanimura int i; 100053553Stanimura u_int32_t acctl; 100153553Stanimura 100253553Stanimura /* 100353553Stanimura * Setup the AC97 control registers on the CS461x to send the 100453553Stanimura * appropriate command to the AC97 to perform the write. 100553553Stanimura * ACCAD = Command Address Register = 46Ch 100653553Stanimura * ACCDA = Command Data Register = 470h 100753553Stanimura * ACCTL = Control Register = 460h 100853553Stanimura * set DCV - will clear when process completed 100953553Stanimura * set VFRM - valid frame enabled 101053553Stanimura * set ESYN - ASYNC generation enabled 101153553Stanimura * set RSTN - ARST# inactive, AC97 codec not reset 101253553Stanimura */ 101353553Stanimura 101453553Stanimura /* 101553553Stanimura * Get the actual AC97 register from the offset 101653553Stanimura */ 101753553Stanimura csa_writeio(resp, BA0_ACCAD, offset - BA0_AC97_RESET); 101853553Stanimura csa_writeio(resp, BA0_ACCDA, data); 101953553Stanimura csa_writeio(resp, BA0_ACCTL, ACCTL_DCV | ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN); 102053553Stanimura 102153553Stanimura /* 102253553Stanimura * Wait for the write to occur. 102353553Stanimura */ 102453553Stanimura acctl = 0; 102553553Stanimura for (i = 0 ; i < 10 ; i++) { 102653553Stanimura /* 102753553Stanimura * First, we want to wait for a short time. 102853553Stanimura */ 102953553Stanimura DELAY(25); 103053553Stanimura 103153553Stanimura /* 103253553Stanimura * Now, check to see if the read has completed. 103353553Stanimura * ACCTL = 460h, DCV should be reset by now and 460h = 17h 103453553Stanimura */ 103553553Stanimura acctl = csa_readio(resp, BA0_ACCTL); 103653553Stanimura if ((acctl & ACCTL_DCV) == 0) 103753553Stanimura break; 103853553Stanimura } 103953553Stanimura 104053553Stanimura /* 104153553Stanimura * Make sure the write completed. 104253553Stanimura */ 104353553Stanimura if ((acctl & ACCTL_DCV) != 0) 104453553Stanimura return (EAGAIN); 104553553Stanimura 104653553Stanimura return (0); 104753553Stanimura} 104853553Stanimura 104953553Stanimurau_int32_t 105053553Stanimuracsa_readio(csa_res *resp, u_long offset) 105153553Stanimura{ 105253553Stanimura u_int32_t ul; 105353553Stanimura 105453553Stanimura if (offset < BA0_AC97_RESET) 105553553Stanimura return bus_space_read_4(rman_get_bustag(resp->io), rman_get_bushandle(resp->io), offset) & 0xffffffff; 105653553Stanimura else { 105753553Stanimura if (csa_readcodec(resp, offset, &ul)) 105853553Stanimura ul = 0; 105953553Stanimura return (ul); 106053553Stanimura } 106153553Stanimura} 106253553Stanimura 106353553Stanimuravoid 106453553Stanimuracsa_writeio(csa_res *resp, u_long offset, u_int32_t data) 106553553Stanimura{ 106653553Stanimura if (offset < BA0_AC97_RESET) 106753553Stanimura bus_space_write_4(rman_get_bustag(resp->io), rman_get_bushandle(resp->io), offset, data); 106853553Stanimura else 106953553Stanimura csa_writecodec(resp, offset, data); 107053553Stanimura} 107153553Stanimura 107253553Stanimurau_int32_t 107353553Stanimuracsa_readmem(csa_res *resp, u_long offset) 107453553Stanimura{ 107577504Scg return bus_space_read_4(rman_get_bustag(resp->mem), rman_get_bushandle(resp->mem), offset); 107653553Stanimura} 107753553Stanimura 107853553Stanimuravoid 107953553Stanimuracsa_writemem(csa_res *resp, u_long offset, u_int32_t data) 108053553Stanimura{ 108153553Stanimura bus_space_write_4(rman_get_bustag(resp->mem), rman_get_bushandle(resp->mem), offset, data); 108253553Stanimura} 108353553Stanimura 108453553Stanimurastatic device_method_t csa_methods[] = { 108553553Stanimura /* Device interface */ 108653553Stanimura DEVMETHOD(device_probe, csa_probe), 108753553Stanimura DEVMETHOD(device_attach, csa_attach), 108877504Scg DEVMETHOD(device_detach, csa_detach), 108953553Stanimura DEVMETHOD(device_shutdown, bus_generic_shutdown), 109053553Stanimura DEVMETHOD(device_suspend, bus_generic_suspend), 1091100634Sambrisko DEVMETHOD(device_resume, csa_resume), 109253553Stanimura 109353553Stanimura /* Bus interface */ 109453553Stanimura DEVMETHOD(bus_alloc_resource, csa_alloc_resource), 109553553Stanimura DEVMETHOD(bus_release_resource, csa_release_resource), 109653553Stanimura DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 109753553Stanimura DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 109855320Stanimura DEVMETHOD(bus_setup_intr, csa_setup_intr), 109955320Stanimura DEVMETHOD(bus_teardown_intr, csa_teardown_intr), 110053553Stanimura 1101227843Smarius DEVMETHOD_END 110253553Stanimura}; 110353553Stanimura 110453553Stanimurastatic driver_t csa_driver = { 110553553Stanimura "csa", 110653553Stanimura csa_methods, 110753553Stanimura sizeof(struct csa_softc), 110853553Stanimura}; 110953553Stanimura 111053553Stanimura/* 111153553Stanimura * csa can be attached to a pci bus. 111253553Stanimura */ 111362483ScgDRIVER_MODULE(snd_csa, pci, csa_driver, csa_devclass, 0, 0); 1114132236StanimuraMODULE_DEPEND(snd_csa, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 111562483ScgMODULE_VERSION(snd_csa, 1); 1116