1 /* 2 * Copyright (c) 2001 Orion Hodson <O.Hodson@cs.ucl.ac.uk> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * This card has the annoying habit of "clicking" when attached and 27 * detached, haven't been able to remedy this with any combination of 28 * muting. 29 * 30 * $FreeBSD: src/sys/dev/sound/pci/vibes.c,v 1.4.2.6 2002/04/22 15:49:33 cg Exp $ 31 * $DragonFly: src/sys/dev/sound/pci/vibes.c,v 1.2 2003/06/17 04:28:31 dillon Exp $ 32 */ 33 34 #include <dev/sound/pcm/sound.h> 35 #include <dev/sound/pci/vibes.h> 36 37 #include <pci/pcireg.h> 38 #include <pci/pcivar.h> 39 40 #include "mixer_if.h" 41 42 SND_DECLARE_FILE("$DragonFly: src/sys/dev/sound/pci/vibes.c,v 1.2 2003/06/17 04:28:31 dillon Exp $"); 43 44 /* ------------------------------------------------------------------------- */ 45 /* Constants */ 46 47 #define SV_PCI_ID 0xca005333 48 #define SV_DEFAULT_BUFSZ 16384 49 #define SV_MIN_BLKSZ 128 50 #define SV_INTR_PER_BUFFER 2 51 52 #ifndef DEB 53 #define DEB(x) /* (x) */ 54 #endif 55 56 /* ------------------------------------------------------------------------- */ 57 /* Structures */ 58 59 struct sc_info; 60 61 struct sc_chinfo { 62 struct sc_info *parent; 63 struct pcm_channel *channel; 64 struct snd_dbuf *buffer; 65 u_int32_t fmt, spd; 66 int dir; 67 int dma_active, dma_was_active; 68 }; 69 70 struct sc_info { 71 device_t dev; 72 73 /* DMA buffer allocator */ 74 bus_dma_tag_t parent_dmat; 75 76 /* Enhanced register resources */ 77 struct resource *enh_reg; 78 bus_space_tag_t enh_st; 79 bus_space_handle_t enh_sh; 80 int enh_type; 81 int enh_rid; 82 83 /* DMA configuration */ 84 struct resource *dmaa_reg, *dmac_reg; 85 bus_space_tag_t dmaa_st, dmac_st; 86 bus_space_handle_t dmaa_sh, dmac_sh; 87 int dmaa_type, dmac_type; 88 int dmaa_rid, dmac_rid; 89 90 /* Interrupt resources */ 91 struct resource *irq; 92 int irqid; 93 void *ih; 94 95 /* User configurable buffer size */ 96 unsigned int bufsz; 97 98 struct sc_chinfo rch, pch; 99 u_int8_t rev; 100 }; 101 102 static u_int32_t sc_fmt[] = { 103 AFMT_U8, 104 AFMT_U8 | AFMT_STEREO, 105 AFMT_S16_LE, 106 AFMT_S16_LE | AFMT_STEREO, 107 0 108 }; 109 110 static struct pcmchan_caps sc_caps = {8000, 48000, sc_fmt, 0}; 111 112 /* ------------------------------------------------------------------------- */ 113 /* Register Manipulations */ 114 115 #define sv_direct_set(x, y, z) _sv_direct_set(x, y, z, __LINE__) 116 117 static u_int8_t 118 sv_direct_get(struct sc_info *sc, u_int8_t reg) 119 { 120 return bus_space_read_1(sc->enh_st, sc->enh_sh, reg); 121 } 122 123 static void 124 _sv_direct_set(struct sc_info *sc, u_int8_t reg, u_int8_t val, int line) 125 { 126 u_int8_t n; 127 bus_space_write_1(sc->enh_st, sc->enh_sh, reg, val); 128 129 n = sv_direct_get(sc, reg); 130 if (n != val) { 131 device_printf(sc->dev, "sv_direct_set register 0x%02x %d != %d from line %d\n", reg, n, val, line); 132 } 133 } 134 135 static u_int8_t 136 sv_indirect_get(struct sc_info *sc, u_int8_t reg) 137 { 138 if (reg == SV_REG_FORMAT || reg == SV_REG_ANALOG_PWR) 139 reg |= SV_CM_INDEX_MCE; 140 141 bus_space_write_1(sc->enh_st, sc->enh_sh, SV_CM_INDEX, reg); 142 return bus_space_read_1(sc->enh_st, sc->enh_sh, SV_CM_DATA); 143 } 144 145 #define sv_indirect_set(x, y, z) _sv_indirect_set(x, y, z, __LINE__) 146 147 static void 148 _sv_indirect_set(struct sc_info *sc, u_int8_t reg, u_int8_t val, int line) 149 { 150 if (reg == SV_REG_FORMAT || reg == SV_REG_ANALOG_PWR) 151 reg |= SV_CM_INDEX_MCE; 152 153 bus_space_write_1(sc->enh_st, sc->enh_sh, SV_CM_INDEX, reg); 154 bus_space_write_1(sc->enh_st, sc->enh_sh, SV_CM_DATA, val); 155 156 reg &= ~SV_CM_INDEX_MCE; 157 if (reg != SV_REG_ADC_PLLM) { 158 u_int8_t n; 159 n = sv_indirect_get(sc, reg); 160 if (n != val) { 161 device_printf(sc->dev, "sv_indirect_set register 0x%02x %d != %d line %d\n", reg, n, val, line); 162 } 163 } 164 } 165 166 static void 167 sv_dma_set_config(bus_space_tag_t st, bus_space_handle_t sh, 168 u_int32_t base, u_int32_t count, u_int8_t mode) 169 { 170 bus_space_write_4(st, sh, SV_DMA_ADDR, base); 171 bus_space_write_4(st, sh, SV_DMA_COUNT, count & 0xffffff); 172 bus_space_write_1(st, sh, SV_DMA_MODE, mode); 173 174 DEB(printf("base 0x%08x count %5d mode 0x%02x\n", 175 base, count, mode)); 176 } 177 178 static u_int32_t 179 sv_dma_get_count(bus_space_tag_t st, bus_space_handle_t sh) 180 { 181 return bus_space_read_4(st, sh, SV_DMA_COUNT) & 0xffffff; 182 } 183 184 /* ------------------------------------------------------------------------- */ 185 /* Play / Record Common Interface */ 186 187 static void * 188 svchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) 189 { 190 struct sc_info *sc = devinfo; 191 struct sc_chinfo *ch; 192 ch = (dir == PCMDIR_PLAY) ? &sc->pch : &sc->rch; 193 194 ch->parent = sc; 195 ch->channel = c; 196 ch->dir = dir; 197 198 if (sndbuf_alloc(b, sc->parent_dmat, sc->bufsz) != 0) { 199 DEB(printf("svchan_init failed\n")); 200 return NULL; 201 } 202 ch->buffer = b; 203 ch->fmt = AFMT_U8; 204 ch->spd = DSP_DEFAULT_SPEED; 205 ch->dma_active = ch->dma_was_active = 0; 206 207 return ch; 208 } 209 210 static struct pcmchan_caps * 211 svchan_getcaps(kobj_t obj, void *data) 212 { 213 return &sc_caps; 214 } 215 216 static int 217 svchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) 218 { 219 struct sc_chinfo *ch = data; 220 struct sc_info *sc = ch->parent; 221 222 /* user has requested interrupts every blocksize bytes */ 223 RANGE(blocksize, SV_MIN_BLKSZ, sc->bufsz / SV_INTR_PER_BUFFER); 224 sndbuf_resize(ch->buffer, SV_INTR_PER_BUFFER, blocksize); 225 DEB(printf("svchan_setblocksize: %d\n", blocksize)); 226 return blocksize; 227 } 228 229 static int 230 svchan_setformat(kobj_t obj, void *data, u_int32_t format) 231 { 232 struct sc_chinfo *ch = data; 233 /* NB Just note format here as setting format register 234 * generates noise if dma channel is inactive. */ 235 ch->fmt = (format & AFMT_STEREO) ? SV_AFMT_STEREO : SV_AFMT_MONO; 236 ch->fmt |= (format & AFMT_16BIT) ? SV_AFMT_S16 : SV_AFMT_U8; 237 return 0; 238 } 239 240 static int 241 svchan_setspeed(kobj_t obj, void *data, u_int32_t speed) 242 { 243 struct sc_chinfo *ch = data; 244 RANGE(speed, 8000, 48000); 245 ch->spd = speed; 246 return speed; 247 } 248 249 /* ------------------------------------------------------------------------- */ 250 /* Recording interface */ 251 252 static int 253 sv_set_recspeed(struct sc_info *sc, u_int32_t speed) 254 { 255 u_int32_t f_out, f_actual; 256 u_int32_t rs, re, r, best_r = 0, r2, t, n, best_n = 0; 257 int32_t m, best_m = 0, ms, me, err, min_err; 258 259 /* This algorithm is a variant described in sonicvibes.pdf 260 * appendix A. This search is marginally more extensive and 261 * results in (nominally) better sample rate matching. */ 262 263 f_out = SV_F_SCALE * speed; 264 min_err = 0x7fffffff; 265 266 /* Find bounds of r to examine, rs <= r <= re */ 267 t = 80000000 / f_out; 268 for (rs = 1; (1 << rs) < t; rs++); 269 270 t = 150000000 / f_out; 271 for (re = 1; (2 << re) < t; re++); 272 if (re > 7) re = 7; 273 274 /* Search over r, n, m */ 275 for (r = rs; r <= re; r++) { 276 r2 = (1 << r); 277 for (n = 3; n < 34; n++) { 278 m = f_out * n / (SV_F_REF / r2); 279 ms = (m > 3) ? (m - 1) : 3; 280 me = (m < 129) ? (m + 1) : 129; 281 for (m = ms; m <= me; m++) { 282 f_actual = m * SV_F_REF / (n * r2); 283 if (f_actual > f_out) { 284 err = f_actual - f_out; 285 } else { 286 err = f_out - f_actual; 287 } 288 if (err < min_err) { 289 best_r = r; 290 best_m = m - 2; 291 best_n = n - 2; 292 min_err = err; 293 if (err == 0) break; 294 } 295 } 296 } 297 } 298 299 sv_indirect_set(sc, SV_REG_ADC_PLLM, best_m); 300 sv_indirect_set(sc, SV_REG_ADC_PLLN, 301 SV_ADC_PLLN(best_n) | SV_ADC_PLLR(best_r)); 302 DEB(printf("svrchan_setspeed: %d -> PLLM 0x%02x PLLNR 0x%08x\n", 303 speed, 304 sv_indirect_get(sc, SV_REG_ADC_PLLM), 305 sv_indirect_get(sc, SV_REG_ADC_PLLN))); 306 return 0; 307 } 308 309 static int 310 svrchan_trigger(kobj_t obj, void *data, int go) 311 { 312 struct sc_chinfo *ch = data; 313 struct sc_info *sc = ch->parent; 314 u_int32_t count, enable; 315 u_int8_t v; 316 317 switch(go) { 318 case PCMTRIG_START: 319 /* Set speed */ 320 sv_set_recspeed(sc, ch->spd); 321 322 /* Set format */ 323 v = sv_indirect_get(sc, SV_REG_FORMAT) & ~SV_AFMT_DMAC_MSK; 324 v |= SV_AFMT_DMAC(ch->fmt); 325 sv_indirect_set(sc, SV_REG_FORMAT, v); 326 327 /* Program DMA */ 328 count = sndbuf_getsize(ch->buffer) / 2; /* DMAC uses words */ 329 sv_dma_set_config(sc->dmac_st, sc->dmac_sh, 330 vtophys(sndbuf_getbuf(ch->buffer)), 331 count - 1, 332 SV_DMA_MODE_AUTO | SV_DMA_MODE_RD); 333 count = count / SV_INTR_PER_BUFFER - 1; 334 sv_indirect_set(sc, SV_REG_DMAC_COUNT_HI, count >> 8); 335 sv_indirect_set(sc, SV_REG_DMAC_COUNT_LO, count & 0xff); 336 337 /* Enable DMA */ 338 enable = sv_indirect_get(sc, SV_REG_ENABLE) | SV_RECORD_ENABLE; 339 sv_indirect_set(sc, SV_REG_ENABLE, enable); 340 ch->dma_active = 1; 341 break; 342 case PCMTRIG_ABORT: 343 enable = sv_indirect_get(sc, SV_REG_ENABLE) & ~SV_RECORD_ENABLE; 344 sv_indirect_set(sc, SV_REG_ENABLE, enable); 345 ch->dma_active = 0; 346 break; 347 } 348 349 return 0; 350 } 351 352 static int 353 svrchan_getptr(kobj_t obj, void *data) 354 { 355 struct sc_chinfo *ch = data; 356 struct sc_info *sc = ch->parent; 357 u_int32_t sz, remain; 358 359 sz = sndbuf_getsize(ch->buffer); 360 /* DMAC uses words */ 361 remain = (sv_dma_get_count(sc->dmac_st, sc->dmac_sh) + 1) * 2; 362 return sz - remain; 363 } 364 365 static kobj_method_t svrchan_methods[] = { 366 KOBJMETHOD(channel_init, svchan_init), 367 KOBJMETHOD(channel_setformat, svchan_setformat), 368 KOBJMETHOD(channel_setspeed, svchan_setspeed), 369 KOBJMETHOD(channel_setblocksize, svchan_setblocksize), 370 KOBJMETHOD(channel_trigger, svrchan_trigger), 371 KOBJMETHOD(channel_getptr, svrchan_getptr), 372 KOBJMETHOD(channel_getcaps, svchan_getcaps), 373 { 0, 0 } 374 }; 375 CHANNEL_DECLARE(svrchan); 376 377 /* ------------------------------------------------------------------------- */ 378 /* Playback interface */ 379 380 static int 381 svpchan_trigger(kobj_t obj, void *data, int go) 382 { 383 struct sc_chinfo *ch = data; 384 struct sc_info *sc = ch->parent; 385 u_int32_t count, enable, speed; 386 u_int8_t v; 387 388 switch(go) { 389 case PCMTRIG_START: 390 /* Set speed */ 391 speed = (ch->spd * 65536) / 48000; 392 if (speed > 65535) 393 speed = 65535; 394 sv_indirect_set(sc, SV_REG_PCM_SAMPLING_HI, speed >> 8); 395 sv_indirect_set(sc, SV_REG_PCM_SAMPLING_LO, speed & 0xff); 396 397 /* Set format */ 398 v = sv_indirect_get(sc, SV_REG_FORMAT) & ~SV_AFMT_DMAA_MSK; 399 v |= SV_AFMT_DMAA(ch->fmt); 400 sv_indirect_set(sc, SV_REG_FORMAT, v); 401 402 /* Program DMA */ 403 count = sndbuf_getsize(ch->buffer); 404 sv_dma_set_config(sc->dmaa_st, sc->dmaa_sh, 405 vtophys(sndbuf_getbuf(ch->buffer)), 406 count - 1, 407 SV_DMA_MODE_AUTO | SV_DMA_MODE_WR); 408 count = count / SV_INTR_PER_BUFFER - 1; 409 sv_indirect_set(sc, SV_REG_DMAA_COUNT_HI, count >> 8); 410 sv_indirect_set(sc, SV_REG_DMAA_COUNT_LO, count & 0xff); 411 412 /* Enable DMA */ 413 enable = sv_indirect_get(sc, SV_REG_ENABLE); 414 enable = (enable | SV_PLAY_ENABLE) & ~SV_PLAYBACK_PAUSE; 415 sv_indirect_set(sc, SV_REG_ENABLE, enable); 416 ch->dma_active = 1; 417 break; 418 case PCMTRIG_ABORT: 419 enable = sv_indirect_get(sc, SV_REG_ENABLE) & ~SV_PLAY_ENABLE; 420 sv_indirect_set(sc, SV_REG_ENABLE, enable); 421 ch->dma_active = 0; 422 break; 423 } 424 425 return 0; 426 } 427 428 static int 429 svpchan_getptr(kobj_t obj, void *data) 430 { 431 struct sc_chinfo *ch = data; 432 struct sc_info *sc = ch->parent; 433 u_int32_t sz, remain; 434 435 sz = sndbuf_getsize(ch->buffer); 436 /* DMAA uses bytes */ 437 remain = sv_dma_get_count(sc->dmaa_st, sc->dmaa_sh) + 1; 438 return (sz - remain); 439 } 440 441 static kobj_method_t svpchan_methods[] = { 442 KOBJMETHOD(channel_init, svchan_init), 443 KOBJMETHOD(channel_setformat, svchan_setformat), 444 KOBJMETHOD(channel_setspeed, svchan_setspeed), 445 KOBJMETHOD(channel_setblocksize, svchan_setblocksize), 446 KOBJMETHOD(channel_trigger, svpchan_trigger), 447 KOBJMETHOD(channel_getptr, svpchan_getptr), 448 KOBJMETHOD(channel_getcaps, svchan_getcaps), 449 { 0, 0 } 450 }; 451 CHANNEL_DECLARE(svpchan); 452 453 /* ------------------------------------------------------------------------- */ 454 /* Mixer support */ 455 456 struct sv_mix_props { 457 u_int8_t reg; /* Register */ 458 u_int8_t stereo:1; /* Supports 2 channels */ 459 u_int8_t mute:1; /* Supports muting */ 460 u_int8_t neg:1; /* Negative gain */ 461 u_int8_t max; /* Max gain */ 462 u_int8_t iselect; /* Input selector */ 463 } static const mt [SOUND_MIXER_NRDEVICES] = { 464 [SOUND_MIXER_LINE1] = {SV_REG_AUX1, 1, 1, 1, SV_DEFAULT_MAX, SV_INPUT_AUX1}, 465 [SOUND_MIXER_CD] = {SV_REG_CD, 1, 1, 1, SV_DEFAULT_MAX, SV_INPUT_CD}, 466 [SOUND_MIXER_LINE] = {SV_REG_LINE, 1, 1, 1, SV_DEFAULT_MAX, SV_INPUT_LINE}, 467 [SOUND_MIXER_MIC] = {SV_REG_MIC, 0, 1, 1, SV_MIC_MAX, SV_INPUT_MIC}, 468 [SOUND_MIXER_SYNTH] = {SV_REG_SYNTH, 0, 1, 1, SV_DEFAULT_MAX, 0}, 469 [SOUND_MIXER_LINE2] = {SV_REG_AUX2, 1, 1, 1, SV_DEFAULT_MAX, SV_INPUT_AUX2}, 470 [SOUND_MIXER_VOLUME] = {SV_REG_MIX, 1, 1, 1, SV_DEFAULT_MAX, 0}, 471 [SOUND_MIXER_PCM] = {SV_REG_PCM, 1, 1, 1, SV_PCM_MAX, 0}, 472 [SOUND_MIXER_RECLEV] = {SV_REG_ADC_INPUT, 1, 0, 0, SV_ADC_MAX, 0}, 473 }; 474 475 static void 476 sv_channel_gain(struct sc_info *sc, u_int32_t dev, u_int32_t gain, u_int32_t channel) 477 { 478 u_int8_t v; 479 int32_t g; 480 481 g = mt[dev].max * gain / 100; 482 if (mt[dev].neg) 483 g = mt[dev].max - g; 484 v = sv_indirect_get(sc, mt[dev].reg + channel) & ~mt[dev].max; 485 v |= g; 486 487 if (mt[dev].mute) { 488 if (gain == 0) { 489 v |= SV_MUTE; 490 } else { 491 v &= ~SV_MUTE; 492 } 493 } 494 sv_indirect_set(sc, mt[dev].reg + channel, v); 495 } 496 497 static int 498 sv_gain(struct sc_info *sc, u_int32_t dev, u_int32_t left, u_int32_t right) 499 { 500 sv_channel_gain(sc, dev, left, 0); 501 if (mt[dev].stereo) 502 sv_channel_gain(sc, dev, right, 1); 503 return 0; 504 } 505 506 static void 507 sv_mix_mute_all(struct sc_info *sc) 508 { 509 int32_t i; 510 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 511 if (mt[i].reg) sv_gain(sc, i, 0, 0); 512 } 513 } 514 515 static int 516 sv_mix_init(struct snd_mixer *m) 517 { 518 u_int32_t i, v; 519 520 for(i = v = 0; i < SOUND_MIXER_NRDEVICES; i++) { 521 if (mt[i].max) v |= (1 << i); 522 } 523 mix_setdevs(m, v); 524 525 for(i = v = 0; i < SOUND_MIXER_NRDEVICES; i++) { 526 if (mt[i].iselect) v |= (1 << i); 527 } 528 mix_setrecdevs(m, v); 529 530 return 0; 531 } 532 533 static int 534 sv_mix_set(struct snd_mixer *m, u_int32_t dev, u_int32_t left, u_int32_t right) 535 { 536 struct sc_info *sc = mix_getdevinfo(m); 537 return sv_gain(sc, dev, left, right); 538 } 539 540 static int 541 sv_mix_setrecsrc(struct snd_mixer *m, u_int32_t mask) 542 { 543 struct sc_info *sc = mix_getdevinfo(m); 544 u_int32_t i, v; 545 546 v = sv_indirect_get(sc, SV_REG_ADC_INPUT) & SV_INPUT_GAIN_MASK; 547 for(i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 548 if ((1 << i) & mask) { 549 v |= mt[i].iselect; 550 } 551 } 552 DEB(printf("sv_mix_setrecsrc: mask 0x%08x adc_input 0x%02x\n", mask, v)); 553 return mask; 554 } 555 556 static kobj_method_t sv_mixer_methods[] = { 557 KOBJMETHOD(mixer_init, sv_mix_init), 558 KOBJMETHOD(mixer_set, sv_mix_set), 559 KOBJMETHOD(mixer_setrecsrc, sv_mix_setrecsrc), 560 { 0, 0 } 561 }; 562 MIXER_DECLARE(sv_mixer); 563 564 /* ------------------------------------------------------------------------- */ 565 /* Power management and reset */ 566 567 static void 568 sv_power(struct sc_info *sc, int state) 569 { 570 u_int8_t v; 571 572 switch (state) { 573 case 0: 574 /* power on */ 575 v = sv_indirect_get(sc, SV_REG_ANALOG_PWR) &~ SV_ANALOG_OFF; 576 v |= SV_ANALOG_OFF_SRS | SV_ANALOG_OFF_SPLL; 577 sv_indirect_set(sc, SV_REG_ANALOG_PWR, v); 578 v = sv_indirect_get(sc, SV_REG_DIGITAL_PWR) &~ SV_DIGITAL_OFF; 579 v |= SV_DIGITAL_OFF_SYN | SV_DIGITAL_OFF_MU | SV_DIGITAL_OFF_GP; 580 sv_indirect_set(sc, SV_REG_DIGITAL_PWR, v); 581 break; 582 default: 583 /* power off */ 584 v = sv_indirect_get(sc, SV_REG_ANALOG_PWR) | SV_ANALOG_OFF; 585 sv_indirect_set(sc, SV_REG_ANALOG_PWR, v); 586 v = sv_indirect_get(sc, SV_REG_DIGITAL_PWR) | SV_DIGITAL_OFF; 587 sv_indirect_set(sc, SV_REG_DIGITAL_PWR, SV_DIGITAL_OFF); 588 break; 589 } 590 DEB(printf("Power state %d\n", state)); 591 } 592 593 static int 594 sv_init(struct sc_info *sc) 595 { 596 u_int8_t v; 597 598 /* Effect reset */ 599 v = sv_direct_get(sc, SV_CM_CONTROL) & ~SV_CM_CONTROL_ENHANCED; 600 v |= SV_CM_CONTROL_RESET; 601 sv_direct_set(sc, SV_CM_CONTROL, v); 602 DELAY(50); 603 604 v = sv_direct_get(sc, SV_CM_CONTROL) & ~SV_CM_CONTROL_RESET; 605 sv_direct_set(sc, SV_CM_CONTROL, v); 606 DELAY(50); 607 608 /* Set in enhanced mode */ 609 v = sv_direct_get(sc, SV_CM_CONTROL); 610 v |= SV_CM_CONTROL_ENHANCED; 611 sv_direct_set(sc, SV_CM_CONTROL, v); 612 613 /* Enable interrupts (UDM and MIDM are superfluous) */ 614 v = sv_direct_get(sc, SV_CM_IMR); 615 v &= ~(SV_CM_IMR_AMSK | SV_CM_IMR_CMSK | SV_CM_IMR_SMSK); 616 sv_direct_set(sc, SV_CM_IMR, v); 617 618 /* Select ADC PLL for ADC clock */ 619 v = sv_indirect_get(sc, SV_REG_CLOCK_SOURCE) & ~SV_CLOCK_ALTERNATE; 620 sv_indirect_set(sc, SV_REG_CLOCK_SOURCE, v); 621 622 /* Disable loopback - binds ADC and DAC rates */ 623 v = sv_indirect_get(sc, SV_REG_LOOPBACK) & ~SV_LOOPBACK_ENABLE; 624 sv_indirect_set(sc, SV_REG_LOOPBACK, v); 625 626 /* Disable SRS */ 627 v = sv_indirect_get(sc, SV_REG_SRS_SPACE) | SV_SRS_DISABLED; 628 sv_indirect_set(sc, SV_REG_SRS_SPACE, v); 629 630 /* Get revision */ 631 sc->rev = sv_indirect_get(sc, SV_REG_REVISION); 632 633 return 0; 634 } 635 636 static int 637 sv_suspend(device_t dev) 638 { 639 struct sc_info *sc = pcm_getdevinfo(dev); 640 641 sc->rch.dma_was_active = sc->rch.dma_active; 642 svrchan_trigger(NULL, &sc->rch, PCMTRIG_ABORT); 643 644 sc->pch.dma_was_active = sc->pch.dma_active; 645 svrchan_trigger(NULL, &sc->pch, PCMTRIG_ABORT); 646 647 sv_mix_mute_all(sc); 648 sv_power(sc, 3); 649 650 return 0; 651 } 652 653 static int 654 sv_resume(device_t dev) 655 { 656 struct sc_info *sc = pcm_getdevinfo(dev); 657 658 sv_mix_mute_all(sc); 659 sv_power(sc, 0); 660 if (sv_init(sc) == -1) { 661 device_printf(dev, "unable to reinitialize the card\n"); 662 return ENXIO; 663 } 664 665 if (mixer_reinit(dev) == -1) { 666 device_printf(dev, "unable to reinitialize the mixer\n"); 667 return ENXIO; 668 } 669 670 if (sc->rch.dma_was_active) { 671 svrchan_trigger(0, &sc->rch, PCMTRIG_START); 672 } 673 674 if (sc->pch.dma_was_active) { 675 svpchan_trigger(0, &sc->pch, PCMTRIG_START); 676 } 677 678 return 0; 679 } 680 681 /* ------------------------------------------------------------------------- */ 682 /* Resource related */ 683 684 static void 685 sv_intr(void *data) 686 { 687 struct sc_info *sc = data; 688 u_int8_t status; 689 690 status = sv_direct_get(sc, SV_CM_STATUS); 691 if (status & SV_CM_STATUS_AINT) 692 chn_intr(sc->pch.channel); 693 694 if (status & SV_CM_STATUS_CINT) 695 chn_intr(sc->rch.channel); 696 697 status &= ~(SV_CM_STATUS_AINT|SV_CM_STATUS_CINT); 698 DEB(if (status) printf("intr 0x%02x ?\n", status)); 699 700 return; 701 } 702 703 static int 704 sv_probe(device_t dev) 705 { 706 switch(pci_get_devid(dev)) { 707 case SV_PCI_ID: 708 device_set_desc(dev, "S3 Sonicvibes"); 709 return 0; 710 default: 711 return ENXIO; 712 } 713 } 714 715 static int 716 sv_attach(device_t dev) { 717 struct snddev_info *d; 718 struct sc_info *sc; 719 u_int32_t data; 720 char status[SND_STATUSLEN]; 721 u_long midi_start, games_start, count, sdmaa, sdmac, ml, mu; 722 723 d = device_get_softc(dev); 724 725 sc = malloc(sizeof(struct sc_info), M_DEVBUF, M_NOWAIT | M_ZERO); 726 if (sc == NULL) { 727 device_printf(dev, "cannot allocate softc"); 728 return ENXIO; 729 } 730 sc->dev = dev; 731 732 data = pci_read_config(dev, PCIR_COMMAND, 2); 733 data |= (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN); 734 pci_write_config(dev, PCIR_COMMAND, data, 2); 735 data = pci_read_config(dev, PCIR_COMMAND, 2); 736 737 #if __FreeBSD_version > 500000 738 if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) { 739 device_printf(dev, "chip is in D%d power mode " 740 "-- setting to D0\n", pci_get_powerstate(dev)); 741 pci_set_powerstate(dev, PCI_POWERSTATE_D0); 742 } 743 #endif 744 sc->enh_rid = SV_PCI_ENHANCED; 745 sc->enh_type = SYS_RES_IOPORT; 746 sc->enh_reg = bus_alloc_resource(dev, sc->enh_type, 747 &sc->enh_rid, 0, ~0, 748 SV_PCI_ENHANCED_SIZE, RF_ACTIVE); 749 if (sc->enh_reg == NULL) { 750 device_printf(dev, "sv_attach: cannot allocate enh\n"); 751 return ENXIO; 752 } 753 sc->enh_st = rman_get_bustag(sc->enh_reg); 754 sc->enh_sh = rman_get_bushandle(sc->enh_reg); 755 756 data = pci_read_config(dev, SV_PCI_DMAA, 4); 757 DEB(printf("sv_attach: initial dmaa 0x%08x\n", data)); 758 data = pci_read_config(dev, SV_PCI_DMAC, 4); 759 DEB(printf("sv_attach: initial dmac 0x%08x\n", data)); 760 761 /* Initialize DMA_A and DMA_C */ 762 pci_write_config(dev, SV_PCI_DMAA, SV_PCI_DMA_EXTENDED, 4); 763 pci_write_config(dev, SV_PCI_DMAC, 0, 4); 764 765 /* Register IRQ handler */ 766 sc->irqid = 0; 767 sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irqid, 768 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); 769 if (!sc->irq || 770 bus_setup_intr(dev, sc->irq, INTR_TYPE_AV, sv_intr, sc, &sc->ih)) { 771 device_printf(dev, "sv_attach: Unable to map interrupt\n"); 772 goto fail; 773 } 774 775 sc->bufsz = pcm_getbuffersize(dev, 4096, SV_DEFAULT_BUFSZ, 65536); 776 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, 777 /*lowaddr*/BUS_SPACE_MAXADDR_24BIT, 778 /*highaddr*/BUS_SPACE_MAXADDR, 779 /*filter*/NULL, /*filterarg*/NULL, 780 /*maxsize*/sc->bufsz, /*nsegments*/1, 781 /*maxsegz*/0x3ffff, /*flags*/0, 782 &sc->parent_dmat) != 0) { 783 device_printf(dev, "sv_attach: Unable to create dma tag\n"); 784 goto fail; 785 } 786 787 /* Power up and initialize */ 788 sv_mix_mute_all(sc); 789 sv_power(sc, 0); 790 sv_init(sc); 791 792 if (mixer_init(dev, &sv_mixer_class, sc) != 0) { 793 device_printf(dev, "sv_attach: Mixer failed to initialize\n"); 794 goto fail; 795 } 796 797 /* XXX This is a hack, and it's ugly. Okay, the deal is this 798 * card has two more io regions that available for automatic 799 * configuration by the pci code. These need to be allocated 800 * to used as control registers for the DMA engines. 801 * Unfortunately FBSD has no bus_space_foo() functions so we 802 * have to grab port space in region of existing resources. Go 803 * for space between midi and game ports. 804 */ 805 bus_get_resource(dev, SYS_RES_IOPORT, SV_PCI_MIDI, &midi_start, &count); 806 bus_get_resource(dev, SYS_RES_IOPORT, SV_PCI_GAMES, &games_start, &count); 807 808 if (games_start < midi_start) { 809 ml = games_start; 810 mu = midi_start; 811 } else { 812 ml = midi_start; 813 mu = games_start; 814 } 815 /* Check assumptions about space availability and 816 alignment. How driver loaded can determine whether 817 games_start > midi_start or vice versa */ 818 if ((mu - ml >= 0x800) || 819 ((mu - ml) % 0x200)) { 820 device_printf(dev, "sv_attach: resource assumptions not met " 821 "(midi 0x%08lx, games 0x%08lx)\n", 822 midi_start, games_start); 823 goto fail; 824 } 825 826 sdmaa = ml + 0x40; 827 sdmac = sdmaa + 0x40; 828 829 /* Add resources to list of pci resources for this device - from here on 830 * they look like normal pci resources. */ 831 bus_set_resource(dev, SYS_RES_IOPORT, SV_PCI_DMAA, sdmaa, SV_PCI_DMAA_SIZE); 832 bus_set_resource(dev, SYS_RES_IOPORT, SV_PCI_DMAC, sdmac, SV_PCI_DMAC_SIZE); 833 834 /* Cache resource short-cuts for dma_a */ 835 sc->dmaa_rid = SV_PCI_DMAA; 836 sc->dmaa_type = SYS_RES_IOPORT; 837 sc->dmaa_reg = bus_alloc_resource(dev, sc->dmaa_type, 838 &sc->dmaa_rid, 0, ~0, 839 SV_PCI_ENHANCED_SIZE, RF_ACTIVE); 840 if (sc->dmaa_reg == NULL) { 841 device_printf(dev, "sv_attach: cannot allocate dmaa\n"); 842 goto fail; 843 } 844 sc->dmaa_st = rman_get_bustag(sc->dmaa_reg); 845 sc->dmaa_sh = rman_get_bushandle(sc->dmaa_reg); 846 847 /* Poke port into dma_a configuration, nb bit flags to enable dma */ 848 data = pci_read_config(dev, SV_PCI_DMAA, 4) | SV_PCI_DMA_ENABLE | SV_PCI_DMA_EXTENDED; 849 data = ((u_int32_t)sdmaa & 0xfffffff0) | (data & 0x0f); 850 pci_write_config(dev, SV_PCI_DMAA, data, 4); 851 DEB(printf("dmaa: 0x%x 0x%x\n", data, pci_read_config(dev, SV_PCI_DMAA, 4))); 852 853 /* Cache resource short-cuts for dma_c */ 854 sc->dmac_rid = SV_PCI_DMAC; 855 sc->dmac_type = SYS_RES_IOPORT; 856 sc->dmac_reg = bus_alloc_resource(dev, sc->dmac_type, 857 &sc->dmac_rid, 0, ~0, 858 SV_PCI_ENHANCED_SIZE, RF_ACTIVE); 859 if (sc->dmac_reg == NULL) { 860 device_printf(dev, "sv_attach: cannot allocate dmac\n"); 861 goto fail; 862 } 863 sc->dmac_st = rman_get_bustag(sc->dmac_reg); 864 sc->dmac_sh = rman_get_bushandle(sc->dmac_reg); 865 866 /* Poke port into dma_c configuration, nb bit flags to enable dma */ 867 data = pci_read_config(dev, SV_PCI_DMAC, 4) | SV_PCI_DMA_ENABLE | SV_PCI_DMA_EXTENDED; 868 data = ((u_int32_t)sdmac & 0xfffffff0) | (data & 0x0f); 869 pci_write_config(dev, SV_PCI_DMAC, data, 4); 870 DEB(printf("dmac: 0x%x 0x%x\n", data, pci_read_config(dev, SV_PCI_DMAC, 4))); 871 872 if (bootverbose) 873 printf("Sonicvibes: revision %d.\n", sc->rev); 874 875 if (pcm_register(dev, sc, 1, 1)) { 876 device_printf(dev, "sv_attach: pcm_register fail\n"); 877 goto fail; 878 } 879 880 pcm_addchan(dev, PCMDIR_PLAY, &svpchan_class, sc); 881 pcm_addchan(dev, PCMDIR_REC, &svrchan_class, sc); 882 883 snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld", 884 rman_get_start(sc->enh_reg), rman_get_start(sc->irq)); 885 pcm_setstatus(dev, status); 886 887 DEB(printf("sv_attach: succeeded\n")); 888 889 return 0; 890 891 fail: 892 if (sc->parent_dmat) 893 bus_dma_tag_destroy(sc->parent_dmat); 894 if (sc->ih) 895 bus_teardown_intr(dev, sc->irq, sc->ih); 896 if (sc->irq) 897 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); 898 if (sc->enh_reg) 899 bus_release_resource(dev, sc->enh_type, sc->enh_rid, sc->enh_reg); 900 if (sc->dmaa_reg) 901 bus_release_resource(dev, sc->dmaa_type, sc->dmaa_rid, sc->dmaa_reg); 902 if (sc->dmac_reg) 903 bus_release_resource(dev, sc->dmac_type, sc->dmac_rid, sc->dmac_reg); 904 return ENXIO; 905 } 906 907 static int 908 sv_detach(device_t dev) { 909 struct sc_info *sc; 910 int r; 911 912 r = pcm_unregister(dev); 913 if (r) return r; 914 915 sc = pcm_getdevinfo(dev); 916 sv_mix_mute_all(sc); 917 sv_power(sc, 3); 918 919 bus_dma_tag_destroy(sc->parent_dmat); 920 bus_teardown_intr(dev, sc->irq, sc->ih); 921 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); 922 bus_release_resource(dev, sc->enh_type, sc->enh_rid, sc->enh_reg); 923 bus_release_resource(dev, sc->dmaa_type, sc->dmaa_rid, sc->dmaa_reg); 924 bus_release_resource(dev, sc->dmac_type, sc->dmac_rid, sc->dmac_reg); 925 926 free(sc, M_DEVBUF); 927 928 return 0; 929 } 930 931 static device_method_t sc_methods[] = { 932 DEVMETHOD(device_probe, sv_probe), 933 DEVMETHOD(device_attach, sv_attach), 934 DEVMETHOD(device_detach, sv_detach), 935 DEVMETHOD(device_resume, sv_resume), 936 DEVMETHOD(device_suspend, sv_suspend), 937 { 0, 0 } 938 }; 939 940 static driver_t sonicvibes_driver = { 941 "pcm", 942 sc_methods, 943 PCM_SOFTC_SIZE 944 }; 945 946 DRIVER_MODULE(snd_vibes, pci, sonicvibes_driver, pcm_devclass, 0, 0); 947 MODULE_DEPEND(snd_vibes, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); 948 MODULE_VERSION(snd_vibes, 1); 949