1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 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(""); 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 | CTLFLAG_MPSAFE, 262 dev, sizeof(dev), 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 | CTLFLAG_MPSAFE, 267 dev, sizeof(dev), 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 | CTLFLAG_MPSAFE, 272 dev, sizeof(dev), sysctl_via_polling, "I", "Enable polling mode"); 273 } 274 275 static __inline uint32_t 276 via_rd(struct via_info *via, int regno, int size) 277 { 278 switch (size) { 279 case 1: 280 return (bus_space_read_1(via->st, via->sh, regno)); 281 case 2: 282 return (bus_space_read_2(via->st, via->sh, regno)); 283 case 4: 284 return (bus_space_read_4(via->st, via->sh, regno)); 285 default: 286 return (0xFFFFFFFF); 287 } 288 } 289 290 static __inline void 291 via_wr(struct via_info *via, int regno, uint32_t data, int size) 292 { 293 294 switch (size) { 295 case 1: 296 bus_space_write_1(via->st, via->sh, regno, data); 297 break; 298 case 2: 299 bus_space_write_2(via->st, via->sh, regno, data); 300 break; 301 case 4: 302 bus_space_write_4(via->st, via->sh, regno, data); 303 break; 304 } 305 } 306 307 /* -------------------------------------------------------------------- */ 308 /* Codec interface */ 309 310 static int 311 via_waitready_codec(struct via_info *via) 312 { 313 int i; 314 315 /* poll until codec not busy */ 316 for (i = 0; i < 1000; i++) { 317 if ((via_rd(via, VIA_AC97_CONTROL, 4) & VIA_AC97_BUSY) == 0) 318 return (0); 319 DELAY(1); 320 } 321 device_printf(via->dev, "%s: codec busy\n", __func__); 322 return (1); 323 } 324 325 static int 326 via_waitvalid_codec(struct via_info *via) 327 { 328 int i; 329 330 /* poll until codec valid */ 331 for (i = 0; i < 1000; i++) { 332 if (via_rd(via, VIA_AC97_CONTROL, 4) & VIA_AC97_CODEC00_VALID) 333 return (0); 334 DELAY(1); 335 } 336 device_printf(via->dev, "%s: codec invalid\n", __func__); 337 return (1); 338 } 339 340 static int 341 via_write_codec(kobj_t obj, void *addr, int reg, uint32_t val) 342 { 343 struct via_info *via = addr; 344 345 if (via_waitready_codec(via)) 346 return (-1); 347 348 via_wr(via, VIA_AC97_CONTROL, 349 VIA_AC97_CODEC00_VALID | VIA_AC97_INDEX(reg) | 350 VIA_AC97_DATA(val), 4); 351 352 return (0); 353 } 354 355 static int 356 via_read_codec(kobj_t obj, void *addr, int reg) 357 { 358 struct via_info *via = addr; 359 360 if (via_waitready_codec(via)) 361 return (-1); 362 363 via_wr(via, VIA_AC97_CONTROL, VIA_AC97_CODEC00_VALID | 364 VIA_AC97_READ | VIA_AC97_INDEX(reg), 4); 365 366 if (via_waitready_codec(via)) 367 return (-1); 368 369 if (via_waitvalid_codec(via)) 370 return (-1); 371 372 return (via_rd(via, VIA_AC97_CONTROL, 2)); 373 } 374 375 static kobj_method_t via_ac97_methods[] = { 376 KOBJMETHOD(ac97_read, via_read_codec), 377 KOBJMETHOD(ac97_write, via_write_codec), 378 KOBJMETHOD_END 379 }; 380 AC97_DECLARE(via_ac97); 381 382 /* -------------------------------------------------------------------- */ 383 384 static int 385 via_buildsgdt(struct via_chinfo *ch) 386 { 387 uint32_t phys_addr, flag; 388 int i; 389 390 phys_addr = sndbuf_getbufaddr(ch->buffer); 391 392 for (i = 0; i < ch->blkcnt; i++) { 393 flag = (i == ch->blkcnt - 1) ? VIA_DMAOP_EOL : VIA_DMAOP_FLAG; 394 ch->sgd_table[i].ptr = phys_addr + (i * ch->blksz); 395 ch->sgd_table[i].flags = flag | ch->blksz; 396 } 397 398 return (0); 399 } 400 401 /* -------------------------------------------------------------------- */ 402 /* Format setting functions */ 403 404 static int 405 via8233wr_setformat(kobj_t obj, void *data, uint32_t format) 406 { 407 struct via_chinfo *ch = data; 408 struct via_info *via = ch->parent; 409 410 uint32_t f = WR_FORMAT_STOP_INDEX; 411 412 if (AFMT_CHANNEL(format) > 1) 413 f |= WR_FORMAT_STEREO; 414 if (format & AFMT_S16_LE) 415 f |= WR_FORMAT_16BIT; 416 snd_mtxlock(via->lock); 417 via_wr(via, VIA_WR0_FORMAT, f, 4); 418 snd_mtxunlock(via->lock); 419 420 return (0); 421 } 422 423 static int 424 via8233dxs_setformat(kobj_t obj, void *data, uint32_t format) 425 { 426 struct via_chinfo *ch = data; 427 struct via_info *via = ch->parent; 428 uint32_t r, v; 429 430 r = ch->rbase + VIA8233_RP_DXS_RATEFMT; 431 snd_mtxlock(via->lock); 432 v = via_rd(via, r, 4); 433 434 v &= ~(VIA8233_DXS_RATEFMT_STEREO | VIA8233_DXS_RATEFMT_16BIT); 435 if (AFMT_CHANNEL(format) > 1) 436 v |= VIA8233_DXS_RATEFMT_STEREO; 437 if (format & AFMT_16BIT) 438 v |= VIA8233_DXS_RATEFMT_16BIT; 439 via_wr(via, r, v, 4); 440 snd_mtxunlock(via->lock); 441 442 return (0); 443 } 444 445 static int 446 via8233msgd_setformat(kobj_t obj, void *data, uint32_t format) 447 { 448 struct via_chinfo *ch = data; 449 struct via_info *via = ch->parent; 450 451 uint32_t s = 0xff000000; 452 uint8_t v = (format & AFMT_S16_LE) ? MC_SGD_16BIT : MC_SGD_8BIT; 453 454 if (AFMT_CHANNEL(format) > 1) { 455 v |= MC_SGD_CHANNELS(2); 456 s |= SLOT3(1) | SLOT4(2); 457 } else { 458 v |= MC_SGD_CHANNELS(1); 459 s |= SLOT3(1) | SLOT4(1); 460 } 461 462 snd_mtxlock(via->lock); 463 via_wr(via, VIA_MC_SLOT_SELECT, s, 4); 464 via_wr(via, VIA_MC_SGD_FORMAT, v, 1); 465 snd_mtxunlock(via->lock); 466 467 return (0); 468 } 469 470 /* -------------------------------------------------------------------- */ 471 /* Speed setting functions */ 472 473 static uint32_t 474 via8233wr_setspeed(kobj_t obj, void *data, uint32_t speed) 475 { 476 struct via_chinfo *ch = data; 477 struct via_info *via = ch->parent; 478 479 if (via->codec_caps & AC97_EXTCAP_VRA) 480 return (ac97_setrate(via->codec, AC97_REGEXT_LADCRATE, speed)); 481 482 return (48000); 483 } 484 485 static uint32_t 486 via8233dxs_setspeed(kobj_t obj, void *data, uint32_t speed) 487 { 488 struct via_chinfo *ch = data; 489 struct via_info *via = ch->parent; 490 uint32_t r, v; 491 492 r = ch->rbase + VIA8233_RP_DXS_RATEFMT; 493 snd_mtxlock(via->lock); 494 v = via_rd(via, r, 4) & ~VIA8233_DXS_RATEFMT_48K; 495 496 /* Careful to avoid overflow (divide by 48 per vt8233c docs) */ 497 498 v |= VIA8233_DXS_RATEFMT_48K * (speed / 48) / (48000 / 48); 499 via_wr(via, r, v, 4); 500 snd_mtxunlock(via->lock); 501 502 return (speed); 503 } 504 505 static uint32_t 506 via8233msgd_setspeed(kobj_t obj, void *data, uint32_t speed) 507 { 508 struct via_chinfo *ch = data; 509 struct via_info *via = ch->parent; 510 511 if (via->codec_caps & AC97_EXTCAP_VRA) 512 return (ac97_setrate(via->codec, AC97_REGEXT_FDACRATE, speed)); 513 514 return (48000); 515 } 516 517 /* -------------------------------------------------------------------- */ 518 /* Format probing functions */ 519 520 static struct pcmchan_caps * 521 via8233wr_getcaps(kobj_t obj, void *data) 522 { 523 struct via_chinfo *ch = data; 524 struct via_info *via = ch->parent; 525 526 /* Controlled by ac97 registers */ 527 if (via->codec_caps & AC97_EXTCAP_VRA) 528 return (&via_vracaps); 529 return (&via_caps); 530 } 531 532 static struct pcmchan_caps * 533 via8233dxs_getcaps(kobj_t obj, void *data) 534 { 535 struct via_chinfo *ch = data; 536 struct via_info *via = ch->parent; 537 538 /* 539 * Controlled by onboard registers 540 * 541 * Apparently, few boards can do DXS sample rate 542 * conversion. 543 */ 544 if (via->dxs_src) 545 return (&via_vracaps); 546 return (&via_caps); 547 } 548 549 static struct pcmchan_caps * 550 via8233msgd_getcaps(kobj_t obj, void *data) 551 { 552 struct via_chinfo *ch = data; 553 struct via_info *via = ch->parent; 554 555 /* Controlled by ac97 registers */ 556 if (via->codec_caps & AC97_EXTCAP_VRA) 557 return (&via_vracaps); 558 return (&via_caps); 559 } 560 561 /* -------------------------------------------------------------------- */ 562 /* Common functions */ 563 564 static int 565 via8233chan_setfragments(kobj_t obj, void *data, 566 uint32_t blksz, uint32_t blkcnt) 567 { 568 struct via_chinfo *ch = data; 569 struct via_info *via = ch->parent; 570 571 blksz &= VIA_BLK_ALIGN; 572 573 if (blksz > (sndbuf_getmaxsize(ch->buffer) / VIA_SEGS_MIN)) 574 blksz = sndbuf_getmaxsize(ch->buffer) / VIA_SEGS_MIN; 575 if (blksz < VIA_BLK_MIN) 576 blksz = VIA_BLK_MIN; 577 if (blkcnt > VIA_SEGS_MAX) 578 blkcnt = VIA_SEGS_MAX; 579 if (blkcnt < VIA_SEGS_MIN) 580 blkcnt = VIA_SEGS_MIN; 581 582 while ((blksz * blkcnt) > sndbuf_getmaxsize(ch->buffer)) { 583 if ((blkcnt >> 1) >= VIA_SEGS_MIN) 584 blkcnt >>= 1; 585 else if ((blksz >> 1) >= VIA_BLK_MIN) 586 blksz >>= 1; 587 else 588 break; 589 } 590 591 if ((sndbuf_getblksz(ch->buffer) != blksz || 592 sndbuf_getblkcnt(ch->buffer) != blkcnt) && 593 sndbuf_resize(ch->buffer, blkcnt, blksz) != 0) 594 device_printf(via->dev, "%s: failed blksz=%u blkcnt=%u\n", 595 __func__, blksz, blkcnt); 596 597 ch->blksz = sndbuf_getblksz(ch->buffer); 598 ch->blkcnt = sndbuf_getblkcnt(ch->buffer); 599 600 return (0); 601 } 602 603 static uint32_t 604 via8233chan_setblocksize(kobj_t obj, void *data, uint32_t blksz) 605 { 606 struct via_chinfo *ch = data; 607 struct via_info *via = ch->parent; 608 609 via8233chan_setfragments(obj, data, blksz, via->blkcnt); 610 611 return (ch->blksz); 612 } 613 614 static uint32_t 615 via8233chan_getptr(kobj_t obj, void *data) 616 { 617 struct via_chinfo *ch = data; 618 struct via_info *via = ch->parent; 619 uint32_t v, index, count, ptr; 620 621 snd_mtxlock(via->lock); 622 if (via->polling != 0) { 623 ptr = ch->ptr; 624 snd_mtxunlock(via->lock); 625 } else { 626 v = via_rd(via, ch->rbase + VIA_RP_CURRENT_COUNT, 4); 627 snd_mtxunlock(via->lock); 628 index = v >> 24; /* Last completed buffer */ 629 count = v & 0x00ffffff; /* Bytes remaining */ 630 ptr = (index + 1) * ch->blksz - count; 631 ptr %= ch->blkcnt * ch->blksz; /* Wrap to available space */ 632 } 633 634 return (ptr); 635 } 636 637 static void 638 via8233chan_reset(struct via_info *via, struct via_chinfo *ch) 639 { 640 via_wr(via, ch->rbase + VIA_RP_CONTROL, SGD_CONTROL_STOP, 1); 641 via_wr(via, ch->rbase + VIA_RP_CONTROL, 0x00, 1); 642 via_wr(via, ch->rbase + VIA_RP_STATUS, 643 SGD_STATUS_EOL | SGD_STATUS_FLAG, 1); 644 } 645 646 /* -------------------------------------------------------------------- */ 647 /* Channel initialization functions */ 648 649 static void 650 via8233chan_sgdinit(struct via_info *via, struct via_chinfo *ch, int chnum) 651 { 652 ch->sgd_table = &via->sgd_table[chnum * VIA_SEGS_MAX]; 653 ch->sgd_addr = via->sgd_addr + chnum * VIA_SEGS_MAX * 654 sizeof(struct via_dma_op); 655 } 656 657 static void* 658 via8233wr_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, 659 struct pcm_channel *c, int dir) 660 { 661 struct via_info *via = devinfo; 662 struct via_chinfo *ch; 663 int num; 664 665 snd_mtxlock(via->lock); 666 num = via->rec_num++; 667 ch = &via->rch[num]; 668 ch->parent = via; 669 ch->channel = c; 670 ch->buffer = b; 671 ch->dir = dir; 672 ch->blkcnt = via->blkcnt; 673 ch->rbase = VIA_WR_BASE(num); 674 via_wr(via, ch->rbase + VIA_WR_RP_SGD_FORMAT, WR_FIFO_ENABLE, 1); 675 snd_mtxunlock(via->lock); 676 677 if (sndbuf_alloc(ch->buffer, via->parent_dmat, 0, via->bufsz) != 0) 678 return (NULL); 679 680 snd_mtxlock(via->lock); 681 via8233chan_sgdinit(via, ch, num); 682 via8233chan_reset(via, ch); 683 snd_mtxunlock(via->lock); 684 685 return (ch); 686 } 687 688 static void* 689 via8233dxs_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, 690 struct pcm_channel *c, int dir) 691 { 692 struct via_info *via = devinfo; 693 struct via_chinfo *ch; 694 int num; 695 696 snd_mtxlock(via->lock); 697 num = via->play_num++; 698 ch = &via->pch[num]; 699 ch->parent = via; 700 ch->channel = c; 701 ch->buffer = b; 702 ch->dir = dir; 703 ch->blkcnt = via->blkcnt; 704 705 /* 706 * All cards apparently support DXS3, but not other DXS 707 * channels. We therefore want to align first DXS channel to 708 * DXS3. 709 */ 710 ch->rbase = VIA_DXS_BASE(NDXSCHANS - 1 - via->n_dxs_registered); 711 via->n_dxs_registered++; 712 snd_mtxunlock(via->lock); 713 714 if (sndbuf_alloc(ch->buffer, via->parent_dmat, 0, via->bufsz) != 0) 715 return (NULL); 716 717 snd_mtxlock(via->lock); 718 via8233chan_sgdinit(via, ch, NWRCHANS + num); 719 via8233chan_reset(via, ch); 720 snd_mtxunlock(via->lock); 721 722 return (ch); 723 } 724 725 static void* 726 via8233msgd_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, 727 struct pcm_channel *c, int dir) 728 { 729 struct via_info *via = devinfo; 730 struct via_chinfo *ch; 731 int num; 732 733 snd_mtxlock(via->lock); 734 num = via->play_num++; 735 ch = &via->pch[num]; 736 ch->parent = via; 737 ch->channel = c; 738 ch->buffer = b; 739 ch->dir = dir; 740 ch->rbase = VIA_MC_SGD_STATUS; 741 ch->blkcnt = via->blkcnt; 742 snd_mtxunlock(via->lock); 743 744 if (sndbuf_alloc(ch->buffer, via->parent_dmat, 0, via->bufsz) != 0) 745 return (NULL); 746 747 snd_mtxlock(via->lock); 748 via8233chan_sgdinit(via, ch, NWRCHANS + num); 749 via8233chan_reset(via, ch); 750 snd_mtxunlock(via->lock); 751 752 return (ch); 753 } 754 755 static void 756 via8233chan_mute(struct via_info *via, struct via_chinfo *ch, int muted) 757 { 758 if (BASE_IS_VIA_DXS_REG(ch->rbase)) { 759 int r; 760 muted = (muted) ? VIA8233_DXS_MUTE : 0; 761 via_wr(via, ch->rbase + VIA8233_RP_DXS_LVOL, muted, 1); 762 via_wr(via, ch->rbase + VIA8233_RP_DXS_RVOL, muted, 1); 763 r = via_rd(via, ch->rbase + VIA8233_RP_DXS_LVOL, 1) & 764 VIA8233_DXS_MUTE; 765 if (r != muted) 766 device_printf(via->dev, 767 "%s: failed to set dxs volume " 768 "(dxs base 0x%02x).\n", __func__, ch->rbase); 769 } 770 } 771 772 static __inline int 773 via_poll_channel(struct via_chinfo *ch) 774 { 775 struct via_info *via; 776 uint32_t sz, delta; 777 uint32_t v, index, count; 778 int ptr; 779 780 if (ch == NULL || ch->channel == NULL || ch->active == 0) 781 return (0); 782 783 via = ch->parent; 784 sz = ch->blksz * ch->blkcnt; 785 v = via_rd(via, ch->rbase + VIA_RP_CURRENT_COUNT, 4); 786 index = v >> 24; 787 count = v & 0x00ffffff; 788 ptr = ((index + 1) * ch->blksz) - count; 789 ptr %= sz; 790 ptr &= ~(ch->blksz - 1); 791 ch->ptr = ptr; 792 delta = (sz + ptr - ch->prevptr) % sz; 793 794 if (delta < ch->blksz) 795 return (0); 796 797 ch->prevptr = ptr; 798 799 return (1); 800 } 801 802 static void 803 via_poll_callback(void *arg) 804 { 805 struct via_info *via = arg; 806 uint32_t ptrigger = 0, rtrigger = 0; 807 int i; 808 809 if (via == NULL) 810 return; 811 812 snd_mtxlock(via->lock); 813 if (via->polling == 0 || via_chan_active(via) == 0) { 814 snd_mtxunlock(via->lock); 815 return; 816 } 817 818 for (i = 0; i < NDXSCHANS + NMSGDCHANS; i++) 819 ptrigger |= (via_poll_channel(&via->pch[i]) != 0) ? 820 (1 << i) : 0; 821 822 for (i = 0; i < NWRCHANS; i++) 823 rtrigger |= (via_poll_channel(&via->rch[i]) != 0) ? 824 (1 << i) : 0; 825 826 /* XXX */ 827 callout_reset(&via->poll_timer, 1/*via->poll_ticks*/, 828 via_poll_callback, via); 829 830 snd_mtxunlock(via->lock); 831 832 for (i = 0; i < NDXSCHANS + NMSGDCHANS; i++) { 833 if (ptrigger & (1 << i)) 834 chn_intr(via->pch[i].channel); 835 } 836 for (i = 0; i < NWRCHANS; i++) { 837 if (rtrigger & (1 << i)) 838 chn_intr(via->rch[i].channel); 839 } 840 } 841 842 static int 843 via_poll_ticks(struct via_info *via) 844 { 845 struct via_chinfo *ch; 846 int i; 847 int ret = hz; 848 int pollticks; 849 850 for (i = 0; i < NDXSCHANS + NMSGDCHANS; i++) { 851 ch = &via->pch[i]; 852 if (ch->channel == NULL || ch->active == 0) 853 continue; 854 pollticks = ((uint64_t)hz * ch->blksz) / 855 ((uint64_t)sndbuf_getalign(ch->buffer) * 856 sndbuf_getspd(ch->buffer)); 857 pollticks >>= 2; 858 if (pollticks > hz) 859 pollticks = hz; 860 if (pollticks < 1) 861 pollticks = 1; 862 if (pollticks < ret) 863 ret = pollticks; 864 } 865 866 for (i = 0; i < NWRCHANS; i++) { 867 ch = &via->rch[i]; 868 if (ch->channel == NULL || ch->active == 0) 869 continue; 870 pollticks = ((uint64_t)hz * ch->blksz) / 871 ((uint64_t)sndbuf_getalign(ch->buffer) * 872 sndbuf_getspd(ch->buffer)); 873 pollticks >>= 2; 874 if (pollticks > hz) 875 pollticks = hz; 876 if (pollticks < 1) 877 pollticks = 1; 878 if (pollticks < ret) 879 ret = pollticks; 880 } 881 882 return (ret); 883 } 884 885 static int 886 via8233chan_trigger(kobj_t obj, void* data, int go) 887 { 888 struct via_chinfo *ch = data; 889 struct via_info *via = ch->parent; 890 int pollticks; 891 892 if (!PCMTRIG_COMMON(go)) 893 return (0); 894 895 snd_mtxlock(via->lock); 896 switch(go) { 897 case PCMTRIG_START: 898 via_buildsgdt(ch); 899 via8233chan_mute(via, ch, 0); 900 via_wr(via, ch->rbase + VIA_RP_TABLE_PTR, ch->sgd_addr, 4); 901 if (via->polling != 0) { 902 ch->ptr = 0; 903 ch->prevptr = 0; 904 pollticks = ((uint64_t)hz * ch->blksz) / 905 ((uint64_t)sndbuf_getalign(ch->buffer) * 906 sndbuf_getspd(ch->buffer)); 907 pollticks >>= 2; 908 if (pollticks > hz) 909 pollticks = hz; 910 if (pollticks < 1) 911 pollticks = 1; 912 if (via_chan_active(via) == 0 || 913 pollticks < via->poll_ticks) { 914 if (bootverbose) { 915 if (via_chan_active(via) == 0) 916 printf("%s: pollticks=%d\n", 917 __func__, pollticks); 918 else 919 printf("%s: " 920 "pollticks %d -> %d\n", 921 __func__, via->poll_ticks, 922 pollticks); 923 } 924 via->poll_ticks = pollticks; 925 callout_reset(&via->poll_timer, 1, 926 via_poll_callback, via); 927 } 928 } 929 via_wr(via, ch->rbase + VIA_RP_CONTROL, 930 SGD_CONTROL_START | SGD_CONTROL_AUTOSTART | 931 ((via->polling == 0) ? 932 (SGD_CONTROL_I_EOL | SGD_CONTROL_I_FLAG) : 0), 1); 933 ch->active = 1; 934 break; 935 case PCMTRIG_STOP: 936 case PCMTRIG_ABORT: 937 via_wr(via, ch->rbase + VIA_RP_CONTROL, SGD_CONTROL_STOP, 1); 938 via8233chan_mute(via, ch, 1); 939 via8233chan_reset(via, ch); 940 ch->active = 0; 941 if (via->polling != 0) { 942 if (via_chan_active(via) == 0) { 943 callout_stop(&via->poll_timer); 944 via->poll_ticks = 1; 945 } else { 946 pollticks = via_poll_ticks(via); 947 if (pollticks > via->poll_ticks) { 948 if (bootverbose) 949 printf("%s: pollticks " 950 "%d -> %d\n", 951 __func__, via->poll_ticks, 952 pollticks); 953 via->poll_ticks = pollticks; 954 callout_reset(&via->poll_timer, 955 1, via_poll_callback, 956 via); 957 } 958 } 959 } 960 break; 961 default: 962 break; 963 } 964 snd_mtxunlock(via->lock); 965 return (0); 966 } 967 968 static kobj_method_t via8233wr_methods[] = { 969 KOBJMETHOD(channel_init, via8233wr_init), 970 KOBJMETHOD(channel_setformat, via8233wr_setformat), 971 KOBJMETHOD(channel_setspeed, via8233wr_setspeed), 972 KOBJMETHOD(channel_getcaps, via8233wr_getcaps), 973 KOBJMETHOD(channel_setblocksize, via8233chan_setblocksize), 974 KOBJMETHOD(channel_setfragments, via8233chan_setfragments), 975 KOBJMETHOD(channel_trigger, via8233chan_trigger), 976 KOBJMETHOD(channel_getptr, via8233chan_getptr), 977 KOBJMETHOD_END 978 }; 979 CHANNEL_DECLARE(via8233wr); 980 981 static kobj_method_t via8233dxs_methods[] = { 982 KOBJMETHOD(channel_init, via8233dxs_init), 983 KOBJMETHOD(channel_setformat, via8233dxs_setformat), 984 KOBJMETHOD(channel_setspeed, via8233dxs_setspeed), 985 KOBJMETHOD(channel_getcaps, via8233dxs_getcaps), 986 KOBJMETHOD(channel_setblocksize, via8233chan_setblocksize), 987 KOBJMETHOD(channel_setfragments, via8233chan_setfragments), 988 KOBJMETHOD(channel_trigger, via8233chan_trigger), 989 KOBJMETHOD(channel_getptr, via8233chan_getptr), 990 KOBJMETHOD_END 991 }; 992 CHANNEL_DECLARE(via8233dxs); 993 994 static kobj_method_t via8233msgd_methods[] = { 995 KOBJMETHOD(channel_init, via8233msgd_init), 996 KOBJMETHOD(channel_setformat, via8233msgd_setformat), 997 KOBJMETHOD(channel_setspeed, via8233msgd_setspeed), 998 KOBJMETHOD(channel_getcaps, via8233msgd_getcaps), 999 KOBJMETHOD(channel_setblocksize, via8233chan_setblocksize), 1000 KOBJMETHOD(channel_setfragments, via8233chan_setfragments), 1001 KOBJMETHOD(channel_trigger, via8233chan_trigger), 1002 KOBJMETHOD(channel_getptr, via8233chan_getptr), 1003 KOBJMETHOD_END 1004 }; 1005 CHANNEL_DECLARE(via8233msgd); 1006 1007 /* -------------------------------------------------------------------- */ 1008 1009 static void 1010 via_intr(void *p) 1011 { 1012 struct via_info *via = p; 1013 uint32_t ptrigger = 0, rtrigger = 0; 1014 int i, reg, stat; 1015 1016 snd_mtxlock(via->lock); 1017 if (via->polling != 0) { 1018 snd_mtxunlock(via->lock); 1019 return; 1020 } 1021 /* Poll playback channels */ 1022 for (i = 0; i < NDXSCHANS + NMSGDCHANS; i++) { 1023 if (via->pch[i].channel == NULL || via->pch[i].active == 0) 1024 continue; 1025 reg = via->pch[i].rbase + VIA_RP_STATUS; 1026 stat = via_rd(via, reg, 1); 1027 if (stat & SGD_STATUS_INTR) { 1028 if (via->dma_eol_wake && ((stat & SGD_STATUS_EOL) || 1029 !(stat & SGD_STATUS_ACTIVE))) 1030 via_wr(via, via->pch[i].rbase + VIA_RP_CONTROL, 1031 SGD_CONTROL_START | SGD_CONTROL_AUTOSTART | 1032 SGD_CONTROL_I_EOL | SGD_CONTROL_I_FLAG, 1); 1033 via_wr(via, reg, stat, 1); 1034 ptrigger |= 1 << i; 1035 } 1036 } 1037 /* Poll record channels */ 1038 for (i = 0; i < NWRCHANS; i++) { 1039 if (via->rch[i].channel == NULL || via->rch[i].active == 0) 1040 continue; 1041 reg = via->rch[i].rbase + VIA_RP_STATUS; 1042 stat = via_rd(via, reg, 1); 1043 if (stat & SGD_STATUS_INTR) { 1044 if (via->dma_eol_wake && ((stat & SGD_STATUS_EOL) || 1045 !(stat & SGD_STATUS_ACTIVE))) 1046 via_wr(via, via->rch[i].rbase + VIA_RP_CONTROL, 1047 SGD_CONTROL_START | SGD_CONTROL_AUTOSTART | 1048 SGD_CONTROL_I_EOL | SGD_CONTROL_I_FLAG, 1); 1049 via_wr(via, reg, stat, 1); 1050 rtrigger |= 1 << i; 1051 } 1052 } 1053 snd_mtxunlock(via->lock); 1054 1055 for (i = 0; i < NDXSCHANS + NMSGDCHANS; i++) { 1056 if (ptrigger & (1 << i)) 1057 chn_intr(via->pch[i].channel); 1058 } 1059 for (i = 0; i < NWRCHANS; i++) { 1060 if (rtrigger & (1 << i)) 1061 chn_intr(via->rch[i].channel); 1062 } 1063 } 1064 1065 /* 1066 * Probe and attach the card 1067 */ 1068 static int 1069 via_probe(device_t dev) 1070 { 1071 switch(pci_get_devid(dev)) { 1072 case VIA8233_PCI_ID: 1073 switch(pci_get_revid(dev)) { 1074 case VIA8233_REV_ID_8233PRE: 1075 device_set_desc(dev, "VIA VT8233 (pre)"); 1076 return (BUS_PROBE_DEFAULT); 1077 case VIA8233_REV_ID_8233C: 1078 device_set_desc(dev, "VIA VT8233C"); 1079 return (BUS_PROBE_DEFAULT); 1080 case VIA8233_REV_ID_8233: 1081 device_set_desc(dev, "VIA VT8233"); 1082 return (BUS_PROBE_DEFAULT); 1083 case VIA8233_REV_ID_8233A: 1084 device_set_desc(dev, "VIA VT8233A"); 1085 return (BUS_PROBE_DEFAULT); 1086 case VIA8233_REV_ID_8235: 1087 device_set_desc(dev, "VIA VT8235"); 1088 return (BUS_PROBE_DEFAULT); 1089 case VIA8233_REV_ID_8237: 1090 device_set_desc(dev, "VIA VT8237"); 1091 return (BUS_PROBE_DEFAULT); 1092 case VIA8233_REV_ID_8251: 1093 device_set_desc(dev, "VIA VT8251"); 1094 return (BUS_PROBE_DEFAULT); 1095 default: 1096 device_set_desc(dev, "VIA VT8233X"); /* Unknown */ 1097 return (BUS_PROBE_DEFAULT); 1098 } 1099 } 1100 return (ENXIO); 1101 } 1102 1103 static void 1104 dma_cb(void *p, bus_dma_segment_t *bds, int a, int b) 1105 { 1106 struct via_info *via = (struct via_info *)p; 1107 via->sgd_addr = bds->ds_addr; 1108 } 1109 1110 static int 1111 via_chip_init(device_t dev) 1112 { 1113 uint32_t data, cnt; 1114 1115 /* Wake up and reset AC97 if necessary */ 1116 data = pci_read_config(dev, VIA_PCI_ACLINK_STAT, 1); 1117 1118 if ((data & VIA_PCI_ACLINK_C00_READY) == 0) { 1119 /* Cold reset per ac97r2.3 spec (page 95) */ 1120 /* Assert low */ 1121 pci_write_config(dev, VIA_PCI_ACLINK_CTRL, 1122 VIA_PCI_ACLINK_EN, 1); 1123 /* Wait T_rst_low */ 1124 DELAY(100); 1125 /* Assert high */ 1126 pci_write_config(dev, VIA_PCI_ACLINK_CTRL, 1127 VIA_PCI_ACLINK_EN | VIA_PCI_ACLINK_NRST, 1); 1128 /* Wait T_rst2clk */ 1129 DELAY(5); 1130 /* Assert low */ 1131 pci_write_config(dev, VIA_PCI_ACLINK_CTRL, 1132 VIA_PCI_ACLINK_EN, 1); 1133 } else { 1134 /* Warm reset */ 1135 /* Force no sync */ 1136 pci_write_config(dev, VIA_PCI_ACLINK_CTRL, 1137 VIA_PCI_ACLINK_EN, 1); 1138 DELAY(100); 1139 /* Sync */ 1140 pci_write_config(dev, VIA_PCI_ACLINK_CTRL, 1141 VIA_PCI_ACLINK_EN | VIA_PCI_ACLINK_SYNC, 1); 1142 /* Wait T_sync_high */ 1143 DELAY(5); 1144 /* Force no sync */ 1145 pci_write_config(dev, VIA_PCI_ACLINK_CTRL, 1146 VIA_PCI_ACLINK_EN, 1); 1147 /* Wait T_sync2clk */ 1148 DELAY(5); 1149 } 1150 1151 /* Power everything up */ 1152 pci_write_config(dev, VIA_PCI_ACLINK_CTRL, VIA_PCI_ACLINK_DESIRED, 1); 1153 1154 /* Wait for codec to become ready (largest reported delay 310ms) */ 1155 for (cnt = 0; cnt < 2000; cnt++) { 1156 data = pci_read_config(dev, VIA_PCI_ACLINK_STAT, 1); 1157 if (data & VIA_PCI_ACLINK_C00_READY) 1158 return (0); 1159 DELAY(5000); 1160 } 1161 device_printf(dev, "primary codec not ready (cnt = 0x%02x)\n", cnt); 1162 return (ENXIO); 1163 } 1164 1165 static int 1166 via_attach(device_t dev) 1167 { 1168 struct via_info *via = NULL; 1169 char status[SND_STATUSLEN]; 1170 int i, via_dxs_disabled, via_dxs_src, via_dxs_chnum, via_sgd_chnum; 1171 int nsegs; 1172 uint32_t revid; 1173 1174 via = malloc(sizeof *via, M_DEVBUF, M_WAITOK | M_ZERO); 1175 via->lock = snd_mtxcreate(device_get_nameunit(dev), 1176 "snd_via8233 softc"); 1177 via->dev = dev; 1178 1179 callout_init(&via->poll_timer, 1); 1180 via->poll_ticks = 1; 1181 1182 if (resource_int_value(device_get_name(dev), 1183 device_get_unit(dev), "polling", &i) == 0 && i != 0) 1184 via->polling = 1; 1185 else 1186 via->polling = 0; 1187 1188 pci_set_powerstate(dev, PCI_POWERSTATE_D0); 1189 pci_enable_busmaster(dev); 1190 1191 via->regid = PCIR_BAR(0); 1192 via->reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &via->regid, 1193 RF_ACTIVE); 1194 if (!via->reg) { 1195 device_printf(dev, "cannot allocate bus resource."); 1196 goto bad; 1197 } 1198 via->st = rman_get_bustag(via->reg); 1199 via->sh = rman_get_bushandle(via->reg); 1200 1201 via->irqid = 0; 1202 via->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &via->irqid, 1203 RF_ACTIVE | RF_SHAREABLE); 1204 if (!via->irq || 1205 snd_setup_intr(dev, via->irq, INTR_MPSAFE, 1206 via_intr, via, &via->ih)) { 1207 device_printf(dev, "unable to map interrupt\n"); 1208 goto bad; 1209 } 1210 1211 via->bufsz = pcm_getbuffersize(dev, 4096, VIA_DEFAULT_BUFSZ, 65536); 1212 if (resource_int_value(device_get_name(dev), 1213 device_get_unit(dev), "blocksize", &i) == 0 && i > 0) { 1214 i &= VIA_BLK_ALIGN; 1215 if (i < VIA_BLK_MIN) 1216 i = VIA_BLK_MIN; 1217 via->blkcnt = via->bufsz / i; 1218 i = 0; 1219 while (via->blkcnt >> i) 1220 i++; 1221 via->blkcnt = 1 << (i - 1); 1222 if (via->blkcnt < VIA_SEGS_MIN) 1223 via->blkcnt = VIA_SEGS_MIN; 1224 else if (via->blkcnt > VIA_SEGS_MAX) 1225 via->blkcnt = VIA_SEGS_MAX; 1226 1227 } else 1228 via->blkcnt = VIA_SEGS_DEFAULT; 1229 1230 revid = pci_get_revid(dev); 1231 1232 /* 1233 * VIA8251 lost its interrupt after DMA EOL, and need 1234 * a gentle spank on its face within interrupt handler. 1235 */ 1236 if (revid == VIA8233_REV_ID_8251) 1237 via->dma_eol_wake = 1; 1238 else 1239 via->dma_eol_wake = 0; 1240 1241 /* 1242 * Decide whether DXS had to be disabled or not 1243 */ 1244 if (revid == VIA8233_REV_ID_8233A) { 1245 /* 1246 * DXS channel is disabled. Reports from multiple users 1247 * that it plays at half-speed. Do not see this behaviour 1248 * on available 8233C or when emulating 8233A register set 1249 * on 8233C (either with or without ac97 VRA). 1250 */ 1251 via_dxs_disabled = 1; 1252 } else if (resource_int_value(device_get_name(dev), 1253 device_get_unit(dev), "via_dxs_disabled", 1254 &via_dxs_disabled) == 0) 1255 via_dxs_disabled = (via_dxs_disabled > 0) ? 1 : 0; 1256 else 1257 via_dxs_disabled = 0; 1258 1259 if (via_dxs_disabled) { 1260 via_dxs_chnum = 0; 1261 via_sgd_chnum = 1; 1262 } else { 1263 if (resource_int_value(device_get_name(dev), 1264 device_get_unit(dev), "via_dxs_channels", 1265 &via_dxs_chnum) != 0) 1266 via_dxs_chnum = NDXSCHANS; 1267 if (resource_int_value(device_get_name(dev), 1268 device_get_unit(dev), "via_sgd_channels", 1269 &via_sgd_chnum) != 0) 1270 via_sgd_chnum = NMSGDCHANS; 1271 } 1272 if (via_dxs_chnum > NDXSCHANS) 1273 via_dxs_chnum = NDXSCHANS; 1274 else if (via_dxs_chnum < 0) 1275 via_dxs_chnum = 0; 1276 if (via_sgd_chnum > NMSGDCHANS) 1277 via_sgd_chnum = NMSGDCHANS; 1278 else if (via_sgd_chnum < 0) 1279 via_sgd_chnum = 0; 1280 if (via_dxs_chnum + via_sgd_chnum < 1) { 1281 /* Minimalist ? */ 1282 via_dxs_chnum = 1; 1283 via_sgd_chnum = 0; 1284 } 1285 if (via_dxs_chnum > 0 && resource_int_value(device_get_name(dev), 1286 device_get_unit(dev), "via_dxs_src", &via_dxs_src) == 0) 1287 via->dxs_src = (via_dxs_src > 0) ? 1 : 0; 1288 else 1289 via->dxs_src = 0; 1290 1291 nsegs = (via_dxs_chnum + via_sgd_chnum + NWRCHANS) * VIA_SEGS_MAX; 1292 1293 /* DMA tag for buffers */ 1294 if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2, 1295 /*boundary*/0, 1296 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 1297 /*highaddr*/BUS_SPACE_MAXADDR, 1298 /*filter*/NULL, /*filterarg*/NULL, 1299 /*maxsize*/via->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff, 1300 /*flags*/0, /*lockfunc*/NULL, 1301 /*lockarg*/NULL, &via->parent_dmat) != 0) { 1302 device_printf(dev, "unable to create dma tag\n"); 1303 goto bad; 1304 } 1305 1306 /* 1307 * DMA tag for SGD table. The 686 uses scatter/gather DMA and 1308 * requires a list in memory of work to do. We need only 16 bytes 1309 * for this list, and it is wasteful to allocate 16K. 1310 */ 1311 if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2, 1312 /*boundary*/0, 1313 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 1314 /*highaddr*/BUS_SPACE_MAXADDR, 1315 /*filter*/NULL, /*filterarg*/NULL, 1316 /*maxsize*/nsegs * sizeof(struct via_dma_op), 1317 /*nsegments*/1, /*maxsegz*/0x3ffff, 1318 /*flags*/0, /*lockfunc*/NULL, 1319 /*lockarg*/NULL, &via->sgd_dmat) != 0) { 1320 device_printf(dev, "unable to create dma tag\n"); 1321 goto bad; 1322 } 1323 1324 if (bus_dmamem_alloc(via->sgd_dmat, (void **)&via->sgd_table, 1325 BUS_DMA_NOWAIT, &via->sgd_dmamap) == -1) 1326 goto bad; 1327 if (bus_dmamap_load(via->sgd_dmat, via->sgd_dmamap, via->sgd_table, 1328 nsegs * sizeof(struct via_dma_op), dma_cb, via, 0)) 1329 goto bad; 1330 1331 if (via_chip_init(dev)) 1332 goto bad; 1333 1334 via->codec = AC97_CREATE(dev, via, via_ac97); 1335 if (!via->codec) 1336 goto bad; 1337 1338 mixer_init(dev, ac97_getmixerclass(), via->codec); 1339 1340 via->codec_caps = ac97_getextcaps(via->codec); 1341 1342 /* Try to set VRA without generating an error, VRM not reqrd yet */ 1343 if (via->codec_caps & 1344 (AC97_EXTCAP_VRA | AC97_EXTCAP_VRM | AC97_EXTCAP_DRA)) { 1345 uint16_t ext = ac97_getextmode(via->codec); 1346 ext |= (via->codec_caps & 1347 (AC97_EXTCAP_VRA | AC97_EXTCAP_VRM)); 1348 ext &= ~AC97_EXTCAP_DRA; 1349 ac97_setextmode(via->codec, ext); 1350 } 1351 1352 snprintf(status, SND_STATUSLEN, "at io 0x%jx irq %jd %s", 1353 rman_get_start(via->reg), rman_get_start(via->irq), 1354 PCM_KLDSTRING(snd_via8233)); 1355 1356 /* Register */ 1357 if (pcm_register(dev, via, via_dxs_chnum + via_sgd_chnum, NWRCHANS)) 1358 goto bad; 1359 for (i = 0; i < via_dxs_chnum; i++) 1360 pcm_addchan(dev, PCMDIR_PLAY, &via8233dxs_class, via); 1361 for (i = 0; i < via_sgd_chnum; i++) 1362 pcm_addchan(dev, PCMDIR_PLAY, &via8233msgd_class, via); 1363 for (i = 0; i < NWRCHANS; i++) 1364 pcm_addchan(dev, PCMDIR_REC, &via8233wr_class, via); 1365 if (via_dxs_chnum > 0) 1366 via_init_sysctls(dev); 1367 device_printf(dev, "<VIA DXS %sabled: DXS%s %d / SGD %d / REC %d>\n", 1368 (via_dxs_chnum > 0) ? "En" : "Dis", (via->dxs_src) ? "(SRC)" : "", 1369 via_dxs_chnum, via_sgd_chnum, NWRCHANS); 1370 1371 pcm_setstatus(dev, status); 1372 1373 return (0); 1374 bad: 1375 if (via->codec) 1376 ac97_destroy(via->codec); 1377 if (via->reg) 1378 bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg); 1379 if (via->ih) 1380 bus_teardown_intr(dev, via->irq, via->ih); 1381 if (via->irq) 1382 bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq); 1383 if (via->parent_dmat) 1384 bus_dma_tag_destroy(via->parent_dmat); 1385 if (via->sgd_addr) 1386 bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap); 1387 if (via->sgd_table) 1388 bus_dmamem_free(via->sgd_dmat, via->sgd_table, via->sgd_dmamap); 1389 if (via->sgd_dmat) 1390 bus_dma_tag_destroy(via->sgd_dmat); 1391 if (via->lock) 1392 snd_mtxfree(via->lock); 1393 if (via) 1394 free(via, M_DEVBUF); 1395 return (ENXIO); 1396 } 1397 1398 static int 1399 via_detach(device_t dev) 1400 { 1401 int r; 1402 struct via_info *via; 1403 1404 r = pcm_unregister(dev); 1405 if (r) 1406 return (r); 1407 1408 via = pcm_getdevinfo(dev); 1409 1410 if (via != NULL && (via->play_num != 0 || via->rec_num != 0)) { 1411 snd_mtxlock(via->lock); 1412 via->polling = 0; 1413 callout_stop(&via->poll_timer); 1414 snd_mtxunlock(via->lock); 1415 callout_drain(&via->poll_timer); 1416 } 1417 1418 bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg); 1419 bus_teardown_intr(dev, via->irq, via->ih); 1420 bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq); 1421 bus_dma_tag_destroy(via->parent_dmat); 1422 bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap); 1423 bus_dmamem_free(via->sgd_dmat, via->sgd_table, via->sgd_dmamap); 1424 bus_dma_tag_destroy(via->sgd_dmat); 1425 snd_mtxfree(via->lock); 1426 free(via, M_DEVBUF); 1427 return (0); 1428 } 1429 1430 static device_method_t via_methods[] = { 1431 DEVMETHOD(device_probe, via_probe), 1432 DEVMETHOD(device_attach, via_attach), 1433 DEVMETHOD(device_detach, via_detach), 1434 { 0, 0} 1435 }; 1436 1437 static driver_t via_driver = { 1438 "pcm", 1439 via_methods, 1440 PCM_SOFTC_SIZE, 1441 }; 1442 1443 DRIVER_MODULE(snd_via8233, pci, via_driver, 0, 0); 1444 MODULE_DEPEND(snd_via8233, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 1445 MODULE_VERSION(snd_via8233, 1); 1446