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, 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 = sndbuf_getsize(ch->buffer) / SEGS_PER_CHAN; 231 232 phys_addr = vtophys(sndbuf_getbuf(ch->buffer)); 233 234 for (i = 0; i < SEGS_PER_CHAN; i++) { 235 flag = (i == SEGS_PER_CHAN - 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 via_wr(via, VIA_WR0_FORMAT, f, 4); 278 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 u_int32_t spd = 48000; 301 if (via->codec_caps & AC97_EXTCAP_VRA) { 302 spd = ac97_setrate(via->codec, AC97_REGEXT_LADCRATE, speed); 303 } 304 return spd; 305 } 306 307 static int 308 via8233chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) 309 { 310 struct via_chinfo *ch = data; 311 312 sndbuf_resize(ch->buffer, SEGS_PER_CHAN, blocksize); 313 ch->blksz = sndbuf_getblksz(ch->buffer); 314 return ch->blksz; 315 } 316 317 static int 318 via8233chan_getptr(kobj_t obj, void *data) 319 { 320 struct via_chinfo *ch = data; 321 struct via_info *via = ch->parent; 322 323 u_int32_t v = via_rd(via, ch->rbase + VIA_RP_CURRENT_COUNT, 4); 324 u_int32_t index = v >> 24; /* Last completed buffer */ 325 u_int32_t count = v & 0x00ffffff; /* Bytes remaining */ 326 int ptr = (index + 1) * ch->blksz - count; 327 ptr %= SEGS_PER_CHAN * ch->blksz; /* Wrap to available space */ 328 329 return ptr; 330 } 331 332 static struct pcmchan_caps * 333 via8233chan_getcaps(kobj_t obj, void *data) 334 { 335 struct via_chinfo *ch = data; 336 struct via_info *via = ch->parent; 337 if (via->codec_caps & AC97_EXTCAP_VRA) 338 return &via_vracaps; 339 return &via_caps; 340 } 341 342 static void 343 via8233chan_reset(struct via_info *via, struct via_chinfo *ch) 344 { 345 via_wr(via, ch->rbase + VIA_RP_CONTROL, SGD_CONTROL_STOP, 1); 346 via_wr(via, ch->rbase + VIA_RP_CONTROL, 0x00, 1); 347 via_wr(via, ch->rbase + VIA_RP_STATUS, 348 SGD_STATUS_EOL | SGD_STATUS_FLAG, 1); 349 } 350 351 static void* 352 via8233chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, 353 struct pcm_channel *c, int dir) 354 { 355 struct via_info *via = devinfo; 356 struct via_chinfo *ch = (dir == PCMDIR_PLAY)? &via->pch : &via->rch; 357 358 ch->parent = via; 359 ch->channel = c; 360 ch->buffer = b; 361 ch->dir = dir; 362 ch->sgd_table = &via->sgd_table[(dir == PCMDIR_PLAY)? 0 : SEGS_PER_CHAN]; 363 364 if (ch->dir == PCMDIR_PLAY) { 365 ch->rbase = VIA_MC_SGD_STATUS; 366 } else { 367 ch->rbase = VIA_WR0_SGD_STATUS; 368 via_wr(via, VIA_WR0_SGD_FORMAT, WR_FIFO_ENABLE, 1); 369 } 370 371 if (sndbuf_alloc(ch->buffer, via->parent_dmat, via->bufsz) == -1) 372 return NULL; 373 374 via8233chan_reset(via, ch); 375 376 return ch; 377 } 378 379 static int 380 via8233chan_trigger(kobj_t obj, void* data, int go) 381 { 382 struct via_chinfo *ch = data; 383 struct via_info *via = ch->parent; 384 struct via_dma_op *ado = ch->sgd_table; 385 386 switch(go) { 387 case PCMTRIG_START: 388 via_buildsgdt(ch); 389 via_wr(via, ch->rbase + VIA_RP_TABLE_PTR, vtophys(ado), 4); 390 via_wr(via, ch->rbase + VIA_RP_CONTROL, 391 SGD_CONTROL_START | SGD_CONTROL_AUTOSTART | 392 SGD_CONTROL_I_EOL | SGD_CONTROL_I_FLAG, 1); 393 break; 394 case PCMTRIG_STOP: 395 case PCMTRIG_ABORT: 396 via_wr(via, ch->rbase + VIA_RP_CONTROL, SGD_CONTROL_STOP, 1); 397 via8233chan_reset(via, ch); 398 break; 399 } 400 return 0; 401 } 402 403 static kobj_method_t via8233pchan_methods[] = { 404 KOBJMETHOD(channel_init, via8233chan_init), 405 KOBJMETHOD(channel_setformat, via8233pchan_setformat), 406 KOBJMETHOD(channel_setspeed, via8233pchan_setspeed), 407 KOBJMETHOD(channel_setblocksize, via8233chan_setblocksize), 408 KOBJMETHOD(channel_trigger, via8233chan_trigger), 409 KOBJMETHOD(channel_getptr, via8233chan_getptr), 410 KOBJMETHOD(channel_getcaps, via8233chan_getcaps), 411 { 0, 0 } 412 }; 413 CHANNEL_DECLARE(via8233pchan); 414 415 static kobj_method_t via8233rchan_methods[] = { 416 KOBJMETHOD(channel_init, via8233chan_init), 417 KOBJMETHOD(channel_setformat, via8233rchan_setformat), 418 KOBJMETHOD(channel_setspeed, via8233rchan_setspeed), 419 KOBJMETHOD(channel_setblocksize, via8233chan_setblocksize), 420 KOBJMETHOD(channel_trigger, via8233chan_trigger), 421 KOBJMETHOD(channel_getptr, via8233chan_getptr), 422 KOBJMETHOD(channel_getcaps, via8233chan_getcaps), 423 { 0, 0 } 424 }; 425 CHANNEL_DECLARE(via8233rchan); 426 427 /* -------------------------------------------------------------------- */ 428 429 static void 430 via_intr(void *p) 431 { 432 struct via_info *via = p; 433 int r = via_rd(via, VIA_MC_SGD_STATUS, 1); 434 if (r & SGD_STATUS_INTR) { 435 via_wr(via, VIA_MC_SGD_STATUS, SGD_STATUS_INTR, 1); 436 chn_intr(via->pch.channel); 437 } 438 439 r = via_rd(via, VIA_WR0_SGD_STATUS, 1); 440 if (r & SGD_STATUS_INTR) { 441 via_wr(via, VIA_WR0_SGD_STATUS, SGD_STATUS_INTR, 1); 442 chn_intr(via->rch.channel); 443 } 444 } 445 446 /* 447 * Probe and attach the card 448 */ 449 static int 450 via_probe(device_t dev) 451 { 452 switch(pci_get_devid(dev)) { 453 case VIA8233_PCI_ID: 454 switch(pci_get_revid(dev)) { 455 case 0x10: 456 device_set_desc(dev, "VIA VT8233 (pre)"); 457 return 0; 458 case 0x20: 459 device_set_desc(dev, "VIA VT8233C"); 460 return 0; 461 case 0x30: 462 device_set_desc(dev, "VIA VT8233"); 463 return 0; 464 case 0x40: 465 device_set_desc(dev, "VIA VT8233A"); 466 return 0; 467 case 0x50: 468 device_set_desc(dev, "VIA VT8235"); 469 return 0; 470 default: 471 device_set_desc(dev, "VIA VT8233X"); /* Unknown */ 472 return 0; 473 } 474 } 475 return ENXIO; 476 } 477 478 static void 479 dma_cb(void *p, bus_dma_segment_t *bds, int a, int b) 480 { 481 } 482 483 static int 484 via_chip_init(device_t dev) 485 { 486 int i, s; 487 488 pci_write_config(dev, VIA_PCI_ACLINK_CTRL, 0, 1); 489 DELAY(100); 490 491 /* assert ACLink reset */ 492 pci_write_config(dev, VIA_PCI_ACLINK_CTRL, VIA_PCI_ACLINK_NRST, 1); 493 DELAY(2); 494 495 /* deassert ACLink reset, force SYNC (warm AC'97 reset) */ 496 pci_write_config(dev, VIA_PCI_ACLINK_CTRL, 497 VIA_PCI_ACLINK_NRST | VIA_PCI_ACLINK_SYNC, 1); 498 499 /* ACLink on, deassert ACLink reset, VSR, SGD data out */ 500 pci_write_config(dev, VIA_PCI_ACLINK_CTRL, 501 VIA_PCI_ACLINK_EN | VIA_PCI_ACLINK_NRST 502 | VIA_PCI_ACLINK_VRATE | VIA_PCI_ACLINK_SGD, 1); 503 504 for (i = 0; i < 100; i++) { 505 s = pci_read_config(dev, VIA_PCI_ACLINK_STAT, 1); 506 if (s & VIA_PCI_ACLINK_C00_READY) { 507 s = pci_read_config(dev, VIA_PCI_ACLINK_CTRL, 1); 508 return 0; 509 } 510 DELAY(10); 511 } 512 device_printf(dev, "primary codec not ready (s = 0x%02x)\n", s); 513 return ENXIO; 514 } 515 516 static int 517 via_attach(device_t dev) 518 { 519 struct via_info *via = 0; 520 char status[SND_STATUSLEN]; 521 522 if ((via = malloc(sizeof *via, M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) { 523 device_printf(dev, "cannot allocate softc\n"); 524 return ENXIO; 525 } 526 527 pci_enable_io(dev, SYS_RES_IOPORT); 528 pci_set_powerstate(dev, PCI_POWERSTATE_D0); 529 pci_enable_busmaster(dev); 530 531 via->regid = PCIR_MAPS; 532 via->reg = bus_alloc_resource(dev, SYS_RES_IOPORT, &via->regid, 0, ~0, 533 1, RF_ACTIVE); 534 if (!via->reg) { 535 device_printf(dev, "cannot allocate bus resource."); 536 goto bad; 537 } 538 via->st = rman_get_bustag(via->reg); 539 via->sh = rman_get_bushandle(via->reg); 540 541 via->bufsz = pcm_getbuffersize(dev, 4096, VIA_DEFAULT_BUFSZ, 65536); 542 543 via->irqid = 0; 544 via->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &via->irqid, 0, ~0, 1, 545 RF_ACTIVE | RF_SHAREABLE); 546 if (!via->irq || 547 snd_setup_intr(dev, via->irq, 0, via_intr, via, &via->ih)) { 548 device_printf(dev, "unable to map interrupt\n"); 549 goto bad; 550 } 551 552 /* DMA tag for buffers */ 553 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, 554 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 555 /*highaddr*/BUS_SPACE_MAXADDR, 556 /*filter*/NULL, /*filterarg*/NULL, 557 /*maxsize*/via->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff, 558 /*flags*/0, &via->parent_dmat) != 0) { 559 device_printf(dev, "unable to create dma tag\n"); 560 goto bad; 561 } 562 563 /* 564 * DMA tag for SGD table. The 686 uses scatter/gather DMA and 565 * requires a list in memory of work to do. We need only 16 bytes 566 * for this list, and it is wasteful to allocate 16K. 567 */ 568 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, 569 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 570 /*highaddr*/BUS_SPACE_MAXADDR, 571 /*filter*/NULL, /*filterarg*/NULL, 572 /*maxsize*/NSEGS * sizeof(struct via_dma_op), 573 /*nsegments*/1, /*maxsegz*/0x3ffff, 574 /*flags*/0, &via->sgd_dmat) != 0) { 575 device_printf(dev, "unable to create dma tag\n"); 576 goto bad; 577 } 578 579 if (bus_dmamem_alloc(via->sgd_dmat, (void **)&via->sgd_table, 580 BUS_DMA_NOWAIT, &via->sgd_dmamap) == -1) 581 goto bad; 582 if (bus_dmamap_load(via->sgd_dmat, via->sgd_dmamap, via->sgd_table, 583 NSEGS * sizeof(struct via_dma_op), dma_cb, 0, 0)) 584 goto bad; 585 586 if (via_chip_init(dev)) 587 goto bad; 588 589 via->codec = AC97_CREATE(dev, via, via_ac97); 590 if (!via->codec) 591 goto bad; 592 593 mixer_init(dev, ac97_getmixerclass(), via->codec); 594 595 via->codec_caps = ac97_getextcaps(via->codec); 596 597 /* Try to set VRA without generating an error, VRM not reqrd yet */ 598 if (via->codec_caps & 599 (AC97_EXTCAP_VRA | AC97_EXTCAP_VRM | AC97_EXTCAP_DRA)) { 600 u_int16_t ext = ac97_getextmode(via->codec); 601 ext |= (via->codec_caps & 602 (AC97_EXTCAP_VRA | AC97_EXTCAP_VRM)); 603 ext &= ~AC97_EXTCAP_DRA; 604 ac97_setextmode(via->codec, ext); 605 } 606 607 snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld", 608 rman_get_start(via->reg), rman_get_start(via->irq)); 609 610 /* Register */ 611 if (pcm_register(dev, via, 1, 1)) goto bad; 612 613 pcm_addchan(dev, PCMDIR_PLAY, &via8233pchan_class, via); 614 pcm_addchan(dev, PCMDIR_REC, &via8233rchan_class, via); 615 616 pcm_setstatus(dev, status); 617 618 return 0; 619 bad: 620 if (via->codec) ac97_destroy(via->codec); 621 if (via->reg) bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg); 622 if (via->ih) bus_teardown_intr(dev, via->irq, via->ih); 623 if (via->irq) bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq); 624 if (via->parent_dmat) bus_dma_tag_destroy(via->parent_dmat); 625 if (via->sgd_dmamap) bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap); 626 if (via->sgd_dmat) bus_dma_tag_destroy(via->sgd_dmat); 627 if (via) free(via, M_DEVBUF); 628 return ENXIO; 629 } 630 631 static int 632 via_detach(device_t dev) 633 { 634 int r; 635 struct via_info *via = 0; 636 637 r = pcm_unregister(dev); 638 if (r) return r; 639 640 via = pcm_getdevinfo(dev); 641 bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg); 642 bus_teardown_intr(dev, via->irq, via->ih); 643 bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq); 644 bus_dma_tag_destroy(via->parent_dmat); 645 bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap); 646 bus_dma_tag_destroy(via->sgd_dmat); 647 free(via, M_DEVBUF); 648 return 0; 649 } 650 651 652 static device_method_t via_methods[] = { 653 DEVMETHOD(device_probe, via_probe), 654 DEVMETHOD(device_attach, via_attach), 655 DEVMETHOD(device_detach, via_detach), 656 { 0, 0} 657 }; 658 659 static driver_t via_driver = { 660 "pcm", 661 via_methods, 662 PCM_SOFTC_SIZE, 663 }; 664 665 DRIVER_MODULE(snd_via8233, pci, via_driver, pcm_devclass, 0, 0); 666 MODULE_DEPEND(snd_via8233, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); 667 MODULE_VERSION(snd_via8233, 1); 668