via8233.c revision 102011
1/* 2 * Copyright (c) 2002 Orion Hodson <orion@freebsd.org> 3 * Portions of this code derived from via82c686.c: 4 * Copyright (c) 2000 David Jones <dej@ox.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29/* Some Credits: 30 * 31 * Grzybowski Rafal, Russell Davies, Mark Handley, Daniel O'Connor for 32 * comments, machine time, testing patches, and patience. VIA for 33 * providing specs. ALSA for helpful comments and some register poke 34 * ordering. 35 */ 36 37#include <dev/sound/pcm/sound.h> 38#include <dev/sound/pcm/ac97.h> 39 40#include <pci/pcireg.h> 41#include <pci/pcivar.h> 42#include <sys/sysctl.h> 43 44#include <dev/sound/pci/via8233.h> 45 46SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/via8233.c 102011 2002-08-17 16:23:44Z orion $"); 47 48#define VIA8233_PCI_ID 0x30591106 49 50#define SEGS_PER_CHAN 2 /* Segments per channel */ 51#define NCHANS 2 /* Lines-in,out (mic later) */ 52#define NSEGS NCHANS * SEGS_PER_CHAN /* Segments in SGD table */ 53 54#define VIA_DEFAULT_BUFSZ 0x1000 55 56#undef DEB 57#define DEB(x) x 58 59/* we rely on this struct being packed to 64 bits */ 60struct via_dma_op { 61 u_int32_t ptr; 62 u_int32_t flags; 63#define VIA_DMAOP_EOL 0x80000000 64#define VIA_DMAOP_FLAG 0x40000000 65#define VIA_DMAOP_STOP 0x20000000 66#define VIA_DMAOP_COUNT(x) ((x)&0x00FFFFFF) 67}; 68 69struct via_info; 70 71struct via_chinfo { 72 struct via_info *parent; 73 struct pcm_channel *channel; 74 struct snd_dbuf *buffer; 75 struct via_dma_op *sgd_table; 76 int dir, blksz; 77 int rbase; /* base register for channel */ 78}; 79 80struct via_info { 81 bus_space_tag_t st; 82 bus_space_handle_t sh; 83 bus_dma_tag_t parent_dmat; 84 bus_dma_tag_t sgd_dmat; 85 bus_dmamap_t sgd_dmamap; 86 87 struct resource *reg, *irq; 88 int regid, irqid; 89 void *ih; 90 struct ac97_info *codec; 91 92 unsigned int bufsz; 93 94 struct via_chinfo pch, rch; 95 struct via_dma_op *sgd_table; 96 u_int16_t codec_caps; 97}; 98 99static u_int32_t via_fmt[] = { 100 AFMT_U8, 101 AFMT_STEREO | AFMT_U8, 102 AFMT_S16_LE, 103 AFMT_STEREO | AFMT_S16_LE, 104 0 105}; 106 107static struct pcmchan_caps via_vracaps = { 4000, 48000, via_fmt, 0 }; 108static struct pcmchan_caps via_caps = { 48000, 48000, via_fmt, 0 }; 109 110static u_int32_t 111via_rd(struct via_info *via, int regno, int size) 112{ 113 switch (size) { 114 case 1: 115 return bus_space_read_1(via->st, via->sh, regno); 116 case 2: 117 return bus_space_read_2(via->st, via->sh, regno); 118 case 4: 119 return bus_space_read_4(via->st, via->sh, regno); 120 default: 121 return 0xFFFFFFFF; 122 } 123} 124 125static void 126via_wr(struct via_info *via, int regno, u_int32_t data, int size) 127{ 128 129 switch (size) { 130 case 1: 131 bus_space_write_1(via->st, via->sh, regno, data); 132 break; 133 case 2: 134 bus_space_write_2(via->st, via->sh, regno, data); 135 break; 136 case 4: 137 bus_space_write_4(via->st, via->sh, regno, data); 138 break; 139 } 140} 141 142/* -------------------------------------------------------------------- */ 143/* Codec interface */ 144 145static int 146via_waitready_codec(struct via_info *via) 147{ 148 int i; 149 150 /* poll until codec not busy */ 151 for (i = 0; i < 1000; i++) { 152 if ((via_rd(via, VIA_AC97_CONTROL, 4) & VIA_AC97_BUSY) == 0) 153 return 0; 154 DELAY(1); 155 } 156 printf("via: codec busy\n"); 157 return 1; 158} 159 160static int 161via_waitvalid_codec(struct via_info *via) 162{ 163 int i; 164 165 /* poll until codec valid */ 166 for (i = 0; i < 1000; i++) { 167 if (via_rd(via, VIA_AC97_CONTROL, 4) & VIA_AC97_CODEC00_VALID) 168 return 0; 169 DELAY(1); 170 } 171 printf("via: codec invalid\n"); 172 return 1; 173} 174 175static int 176via_write_codec(kobj_t obj, void *addr, int reg, u_int32_t val) 177{ 178 struct via_info *via = addr; 179 180 if (via_waitready_codec(via)) return -1; 181 182 via_wr(via, VIA_AC97_CONTROL, 183 VIA_AC97_CODEC00_VALID | VIA_AC97_INDEX(reg) | 184 VIA_AC97_DATA(val), 4); 185 186 return 0; 187} 188 189static int 190via_read_codec(kobj_t obj, void *addr, int reg) 191{ 192 struct via_info *via = addr; 193 194 if (via_waitready_codec(via)) 195 return -1; 196 197 via_wr(via, VIA_AC97_CONTROL, VIA_AC97_CODEC00_VALID | 198 VIA_AC97_READ | VIA_AC97_INDEX(reg), 4); 199 200 if (via_waitready_codec(via)) 201 return -1; 202 203 if (via_waitvalid_codec(via)) 204 return -1; 205 206 return via_rd(via, VIA_AC97_CONTROL, 2); 207} 208 209static kobj_method_t via_ac97_methods[] = { 210 KOBJMETHOD(ac97_read, via_read_codec), 211 KOBJMETHOD(ac97_write, via_write_codec), 212 { 0, 0 } 213}; 214AC97_DECLARE(via_ac97); 215 216/* -------------------------------------------------------------------- */ 217 218static int 219via_buildsgdt(struct via_chinfo *ch) 220{ 221 u_int32_t phys_addr, flag; 222 int i, segs, seg_size; 223 224 /* 225 * Build the scatter/gather DMA (SGD) table. 226 * There are four slots in the table: two for play, two for record. 227 * This creates two half-buffers, one of which is playing; the other 228 * is feeding. 229 */ 230 seg_size = ch->blksz; 231 segs = sndbuf_getsize(ch->buffer) / seg_size; 232 phys_addr = vtophys(sndbuf_getbuf(ch->buffer)); 233 234 for (i = 0; i < segs; i++) { 235 flag = (i == segs - 1) ? VIA_DMAOP_EOL : VIA_DMAOP_FLAG; 236 ch->sgd_table[i].ptr = phys_addr + (i * seg_size); 237 ch->sgd_table[i].flags = flag | seg_size; 238 } 239 240 return 0; 241} 242 243static int 244via8233pchan_setformat(kobj_t obj, void *data, u_int32_t format) 245{ 246 struct via_chinfo *ch = data; 247 struct via_info *via = ch->parent; 248 249 u_int32_t s = 0xff000000; 250 u_int8_t v = (format & AFMT_S16_LE) ? MC_SGD_16BIT : MC_SGD_8BIT; 251 252 if (format & AFMT_STEREO) { 253 v |= MC_SGD_CHANNELS(2); 254 s |= SLOT3(1) | SLOT4(2); 255 } else { 256 v |= MC_SGD_CHANNELS(1); 257 s |= SLOT3(1) | SLOT4(1); 258 } 259 260 via_wr(via, VIA_MC_SLOT_SELECT, s, 4); 261 via_wr(via, VIA_MC_SGD_FORMAT, v, 1); 262 263 return 0; 264} 265 266static int 267via8233rchan_setformat(kobj_t obj, void *data, u_int32_t format) 268{ 269 struct via_chinfo *ch = data; 270 struct via_info *via = ch->parent; 271 272 u_int32_t f = WR_FORMAT_STOP_INDEX; 273 if (format & AFMT_STEREO) 274 f |= WR_FORMAT_STEREO; 275 if (format & AFMT_S16_LE) 276 f |= WR_FORMAT_16BIT; 277 278 via_wr(via, VIA_WR0_FORMAT, f, 4); 279 return 0; 280} 281 282static int 283via8233pchan_setspeed(kobj_t obj, void *data, u_int32_t speed) 284{ 285 struct via_chinfo *ch = data; 286 struct via_info *via = ch->parent; 287 288 if (via->codec_caps & AC97_EXTCAP_VRA) 289 return ac97_setrate(via->codec, AC97_REGEXT_FDACRATE, speed); 290 291 return 48000; 292} 293 294static int 295via8233rchan_setspeed(kobj_t obj, void *data, u_int32_t speed) 296{ 297 struct via_chinfo *ch = data; 298 struct via_info *via = ch->parent; 299 300 if (via->codec_caps & AC97_EXTCAP_VRA) 301 return ac97_setrate(via->codec, AC97_REGEXT_LADCRATE, speed); 302 303 return 48000; 304} 305 306static int 307via8233chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) 308{ 309 struct via_chinfo *ch = data; 310 311 ch->blksz = blocksize; 312 sndbuf_resize(ch->buffer, SEGS_PER_CHAN, ch->blksz); 313 return ch->blksz; 314} 315 316static int 317via8233chan_getptr(kobj_t obj, void *data) 318{ 319 struct via_chinfo *ch = data; 320 struct via_info *via = ch->parent; 321 322 u_int32_t v = via_rd(via, ch->rbase + VIA_RP_CURRENT_COUNT, 4); 323 u_int32_t index = v >> 24; /* Last completed buffer */ 324 u_int32_t count = v & 0x00ffffff; /* Bytes remaining */ 325 int ptr = (index + 1) * ch->blksz - count; 326 ptr %= SEGS_PER_CHAN * ch->blksz; /* Wrap to available space */ 327 return ptr; 328} 329 330static struct pcmchan_caps * 331via8233chan_getcaps(kobj_t obj, void *data) 332{ 333 struct via_chinfo *ch = data; 334 struct via_info *via = ch->parent; 335 if (via->codec_caps & AC97_EXTCAP_VRA) 336 return &via_vracaps; 337 return &via_caps; 338} 339 340static void 341via8233chan_reset(struct via_info *via, struct via_chinfo *ch) 342{ 343 via_wr(via, ch->rbase + VIA_RP_CONTROL, SGD_CONTROL_STOP, 1); 344 via_wr(via, ch->rbase + VIA_RP_CONTROL, 0x00, 1); 345 via_wr(via, ch->rbase + VIA_RP_STATUS, 346 SGD_STATUS_EOL | SGD_STATUS_FLAG, 1); 347} 348 349static void* 350via8233chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, 351 struct pcm_channel *c, int dir) 352{ 353 struct via_info *via = devinfo; 354 struct via_chinfo *ch = (dir == PCMDIR_PLAY)? &via->pch : &via->rch; 355 356 ch->parent = via; 357 ch->channel = c; 358 ch->buffer = b; 359 ch->dir = dir; 360 ch->sgd_table = &via->sgd_table[(dir == PCMDIR_PLAY)? 0 : SEGS_PER_CHAN]; 361 362 if (ch->dir == PCMDIR_PLAY) { 363 ch->rbase = VIA_MC_SGD_STATUS; 364 } else { 365 ch->rbase = VIA_WR0_SGD_STATUS; 366 via_wr(via, VIA_WR0_SGD_FORMAT, WR_FIFO_ENABLE, 1); 367 } 368 369 if (sndbuf_alloc(ch->buffer, via->parent_dmat, via->bufsz) == -1) 370 return NULL; 371 372 via8233chan_reset(via, ch); 373 374 return ch; 375} 376 377static int 378via8233chan_trigger(kobj_t obj, void* data, int go) 379{ 380 struct via_chinfo *ch = data; 381 struct via_info *via = ch->parent; 382 struct via_dma_op *ado = ch->sgd_table; 383 384 switch(go) { 385 case PCMTRIG_START: 386 via_buildsgdt(ch); 387 via_wr(via, ch->rbase + VIA_RP_TABLE_PTR, vtophys(ado), 4); 388 via_wr(via, ch->rbase + VIA_RP_CONTROL, 389 SGD_CONTROL_START | SGD_CONTROL_AUTOSTART | 390 SGD_CONTROL_I_EOL | SGD_CONTROL_I_FLAG, 1); 391 break; 392 case PCMTRIG_STOP: 393 case PCMTRIG_ABORT: 394 via_wr(via, ch->rbase + VIA_RP_CONTROL, SGD_CONTROL_STOP, 1); 395 via8233chan_reset(via, ch); 396 break; 397 } 398 return 0; 399} 400 401static kobj_method_t via8233pchan_methods[] = { 402 KOBJMETHOD(channel_init, via8233chan_init), 403 KOBJMETHOD(channel_setformat, via8233pchan_setformat), 404 KOBJMETHOD(channel_setspeed, via8233pchan_setspeed), 405 KOBJMETHOD(channel_setblocksize, via8233chan_setblocksize), 406 KOBJMETHOD(channel_trigger, via8233chan_trigger), 407 KOBJMETHOD(channel_getptr, via8233chan_getptr), 408 KOBJMETHOD(channel_getcaps, via8233chan_getcaps), 409 { 0, 0 } 410}; 411CHANNEL_DECLARE(via8233pchan); 412 413static kobj_method_t via8233rchan_methods[] = { 414 KOBJMETHOD(channel_init, via8233chan_init), 415 KOBJMETHOD(channel_setformat, via8233rchan_setformat), 416 KOBJMETHOD(channel_setspeed, via8233rchan_setspeed), 417 KOBJMETHOD(channel_setblocksize, via8233chan_setblocksize), 418 KOBJMETHOD(channel_trigger, via8233chan_trigger), 419 KOBJMETHOD(channel_getptr, via8233chan_getptr), 420 KOBJMETHOD(channel_getcaps, via8233chan_getcaps), 421 { 0, 0 } 422}; 423CHANNEL_DECLARE(via8233rchan); 424 425/* -------------------------------------------------------------------- */ 426 427static void 428via_intr(void *p) 429{ 430 struct via_info *via = p; 431 int r = via_rd(via, VIA_MC_SGD_STATUS, 1); 432 if (r & SGD_STATUS_INTR) { 433 via_wr(via, VIA_MC_SGD_STATUS, SGD_STATUS_INTR, 1); 434 chn_intr(via->pch.channel); 435 } 436 437 r = via_rd(via, VIA_WR0_SGD_STATUS, 1); 438 if (r & SGD_STATUS_INTR) { 439 via_wr(via, VIA_WR0_SGD_STATUS, SGD_STATUS_INTR, 1); 440 chn_intr(via->rch.channel); 441 } 442} 443 444/* 445 * Probe and attach the card 446 */ 447static int 448via_probe(device_t dev) 449{ 450 switch(pci_get_devid(dev)) { 451 case VIA8233_PCI_ID: 452 switch(pci_get_revid(dev)) { 453 case 0x10: 454 device_set_desc(dev, "VIA VT8233 (pre)"); 455 return 0; 456 case 0x20: 457 device_set_desc(dev, "VIA VT8233C"); 458 return 0; 459 case 0x30: 460 device_set_desc(dev, "VIA VT8233"); 461 return 0; 462 case 0x40: 463 device_set_desc(dev, "VIA VT8233A"); 464 return 0; 465 case 0x50: 466 device_set_desc(dev, "VIA VT8235"); 467 return 0; 468 default: 469 device_set_desc(dev, "VIA VT8233X"); /* Unknown */ 470 return 0; 471 } 472 } 473 return ENXIO; 474} 475 476static void 477dma_cb(void *p, bus_dma_segment_t *bds, int a, int b) 478{ 479} 480 481static int 482via_chip_init(device_t dev) 483{ 484 int i, s; 485 486 pci_write_config(dev, VIA_PCI_ACLINK_CTRL, 0, 1); 487 DELAY(100); 488 489 /* assert ACLink reset */ 490 pci_write_config(dev, VIA_PCI_ACLINK_CTRL, VIA_PCI_ACLINK_NRST, 1); 491 DELAY(2); 492 493 /* deassert ACLink reset, force SYNC (warm AC'97 reset) */ 494 pci_write_config(dev, VIA_PCI_ACLINK_CTRL, 495 VIA_PCI_ACLINK_NRST | VIA_PCI_ACLINK_SYNC, 1); 496 497 /* ACLink on, deassert ACLink reset, VSR, SGD data out */ 498 pci_write_config(dev, VIA_PCI_ACLINK_CTRL, 499 VIA_PCI_ACLINK_EN | VIA_PCI_ACLINK_NRST 500 | VIA_PCI_ACLINK_VRATE | VIA_PCI_ACLINK_SGD, 1); 501 502 for (i = 0; i < 100; i++) { 503 s = pci_read_config(dev, VIA_PCI_ACLINK_STAT, 1); 504 if (s & VIA_PCI_ACLINK_C00_READY) { 505 s = pci_read_config(dev, VIA_PCI_ACLINK_CTRL, 1); 506 return 0; 507 } 508 DELAY(10); 509 } 510 device_printf(dev, "primary codec not ready (s = 0x%02x)\n", s); 511 return ENXIO; 512} 513 514static int 515via_attach(device_t dev) 516{ 517 struct via_info *via = 0; 518 char status[SND_STATUSLEN]; 519 520 if ((via = malloc(sizeof *via, M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) { 521 device_printf(dev, "cannot allocate softc\n"); 522 return ENXIO; 523 } 524 525 pci_enable_io(dev, SYS_RES_IOPORT); 526 pci_set_powerstate(dev, PCI_POWERSTATE_D0); 527 pci_enable_busmaster(dev); 528 529 via->regid = PCIR_MAPS; 530 via->reg = bus_alloc_resource(dev, SYS_RES_IOPORT, &via->regid, 0, ~0, 531 1, RF_ACTIVE); 532 if (!via->reg) { 533 device_printf(dev, "cannot allocate bus resource."); 534 goto bad; 535 } 536 via->st = rman_get_bustag(via->reg); 537 via->sh = rman_get_bushandle(via->reg); 538 539 via->bufsz = pcm_getbuffersize(dev, 4096, VIA_DEFAULT_BUFSZ, 65536); 540 541 via->irqid = 0; 542 via->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &via->irqid, 0, ~0, 1, 543 RF_ACTIVE | RF_SHAREABLE); 544 if (!via->irq || 545 snd_setup_intr(dev, via->irq, 0, via_intr, via, &via->ih)) { 546 device_printf(dev, "unable to map interrupt\n"); 547 goto bad; 548 } 549 550 /* DMA tag for buffers */ 551 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, 552 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 553 /*highaddr*/BUS_SPACE_MAXADDR, 554 /*filter*/NULL, /*filterarg*/NULL, 555 /*maxsize*/via->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff, 556 /*flags*/0, &via->parent_dmat) != 0) { 557 device_printf(dev, "unable to create dma tag\n"); 558 goto bad; 559 } 560 561 /* 562 * DMA tag for SGD table. The 686 uses scatter/gather DMA and 563 * requires a list in memory of work to do. We need only 16 bytes 564 * for this list, and it is wasteful to allocate 16K. 565 */ 566 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, 567 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 568 /*highaddr*/BUS_SPACE_MAXADDR, 569 /*filter*/NULL, /*filterarg*/NULL, 570 /*maxsize*/NSEGS * sizeof(struct via_dma_op), 571 /*nsegments*/1, /*maxsegz*/0x3ffff, 572 /*flags*/0, &via->sgd_dmat) != 0) { 573 device_printf(dev, "unable to create dma tag\n"); 574 goto bad; 575 } 576 577 if (bus_dmamem_alloc(via->sgd_dmat, (void **)&via->sgd_table, 578 BUS_DMA_NOWAIT, &via->sgd_dmamap) == -1) 579 goto bad; 580 if (bus_dmamap_load(via->sgd_dmat, via->sgd_dmamap, via->sgd_table, 581 NSEGS * sizeof(struct via_dma_op), dma_cb, 0, 0)) 582 goto bad; 583 584 if (via_chip_init(dev)) 585 goto bad; 586 587 via->codec = AC97_CREATE(dev, via, via_ac97); 588 if (!via->codec) 589 goto bad; 590 591 mixer_init(dev, ac97_getmixerclass(), via->codec); 592 593 via->codec_caps = ac97_getextcaps(via->codec); 594 595 /* Try to set VRA (depends on codec) */ 596 ac97_setextmode(via->codec, via->codec_caps & 597 (AC97_EXTCAP_VRA | AC97_EXTCAP_VRM)); 598 599 snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld", 600 rman_get_start(via->reg), rman_get_start(via->irq)); 601 602 /* Register */ 603 if (pcm_register(dev, via, 1, 1)) goto bad; 604 605 pcm_addchan(dev, PCMDIR_PLAY, &via8233pchan_class, via); 606 pcm_addchan(dev, PCMDIR_REC, &via8233rchan_class, via); 607 608 pcm_setstatus(dev, status); 609 610 return 0; 611bad: 612 if (via->codec) ac97_destroy(via->codec); 613 if (via->reg) bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg); 614 if (via->ih) bus_teardown_intr(dev, via->irq, via->ih); 615 if (via->irq) bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq); 616 if (via->parent_dmat) bus_dma_tag_destroy(via->parent_dmat); 617 if (via->sgd_dmamap) bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap); 618 if (via->sgd_dmat) bus_dma_tag_destroy(via->sgd_dmat); 619 if (via) free(via, M_DEVBUF); 620 return ENXIO; 621} 622 623static int 624via_detach(device_t dev) 625{ 626 int r; 627 struct via_info *via = 0; 628 629 r = pcm_unregister(dev); 630 if (r) return r; 631 632 via = pcm_getdevinfo(dev); 633 bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg); 634 bus_teardown_intr(dev, via->irq, via->ih); 635 bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq); 636 bus_dma_tag_destroy(via->parent_dmat); 637 bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap); 638 bus_dma_tag_destroy(via->sgd_dmat); 639 free(via, M_DEVBUF); 640 return 0; 641} 642 643 644static device_method_t via_methods[] = { 645 DEVMETHOD(device_probe, via_probe), 646 DEVMETHOD(device_attach, via_attach), 647 DEVMETHOD(device_detach, via_detach), 648 { 0, 0} 649}; 650 651static driver_t via_driver = { 652 "pcm", 653 via_methods, 654 PCM_SOFTC_SIZE, 655}; 656 657DRIVER_MODULE(snd_via8233, pci, via_driver, pcm_devclass, 0, 0); 658MODULE_DEPEND(snd_via8233, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); 659MODULE_VERSION(snd_via8233, 1); 660