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 46 SND_DECLARE_FILE("$FreeBSD$"); 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 */ 60 struct 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 69 struct via_info; 70 71 struct 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 80 struct 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 99 static 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 107 static struct pcmchan_caps via_vracaps = { 4000, 48000, via_fmt, 0 }; 108 static struct pcmchan_caps via_caps = { 48000, 48000, via_fmt, 0 }; 109 110 static u_int32_t 111 via_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 125 static void 126 via_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 145 static int 146 via_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 160 static int 161 via_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 175 static int 176 via_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 189 static int 190 via_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 209 static kobj_method_t via_ac97_methods[] = { 210 KOBJMETHOD(ac97_read, via_read_codec), 211 KOBJMETHOD(ac97_write, via_write_codec), 212 { 0, 0 } 213 }; 214 AC97_DECLARE(via_ac97); 215 216 /* -------------------------------------------------------------------- */ 217 218 static int 219 via_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 243 static int 244 via8233pchan_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 266 static int 267 via8233rchan_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 282 static int 283 via8233pchan_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 294 static int 295 via8233rchan_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 306 static int 307 via8233chan_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 316 static int 317 via8233chan_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 330 static struct pcmchan_caps * 331 via8233chan_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 340 static void 341 via8233chan_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 349 static void* 350 via8233chan_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 377 static int 378 via8233chan_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 401 static 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 }; 411 CHANNEL_DECLARE(via8233pchan); 412 413 static 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 }; 423 CHANNEL_DECLARE(via8233rchan); 424 425 /* -------------------------------------------------------------------- */ 426 427 static void 428 via_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 */ 447 static int 448 via_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 476 static void 477 dma_cb(void *p, bus_dma_segment_t *bds, int a, int b) 478 { 479 } 480 481 static int 482 via_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 514 static int 515 via_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 without generating an error, VRM not reqrd yet */ 596 if (via->codec_caps & (AC97_EXTCAP_VRA | AC97_EXTCAP_VRM)) { 597 u_int16_t ext = ac97_getextmode(via->codec); 598 ext |= (via->codec_caps & (AC97_EXTCAP_VRA | AC97_EXTCAP_VRM)); 599 ac97_setextmode(via->codec, ext); 600 } 601 602 snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld", 603 rman_get_start(via->reg), rman_get_start(via->irq)); 604 605 /* Register */ 606 if (pcm_register(dev, via, 1, 1)) goto bad; 607 608 pcm_addchan(dev, PCMDIR_PLAY, &via8233pchan_class, via); 609 pcm_addchan(dev, PCMDIR_REC, &via8233rchan_class, via); 610 611 pcm_setstatus(dev, status); 612 613 return 0; 614 bad: 615 if (via->codec) ac97_destroy(via->codec); 616 if (via->reg) bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg); 617 if (via->ih) bus_teardown_intr(dev, via->irq, via->ih); 618 if (via->irq) bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq); 619 if (via->parent_dmat) bus_dma_tag_destroy(via->parent_dmat); 620 if (via->sgd_dmamap) bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap); 621 if (via->sgd_dmat) bus_dma_tag_destroy(via->sgd_dmat); 622 if (via) free(via, M_DEVBUF); 623 return ENXIO; 624 } 625 626 static int 627 via_detach(device_t dev) 628 { 629 int r; 630 struct via_info *via = 0; 631 632 r = pcm_unregister(dev); 633 if (r) return r; 634 635 via = pcm_getdevinfo(dev); 636 bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg); 637 bus_teardown_intr(dev, via->irq, via->ih); 638 bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq); 639 bus_dma_tag_destroy(via->parent_dmat); 640 bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap); 641 bus_dma_tag_destroy(via->sgd_dmat); 642 free(via, M_DEVBUF); 643 return 0; 644 } 645 646 647 static device_method_t via_methods[] = { 648 DEVMETHOD(device_probe, via_probe), 649 DEVMETHOD(device_attach, via_attach), 650 DEVMETHOD(device_detach, via_detach), 651 { 0, 0} 652 }; 653 654 static driver_t via_driver = { 655 "pcm", 656 via_methods, 657 PCM_SOFTC_SIZE, 658 }; 659 660 DRIVER_MODULE(snd_via8233, pci, via_driver, pcm_devclass, 0, 0); 661 MODULE_DEPEND(snd_via8233, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); 662 MODULE_VERSION(snd_via8233, 1); 663