1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2002 Orion Hodson <orion@freebsd.org> 5 * Portions of this code derived from via82c686.c: 6 * Copyright (c) 2000 David Jones <dej@ox.org> 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 /* 32 * Credits due to: 33 * 34 * Grzybowski Rafal, Russell Davies, Mark Handley, Daniel O'Connor for 35 * comments, machine time, testing patches, and patience. VIA for 36 * providing specs. ALSA for helpful comments and some register poke 37 * ordering. 38 */ 39 40 #ifdef HAVE_KERNEL_OPTION_HEADERS 41 #include "opt_snd.h" 42 #endif 43 44 #include <dev/sound/pcm/sound.h> 45 #include <dev/sound/pcm/ac97.h> 46 47 #include <dev/pci/pcireg.h> 48 #include <dev/pci/pcivar.h> 49 #include <sys/sysctl.h> 50 51 #include <dev/sound/pci/via8233.h> 52 53 SND_DECLARE_FILE("$FreeBSD$"); 54 55 #define VIA8233_PCI_ID 0x30591106 56 57 #define VIA8233_REV_ID_8233PRE 0x10 58 #define VIA8233_REV_ID_8233C 0x20 59 #define VIA8233_REV_ID_8233 0x30 60 #define VIA8233_REV_ID_8233A 0x40 61 #define VIA8233_REV_ID_8235 0x50 62 #define VIA8233_REV_ID_8237 0x60 63 #define VIA8233_REV_ID_8251 0x70 64 65 #define SEGS_PER_CHAN 2 /* Segments per channel */ 66 #define NDXSCHANS 4 /* No of DXS channels */ 67 #define NMSGDCHANS 1 /* No of multichannel SGD */ 68 #define NWRCHANS 1 /* No of write channels */ 69 #define NCHANS (NWRCHANS + NDXSCHANS + NMSGDCHANS) 70 #define NSEGS NCHANS * SEGS_PER_CHAN /* Segments in SGD table */ 71 #define VIA_SEGS_MIN 2 72 #define VIA_SEGS_MAX 64 73 #define VIA_SEGS_DEFAULT 2 74 #define VIA_BLK_MIN 32 75 #define VIA_BLK_ALIGN (~(VIA_BLK_MIN - 1)) 76 77 #define VIA_DEFAULT_BUFSZ 0x1000 78 79 /* we rely on this struct being packed to 64 bits */ 80 struct via_dma_op { 81 volatile uint32_t ptr; 82 volatile uint32_t flags; 83 #define VIA_DMAOP_EOL 0x80000000 84 #define VIA_DMAOP_FLAG 0x40000000 85 #define VIA_DMAOP_STOP 0x20000000 86 #define VIA_DMAOP_COUNT(x) ((x)&0x00FFFFFF) 87 }; 88 89 struct via_info; 90 91 struct via_chinfo { 92 struct via_info *parent; 93 struct pcm_channel *channel; 94 struct snd_dbuf *buffer; 95 struct via_dma_op *sgd_table; 96 bus_addr_t sgd_addr; 97 int dir, rbase, active; 98 unsigned int blksz, blkcnt; 99 unsigned int ptr, prevptr; 100 }; 101 102 struct via_info { 103 device_t dev; 104 105 bus_space_tag_t st; 106 bus_space_handle_t sh; 107 bus_dma_tag_t parent_dmat; 108 bus_dma_tag_t sgd_dmat; 109 bus_dmamap_t sgd_dmamap; 110 bus_addr_t sgd_addr; 111 112 struct resource *reg, *irq; 113 int regid, irqid; 114 void *ih; 115 struct ac97_info *codec; 116 117 unsigned int bufsz, blkcnt; 118 int dxs_src, dma_eol_wake; 119 120 struct via_chinfo pch[NDXSCHANS + NMSGDCHANS]; 121 struct via_chinfo rch[NWRCHANS]; 122 struct via_dma_op *sgd_table; 123 uint16_t codec_caps; 124 uint16_t n_dxs_registered; 125 int play_num, rec_num; 126 struct mtx *lock; 127 struct callout poll_timer; 128 int poll_ticks, polling; 129 }; 130 131 static uint32_t via_fmt[] = { 132 SND_FORMAT(AFMT_U8, 1, 0), 133 SND_FORMAT(AFMT_U8, 2, 0), 134 SND_FORMAT(AFMT_S16_LE, 1, 0), 135 SND_FORMAT(AFMT_S16_LE, 2, 0), 136 0 137 }; 138 139 static struct pcmchan_caps via_vracaps = { 4000, 48000, via_fmt, 0 }; 140 static struct pcmchan_caps via_caps = { 48000, 48000, via_fmt, 0 }; 141 142 static __inline int 143 via_chan_active(struct via_info *via) 144 { 145 int i, ret = 0; 146 147 if (via == NULL) 148 return (0); 149 150 for (i = 0; i < NDXSCHANS + NMSGDCHANS; i++) 151 ret += via->pch[i].active; 152 153 for (i = 0; i < NWRCHANS; i++) 154 ret += via->rch[i].active; 155 156 return (ret); 157 } 158 159 static int 160 sysctl_via8233_spdif_enable(SYSCTL_HANDLER_ARGS) 161 { 162 struct via_info *via; 163 device_t dev; 164 uint32_t r; 165 int err, new_en; 166 167 dev = oidp->oid_arg1; 168 via = pcm_getdevinfo(dev); 169 snd_mtxlock(via->lock); 170 r = pci_read_config(dev, VIA_PCI_SPDIF, 1); 171 snd_mtxunlock(via->lock); 172 new_en = (r & VIA_SPDIF_EN) ? 1 : 0; 173 err = sysctl_handle_int(oidp, &new_en, 0, req); 174 175 if (err || req->newptr == NULL) 176 return (err); 177 if (new_en < 0 || new_en > 1) 178 return (EINVAL); 179 180 if (new_en) 181 r |= VIA_SPDIF_EN; 182 else 183 r &= ~VIA_SPDIF_EN; 184 snd_mtxlock(via->lock); 185 pci_write_config(dev, VIA_PCI_SPDIF, r, 1); 186 snd_mtxunlock(via->lock); 187 188 return (0); 189 } 190 191 static int 192 sysctl_via8233_dxs_src(SYSCTL_HANDLER_ARGS) 193 { 194 struct via_info *via; 195 device_t dev; 196 int err, val; 197 198 dev = oidp->oid_arg1; 199 via = pcm_getdevinfo(dev); 200 snd_mtxlock(via->lock); 201 val = via->dxs_src; 202 snd_mtxunlock(via->lock); 203 err = sysctl_handle_int(oidp, &val, 0, req); 204 205 if (err || req->newptr == NULL) 206 return (err); 207 if (val < 0 || val > 1) 208 return (EINVAL); 209 210 snd_mtxlock(via->lock); 211 via->dxs_src = val; 212 snd_mtxunlock(via->lock); 213 214 return (0); 215 } 216 217 static int 218 sysctl_via_polling(SYSCTL_HANDLER_ARGS) 219 { 220 struct via_info *via; 221 device_t dev; 222 int err, val; 223 224 dev = oidp->oid_arg1; 225 via = pcm_getdevinfo(dev); 226 if (via == NULL) 227 return (EINVAL); 228 snd_mtxlock(via->lock); 229 val = via->polling; 230 snd_mtxunlock(via->lock); 231 err = sysctl_handle_int(oidp, &val, 0, req); 232 233 if (err || req->newptr == NULL) 234 return (err); 235 if (val < 0 || val > 1) 236 return (EINVAL); 237 238 snd_mtxlock(via->lock); 239 if (val != via->polling) { 240 if (via_chan_active(via) != 0) 241 err = EBUSY; 242 else if (val == 0) 243 via->polling = 0; 244 else 245 via->polling = 1; 246 } 247 snd_mtxunlock(via->lock); 248 249 return (err); 250 } 251 252 static void 253 via_init_sysctls(device_t dev) 254 { 255 /* XXX: an user should be able to set this with a control tool, 256 if not done before 7.0-RELEASE, this needs to be converted to 257 a device specific sysctl "dev.pcm.X.yyy" via device_get_sysctl_*() 258 as discussed on multimedia@ in msg-id <861wujij2q.fsf@xps.des.no> */ 259 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 260 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 261 "spdif_enabled", CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev), 262 sysctl_via8233_spdif_enable, "I", 263 "Enable S/PDIF output on primary playback channel"); 264 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 265 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 266 "dxs_src", CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev), 267 sysctl_via8233_dxs_src, "I", 268 "Enable VIA DXS Sample Rate Converter"); 269 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 270 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 271 "polling", CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev), 272 sysctl_via_polling, "I", 273 "Enable polling mode"); 274 } 275 276 static __inline uint32_t 277 via_rd(struct via_info *via, int regno, int size) 278 { 279 switch (size) { 280 case 1: 281 return (bus_space_read_1(via->st, via->sh, regno)); 282 case 2: 283 return (bus_space_read_2(via->st, via->sh, regno)); 284 case 4: 285 return (bus_space_read_4(via->st, via->sh, regno)); 286 default: 287 return (0xFFFFFFFF); 288 } 289 } 290 291 static __inline void 292 via_wr(struct via_info *via, int regno, uint32_t data, int size) 293 { 294 295 switch (size) { 296 case 1: 297 bus_space_write_1(via->st, via->sh, regno, data); 298 break; 299 case 2: 300 bus_space_write_2(via->st, via->sh, regno, data); 301 break; 302 case 4: 303 bus_space_write_4(via->st, via->sh, regno, data); 304 break; 305 } 306 } 307 308 /* -------------------------------------------------------------------- */ 309 /* Codec interface */ 310 311 static int 312 via_waitready_codec(struct via_info *via) 313 { 314 int i; 315 316 /* poll until codec not busy */ 317 for (i = 0; i < 1000; i++) { 318 if ((via_rd(via, VIA_AC97_CONTROL, 4) & VIA_AC97_BUSY) == 0) 319 return (0); 320 DELAY(1); 321 } 322 device_printf(via->dev, "%s: codec busy\n", __func__); 323 return (1); 324 } 325 326 static int 327 via_waitvalid_codec(struct via_info *via) 328 { 329 int i; 330 331 /* poll until codec valid */ 332 for (i = 0; i < 1000; i++) { 333 if (via_rd(via, VIA_AC97_CONTROL, 4) & VIA_AC97_CODEC00_VALID) 334 return (0); 335 DELAY(1); 336 } 337 device_printf(via->dev, "%s: codec invalid\n", __func__); 338 return (1); 339 } 340 341 static int 342 via_write_codec(kobj_t obj, void *addr, int reg, uint32_t val) 343 { 344 struct via_info *via = addr; 345 346 if (via_waitready_codec(via)) 347 return (-1); 348 349 via_wr(via, VIA_AC97_CONTROL, 350 VIA_AC97_CODEC00_VALID | VIA_AC97_INDEX(reg) | 351 VIA_AC97_DATA(val), 4); 352 353 return (0); 354 } 355 356 static int 357 via_read_codec(kobj_t obj, void *addr, int reg) 358 { 359 struct via_info *via = addr; 360 361 if (via_waitready_codec(via)) 362 return (-1); 363 364 via_wr(via, VIA_AC97_CONTROL, VIA_AC97_CODEC00_VALID | 365 VIA_AC97_READ | VIA_AC97_INDEX(reg), 4); 366 367 if (via_waitready_codec(via)) 368 return (-1); 369 370 if (via_waitvalid_codec(via)) 371 return (-1); 372 373 return (via_rd(via, VIA_AC97_CONTROL, 2)); 374 } 375 376 static kobj_method_t via_ac97_methods[] = { 377 KOBJMETHOD(ac97_read, via_read_codec), 378 KOBJMETHOD(ac97_write, via_write_codec), 379 KOBJMETHOD_END 380 }; 381 AC97_DECLARE(via_ac97); 382 383 /* -------------------------------------------------------------------- */ 384 385 static int 386 via_buildsgdt(struct via_chinfo *ch) 387 { 388 uint32_t phys_addr, flag; 389 int i; 390 391 phys_addr = sndbuf_getbufaddr(ch->buffer); 392 393 for (i = 0; i < ch->blkcnt; i++) { 394 flag = (i == ch->blkcnt - 1) ? VIA_DMAOP_EOL : VIA_DMAOP_FLAG; 395 ch->sgd_table[i].ptr = phys_addr + (i * ch->blksz); 396 ch->sgd_table[i].flags = flag | ch->blksz; 397 } 398 399 return (0); 400 } 401 402 /* -------------------------------------------------------------------- */ 403 /* Format setting functions */ 404 405 static int 406 via8233wr_setformat(kobj_t obj, void *data, uint32_t format) 407 { 408 struct via_chinfo *ch = data; 409 struct via_info *via = ch->parent; 410 411 uint32_t f = WR_FORMAT_STOP_INDEX; 412 413 if (AFMT_CHANNEL(format) > 1) 414 f |= WR_FORMAT_STEREO; 415 if (format & AFMT_S16_LE) 416 f |= WR_FORMAT_16BIT; 417 snd_mtxlock(via->lock); 418 via_wr(via, VIA_WR0_FORMAT, f, 4); 419 snd_mtxunlock(via->lock); 420 421 return (0); 422 } 423 424 static int 425 via8233dxs_setformat(kobj_t obj, void *data, uint32_t format) 426 { 427 struct via_chinfo *ch = data; 428 struct via_info *via = ch->parent; 429 uint32_t r, v; 430 431 r = ch->rbase + VIA8233_RP_DXS_RATEFMT; 432 snd_mtxlock(via->lock); 433 v = via_rd(via, r, 4); 434 435 v &= ~(VIA8233_DXS_RATEFMT_STEREO | VIA8233_DXS_RATEFMT_16BIT); 436 if (AFMT_CHANNEL(format) > 1) 437 v |= VIA8233_DXS_RATEFMT_STEREO; 438 if (format & AFMT_16BIT) 439 v |= VIA8233_DXS_RATEFMT_16BIT; 440 via_wr(via, r, v, 4); 441 snd_mtxunlock(via->lock); 442 443 return (0); 444 } 445 446 static int 447 via8233msgd_setformat(kobj_t obj, void *data, uint32_t format) 448 { 449 struct via_chinfo *ch = data; 450 struct via_info *via = ch->parent; 451 452 uint32_t s = 0xff000000; 453 uint8_t v = (format & AFMT_S16_LE) ? MC_SGD_16BIT : MC_SGD_8BIT; 454 455 if (AFMT_CHANNEL(format) > 1) { 456 v |= MC_SGD_CHANNELS(2); 457 s |= SLOT3(1) | SLOT4(2); 458 } else { 459 v |= MC_SGD_CHANNELS(1); 460 s |= SLOT3(1) | SLOT4(1); 461 } 462 463 snd_mtxlock(via->lock); 464 via_wr(via, VIA_MC_SLOT_SELECT, s, 4); 465 via_wr(via, VIA_MC_SGD_FORMAT, v, 1); 466 snd_mtxunlock(via->lock); 467 468 return (0); 469 } 470 471 /* -------------------------------------------------------------------- */ 472 /* Speed setting functions */ 473 474 static uint32_t 475 via8233wr_setspeed(kobj_t obj, void *data, uint32_t speed) 476 { 477 struct via_chinfo *ch = data; 478 struct via_info *via = ch->parent; 479 480 if (via->codec_caps & AC97_EXTCAP_VRA) 481 return (ac97_setrate(via->codec, AC97_REGEXT_LADCRATE, speed)); 482 483 return (48000); 484 } 485 486 static uint32_t 487 via8233dxs_setspeed(kobj_t obj, void *data, uint32_t speed) 488 { 489 struct via_chinfo *ch = data; 490 struct via_info *via = ch->parent; 491 uint32_t r, v; 492 493 r = ch->rbase + VIA8233_RP_DXS_RATEFMT; 494 snd_mtxlock(via->lock); 495 v = via_rd(via, r, 4) & ~VIA8233_DXS_RATEFMT_48K; 496 497 /* Careful to avoid overflow (divide by 48 per vt8233c docs) */ 498 499 v |= VIA8233_DXS_RATEFMT_48K * (speed / 48) / (48000 / 48); 500 via_wr(via, r, v, 4); 501 snd_mtxunlock(via->lock); 502 503 return (speed); 504 } 505 506 static uint32_t 507 via8233msgd_setspeed(kobj_t obj, void *data, uint32_t speed) 508 { 509 struct via_chinfo *ch = data; 510 struct via_info *via = ch->parent; 511 512 if (via->codec_caps & AC97_EXTCAP_VRA) 513 return (ac97_setrate(via->codec, AC97_REGEXT_FDACRATE, speed)); 514 515 return (48000); 516 } 517 518 /* -------------------------------------------------------------------- */ 519 /* Format probing functions */ 520 521 static struct pcmchan_caps * 522 via8233wr_getcaps(kobj_t obj, void *data) 523 { 524 struct via_chinfo *ch = data; 525 struct via_info *via = ch->parent; 526 527 /* Controlled by ac97 registers */ 528 if (via->codec_caps & AC97_EXTCAP_VRA) 529 return (&via_vracaps); 530 return (&via_caps); 531 } 532 533 static struct pcmchan_caps * 534 via8233dxs_getcaps(kobj_t obj, void *data) 535 { 536 struct via_chinfo *ch = data; 537 struct via_info *via = ch->parent; 538 539 /* 540 * Controlled by onboard registers 541 * 542 * Apparently, few boards can do DXS sample rate 543 * conversion. 544 */ 545 if (via->dxs_src) 546 return (&via_vracaps); 547 return (&via_caps); 548 } 549 550 static struct pcmchan_caps * 551 via8233msgd_getcaps(kobj_t obj, void *data) 552 { 553 struct via_chinfo *ch = data; 554 struct via_info *via = ch->parent; 555 556 /* Controlled by ac97 registers */ 557 if (via->codec_caps & AC97_EXTCAP_VRA) 558 return (&via_vracaps); 559 return (&via_caps); 560 } 561 562 /* -------------------------------------------------------------------- */ 563 /* Common functions */ 564 565 static int 566 via8233chan_setfragments(kobj_t obj, void *data, 567 uint32_t blksz, uint32_t blkcnt) 568 { 569 struct via_chinfo *ch = data; 570 struct via_info *via = ch->parent; 571 572 blksz &= VIA_BLK_ALIGN; 573 574 if (blksz > (sndbuf_getmaxsize(ch->buffer) / VIA_SEGS_MIN)) 575 blksz = sndbuf_getmaxsize(ch->buffer) / VIA_SEGS_MIN; 576 if (blksz < VIA_BLK_MIN) 577 blksz = VIA_BLK_MIN; 578 if (blkcnt > VIA_SEGS_MAX) 579 blkcnt = VIA_SEGS_MAX; 580 if (blkcnt < VIA_SEGS_MIN) 581 blkcnt = VIA_SEGS_MIN; 582 583 while ((blksz * blkcnt) > sndbuf_getmaxsize(ch->buffer)) { 584 if ((blkcnt >> 1) >= VIA_SEGS_MIN) 585 blkcnt >>= 1; 586 else if ((blksz >> 1) >= VIA_BLK_MIN) 587 blksz >>= 1; 588 else 589 break; 590 } 591 592 if ((sndbuf_getblksz(ch->buffer) != blksz || 593 sndbuf_getblkcnt(ch->buffer) != blkcnt) && 594 sndbuf_resize(ch->buffer, blkcnt, blksz) != 0) 595 device_printf(via->dev, "%s: failed blksz=%u blkcnt=%u\n", 596 __func__, blksz, blkcnt); 597 598 ch->blksz = sndbuf_getblksz(ch->buffer); 599 ch->blkcnt = sndbuf_getblkcnt(ch->buffer); 600 601 return (0); 602 } 603 604 static uint32_t 605 via8233chan_setblocksize(kobj_t obj, void *data, uint32_t blksz) 606 { 607 struct via_chinfo *ch = data; 608 struct via_info *via = ch->parent; 609 610 via8233chan_setfragments(obj, data, blksz, via->blkcnt); 611 612 return (ch->blksz); 613 } 614 615 static uint32_t 616 via8233chan_getptr(kobj_t obj, void *data) 617 { 618 struct via_chinfo *ch = data; 619 struct via_info *via = ch->parent; 620 uint32_t v, index, count, ptr; 621 622 snd_mtxlock(via->lock); 623 if (via->polling != 0) { 624 ptr = ch->ptr; 625 snd_mtxunlock(via->lock); 626 } else { 627 v = via_rd(via, ch->rbase + VIA_RP_CURRENT_COUNT, 4); 628 snd_mtxunlock(via->lock); 629 index = v >> 24; /* Last completed buffer */ 630 count = v & 0x00ffffff; /* Bytes remaining */ 631 ptr = (index + 1) * ch->blksz - count; 632 ptr %= ch->blkcnt * ch->blksz; /* Wrap to available space */ 633 } 634 635 return (ptr); 636 } 637 638 static void 639 via8233chan_reset(struct via_info *via, struct via_chinfo *ch) 640 { 641 via_wr(via, ch->rbase + VIA_RP_CONTROL, SGD_CONTROL_STOP, 1); 642 via_wr(via, ch->rbase + VIA_RP_CONTROL, 0x00, 1); 643 via_wr(via, ch->rbase + VIA_RP_STATUS, 644 SGD_STATUS_EOL | SGD_STATUS_FLAG, 1); 645 } 646 647 /* -------------------------------------------------------------------- */ 648 /* Channel initialization functions */ 649 650 static void 651 via8233chan_sgdinit(struct via_info *via, struct via_chinfo *ch, int chnum) 652 { 653 ch->sgd_table = &via->sgd_table[chnum * VIA_SEGS_MAX]; 654 ch->sgd_addr = via->sgd_addr + chnum * VIA_SEGS_MAX * 655 sizeof(struct via_dma_op); 656 } 657 658 static void* 659 via8233wr_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, 660 struct pcm_channel *c, int dir) 661 { 662 struct via_info *via = devinfo; 663 struct via_chinfo *ch; 664 int num; 665 666 snd_mtxlock(via->lock); 667 num = via->rec_num++; 668 ch = &via->rch[num]; 669 ch->parent = via; 670 ch->channel = c; 671 ch->buffer = b; 672 ch->dir = dir; 673 ch->blkcnt = via->blkcnt; 674 ch->rbase = VIA_WR_BASE(num); 675 via_wr(via, ch->rbase + VIA_WR_RP_SGD_FORMAT, WR_FIFO_ENABLE, 1); 676 snd_mtxunlock(via->lock); 677 678 if (sndbuf_alloc(ch->buffer, via->parent_dmat, 0, via->bufsz) != 0) 679 return (NULL); 680 681 snd_mtxlock(via->lock); 682 via8233chan_sgdinit(via, ch, num); 683 via8233chan_reset(via, ch); 684 snd_mtxunlock(via->lock); 685 686 return (ch); 687 } 688 689 static void* 690 via8233dxs_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, 691 struct pcm_channel *c, int dir) 692 { 693 struct via_info *via = devinfo; 694 struct via_chinfo *ch; 695 int num; 696 697 snd_mtxlock(via->lock); 698 num = via->play_num++; 699 ch = &via->pch[num]; 700 ch->parent = via; 701 ch->channel = c; 702 ch->buffer = b; 703 ch->dir = dir; 704 ch->blkcnt = via->blkcnt; 705 706 /* 707 * All cards apparently support DXS3, but not other DXS 708 * channels. We therefore want to align first DXS channel to 709 * DXS3. 710 */ 711 ch->rbase = VIA_DXS_BASE(NDXSCHANS - 1 - via->n_dxs_registered); 712 via->n_dxs_registered++; 713 snd_mtxunlock(via->lock); 714 715 if (sndbuf_alloc(ch->buffer, via->parent_dmat, 0, via->bufsz) != 0) 716 return (NULL); 717 718 snd_mtxlock(via->lock); 719 via8233chan_sgdinit(via, ch, NWRCHANS + num); 720 via8233chan_reset(via, ch); 721 snd_mtxunlock(via->lock); 722 723 return (ch); 724 } 725 726 static void* 727 via8233msgd_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, 728 struct pcm_channel *c, int dir) 729 { 730 struct via_info *via = devinfo; 731 struct via_chinfo *ch; 732 int num; 733 734 snd_mtxlock(via->lock); 735 num = via->play_num++; 736 ch = &via->pch[num]; 737 ch->parent = via; 738 ch->channel = c; 739 ch->buffer = b; 740 ch->dir = dir; 741 ch->rbase = VIA_MC_SGD_STATUS; 742 ch->blkcnt = via->blkcnt; 743 snd_mtxunlock(via->lock); 744 745 if (sndbuf_alloc(ch->buffer, via->parent_dmat, 0, via->bufsz) != 0) 746 return (NULL); 747 748 snd_mtxlock(via->lock); 749 via8233chan_sgdinit(via, ch, NWRCHANS + num); 750 via8233chan_reset(via, ch); 751 snd_mtxunlock(via->lock); 752 753 return (ch); 754 } 755 756 static void 757 via8233chan_mute(struct via_info *via, struct via_chinfo *ch, int muted) 758 { 759 if (BASE_IS_VIA_DXS_REG(ch->rbase)) { 760 int r; 761 muted = (muted) ? VIA8233_DXS_MUTE : 0; 762 via_wr(via, ch->rbase + VIA8233_RP_DXS_LVOL, muted, 1); 763 via_wr(via, ch->rbase + VIA8233_RP_DXS_RVOL, muted, 1); 764 r = via_rd(via, ch->rbase + VIA8233_RP_DXS_LVOL, 1) & 765 VIA8233_DXS_MUTE; 766 if (r != muted) 767 device_printf(via->dev, 768 "%s: failed to set dxs volume " 769 "(dxs base 0x%02x).\n", __func__, ch->rbase); 770 } 771 } 772 773 static __inline int 774 via_poll_channel(struct via_chinfo *ch) 775 { 776 struct via_info *via; 777 uint32_t sz, delta; 778 uint32_t v, index, count; 779 int ptr; 780 781 if (ch == NULL || ch->channel == NULL || ch->active == 0) 782 return (0); 783 784 via = ch->parent; 785 sz = ch->blksz * ch->blkcnt; 786 v = via_rd(via, ch->rbase + VIA_RP_CURRENT_COUNT, 4); 787 index = v >> 24; 788 count = v & 0x00ffffff; 789 ptr = ((index + 1) * ch->blksz) - count; 790 ptr %= sz; 791 ptr &= ~(ch->blksz - 1); 792 ch->ptr = ptr; 793 delta = (sz + ptr - ch->prevptr) % sz; 794 795 if (delta < ch->blksz) 796 return (0); 797 798 ch->prevptr = ptr; 799 800 return (1); 801 } 802 803 static void 804 via_poll_callback(void *arg) 805 { 806 struct via_info *via = arg; 807 uint32_t ptrigger = 0, rtrigger = 0; 808 int i; 809 810 if (via == NULL) 811 return; 812 813 snd_mtxlock(via->lock); 814 if (via->polling == 0 || via_chan_active(via) == 0) { 815 snd_mtxunlock(via->lock); 816 return; 817 } 818 819 for (i = 0; i < NDXSCHANS + NMSGDCHANS; i++) 820 ptrigger |= (via_poll_channel(&via->pch[i]) != 0) ? 821 (1 << i) : 0; 822 823 for (i = 0; i < NWRCHANS; i++) 824 rtrigger |= (via_poll_channel(&via->rch[i]) != 0) ? 825 (1 << i) : 0; 826 827 /* XXX */ 828 callout_reset(&via->poll_timer, 1/*via->poll_ticks*/, 829 via_poll_callback, via); 830 831 snd_mtxunlock(via->lock); 832 833 for (i = 0; i < NDXSCHANS + NMSGDCHANS; i++) { 834 if (ptrigger & (1 << i)) 835 chn_intr(via->pch[i].channel); 836 } 837 for (i = 0; i < NWRCHANS; i++) { 838 if (rtrigger & (1 << i)) 839 chn_intr(via->rch[i].channel); 840 } 841 } 842 843 static int 844 via_poll_ticks(struct via_info *via) 845 { 846 struct via_chinfo *ch; 847 int i; 848 int ret = hz; 849 int pollticks; 850 851 for (i = 0; i < NDXSCHANS + NMSGDCHANS; i++) { 852 ch = &via->pch[i]; 853 if (ch->channel == NULL || ch->active == 0) 854 continue; 855 pollticks = ((uint64_t)hz * ch->blksz) / 856 ((uint64_t)sndbuf_getalign(ch->buffer) * 857 sndbuf_getspd(ch->buffer)); 858 pollticks >>= 2; 859 if (pollticks > hz) 860 pollticks = hz; 861 if (pollticks < 1) 862 pollticks = 1; 863 if (pollticks < ret) 864 ret = pollticks; 865 } 866 867 for (i = 0; i < NWRCHANS; i++) { 868 ch = &via->rch[i]; 869 if (ch->channel == NULL || ch->active == 0) 870 continue; 871 pollticks = ((uint64_t)hz * ch->blksz) / 872 ((uint64_t)sndbuf_getalign(ch->buffer) * 873 sndbuf_getspd(ch->buffer)); 874 pollticks >>= 2; 875 if (pollticks > hz) 876 pollticks = hz; 877 if (pollticks < 1) 878 pollticks = 1; 879 if (pollticks < ret) 880 ret = pollticks; 881 } 882 883 return (ret); 884 } 885 886 static int 887 via8233chan_trigger(kobj_t obj, void* data, int go) 888 { 889 struct via_chinfo *ch = data; 890 struct via_info *via = ch->parent; 891 int pollticks; 892 893 if (!PCMTRIG_COMMON(go)) 894 return (0); 895 896 snd_mtxlock(via->lock); 897 switch(go) { 898 case PCMTRIG_START: 899 via_buildsgdt(ch); 900 via8233chan_mute(via, ch, 0); 901 via_wr(via, ch->rbase + VIA_RP_TABLE_PTR, ch->sgd_addr, 4); 902 if (via->polling != 0) { 903 ch->ptr = 0; 904 ch->prevptr = 0; 905 pollticks = ((uint64_t)hz * ch->blksz) / 906 ((uint64_t)sndbuf_getalign(ch->buffer) * 907 sndbuf_getspd(ch->buffer)); 908 pollticks >>= 2; 909 if (pollticks > hz) 910 pollticks = hz; 911 if (pollticks < 1) 912 pollticks = 1; 913 if (via_chan_active(via) == 0 || 914 pollticks < via->poll_ticks) { 915 if (bootverbose) { 916 if (via_chan_active(via) == 0) 917 printf("%s: pollticks=%d\n", 918 __func__, pollticks); 919 else 920 printf("%s: " 921 "pollticks %d -> %d\n", 922 __func__, via->poll_ticks, 923 pollticks); 924 } 925 via->poll_ticks = pollticks; 926 callout_reset(&via->poll_timer, 1, 927 via_poll_callback, via); 928 } 929 } 930 via_wr(via, ch->rbase + VIA_RP_CONTROL, 931 SGD_CONTROL_START | SGD_CONTROL_AUTOSTART | 932 ((via->polling == 0) ? 933 (SGD_CONTROL_I_EOL | SGD_CONTROL_I_FLAG) : 0), 1); 934 ch->active = 1; 935 break; 936 case PCMTRIG_STOP: 937 case PCMTRIG_ABORT: 938 via_wr(via, ch->rbase + VIA_RP_CONTROL, SGD_CONTROL_STOP, 1); 939 via8233chan_mute(via, ch, 1); 940 via8233chan_reset(via, ch); 941 ch->active = 0; 942 if (via->polling != 0) { 943 if (via_chan_active(via) == 0) { 944 callout_stop(&via->poll_timer); 945 via->poll_ticks = 1; 946 } else { 947 pollticks = via_poll_ticks(via); 948 if (pollticks > via->poll_ticks) { 949 if (bootverbose) 950 printf("%s: pollticks " 951 "%d -> %d\n", 952 __func__, via->poll_ticks, 953 pollticks); 954 via->poll_ticks = pollticks; 955 callout_reset(&via->poll_timer, 956 1, via_poll_callback, 957 via); 958 } 959 } 960 } 961 break; 962 default: 963 break; 964 } 965 snd_mtxunlock(via->lock); 966 return (0); 967 } 968 969 static kobj_method_t via8233wr_methods[] = { 970 KOBJMETHOD(channel_init, via8233wr_init), 971 KOBJMETHOD(channel_setformat, via8233wr_setformat), 972 KOBJMETHOD(channel_setspeed, via8233wr_setspeed), 973 KOBJMETHOD(channel_getcaps, via8233wr_getcaps), 974 KOBJMETHOD(channel_setblocksize, via8233chan_setblocksize), 975 KOBJMETHOD(channel_setfragments, via8233chan_setfragments), 976 KOBJMETHOD(channel_trigger, via8233chan_trigger), 977 KOBJMETHOD(channel_getptr, via8233chan_getptr), 978 KOBJMETHOD_END 979 }; 980 CHANNEL_DECLARE(via8233wr); 981 982 static kobj_method_t via8233dxs_methods[] = { 983 KOBJMETHOD(channel_init, via8233dxs_init), 984 KOBJMETHOD(channel_setformat, via8233dxs_setformat), 985 KOBJMETHOD(channel_setspeed, via8233dxs_setspeed), 986 KOBJMETHOD(channel_getcaps, via8233dxs_getcaps), 987 KOBJMETHOD(channel_setblocksize, via8233chan_setblocksize), 988 KOBJMETHOD(channel_setfragments, via8233chan_setfragments), 989 KOBJMETHOD(channel_trigger, via8233chan_trigger), 990 KOBJMETHOD(channel_getptr, via8233chan_getptr), 991 KOBJMETHOD_END 992 }; 993 CHANNEL_DECLARE(via8233dxs); 994 995 static kobj_method_t via8233msgd_methods[] = { 996 KOBJMETHOD(channel_init, via8233msgd_init), 997 KOBJMETHOD(channel_setformat, via8233msgd_setformat), 998 KOBJMETHOD(channel_setspeed, via8233msgd_setspeed), 999 KOBJMETHOD(channel_getcaps, via8233msgd_getcaps), 1000 KOBJMETHOD(channel_setblocksize, via8233chan_setblocksize), 1001 KOBJMETHOD(channel_setfragments, via8233chan_setfragments), 1002 KOBJMETHOD(channel_trigger, via8233chan_trigger), 1003 KOBJMETHOD(channel_getptr, via8233chan_getptr), 1004 KOBJMETHOD_END 1005 }; 1006 CHANNEL_DECLARE(via8233msgd); 1007 1008 /* -------------------------------------------------------------------- */ 1009 1010 static void 1011 via_intr(void *p) 1012 { 1013 struct via_info *via = p; 1014 uint32_t ptrigger = 0, rtrigger = 0; 1015 int i, reg, stat; 1016 1017 snd_mtxlock(via->lock); 1018 if (via->polling != 0) { 1019 snd_mtxunlock(via->lock); 1020 return; 1021 } 1022 /* Poll playback channels */ 1023 for (i = 0; i < NDXSCHANS + NMSGDCHANS; i++) { 1024 if (via->pch[i].channel == NULL || via->pch[i].active == 0) 1025 continue; 1026 reg = via->pch[i].rbase + VIA_RP_STATUS; 1027 stat = via_rd(via, reg, 1); 1028 if (stat & SGD_STATUS_INTR) { 1029 if (via->dma_eol_wake && ((stat & SGD_STATUS_EOL) || 1030 !(stat & SGD_STATUS_ACTIVE))) 1031 via_wr(via, via->pch[i].rbase + VIA_RP_CONTROL, 1032 SGD_CONTROL_START | SGD_CONTROL_AUTOSTART | 1033 SGD_CONTROL_I_EOL | SGD_CONTROL_I_FLAG, 1); 1034 via_wr(via, reg, stat, 1); 1035 ptrigger |= 1 << i; 1036 } 1037 } 1038 /* Poll record channels */ 1039 for (i = 0; i < NWRCHANS; i++) { 1040 if (via->rch[i].channel == NULL || via->rch[i].active == 0) 1041 continue; 1042 reg = via->rch[i].rbase + VIA_RP_STATUS; 1043 stat = via_rd(via, reg, 1); 1044 if (stat & SGD_STATUS_INTR) { 1045 if (via->dma_eol_wake && ((stat & SGD_STATUS_EOL) || 1046 !(stat & SGD_STATUS_ACTIVE))) 1047 via_wr(via, via->rch[i].rbase + VIA_RP_CONTROL, 1048 SGD_CONTROL_START | SGD_CONTROL_AUTOSTART | 1049 SGD_CONTROL_I_EOL | SGD_CONTROL_I_FLAG, 1); 1050 via_wr(via, reg, stat, 1); 1051 rtrigger |= 1 << i; 1052 } 1053 } 1054 snd_mtxunlock(via->lock); 1055 1056 for (i = 0; i < NDXSCHANS + NMSGDCHANS; i++) { 1057 if (ptrigger & (1 << i)) 1058 chn_intr(via->pch[i].channel); 1059 } 1060 for (i = 0; i < NWRCHANS; i++) { 1061 if (rtrigger & (1 << i)) 1062 chn_intr(via->rch[i].channel); 1063 } 1064 } 1065 1066 /* 1067 * Probe and attach the card 1068 */ 1069 static int 1070 via_probe(device_t dev) 1071 { 1072 switch(pci_get_devid(dev)) { 1073 case VIA8233_PCI_ID: 1074 switch(pci_get_revid(dev)) { 1075 case VIA8233_REV_ID_8233PRE: 1076 device_set_desc(dev, "VIA VT8233 (pre)"); 1077 return (BUS_PROBE_DEFAULT); 1078 case VIA8233_REV_ID_8233C: 1079 device_set_desc(dev, "VIA VT8233C"); 1080 return (BUS_PROBE_DEFAULT); 1081 case VIA8233_REV_ID_8233: 1082 device_set_desc(dev, "VIA VT8233"); 1083 return (BUS_PROBE_DEFAULT); 1084 case VIA8233_REV_ID_8233A: 1085 device_set_desc(dev, "VIA VT8233A"); 1086 return (BUS_PROBE_DEFAULT); 1087 case VIA8233_REV_ID_8235: 1088 device_set_desc(dev, "VIA VT8235"); 1089 return (BUS_PROBE_DEFAULT); 1090 case VIA8233_REV_ID_8237: 1091 device_set_desc(dev, "VIA VT8237"); 1092 return (BUS_PROBE_DEFAULT); 1093 case VIA8233_REV_ID_8251: 1094 device_set_desc(dev, "VIA VT8251"); 1095 return (BUS_PROBE_DEFAULT); 1096 default: 1097 device_set_desc(dev, "VIA VT8233X"); /* Unknown */ 1098 return (BUS_PROBE_DEFAULT); 1099 } 1100 } 1101 return (ENXIO); 1102 } 1103 1104 static void 1105 dma_cb(void *p, bus_dma_segment_t *bds, int a, int b) 1106 { 1107 struct via_info *via = (struct via_info *)p; 1108 via->sgd_addr = bds->ds_addr; 1109 } 1110 1111 static int 1112 via_chip_init(device_t dev) 1113 { 1114 uint32_t data, cnt; 1115 1116 /* Wake up and reset AC97 if necessary */ 1117 data = pci_read_config(dev, VIA_PCI_ACLINK_STAT, 1); 1118 1119 if ((data & VIA_PCI_ACLINK_C00_READY) == 0) { 1120 /* Cold reset per ac97r2.3 spec (page 95) */ 1121 /* Assert low */ 1122 pci_write_config(dev, VIA_PCI_ACLINK_CTRL, 1123 VIA_PCI_ACLINK_EN, 1); 1124 /* Wait T_rst_low */ 1125 DELAY(100); 1126 /* Assert high */ 1127 pci_write_config(dev, VIA_PCI_ACLINK_CTRL, 1128 VIA_PCI_ACLINK_EN | VIA_PCI_ACLINK_NRST, 1); 1129 /* Wait T_rst2clk */ 1130 DELAY(5); 1131 /* Assert low */ 1132 pci_write_config(dev, VIA_PCI_ACLINK_CTRL, 1133 VIA_PCI_ACLINK_EN, 1); 1134 } else { 1135 /* Warm reset */ 1136 /* Force no sync */ 1137 pci_write_config(dev, VIA_PCI_ACLINK_CTRL, 1138 VIA_PCI_ACLINK_EN, 1); 1139 DELAY(100); 1140 /* Sync */ 1141 pci_write_config(dev, VIA_PCI_ACLINK_CTRL, 1142 VIA_PCI_ACLINK_EN | VIA_PCI_ACLINK_SYNC, 1); 1143 /* Wait T_sync_high */ 1144 DELAY(5); 1145 /* Force no sync */ 1146 pci_write_config(dev, VIA_PCI_ACLINK_CTRL, 1147 VIA_PCI_ACLINK_EN, 1); 1148 /* Wait T_sync2clk */ 1149 DELAY(5); 1150 } 1151 1152 /* Power everything up */ 1153 pci_write_config(dev, VIA_PCI_ACLINK_CTRL, VIA_PCI_ACLINK_DESIRED, 1); 1154 1155 /* Wait for codec to become ready (largest reported delay 310ms) */ 1156 for (cnt = 0; cnt < 2000; cnt++) { 1157 data = pci_read_config(dev, VIA_PCI_ACLINK_STAT, 1); 1158 if (data & VIA_PCI_ACLINK_C00_READY) 1159 return (0); 1160 DELAY(5000); 1161 } 1162 device_printf(dev, "primary codec not ready (cnt = 0x%02x)\n", cnt); 1163 return (ENXIO); 1164 } 1165 1166 static int 1167 via_attach(device_t dev) 1168 { 1169 struct via_info *via = NULL; 1170 char status[SND_STATUSLEN]; 1171 int i, via_dxs_disabled, via_dxs_src, via_dxs_chnum, via_sgd_chnum; 1172 int nsegs; 1173 uint32_t revid; 1174 1175 via = malloc(sizeof *via, M_DEVBUF, M_WAITOK | M_ZERO); 1176 via->lock = snd_mtxcreate(device_get_nameunit(dev), 1177 "snd_via8233 softc"); 1178 via->dev = dev; 1179 1180 callout_init(&via->poll_timer, 1); 1181 via->poll_ticks = 1; 1182 1183 if (resource_int_value(device_get_name(dev), 1184 device_get_unit(dev), "polling", &i) == 0 && i != 0) 1185 via->polling = 1; 1186 else 1187 via->polling = 0; 1188 1189 pci_set_powerstate(dev, PCI_POWERSTATE_D0); 1190 pci_enable_busmaster(dev); 1191 1192 via->regid = PCIR_BAR(0); 1193 via->reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &via->regid, 1194 RF_ACTIVE); 1195 if (!via->reg) { 1196 device_printf(dev, "cannot allocate bus resource."); 1197 goto bad; 1198 } 1199 via->st = rman_get_bustag(via->reg); 1200 via->sh = rman_get_bushandle(via->reg); 1201 1202 via->irqid = 0; 1203 via->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &via->irqid, 1204 RF_ACTIVE | RF_SHAREABLE); 1205 if (!via->irq || 1206 snd_setup_intr(dev, via->irq, INTR_MPSAFE, 1207 via_intr, via, &via->ih)) { 1208 device_printf(dev, "unable to map interrupt\n"); 1209 goto bad; 1210 } 1211 1212 via->bufsz = pcm_getbuffersize(dev, 4096, VIA_DEFAULT_BUFSZ, 65536); 1213 if (resource_int_value(device_get_name(dev), 1214 device_get_unit(dev), "blocksize", &i) == 0 && i > 0) { 1215 i &= VIA_BLK_ALIGN; 1216 if (i < VIA_BLK_MIN) 1217 i = VIA_BLK_MIN; 1218 via->blkcnt = via->bufsz / i; 1219 i = 0; 1220 while (via->blkcnt >> i) 1221 i++; 1222 via->blkcnt = 1 << (i - 1); 1223 if (via->blkcnt < VIA_SEGS_MIN) 1224 via->blkcnt = VIA_SEGS_MIN; 1225 else if (via->blkcnt > VIA_SEGS_MAX) 1226 via->blkcnt = VIA_SEGS_MAX; 1227 1228 } else 1229 via->blkcnt = VIA_SEGS_DEFAULT; 1230 1231 revid = pci_get_revid(dev); 1232 1233 /* 1234 * VIA8251 lost its interrupt after DMA EOL, and need 1235 * a gentle spank on its face within interrupt handler. 1236 */ 1237 if (revid == VIA8233_REV_ID_8251) 1238 via->dma_eol_wake = 1; 1239 else 1240 via->dma_eol_wake = 0; 1241 1242 /* 1243 * Decide whether DXS had to be disabled or not 1244 */ 1245 if (revid == VIA8233_REV_ID_8233A) { 1246 /* 1247 * DXS channel is disabled. Reports from multiple users 1248 * that it plays at half-speed. Do not see this behaviour 1249 * on available 8233C or when emulating 8233A register set 1250 * on 8233C (either with or without ac97 VRA). 1251 */ 1252 via_dxs_disabled = 1; 1253 } else if (resource_int_value(device_get_name(dev), 1254 device_get_unit(dev), "via_dxs_disabled", 1255 &via_dxs_disabled) == 0) 1256 via_dxs_disabled = (via_dxs_disabled > 0) ? 1 : 0; 1257 else 1258 via_dxs_disabled = 0; 1259 1260 if (via_dxs_disabled) { 1261 via_dxs_chnum = 0; 1262 via_sgd_chnum = 1; 1263 } else { 1264 if (resource_int_value(device_get_name(dev), 1265 device_get_unit(dev), "via_dxs_channels", 1266 &via_dxs_chnum) != 0) 1267 via_dxs_chnum = NDXSCHANS; 1268 if (resource_int_value(device_get_name(dev), 1269 device_get_unit(dev), "via_sgd_channels", 1270 &via_sgd_chnum) != 0) 1271 via_sgd_chnum = NMSGDCHANS; 1272 } 1273 if (via_dxs_chnum > NDXSCHANS) 1274 via_dxs_chnum = NDXSCHANS; 1275 else if (via_dxs_chnum < 0) 1276 via_dxs_chnum = 0; 1277 if (via_sgd_chnum > NMSGDCHANS) 1278 via_sgd_chnum = NMSGDCHANS; 1279 else if (via_sgd_chnum < 0) 1280 via_sgd_chnum = 0; 1281 if (via_dxs_chnum + via_sgd_chnum < 1) { 1282 /* Minimalist ? */ 1283 via_dxs_chnum = 1; 1284 via_sgd_chnum = 0; 1285 } 1286 if (via_dxs_chnum > 0 && resource_int_value(device_get_name(dev), 1287 device_get_unit(dev), "via_dxs_src", &via_dxs_src) == 0) 1288 via->dxs_src = (via_dxs_src > 0) ? 1 : 0; 1289 else 1290 via->dxs_src = 0; 1291 1292 nsegs = (via_dxs_chnum + via_sgd_chnum + NWRCHANS) * VIA_SEGS_MAX; 1293 1294 /* DMA tag for buffers */ 1295 if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2, 1296 /*boundary*/0, 1297 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 1298 /*highaddr*/BUS_SPACE_MAXADDR, 1299 /*filter*/NULL, /*filterarg*/NULL, 1300 /*maxsize*/via->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff, 1301 /*flags*/0, /*lockfunc*/NULL, 1302 /*lockarg*/NULL, &via->parent_dmat) != 0) { 1303 device_printf(dev, "unable to create dma tag\n"); 1304 goto bad; 1305 } 1306 1307 /* 1308 * DMA tag for SGD table. The 686 uses scatter/gather DMA and 1309 * requires a list in memory of work to do. We need only 16 bytes 1310 * for this list, and it is wasteful to allocate 16K. 1311 */ 1312 if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2, 1313 /*boundary*/0, 1314 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 1315 /*highaddr*/BUS_SPACE_MAXADDR, 1316 /*filter*/NULL, /*filterarg*/NULL, 1317 /*maxsize*/nsegs * sizeof(struct via_dma_op), 1318 /*nsegments*/1, /*maxsegz*/0x3ffff, 1319 /*flags*/0, /*lockfunc*/NULL, 1320 /*lockarg*/NULL, &via->sgd_dmat) != 0) { 1321 device_printf(dev, "unable to create dma tag\n"); 1322 goto bad; 1323 } 1324 1325 if (bus_dmamem_alloc(via->sgd_dmat, (void **)&via->sgd_table, 1326 BUS_DMA_NOWAIT, &via->sgd_dmamap) == -1) 1327 goto bad; 1328 if (bus_dmamap_load(via->sgd_dmat, via->sgd_dmamap, via->sgd_table, 1329 nsegs * sizeof(struct via_dma_op), dma_cb, via, 0)) 1330 goto bad; 1331 1332 if (via_chip_init(dev)) 1333 goto bad; 1334 1335 via->codec = AC97_CREATE(dev, via, via_ac97); 1336 if (!via->codec) 1337 goto bad; 1338 1339 mixer_init(dev, ac97_getmixerclass(), via->codec); 1340 1341 via->codec_caps = ac97_getextcaps(via->codec); 1342 1343 /* Try to set VRA without generating an error, VRM not reqrd yet */ 1344 if (via->codec_caps & 1345 (AC97_EXTCAP_VRA | AC97_EXTCAP_VRM | AC97_EXTCAP_DRA)) { 1346 uint16_t ext = ac97_getextmode(via->codec); 1347 ext |= (via->codec_caps & 1348 (AC97_EXTCAP_VRA | AC97_EXTCAP_VRM)); 1349 ext &= ~AC97_EXTCAP_DRA; 1350 ac97_setextmode(via->codec, ext); 1351 } 1352 1353 snprintf(status, SND_STATUSLEN, "at io 0x%jx irq %jd %s", 1354 rman_get_start(via->reg), rman_get_start(via->irq), 1355 PCM_KLDSTRING(snd_via8233)); 1356 1357 /* Register */ 1358 if (pcm_register(dev, via, via_dxs_chnum + via_sgd_chnum, NWRCHANS)) 1359 goto bad; 1360 for (i = 0; i < via_dxs_chnum; i++) 1361 pcm_addchan(dev, PCMDIR_PLAY, &via8233dxs_class, via); 1362 for (i = 0; i < via_sgd_chnum; i++) 1363 pcm_addchan(dev, PCMDIR_PLAY, &via8233msgd_class, via); 1364 for (i = 0; i < NWRCHANS; i++) 1365 pcm_addchan(dev, PCMDIR_REC, &via8233wr_class, via); 1366 if (via_dxs_chnum > 0) 1367 via_init_sysctls(dev); 1368 device_printf(dev, "<VIA DXS %sabled: DXS%s %d / SGD %d / REC %d>\n", 1369 (via_dxs_chnum > 0) ? "En" : "Dis", (via->dxs_src) ? "(SRC)" : "", 1370 via_dxs_chnum, via_sgd_chnum, NWRCHANS); 1371 1372 pcm_setstatus(dev, status); 1373 1374 return (0); 1375 bad: 1376 if (via->codec) 1377 ac97_destroy(via->codec); 1378 if (via->reg) 1379 bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg); 1380 if (via->ih) 1381 bus_teardown_intr(dev, via->irq, via->ih); 1382 if (via->irq) 1383 bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq); 1384 if (via->parent_dmat) 1385 bus_dma_tag_destroy(via->parent_dmat); 1386 if (via->sgd_addr) 1387 bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap); 1388 if (via->sgd_table) 1389 bus_dmamem_free(via->sgd_dmat, via->sgd_table, via->sgd_dmamap); 1390 if (via->sgd_dmat) 1391 bus_dma_tag_destroy(via->sgd_dmat); 1392 if (via->lock) 1393 snd_mtxfree(via->lock); 1394 if (via) 1395 free(via, M_DEVBUF); 1396 return (ENXIO); 1397 } 1398 1399 static int 1400 via_detach(device_t dev) 1401 { 1402 int r; 1403 struct via_info *via; 1404 1405 r = pcm_unregister(dev); 1406 if (r) 1407 return (r); 1408 1409 via = pcm_getdevinfo(dev); 1410 1411 if (via != NULL && (via->play_num != 0 || via->rec_num != 0)) { 1412 snd_mtxlock(via->lock); 1413 via->polling = 0; 1414 callout_stop(&via->poll_timer); 1415 snd_mtxunlock(via->lock); 1416 callout_drain(&via->poll_timer); 1417 } 1418 1419 bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg); 1420 bus_teardown_intr(dev, via->irq, via->ih); 1421 bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq); 1422 bus_dma_tag_destroy(via->parent_dmat); 1423 bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap); 1424 bus_dmamem_free(via->sgd_dmat, via->sgd_table, via->sgd_dmamap); 1425 bus_dma_tag_destroy(via->sgd_dmat); 1426 snd_mtxfree(via->lock); 1427 free(via, M_DEVBUF); 1428 return (0); 1429 } 1430 1431 1432 static device_method_t via_methods[] = { 1433 DEVMETHOD(device_probe, via_probe), 1434 DEVMETHOD(device_attach, via_attach), 1435 DEVMETHOD(device_detach, via_detach), 1436 { 0, 0} 1437 }; 1438 1439 static driver_t via_driver = { 1440 "pcm", 1441 via_methods, 1442 PCM_SOFTC_SIZE, 1443 }; 1444 1445 DRIVER_MODULE(snd_via8233, pci, via_driver, pcm_devclass, 0, 0); 1446 MODULE_DEPEND(snd_via8233, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 1447 MODULE_VERSION(snd_via8233, 1); 1448