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