via8233.c revision 148596
1/*- 2 * Copyright (c) 2002 Orion Hodson <orion@freebsd.org> 3 * Portions of this code derived from via82c686.c: 4 * Copyright (c) 2000 David Jones <dej@ox.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29/* 30 * Credits due to: 31 * 32 * Grzybowski Rafal, Russell Davies, Mark Handley, Daniel O'Connor for 33 * comments, machine time, testing patches, and patience. VIA for 34 * providing specs. ALSA for helpful comments and some register poke 35 * ordering. 36 */ 37 38#include <dev/sound/pcm/sound.h> 39#include <dev/sound/pcm/ac97.h> 40 41#include <dev/pci/pcireg.h> 42#include <dev/pci/pcivar.h> 43#include <sys/sysctl.h> 44 45#include <dev/sound/pci/via8233.h> 46 47SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/via8233.c 148596 2005-07-31 13:43:42Z netchild $"); 48 49#define VIA8233_PCI_ID 0x30591106 50 51#define VIA8233_REV_ID_8233PRE 0x10 52#define VIA8233_REV_ID_8233C 0x20 53#define VIA8233_REV_ID_8233 0x30 54#define VIA8233_REV_ID_8233A 0x40 55#define VIA8233_REV_ID_8235 0x50 56#define VIA8233_REV_ID_8237 0x60 57 58#define SEGS_PER_CHAN 2 /* Segments per channel */ 59#define NDXSCHANS 4 /* No of DXS channels */ 60#define NMSGDCHANS 1 /* No of multichannel SGD */ 61#define NWRCHANS 1 /* No of write channels */ 62#define NCHANS (NWRCHANS + NDXSCHANS + NMSGDCHANS) 63#define NSEGS NCHANS * SEGS_PER_CHAN /* Segments in SGD table */ 64 65#define VIA_DEFAULT_BUFSZ 0x1000 66 67/* we rely on this struct being packed to 64 bits */ 68struct via_dma_op { 69 volatile u_int32_t ptr; 70 volatile u_int32_t flags; 71#define VIA_DMAOP_EOL 0x80000000 72#define VIA_DMAOP_FLAG 0x40000000 73#define VIA_DMAOP_STOP 0x20000000 74#define VIA_DMAOP_COUNT(x) ((x)&0x00FFFFFF) 75}; 76 77struct via_info; 78 79struct via_chinfo { 80 struct via_info *parent; 81 struct pcm_channel *channel; 82 struct snd_dbuf *buffer; 83 struct via_dma_op *sgd_table; 84 bus_addr_t sgd_addr; 85 int dir, blksz; 86 int rbase; 87}; 88 89struct via_info { 90 bus_space_tag_t st; 91 bus_space_handle_t sh; 92 bus_dma_tag_t parent_dmat; 93 bus_dma_tag_t sgd_dmat; 94 bus_dmamap_t sgd_dmamap; 95 bus_addr_t sgd_addr; 96 97 struct resource *reg, *irq; 98 int regid, irqid; 99 void *ih; 100 struct ac97_info *codec; 101 102 unsigned int bufsz; 103 int spdif_en, dxs_src; 104 105 struct via_chinfo pch[NDXSCHANS + NMSGDCHANS]; 106 struct via_chinfo rch[NWRCHANS]; 107 struct via_dma_op *sgd_table; 108 u_int16_t codec_caps; 109 u_int16_t n_dxs_registered; 110 struct mtx *lock; 111}; 112 113static u_int32_t via_fmt[] = { 114 AFMT_U8, 115 AFMT_STEREO | AFMT_U8, 116 AFMT_S16_LE, 117 AFMT_STEREO | AFMT_S16_LE, 118 0 119}; 120 121static struct pcmchan_caps via_vracaps = { 4000, 48000, via_fmt, 0 }; 122static struct pcmchan_caps via_caps = { 48000, 48000, via_fmt, 0 }; 123 124#ifdef SND_DYNSYSCTL 125static int 126sysctl_via8233_spdif_enable(SYSCTL_HANDLER_ARGS) 127{ 128 struct via_info *via; 129 device_t dev; 130 int err, new_en, r; 131 132 dev = oidp->oid_arg1; 133 via = pcm_getdevinfo(dev); 134 snd_mtxlock(via->lock); 135 new_en = via->spdif_en; 136 snd_mtxunlock(via->lock); 137 err = sysctl_handle_int(oidp, &new_en, sizeof(new_en), req); 138 139 if (err || req->newptr == NULL) 140 return err; 141 if (new_en < 0 || new_en > 1) 142 return EINVAL; 143 144 snd_mtxlock(via->lock); 145 via->spdif_en = new_en; 146 147 r = pci_read_config(dev, VIA_PCI_SPDIF, 1) & ~VIA_SPDIF_EN; 148 if (new_en) 149 r |= VIA_SPDIF_EN; 150 pci_write_config(dev, VIA_PCI_SPDIF, r, 1); 151 snd_mtxunlock(via->lock); 152 153 return 0; 154} 155 156static int 157sysctl_via8233_dxs_src(SYSCTL_HANDLER_ARGS) 158{ 159 struct via_info *via; 160 device_t dev; 161 int err, val; 162 163 dev = oidp->oid_arg1; 164 via = pcm_getdevinfo(dev); 165 snd_mtxlock(via->lock); 166 val = via->dxs_src; 167 snd_mtxunlock(via->lock); 168 err = sysctl_handle_int(oidp, &val, sizeof(val), req); 169 170 if (err || req->newptr == NULL) 171 return err; 172 if (val < 0 || val > 1) 173 return EINVAL; 174 175 snd_mtxlock(via->lock); 176 via->dxs_src = val; 177 snd_mtxunlock(via->lock); 178 179 return 0; 180} 181#endif /* SND_DYNSYSCTL */ 182 183static void 184via_init_sysctls(device_t dev) 185{ 186#ifdef SND_DYNSYSCTL 187 struct via_info *via; 188 int r; 189 190 via = pcm_getdevinfo(dev); 191 r = pci_read_config(dev, VIA_PCI_SPDIF, 1); 192 via->spdif_en = (r & VIA_SPDIF_EN) ? 1 : 0; 193 194 SYSCTL_ADD_PROC(snd_sysctl_tree(dev), 195 SYSCTL_CHILDREN(snd_sysctl_tree_top(dev)), 196 OID_AUTO, "spdif_enabled", 197 CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev), 198 sysctl_via8233_spdif_enable, "I", 199 "Enable S/PDIF output on primary playback channel"); 200 SYSCTL_ADD_PROC(snd_sysctl_tree(dev), 201 SYSCTL_CHILDREN(snd_sysctl_tree_top(dev)), 202 OID_AUTO, "via_dxs_src", 203 CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev), 204 sysctl_via8233_dxs_src, "I", 205 "Enable VIA DXS Sample Rate Converter"); 206#endif 207} 208 209static u_int32_t 210via_rd(struct via_info *via, int regno, int size) 211{ 212 switch (size) { 213 case 1: 214 return bus_space_read_1(via->st, via->sh, regno); 215 case 2: 216 return bus_space_read_2(via->st, via->sh, regno); 217 case 4: 218 return bus_space_read_4(via->st, via->sh, regno); 219 default: 220 return 0xFFFFFFFF; 221 } 222} 223 224static void 225via_wr(struct via_info *via, int regno, u_int32_t data, int size) 226{ 227 228 switch (size) { 229 case 1: 230 bus_space_write_1(via->st, via->sh, regno, data); 231 break; 232 case 2: 233 bus_space_write_2(via->st, via->sh, regno, data); 234 break; 235 case 4: 236 bus_space_write_4(via->st, via->sh, regno, data); 237 break; 238 } 239} 240 241/* -------------------------------------------------------------------- */ 242/* Codec interface */ 243 244static int 245via_waitready_codec(struct via_info *via) 246{ 247 int i; 248 249 /* poll until codec not busy */ 250 for (i = 0; i < 1000; i++) { 251 if ((via_rd(via, VIA_AC97_CONTROL, 4) & VIA_AC97_BUSY) == 0) 252 return 0; 253 DELAY(1); 254 } 255 printf("via: codec busy\n"); 256 return 1; 257} 258 259static int 260via_waitvalid_codec(struct via_info *via) 261{ 262 int i; 263 264 /* poll until codec valid */ 265 for (i = 0; i < 1000; i++) { 266 if (via_rd(via, VIA_AC97_CONTROL, 4) & VIA_AC97_CODEC00_VALID) 267 return 0; 268 DELAY(1); 269 } 270 printf("via: codec invalid\n"); 271 return 1; 272} 273 274static int 275via_write_codec(kobj_t obj, void *addr, int reg, u_int32_t val) 276{ 277 struct via_info *via = addr; 278 279 if (via_waitready_codec(via)) return -1; 280 281 via_wr(via, VIA_AC97_CONTROL, 282 VIA_AC97_CODEC00_VALID | VIA_AC97_INDEX(reg) | 283 VIA_AC97_DATA(val), 4); 284 285 return 0; 286} 287 288static int 289via_read_codec(kobj_t obj, void *addr, int reg) 290{ 291 struct via_info *via = addr; 292 293 if (via_waitready_codec(via)) 294 return -1; 295 296 via_wr(via, VIA_AC97_CONTROL, VIA_AC97_CODEC00_VALID | 297 VIA_AC97_READ | VIA_AC97_INDEX(reg), 4); 298 299 if (via_waitready_codec(via)) 300 return -1; 301 302 if (via_waitvalid_codec(via)) 303 return -1; 304 305 return via_rd(via, VIA_AC97_CONTROL, 2); 306} 307 308static kobj_method_t via_ac97_methods[] = { 309 KOBJMETHOD(ac97_read, via_read_codec), 310 KOBJMETHOD(ac97_write, via_write_codec), 311 { 0, 0 } 312}; 313AC97_DECLARE(via_ac97); 314 315/* -------------------------------------------------------------------- */ 316 317static int 318via_buildsgdt(struct via_chinfo *ch) 319{ 320 u_int32_t phys_addr, flag; 321 int i, seg_size; 322 323 seg_size = sndbuf_getsize(ch->buffer) / SEGS_PER_CHAN; 324 phys_addr = sndbuf_getbufaddr(ch->buffer); 325 326 for (i = 0; i < SEGS_PER_CHAN; i++) { 327 flag = (i == SEGS_PER_CHAN - 1) ? VIA_DMAOP_EOL : VIA_DMAOP_FLAG; 328 ch->sgd_table[i].ptr = phys_addr + (i * seg_size); 329 ch->sgd_table[i].flags = flag | seg_size; 330 } 331 332 return 0; 333} 334 335/* -------------------------------------------------------------------- */ 336/* Format setting functions */ 337 338static int 339via8233wr_setformat(kobj_t obj, void *data, u_int32_t format) 340{ 341 struct via_chinfo *ch = data; 342 struct via_info *via = ch->parent; 343 344 u_int32_t f = WR_FORMAT_STOP_INDEX; 345 346 if (format & AFMT_STEREO) 347 f |= WR_FORMAT_STEREO; 348 if (format & AFMT_S16_LE) 349 f |= WR_FORMAT_16BIT; 350 via_wr(via, VIA_WR0_FORMAT, f, 4); 351 352 return 0; 353} 354 355static int 356via8233dxs_setformat(kobj_t obj, void *data, u_int32_t format) 357{ 358 struct via_chinfo *ch = data; 359 struct via_info *via = ch->parent; 360 u_int32_t r, v; 361 362 r = ch->rbase + VIA8233_RP_DXS_RATEFMT; 363 v = via_rd(via, r, 4); 364 365 v &= ~(VIA8233_DXS_RATEFMT_STEREO | VIA8233_DXS_RATEFMT_16BIT); 366 if (format & AFMT_STEREO) 367 v |= VIA8233_DXS_RATEFMT_STEREO; 368 if (format & AFMT_16BIT) 369 v |= VIA8233_DXS_RATEFMT_16BIT; 370 via_wr(via, r, v, 4); 371 372 return 0; 373} 374 375static int 376via8233msgd_setformat(kobj_t obj, void *data, u_int32_t format) 377{ 378 struct via_chinfo *ch = data; 379 struct via_info *via = ch->parent; 380 381 u_int32_t s = 0xff000000; 382 u_int8_t v = (format & AFMT_S16_LE) ? MC_SGD_16BIT : MC_SGD_8BIT; 383 384 if (format & AFMT_STEREO) { 385 v |= MC_SGD_CHANNELS(2); 386 s |= SLOT3(1) | SLOT4(2); 387 } else { 388 v |= MC_SGD_CHANNELS(1); 389 s |= SLOT3(1) | SLOT4(1); 390 } 391 392 via_wr(via, VIA_MC_SLOT_SELECT, s, 4); 393 via_wr(via, VIA_MC_SGD_FORMAT, v, 1); 394 395 return 0; 396} 397 398/* -------------------------------------------------------------------- */ 399/* Speed setting functions */ 400 401static int 402via8233wr_setspeed(kobj_t obj, void *data, u_int32_t speed) 403{ 404 struct via_chinfo *ch = data; 405 struct via_info *via = ch->parent; 406 407 if (via->codec_caps & AC97_EXTCAP_VRA) 408 return ac97_setrate(via->codec, AC97_REGEXT_LADCRATE, speed); 409 410 return 48000; 411} 412 413static int 414via8233dxs_setspeed(kobj_t obj, void *data, u_int32_t speed) 415{ 416 struct via_chinfo *ch = data; 417 struct via_info *via = ch->parent; 418 u_int32_t r, v; 419 420 r = ch->rbase + VIA8233_RP_DXS_RATEFMT; 421 v = via_rd(via, r, 4) & ~VIA8233_DXS_RATEFMT_48K; 422 423 /* Careful to avoid overflow (divide by 48 per vt8233c docs) */ 424 425 v |= VIA8233_DXS_RATEFMT_48K * (speed / 48) / (48000 / 48); 426 via_wr(via, r, v, 4); 427 428 return speed; 429} 430 431static int 432via8233msgd_setspeed(kobj_t obj, void *data, u_int32_t speed) 433{ 434 struct via_chinfo *ch = data; 435 struct via_info *via = ch->parent; 436 437 if (via->codec_caps & AC97_EXTCAP_VRA) 438 return ac97_setrate(via->codec, AC97_REGEXT_FDACRATE, speed); 439 440 return 48000; 441} 442 443/* -------------------------------------------------------------------- */ 444/* Format probing functions */ 445 446static struct pcmchan_caps * 447via8233wr_getcaps(kobj_t obj, void *data) 448{ 449 struct via_chinfo *ch = data; 450 struct via_info *via = ch->parent; 451 452 /* Controlled by ac97 registers */ 453 if (via->codec_caps & AC97_EXTCAP_VRA) 454 return &via_vracaps; 455 return &via_caps; 456} 457 458static struct pcmchan_caps * 459via8233dxs_getcaps(kobj_t obj, void *data) 460{ 461 struct via_chinfo *ch = data; 462 struct via_info *via = ch->parent; 463 464 /* 465 * Controlled by onboard registers 466 * 467 * Apparently, few boards can do DXS sample rate 468 * conversion. 469 */ 470 if (via->dxs_src) 471 return &via_vracaps; 472 return &via_caps; 473} 474 475static struct pcmchan_caps * 476via8233msgd_getcaps(kobj_t obj, void *data) 477{ 478 struct via_chinfo *ch = data; 479 struct via_info *via = ch->parent; 480 481 /* Controlled by ac97 registers */ 482 if (via->codec_caps & AC97_EXTCAP_VRA) 483 return &via_vracaps; 484 return &via_caps; 485} 486 487/* -------------------------------------------------------------------- */ 488/* Common functions */ 489 490static int 491via8233chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) 492{ 493 struct via_chinfo *ch = data; 494 495 sndbuf_resize(ch->buffer, SEGS_PER_CHAN, blocksize); 496 ch->blksz = sndbuf_getblksz(ch->buffer); 497 return ch->blksz; 498} 499 500static int 501via8233chan_getptr(kobj_t obj, void *data) 502{ 503 struct via_chinfo *ch = data; 504 struct via_info *via = ch->parent; 505 u_int32_t v, index, count; 506 int ptr; 507 508 v = via_rd(via, ch->rbase + VIA_RP_CURRENT_COUNT, 4); 509 index = v >> 24; /* Last completed buffer */ 510 count = v & 0x00ffffff; /* Bytes remaining */ 511 ptr = (index + 1) * ch->blksz - count; 512 ptr %= SEGS_PER_CHAN * ch->blksz; /* Wrap to available space */ 513 514 return ptr; 515} 516 517static void 518via8233chan_reset(struct via_info *via, struct via_chinfo *ch) 519{ 520 via_wr(via, ch->rbase + VIA_RP_CONTROL, SGD_CONTROL_STOP, 1); 521 via_wr(via, ch->rbase + VIA_RP_CONTROL, 0x00, 1); 522 via_wr(via, ch->rbase + VIA_RP_STATUS, 523 SGD_STATUS_EOL | SGD_STATUS_FLAG, 1); 524} 525 526/* -------------------------------------------------------------------- */ 527/* Channel initialization functions */ 528 529static void 530via8233chan_sgdinit(struct via_info *via, struct via_chinfo *ch, int chnum) 531{ 532 ch->sgd_table = &via->sgd_table[chnum * SEGS_PER_CHAN]; 533 ch->sgd_addr = via->sgd_addr + chnum * SEGS_PER_CHAN * sizeof(struct via_dma_op); 534} 535 536static void* 537via8233wr_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, 538 struct pcm_channel *c, int dir) 539{ 540 struct via_info *via = devinfo; 541 struct via_chinfo *ch = &via->rch[c->num]; 542 543 snd_mtxlock(via->lock); 544 ch->parent = via; 545 ch->channel = c; 546 ch->buffer = b; 547 ch->dir = dir; 548 549 ch->rbase = VIA_WR_BASE(c->num); 550 via_wr(via, ch->rbase + VIA_WR_RP_SGD_FORMAT, WR_FIFO_ENABLE, 1); 551 snd_mtxunlock(via->lock); 552 553 if (sndbuf_alloc(ch->buffer, via->parent_dmat, via->bufsz) != 0) 554 return NULL; 555 556 snd_mtxlock(via->lock); 557 via8233chan_sgdinit(via, ch, c->num); 558 via8233chan_reset(via, ch); 559 snd_mtxunlock(via->lock); 560 561 return ch; 562} 563 564static void* 565via8233dxs_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, 566 struct pcm_channel *c, int dir) 567{ 568 struct via_info *via = devinfo; 569 struct via_chinfo *ch = &via->pch[c->num]; 570 571 snd_mtxlock(via->lock); 572 ch->parent = via; 573 ch->channel = c; 574 ch->buffer = b; 575 ch->dir = dir; 576 577 /* 578 * All cards apparently support DXS3, but not other DXS 579 * channels. We therefore want to align first DXS channel to 580 * DXS3. 581 */ 582 ch->rbase = VIA_DXS_BASE(NDXSCHANS - 1 - via->n_dxs_registered); 583 via->n_dxs_registered++; 584 snd_mtxunlock(via->lock); 585 586 if (sndbuf_alloc(ch->buffer, via->parent_dmat, via->bufsz) != 0) 587 return NULL; 588 589 snd_mtxlock(via->lock); 590 via8233chan_sgdinit(via, ch, NWRCHANS + c->num); 591 via8233chan_reset(via, ch); 592 snd_mtxunlock(via->lock); 593 594 return ch; 595} 596 597static void* 598via8233msgd_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, 599 struct pcm_channel *c, int dir) 600{ 601 struct via_info *via = devinfo; 602 struct via_chinfo *ch = &via->pch[c->num]; 603 604 snd_mtxlock(via->lock); 605 ch->parent = via; 606 ch->channel = c; 607 ch->buffer = b; 608 ch->dir = dir; 609 ch->rbase = VIA_MC_SGD_STATUS; 610 snd_mtxunlock(via->lock); 611 612 if (sndbuf_alloc(ch->buffer, via->parent_dmat, via->bufsz) != 0) 613 return NULL; 614 615 snd_mtxlock(via->lock); 616 via8233chan_sgdinit(via, ch, NWRCHANS + c->num); 617 via8233chan_reset(via, ch); 618 snd_mtxunlock(via->lock); 619 620 return ch; 621} 622 623static void 624via8233chan_mute(struct via_info *via, struct via_chinfo *ch, int muted) 625{ 626 if (BASE_IS_VIA_DXS_REG(ch->rbase)) { 627 int r; 628 muted = (muted) ? VIA8233_DXS_MUTE : 0; 629 via_wr(via, ch->rbase + VIA8233_RP_DXS_LVOL, muted, 1); 630 via_wr(via, ch->rbase + VIA8233_RP_DXS_RVOL, muted, 1); 631 r = via_rd(via, ch->rbase + VIA8233_RP_DXS_LVOL, 1) & VIA8233_DXS_MUTE; 632 if (r != muted) { 633 printf("via: failed to set dxs volume " 634 "(dxs base 0x%02x).\n", ch->rbase); 635 } 636 } 637} 638 639static int 640via8233chan_trigger(kobj_t obj, void* data, int go) 641{ 642 struct via_chinfo *ch = data; 643 struct via_info *via = ch->parent; 644 645 switch(go) { 646 case PCMTRIG_START: 647 via_buildsgdt(ch); 648 via8233chan_mute(via, ch, 0); 649 via_wr(via, ch->rbase + VIA_RP_TABLE_PTR, ch->sgd_addr, 4); 650 via_wr(via, ch->rbase + VIA_RP_CONTROL, 651 SGD_CONTROL_START | SGD_CONTROL_AUTOSTART | 652 SGD_CONTROL_I_EOL | SGD_CONTROL_I_FLAG, 1); 653 break; 654 case PCMTRIG_STOP: 655 case PCMTRIG_ABORT: 656 via_wr(via, ch->rbase + VIA_RP_CONTROL, SGD_CONTROL_STOP, 1); 657 via8233chan_mute(via, ch, 1); 658 via8233chan_reset(via, ch); 659 break; 660 } 661 return 0; 662} 663 664static kobj_method_t via8233wr_methods[] = { 665 KOBJMETHOD(channel_init, via8233wr_init), 666 KOBJMETHOD(channel_setformat, via8233wr_setformat), 667 KOBJMETHOD(channel_setspeed, via8233wr_setspeed), 668 KOBJMETHOD(channel_getcaps, via8233wr_getcaps), 669 KOBJMETHOD(channel_setblocksize, via8233chan_setblocksize), 670 KOBJMETHOD(channel_trigger, via8233chan_trigger), 671 KOBJMETHOD(channel_getptr, via8233chan_getptr), 672 { 0, 0 } 673}; 674CHANNEL_DECLARE(via8233wr); 675 676static kobj_method_t via8233dxs_methods[] = { 677 KOBJMETHOD(channel_init, via8233dxs_init), 678 KOBJMETHOD(channel_setformat, via8233dxs_setformat), 679 KOBJMETHOD(channel_setspeed, via8233dxs_setspeed), 680 KOBJMETHOD(channel_getcaps, via8233dxs_getcaps), 681 KOBJMETHOD(channel_setblocksize, via8233chan_setblocksize), 682 KOBJMETHOD(channel_trigger, via8233chan_trigger), 683 KOBJMETHOD(channel_getptr, via8233chan_getptr), 684 { 0, 0 } 685}; 686CHANNEL_DECLARE(via8233dxs); 687 688static kobj_method_t via8233msgd_methods[] = { 689 KOBJMETHOD(channel_init, via8233msgd_init), 690 KOBJMETHOD(channel_setformat, via8233msgd_setformat), 691 KOBJMETHOD(channel_setspeed, via8233msgd_setspeed), 692 KOBJMETHOD(channel_getcaps, via8233msgd_getcaps), 693 KOBJMETHOD(channel_setblocksize, via8233chan_setblocksize), 694 KOBJMETHOD(channel_trigger, via8233chan_trigger), 695 KOBJMETHOD(channel_getptr, via8233chan_getptr), 696 { 0, 0 } 697}; 698CHANNEL_DECLARE(via8233msgd); 699 700/* -------------------------------------------------------------------- */ 701 702static void 703via_intr(void *p) 704{ 705 struct via_info *via = p; 706 int i, stat; 707 708 /* Poll playback channels */ 709 snd_mtxlock(via->lock); 710 for (i = 0; i < NDXSCHANS + NMSGDCHANS; i++) { 711 if (via->pch[i].rbase == 0) 712 continue; 713 stat = via->pch[i].rbase + VIA_RP_STATUS; 714 if (via_rd(via, stat, 1) & SGD_STATUS_INTR) { 715 via_wr(via, stat, SGD_STATUS_INTR, 1); 716 snd_mtxunlock(via->lock); 717 chn_intr(via->pch[i].channel); 718 snd_mtxlock(via->lock); 719 } 720 } 721 722 /* Poll record channels */ 723 for (i = 0; i < NWRCHANS; i++) { 724 if (via->rch[i].rbase == 0) 725 continue; 726 stat = via->rch[i].rbase + VIA_RP_STATUS; 727 if (via_rd(via, stat, 1) & SGD_STATUS_INTR) { 728 via_wr(via, stat, SGD_STATUS_INTR, 1); 729 snd_mtxunlock(via->lock); 730 chn_intr(via->rch[i].channel); 731 snd_mtxlock(via->lock); 732 } 733 } 734 snd_mtxunlock(via->lock); 735} 736 737/* 738 * Probe and attach the card 739 */ 740static int 741via_probe(device_t dev) 742{ 743 switch(pci_get_devid(dev)) { 744 case VIA8233_PCI_ID: 745 switch(pci_get_revid(dev)) { 746 case VIA8233_REV_ID_8233PRE: 747 device_set_desc(dev, "VIA VT8233 (pre)"); 748 return BUS_PROBE_DEFAULT; 749 case VIA8233_REV_ID_8233C: 750 device_set_desc(dev, "VIA VT8233C"); 751 return BUS_PROBE_DEFAULT; 752 case VIA8233_REV_ID_8233: 753 device_set_desc(dev, "VIA VT8233"); 754 return BUS_PROBE_DEFAULT; 755 case VIA8233_REV_ID_8233A: 756 device_set_desc(dev, "VIA VT8233A"); 757 return BUS_PROBE_DEFAULT; 758 case VIA8233_REV_ID_8235: 759 device_set_desc(dev, "VIA VT8235"); 760 return BUS_PROBE_DEFAULT; 761 case VIA8233_REV_ID_8237: 762 device_set_desc(dev, "VIA VT8237"); 763 return BUS_PROBE_DEFAULT; 764 default: 765 device_set_desc(dev, "VIA VT8233X"); /* Unknown */ 766 return BUS_PROBE_DEFAULT; 767 } 768 } 769 return ENXIO; 770} 771 772static void 773dma_cb(void *p, bus_dma_segment_t *bds, int a, int b) 774{ 775 struct via_info *via = (struct via_info *)p; 776 via->sgd_addr = bds->ds_addr; 777} 778 779static int 780via_chip_init(device_t dev) 781{ 782 u_int32_t data, cnt; 783 784 /* Wake up and reset AC97 if necessary */ 785 data = pci_read_config(dev, VIA_PCI_ACLINK_STAT, 1); 786 787 if ((data & VIA_PCI_ACLINK_C00_READY) == 0) { 788 /* Cold reset per ac97r2.3 spec (page 95) */ 789 /* Assert low */ 790 pci_write_config(dev, VIA_PCI_ACLINK_CTRL, 791 VIA_PCI_ACLINK_EN, 1); 792 /* Wait T_rst_low */ 793 DELAY(100); 794 /* Assert high */ 795 pci_write_config(dev, VIA_PCI_ACLINK_CTRL, 796 VIA_PCI_ACLINK_EN | VIA_PCI_ACLINK_NRST, 1); 797 /* Wait T_rst2clk */ 798 DELAY(5); 799 /* Assert low */ 800 pci_write_config(dev, VIA_PCI_ACLINK_CTRL, 801 VIA_PCI_ACLINK_EN, 1); 802 } else { 803 /* Warm reset */ 804 /* Force no sync */ 805 pci_write_config(dev, VIA_PCI_ACLINK_CTRL, 806 VIA_PCI_ACLINK_EN, 1); 807 DELAY(100); 808 /* Sync */ 809 pci_write_config(dev, VIA_PCI_ACLINK_CTRL, 810 VIA_PCI_ACLINK_EN | VIA_PCI_ACLINK_SYNC, 1); 811 /* Wait T_sync_high */ 812 DELAY(5); 813 /* Force no sync */ 814 pci_write_config(dev, VIA_PCI_ACLINK_CTRL, 815 VIA_PCI_ACLINK_EN, 1); 816 /* Wait T_sync2clk */ 817 DELAY(5); 818 } 819 820 /* Power everything up */ 821 pci_write_config(dev, VIA_PCI_ACLINK_CTRL, VIA_PCI_ACLINK_DESIRED, 1); 822 823 /* Wait for codec to become ready (largest reported delay 310ms) */ 824 for (cnt = 0; cnt < 2000; cnt++) { 825 data = pci_read_config(dev, VIA_PCI_ACLINK_STAT, 1); 826 if (data & VIA_PCI_ACLINK_C00_READY) { 827 return 0; 828 } 829 DELAY(5000); 830 } 831 device_printf(dev, "primary codec not ready (cnt = 0x%02x)\n", cnt); 832 return ENXIO; 833} 834 835static int 836via_attach(device_t dev) 837{ 838 struct via_info *via = 0; 839 char status[SND_STATUSLEN]; 840 int i, via_dxs_disabled, via_dxs_src, via_dxs_chnum, via_sgd_chnum; 841 842 if ((via = malloc(sizeof *via, M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) { 843 device_printf(dev, "cannot allocate softc\n"); 844 return ENXIO; 845 } 846 via->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc"); 847 848 pci_set_powerstate(dev, PCI_POWERSTATE_D0); 849 pci_enable_busmaster(dev); 850 851 via->regid = PCIR_BAR(0); 852 via->reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &via->regid, 853 RF_ACTIVE); 854 if (!via->reg) { 855 device_printf(dev, "cannot allocate bus resource."); 856 goto bad; 857 } 858 via->st = rman_get_bustag(via->reg); 859 via->sh = rman_get_bushandle(via->reg); 860 861 via->bufsz = pcm_getbuffersize(dev, 4096, VIA_DEFAULT_BUFSZ, 65536); 862 863 via->irqid = 0; 864 via->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &via->irqid, 865 RF_ACTIVE | RF_SHAREABLE); 866 if (!via->irq || 867 snd_setup_intr(dev, via->irq, INTR_MPSAFE, via_intr, via, &via->ih)) { 868 device_printf(dev, "unable to map interrupt\n"); 869 goto bad; 870 } 871 872 /* DMA tag for buffers */ 873 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, 874 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 875 /*highaddr*/BUS_SPACE_MAXADDR, 876 /*filter*/NULL, /*filterarg*/NULL, 877 /*maxsize*/via->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff, 878 /*flags*/0, /*lockfunc*/NULL, 879 /*lockarg*/NULL, &via->parent_dmat) != 0) { 880 device_printf(dev, "unable to create dma tag\n"); 881 goto bad; 882 } 883 884 /* 885 * DMA tag for SGD table. The 686 uses scatter/gather DMA and 886 * requires a list in memory of work to do. We need only 16 bytes 887 * for this list, and it is wasteful to allocate 16K. 888 */ 889 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, 890 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 891 /*highaddr*/BUS_SPACE_MAXADDR, 892 /*filter*/NULL, /*filterarg*/NULL, 893 /*maxsize*/NSEGS * sizeof(struct via_dma_op), 894 /*nsegments*/1, /*maxsegz*/0x3ffff, 895 /*flags*/0, /*lockfunc*/NULL, 896 /*lockarg*/NULL, &via->sgd_dmat) != 0) { 897 device_printf(dev, "unable to create dma tag\n"); 898 goto bad; 899 } 900 901 if (bus_dmamem_alloc(via->sgd_dmat, (void **)&via->sgd_table, 902 BUS_DMA_NOWAIT, &via->sgd_dmamap) == -1) 903 goto bad; 904 if (bus_dmamap_load(via->sgd_dmat, via->sgd_dmamap, via->sgd_table, 905 NSEGS * sizeof(struct via_dma_op), dma_cb, via, 0)) 906 goto bad; 907 908 if (via_chip_init(dev)) 909 goto bad; 910 911 via->codec = AC97_CREATE(dev, via, via_ac97); 912 if (!via->codec) 913 goto bad; 914 915 mixer_init(dev, ac97_getmixerclass(), via->codec); 916 917 via->codec_caps = ac97_getextcaps(via->codec); 918 919 /* Try to set VRA without generating an error, VRM not reqrd yet */ 920 if (via->codec_caps & 921 (AC97_EXTCAP_VRA | AC97_EXTCAP_VRM | AC97_EXTCAP_DRA)) { 922 u_int16_t ext = ac97_getextmode(via->codec); 923 ext |= (via->codec_caps & 924 (AC97_EXTCAP_VRA | AC97_EXTCAP_VRM)); 925 ext &= ~AC97_EXTCAP_DRA; 926 ac97_setextmode(via->codec, ext); 927 } 928 929 snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld %s", 930 rman_get_start(via->reg), rman_get_start(via->irq),PCM_KLDSTRING(snd_via8233)); 931 932 /* 933 * Decide whether DXS had to be disabled or not 934 */ 935 if (pci_get_revid(dev) == VIA8233_REV_ID_8233A) { 936 /* 937 * DXS channel is disabled. Reports from multiple users 938 * that it plays at half-speed. Do not see this behaviour 939 * on available 8233C or when emulating 8233A register set 940 * on 8233C (either with or without ac97 VRA). 941 */ 942 via_dxs_disabled = 1; 943 } else if (resource_int_value(device_get_name(dev), 944 device_get_unit(dev), "via_dxs_disabled", 945 &via_dxs_disabled) == 0) 946 via_dxs_disabled = (via_dxs_disabled > 0) ? 1 : 0; 947 else 948 via_dxs_disabled = 0; 949 950 if (via_dxs_disabled) { 951 via_dxs_chnum = 0; 952 via_sgd_chnum = 1; 953 } else { 954 if (resource_int_value(device_get_name(dev), 955 device_get_unit(dev), "via_dxs_channels", 956 &via_dxs_chnum) != 0) 957 via_dxs_chnum = NDXSCHANS; 958 if (resource_int_value(device_get_name(dev), 959 device_get_unit(dev), "via_sgd_channels", 960 &via_sgd_chnum) != 0) 961 via_sgd_chnum = NMSGDCHANS; 962 } 963 if (via_dxs_chnum > NDXSCHANS) 964 via_dxs_chnum = NDXSCHANS; 965 else if (via_dxs_chnum < 0) 966 via_dxs_chnum = 0; 967 if (via_sgd_chnum > NMSGDCHANS) 968 via_sgd_chnum = NMSGDCHANS; 969 else if (via_sgd_chnum < 0) 970 via_sgd_chnum = 0; 971 if (via_dxs_chnum + via_sgd_chnum < 1) { 972 /* Minimalist ? */ 973 via_dxs_chnum = 1; 974 via_sgd_chnum = 0; 975 } 976 if (via_dxs_chnum > 0 && resource_int_value(device_get_name(dev), 977 device_get_unit(dev), "via_dxs_src", 978 &via_dxs_src) == 0) 979 via->dxs_src = (via_dxs_src > 0) ? 1 : 0; 980 else 981 via->dxs_src = 0; 982 /* Register */ 983 if (pcm_register(dev, via, via_dxs_chnum + via_sgd_chnum, NWRCHANS)) 984 goto bad; 985 for (i = 0; i < via_dxs_chnum; i++) 986 pcm_addchan(dev, PCMDIR_PLAY, &via8233dxs_class, via); 987 for (i = 0; i < via_sgd_chnum; i++) 988 pcm_addchan(dev, PCMDIR_PLAY, &via8233msgd_class, via); 989 for (i = 0; i < NWRCHANS; i++) 990 pcm_addchan(dev, PCMDIR_REC, &via8233wr_class, via); 991 if (via_dxs_chnum > 0) 992 via_init_sysctls(dev); 993 device_printf(dev, "<VIA DXS %sabled: DXS%s %d / SGD %d / REC %d>\n", 994 (via_dxs_chnum > 0) ? "En" : "Dis", 995 (via->dxs_src) ? "(SRC)" : "", 996 via_dxs_chnum, via_sgd_chnum, NWRCHANS); 997 998 pcm_setstatus(dev, status); 999 1000 return 0; 1001bad: 1002 if (via->codec) ac97_destroy(via->codec); 1003 if (via->reg) bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg); 1004 if (via->ih) bus_teardown_intr(dev, via->irq, via->ih); 1005 if (via->irq) bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq); 1006 if (via->parent_dmat) bus_dma_tag_destroy(via->parent_dmat); 1007 if (via->sgd_dmamap) bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap); 1008 if (via->sgd_dmat) bus_dma_tag_destroy(via->sgd_dmat); 1009 if (via->lock) snd_mtxfree(via->lock); 1010 if (via) free(via, M_DEVBUF); 1011 return ENXIO; 1012} 1013 1014static int 1015via_detach(device_t dev) 1016{ 1017 int r; 1018 struct via_info *via = 0; 1019 1020 r = pcm_unregister(dev); 1021 if (r) return r; 1022 1023 via = pcm_getdevinfo(dev); 1024 bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg); 1025 bus_teardown_intr(dev, via->irq, via->ih); 1026 bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq); 1027 bus_dma_tag_destroy(via->parent_dmat); 1028 bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap); 1029 bus_dma_tag_destroy(via->sgd_dmat); 1030 snd_mtxfree(via->lock); 1031 free(via, M_DEVBUF); 1032 return 0; 1033} 1034 1035 1036static device_method_t via_methods[] = { 1037 DEVMETHOD(device_probe, via_probe), 1038 DEVMETHOD(device_attach, via_attach), 1039 DEVMETHOD(device_detach, via_detach), 1040 { 0, 0} 1041}; 1042 1043static driver_t via_driver = { 1044 "pcm", 1045 via_methods, 1046 PCM_SOFTC_SIZE, 1047}; 1048 1049DRIVER_MODULE(snd_via8233, pci, via_driver, pcm_devclass, 0, 0); 1050MODULE_DEPEND(snd_via8233, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 1051MODULE_VERSION(snd_via8233, 1); 1052