1 /* 2 * Copyright (c) 2001 Katsurajima Naoto <raven@katsurajima.seya.yokohama.jp> 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, WHETHERIN 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 THEPOSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 */ 27 28 #include <dev/sound/pcm/sound.h> 29 #include <dev/sound/pcm/ac97.h> 30 #include <dev/sound/pci/spicds.h> 31 #include <dev/sound/pci/envy24.h> 32 33 #include <dev/pci/pcireg.h> 34 #include <dev/pci/pcivar.h> 35 36 #include "mixer_if.h" 37 38 SND_DECLARE_FILE("$FreeBSD$"); 39 40 MALLOC_DEFINE(M_ENVY24, "envy24", "envy24 audio"); 41 42 /* -------------------------------------------------------------------- */ 43 44 struct sc_info; 45 46 #define ENVY24_PLAY_CHNUM 10 47 #define ENVY24_REC_CHNUM 12 48 #define ENVY24_PLAY_BUFUNIT (4 /* byte/sample */ * 10 /* channel */) 49 #define ENVY24_REC_BUFUNIT (4 /* byte/sample */ * 12 /* channel */) 50 #define ENVY24_SAMPLE_NUM 4096 51 52 #define ENVY24_TIMEOUT 1000 53 54 #define ENVY24_DEFAULT_FORMAT (AFMT_STEREO | AFMT_S16_LE) 55 56 #define ENVY24_NAMELEN 32 57 58 #define SDA_GPIO 0x10 59 #define SCL_GPIO 0x20 60 61 struct envy24_sample { 62 volatile u_int32_t buffer; 63 }; 64 65 typedef struct envy24_sample sample32_t; 66 67 /* channel registers */ 68 struct sc_chinfo { 69 struct snd_dbuf *buffer; 70 struct pcm_channel *channel; 71 struct sc_info *parent; 72 int dir; 73 unsigned num; /* hw channel number */ 74 75 /* channel information */ 76 u_int32_t format; 77 u_int32_t speed; 78 u_int32_t blk; /* hw block size(dword) */ 79 80 /* format conversion structure */ 81 u_int8_t *data; 82 unsigned int size; /* data buffer size(byte) */ 83 int unit; /* sample size(byte) */ 84 unsigned int offset; /* samples number offset */ 85 void (*emldma)(struct sc_chinfo *); 86 87 /* flags */ 88 int run; 89 }; 90 91 /* codec interface entrys */ 92 struct codec_entry { 93 void *(*create)(device_t dev, void *devinfo, int dir, int num); 94 void (*destroy)(void *codec); 95 void (*init)(void *codec); 96 void (*reinit)(void *codec); 97 void (*setvolume)(void *codec, int dir, unsigned int left, unsigned int right); 98 void (*setrate)(void *codec, int which, int rate); 99 }; 100 101 /* system configuration information */ 102 struct cfg_info { 103 char *name; 104 u_int16_t subvendor, subdevice; 105 u_int8_t scfg, acl, i2s, spdif; 106 u_int8_t gpiomask, gpiostate, gpiodir; 107 u_int8_t cdti, cclk, cs, cif, type; 108 u_int8_t free; 109 struct codec_entry *codec; 110 }; 111 112 /* device private data */ 113 struct sc_info { 114 device_t dev; 115 struct mtx *lock; 116 117 /* Control/Status registor */ 118 struct resource *cs; 119 int csid; 120 bus_space_tag_t cst; 121 bus_space_handle_t csh; 122 /* DDMA registor */ 123 struct resource *ddma; 124 int ddmaid; 125 bus_space_tag_t ddmat; 126 bus_space_handle_t ddmah; 127 /* Consumer Section DMA Channel Registers */ 128 struct resource *ds; 129 int dsid; 130 bus_space_tag_t dst; 131 bus_space_handle_t dsh; 132 /* MultiTrack registor */ 133 struct resource *mt; 134 int mtid; 135 bus_space_tag_t mtt; 136 bus_space_handle_t mth; 137 /* DMA tag */ 138 bus_dma_tag_t dmat; 139 /* IRQ resource */ 140 struct resource *irq; 141 int irqid; 142 void *ih; 143 144 /* system configuration data */ 145 struct cfg_info *cfg; 146 147 /* ADC/DAC number and info */ 148 int adcn, dacn; 149 void *adc[4], *dac[4]; 150 151 /* mixer control data */ 152 u_int32_t src; 153 u_int8_t left[ENVY24_CHAN_NUM]; 154 u_int8_t right[ENVY24_CHAN_NUM]; 155 156 /* Play/Record DMA fifo */ 157 sample32_t *pbuf; 158 sample32_t *rbuf; 159 u_int32_t psize, rsize; /* DMA buffer size(byte) */ 160 u_int16_t blk[2]; /* transfer check blocksize(dword) */ 161 bus_dmamap_t pmap, rmap; 162 163 /* current status */ 164 u_int32_t speed; 165 int run[2]; 166 u_int16_t intr[2]; 167 struct pcmchan_caps caps[2]; 168 169 /* channel info table */ 170 unsigned chnum; 171 struct sc_chinfo chan[11]; 172 }; 173 174 /* -------------------------------------------------------------------- */ 175 176 /* 177 * prototypes 178 */ 179 180 /* DMA emulator */ 181 static void envy24_p8u(struct sc_chinfo *); 182 static void envy24_p16sl(struct sc_chinfo *); 183 static void envy24_p32sl(struct sc_chinfo *); 184 static void envy24_r16sl(struct sc_chinfo *); 185 static void envy24_r32sl(struct sc_chinfo *); 186 187 /* channel interface */ 188 static void *envy24chan_init(kobj_t, void *, struct snd_dbuf *, struct pcm_channel *, int); 189 static int envy24chan_setformat(kobj_t, void *, u_int32_t); 190 static int envy24chan_setspeed(kobj_t, void *, u_int32_t); 191 static int envy24chan_setblocksize(kobj_t, void *, u_int32_t); 192 static int envy24chan_trigger(kobj_t, void *, int); 193 static int envy24chan_getptr(kobj_t, void *); 194 static struct pcmchan_caps *envy24chan_getcaps(kobj_t, void *); 195 196 /* mixer interface */ 197 static int envy24mixer_init(struct snd_mixer *); 198 static int envy24mixer_reinit(struct snd_mixer *); 199 static int envy24mixer_uninit(struct snd_mixer *); 200 static int envy24mixer_set(struct snd_mixer *, unsigned, unsigned, unsigned); 201 static u_int32_t envy24mixer_setrecsrc(struct snd_mixer *, u_int32_t); 202 203 /* M-Audio Delta series AK4524 access interface */ 204 static void *envy24_delta_ak4524_create(device_t, void *, int, int); 205 static void envy24_delta_ak4524_destroy(void *); 206 static void envy24_delta_ak4524_init(void *); 207 static void envy24_delta_ak4524_reinit(void *); 208 static void envy24_delta_ak4524_setvolume(void *, int, unsigned int, unsigned int); 209 210 /* -------------------------------------------------------------------- */ 211 212 /* 213 system constant tables 214 */ 215 216 /* API -> hardware channel map */ 217 static unsigned envy24_chanmap[ENVY24_CHAN_NUM] = { 218 ENVY24_CHAN_PLAY_SPDIF, /* 0 */ 219 ENVY24_CHAN_PLAY_DAC1, /* 1 */ 220 ENVY24_CHAN_PLAY_DAC2, /* 2 */ 221 ENVY24_CHAN_PLAY_DAC3, /* 3 */ 222 ENVY24_CHAN_PLAY_DAC4, /* 4 */ 223 ENVY24_CHAN_REC_MIX, /* 5 */ 224 ENVY24_CHAN_REC_SPDIF, /* 6 */ 225 ENVY24_CHAN_REC_ADC1, /* 7 */ 226 ENVY24_CHAN_REC_ADC2, /* 8 */ 227 ENVY24_CHAN_REC_ADC3, /* 9 */ 228 ENVY24_CHAN_REC_ADC4, /* 10 */ 229 }; 230 231 /* mixer -> API channel map. see above */ 232 static int envy24_mixmap[] = { 233 -1, /* Master output level. It is depend on codec support */ 234 -1, /* Treble level of all output channels */ 235 -1, /* Bass level of all output channels */ 236 -1, /* Volume of synthesier input */ 237 0, /* Output level for the audio device */ 238 -1, /* Output level for the PC speaker */ 239 7, /* line in jack */ 240 -1, /* microphone jack */ 241 -1, /* CD audio input */ 242 -1, /* Recording monitor */ 243 1, /* alternative codec */ 244 -1, /* global recording level */ 245 -1, /* Input gain */ 246 -1, /* Output gain */ 247 8, /* Input source 1 */ 248 9, /* Input source 2 */ 249 10, /* Input source 3 */ 250 6, /* Digital (input) 1 */ 251 -1, /* Digital (input) 2 */ 252 -1, /* Digital (input) 3 */ 253 -1, /* Phone input */ 254 -1, /* Phone output */ 255 -1, /* Video/TV (audio) in */ 256 -1, /* Radio in */ 257 -1, /* Monitor volume */ 258 }; 259 260 /* variable rate audio */ 261 static u_int32_t envy24_speed[] = { 262 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 263 12000, 11025, 9600, 8000, 0 264 }; 265 266 /* known boards configuration */ 267 static struct codec_entry delta_codec = { 268 envy24_delta_ak4524_create, 269 envy24_delta_ak4524_destroy, 270 envy24_delta_ak4524_init, 271 envy24_delta_ak4524_reinit, 272 envy24_delta_ak4524_setvolume, 273 NULL, /* setrate */ 274 }; 275 276 static struct cfg_info cfg_table[] = { 277 { 278 "Envy24 audio (M Audio Delta Dio 2496)", 279 0x1412, 0xd631, 280 0x10, 0x80, 0xf0, 0x03, 281 0xff, 0x00, 0x00, 282 0x10, 0x20, 0x40, 0x00, 0x00, 283 0x00, 284 &delta_codec, 285 }, 286 { 287 "Envy24 audio (Terratec DMX 6fire)", 288 0x153b, 0x1138, 289 0x2f, 0x80, 0xf0, 0x03, 290 0xc0, 0xff, 0x7f, 291 0x10, 0x20, 0x01, 0x01, 0x00, 292 0x00, 293 &delta_codec, 294 }, 295 { 296 "Envy24 audio (M Audio Audiophile 2496)", 297 0x1412, 0xd634, 298 0x10, 0x80, 0x72, 0x03, 299 0x04, 0xfe, 0xfb, 300 0x08, 0x02, 0x20, 0x00, 0x01, 301 0x00, 302 &delta_codec, 303 }, 304 { 305 "Envy24 audio (Generic)", 306 0, 0, 307 0x0f, 0x00, 0x01, 0x03, 308 0xff, 0x00, 0x00, 309 0x10, 0x20, 0x40, 0x00, 0x00, 310 0x00, 311 &delta_codec, /* default codec routines */ 312 } 313 }; 314 315 static u_int32_t envy24_recfmt[] = { 316 AFMT_STEREO | AFMT_S16_LE, 317 AFMT_STEREO | AFMT_S32_LE, 318 0 319 }; 320 static struct pcmchan_caps envy24_reccaps = {8000, 96000, envy24_recfmt, 0}; 321 322 static u_int32_t envy24_playfmt[] = { 323 AFMT_STEREO | AFMT_U8, 324 AFMT_STEREO | AFMT_S16_LE, 325 AFMT_STEREO | AFMT_S32_LE, 326 0 327 }; 328 329 static struct pcmchan_caps envy24_playcaps = {8000, 96000, envy24_playfmt, 0}; 330 331 struct envy24_emldma { 332 u_int32_t format; 333 void (*emldma)(struct sc_chinfo *); 334 int unit; 335 }; 336 337 static struct envy24_emldma envy24_pemltab[] = { 338 {AFMT_STEREO | AFMT_U8, envy24_p8u, 2}, 339 {AFMT_STEREO | AFMT_S16_LE, envy24_p16sl, 4}, 340 {AFMT_STEREO | AFMT_S32_LE, envy24_p32sl, 8}, 341 {0, NULL, 0} 342 }; 343 344 static struct envy24_emldma envy24_remltab[] = { 345 {AFMT_STEREO | AFMT_S16_LE, envy24_r16sl, 4}, 346 {AFMT_STEREO | AFMT_S32_LE, envy24_r32sl, 8}, 347 {0, NULL, 0} 348 }; 349 350 /* -------------------------------------------------------------------- */ 351 352 /* common routines */ 353 static u_int32_t 354 envy24_rdcs(struct sc_info *sc, int regno, int size) 355 { 356 switch (size) { 357 case 1: 358 return bus_space_read_1(sc->cst, sc->csh, regno); 359 case 2: 360 return bus_space_read_2(sc->cst, sc->csh, regno); 361 case 4: 362 return bus_space_read_4(sc->cst, sc->csh, regno); 363 default: 364 return 0xffffffff; 365 } 366 } 367 368 static void 369 envy24_wrcs(struct sc_info *sc, int regno, u_int32_t data, int size) 370 { 371 switch (size) { 372 case 1: 373 bus_space_write_1(sc->cst, sc->csh, regno, data); 374 break; 375 case 2: 376 bus_space_write_2(sc->cst, sc->csh, regno, data); 377 break; 378 case 4: 379 bus_space_write_4(sc->cst, sc->csh, regno, data); 380 break; 381 } 382 } 383 384 static u_int32_t 385 envy24_rdmt(struct sc_info *sc, int regno, int size) 386 { 387 switch (size) { 388 case 1: 389 return bus_space_read_1(sc->mtt, sc->mth, regno); 390 case 2: 391 return bus_space_read_2(sc->mtt, sc->mth, regno); 392 case 4: 393 return bus_space_read_4(sc->mtt, sc->mth, regno); 394 default: 395 return 0xffffffff; 396 } 397 } 398 399 static void 400 envy24_wrmt(struct sc_info *sc, int regno, u_int32_t data, int size) 401 { 402 switch (size) { 403 case 1: 404 bus_space_write_1(sc->mtt, sc->mth, regno, data); 405 break; 406 case 2: 407 bus_space_write_2(sc->mtt, sc->mth, regno, data); 408 break; 409 case 4: 410 bus_space_write_4(sc->mtt, sc->mth, regno, data); 411 break; 412 } 413 } 414 415 static u_int32_t 416 envy24_rdci(struct sc_info *sc, int regno) 417 { 418 envy24_wrcs(sc, ENVY24_CCS_INDEX, regno, 1); 419 return envy24_rdcs(sc, ENVY24_CCS_DATA, 1); 420 } 421 422 static void 423 envy24_wrci(struct sc_info *sc, int regno, u_int32_t data) 424 { 425 envy24_wrcs(sc, ENVY24_CCS_INDEX, regno, 1); 426 envy24_wrcs(sc, ENVY24_CCS_DATA, data, 1); 427 } 428 429 /* -------------------------------------------------------------------- */ 430 431 /* I2C port/E2PROM access routines */ 432 433 static int 434 envy24_rdi2c(struct sc_info *sc, u_int32_t dev, u_int32_t addr) 435 { 436 u_int32_t data; 437 int i; 438 439 #if(0) 440 device_printf(sc->dev, "envy24_rdi2c(sc, 0x%02x, 0x%02x)\n", dev, addr); 441 #endif 442 for (i = 0; i < ENVY24_TIMEOUT; i++) { 443 data = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1); 444 if ((data & ENVY24_CCS_I2CSTAT_BSY) == 0) 445 break; 446 DELAY(32); /* 31.25kHz */ 447 } 448 if (i == ENVY24_TIMEOUT) { 449 return -1; 450 } 451 envy24_wrcs(sc, ENVY24_CCS_I2CADDR, addr, 1); 452 envy24_wrcs(sc, ENVY24_CCS_I2CDEV, 453 (dev & ENVY24_CCS_I2CDEV_ADDR) | ENVY24_CCS_I2CDEV_RD, 1); 454 for (i = 0; i < ENVY24_TIMEOUT; i++) { 455 data = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1); 456 if ((data & ENVY24_CCS_I2CSTAT_BSY) == 0) 457 break; 458 DELAY(32); /* 31.25kHz */ 459 } 460 if (i == ENVY24_TIMEOUT) { 461 return -1; 462 } 463 data = envy24_rdcs(sc, ENVY24_CCS_I2CDATA, 1); 464 465 #if(0) 466 device_printf(sc->dev, "envy24_rdi2c(): return 0x%x\n", data); 467 #endif 468 return (int)data; 469 } 470 471 #if 0 472 static int 473 envy24_wri2c(struct sc_info *sc, u_int32_t dev, u_int32_t addr, u_int32_t data) 474 { 475 u_int32_t tmp; 476 int i; 477 478 #if(0) 479 device_printf(sc->dev, "envy24_rdi2c(sc, 0x%02x, 0x%02x)\n", dev, addr); 480 #endif 481 for (i = 0; i < ENVY24_TIMEOUT; i++) { 482 tmp = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1); 483 if ((tmp & ENVY24_CCS_I2CSTAT_BSY) == 0) 484 break; 485 DELAY(32); /* 31.25kHz */ 486 } 487 if (i == ENVY24_TIMEOUT) { 488 return -1; 489 } 490 envy24_wrcs(sc, ENVY24_CCS_I2CADDR, addr, 1); 491 envy24_wrcs(sc, ENVY24_CCS_I2CDATA, data, 1); 492 envy24_wrcs(sc, ENVY24_CCS_I2CDEV, 493 (dev & ENVY24_CCS_I2CDEV_ADDR) | ENVY24_CCS_I2CDEV_WR, 1); 494 for (i = 0; i < ENVY24_TIMEOUT; i++) { 495 data = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1); 496 if ((data & ENVY24_CCS_I2CSTAT_BSY) == 0) 497 break; 498 DELAY(32); /* 31.25kHz */ 499 } 500 if (i == ENVY24_TIMEOUT) { 501 return -1; 502 } 503 504 return 0; 505 } 506 #endif 507 508 static int 509 envy24_rdrom(struct sc_info *sc, u_int32_t addr) 510 { 511 u_int32_t data; 512 513 #if(0) 514 device_printf(sc->dev, "envy24_rdrom(sc, 0x%02x)\n", addr); 515 #endif 516 data = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1); 517 if ((data & ENVY24_CCS_I2CSTAT_ROM) == 0) { 518 #if(0) 519 device_printf(sc->dev, "envy24_rdrom(): E2PROM not presented\n"); 520 #endif 521 return -1; 522 } 523 524 return envy24_rdi2c(sc, ENVY24_CCS_I2CDEV_ROM, addr); 525 } 526 527 static struct cfg_info * 528 envy24_rom2cfg(struct sc_info *sc) 529 { 530 struct cfg_info *buff; 531 int size; 532 int i; 533 534 #if(0) 535 device_printf(sc->dev, "envy24_rom2cfg(sc)\n"); 536 #endif 537 size = envy24_rdrom(sc, ENVY24_E2PROM_SIZE); 538 if (size < ENVY24_E2PROM_GPIODIR + 1) { 539 #if(0) 540 device_printf(sc->dev, "envy24_rom2cfg(): ENVY24_E2PROM_SIZE-->%d\n", size); 541 #endif 542 return NULL; 543 } 544 buff = malloc(sizeof(*buff), M_ENVY24, M_NOWAIT); 545 if (buff == NULL) { 546 #if(0) 547 device_printf(sc->dev, "envy24_rom2cfg(): malloc()\n"); 548 #endif 549 return NULL; 550 } 551 buff->free = 1; 552 553 buff->subvendor = envy24_rdrom(sc, ENVY24_E2PROM_SUBVENDOR) << 8; 554 buff->subvendor += envy24_rdrom(sc, ENVY24_E2PROM_SUBVENDOR + 1); 555 buff->subdevice = envy24_rdrom(sc, ENVY24_E2PROM_SUBDEVICE) << 8; 556 buff->subdevice += envy24_rdrom(sc, ENVY24_E2PROM_SUBDEVICE + 1); 557 buff->scfg = envy24_rdrom(sc, ENVY24_E2PROM_SCFG); 558 buff->acl = envy24_rdrom(sc, ENVY24_E2PROM_ACL); 559 buff->i2s = envy24_rdrom(sc, ENVY24_E2PROM_I2S); 560 buff->spdif = envy24_rdrom(sc, ENVY24_E2PROM_SPDIF); 561 buff->gpiomask = envy24_rdrom(sc, ENVY24_E2PROM_GPIOMASK); 562 buff->gpiostate = envy24_rdrom(sc, ENVY24_E2PROM_GPIOSTATE); 563 buff->gpiodir = envy24_rdrom(sc, ENVY24_E2PROM_GPIODIR); 564 565 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++) 566 if (cfg_table[i].subvendor == buff->subvendor && 567 cfg_table[i].subdevice == buff->subdevice) 568 break; 569 buff->name = cfg_table[i].name; 570 buff->codec = cfg_table[i].codec; 571 572 return buff; 573 } 574 575 static void 576 envy24_cfgfree(struct cfg_info *cfg) { 577 if (cfg == NULL) 578 return; 579 if (cfg->free) 580 free(cfg, M_ENVY24); 581 return; 582 } 583 584 /* -------------------------------------------------------------------- */ 585 586 /* AC'97 codec access routines */ 587 588 #if 0 589 static int 590 envy24_coldcd(struct sc_info *sc) 591 { 592 u_int32_t data; 593 int i; 594 595 #if(0) 596 device_printf(sc->dev, "envy24_coldcd()\n"); 597 #endif 598 envy24_wrmt(sc, ENVY24_MT_AC97CMD, ENVY24_MT_AC97CMD_CLD, 1); 599 DELAY(10); 600 envy24_wrmt(sc, ENVY24_MT_AC97CMD, 0, 1); 601 DELAY(1000); 602 for (i = 0; i < ENVY24_TIMEOUT; i++) { 603 data = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1); 604 if (data & ENVY24_MT_AC97CMD_RDY) { 605 return 0; 606 } 607 } 608 609 return -1; 610 } 611 #endif 612 613 static int 614 envy24_slavecd(struct sc_info *sc) 615 { 616 u_int32_t data; 617 int i; 618 619 #if(0) 620 device_printf(sc->dev, "envy24_slavecd()\n"); 621 #endif 622 envy24_wrmt(sc, ENVY24_MT_AC97CMD, 623 ENVY24_MT_AC97CMD_CLD | ENVY24_MT_AC97CMD_WRM, 1); 624 DELAY(10); 625 envy24_wrmt(sc, ENVY24_MT_AC97CMD, 0, 1); 626 DELAY(1000); 627 for (i = 0; i < ENVY24_TIMEOUT; i++) { 628 data = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1); 629 if (data & ENVY24_MT_AC97CMD_RDY) { 630 return 0; 631 } 632 } 633 634 return -1; 635 } 636 637 #if 0 638 static int 639 envy24_rdcd(kobj_t obj, void *devinfo, int regno) 640 { 641 struct sc_info *sc = (struct sc_info *)devinfo; 642 u_int32_t data; 643 int i; 644 645 #if(0) 646 device_printf(sc->dev, "envy24_rdcd(obj, sc, 0x%02x)\n", regno); 647 #endif 648 envy24_wrmt(sc, ENVY24_MT_AC97IDX, (u_int32_t)regno, 1); 649 envy24_wrmt(sc, ENVY24_MT_AC97CMD, ENVY24_MT_AC97CMD_RD, 1); 650 for (i = 0; i < ENVY24_TIMEOUT; i++) { 651 data = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1); 652 if ((data & ENVY24_MT_AC97CMD_RD) == 0) 653 break; 654 } 655 data = envy24_rdmt(sc, ENVY24_MT_AC97DLO, 2); 656 657 #if(0) 658 device_printf(sc->dev, "envy24_rdcd(): return 0x%x\n", data); 659 #endif 660 return (int)data; 661 } 662 663 static int 664 envy24_wrcd(kobj_t obj, void *devinfo, int regno, u_int16_t data) 665 { 666 struct sc_info *sc = (struct sc_info *)devinfo; 667 u_int32_t cmd; 668 int i; 669 670 #if(0) 671 device_printf(sc->dev, "envy24_wrcd(obj, sc, 0x%02x, 0x%04x)\n", regno, data); 672 #endif 673 envy24_wrmt(sc, ENVY24_MT_AC97IDX, (u_int32_t)regno, 1); 674 envy24_wrmt(sc, ENVY24_MT_AC97DLO, (u_int32_t)data, 2); 675 envy24_wrmt(sc, ENVY24_MT_AC97CMD, ENVY24_MT_AC97CMD_WR, 1); 676 for (i = 0; i < ENVY24_TIMEOUT; i++) { 677 cmd = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1); 678 if ((cmd & ENVY24_MT_AC97CMD_WR) == 0) 679 break; 680 } 681 682 return 0; 683 } 684 685 static kobj_method_t envy24_ac97_methods[] = { 686 KOBJMETHOD(ac97_read, envy24_rdcd), 687 KOBJMETHOD(ac97_write, envy24_wrcd), 688 {0, 0} 689 }; 690 AC97_DECLARE(envy24_ac97); 691 #endif 692 693 /* -------------------------------------------------------------------- */ 694 695 /* GPIO access routines */ 696 697 static u_int32_t 698 envy24_gpiord(struct sc_info *sc) 699 { 700 return envy24_rdci(sc, ENVY24_CCI_GPIODAT); 701 } 702 703 static void 704 envy24_gpiowr(struct sc_info *sc, u_int32_t data) 705 { 706 #if(0) 707 device_printf(sc->dev, "envy24_gpiowr(sc, 0x%02x)\n", data & 0xff); 708 return; 709 #endif 710 envy24_wrci(sc, ENVY24_CCI_GPIODAT, data); 711 return; 712 } 713 714 #if 0 715 static u_int32_t 716 envy24_gpiogetmask(struct sc_info *sc) 717 { 718 return envy24_rdci(sc, ENVY24_CCI_GPIOMASK); 719 } 720 #endif 721 722 static void 723 envy24_gpiosetmask(struct sc_info *sc, u_int32_t mask) 724 { 725 envy24_wrci(sc, ENVY24_CCI_GPIOMASK, mask); 726 return; 727 } 728 729 #if 0 730 static u_int32_t 731 envy24_gpiogetdir(struct sc_info *sc) 732 { 733 return envy24_rdci(sc, ENVY24_CCI_GPIOCTL); 734 } 735 #endif 736 737 static void 738 envy24_gpiosetdir(struct sc_info *sc, u_int32_t dir) 739 { 740 envy24_wrci(sc, ENVY24_CCI_GPIOCTL, dir); 741 return; 742 } 743 744 /* -------------------------------------------------------------------- */ 745 746 /* Envy24 I2C through GPIO bit-banging */ 747 748 struct envy24_delta_ak4524_codec { 749 struct spicds_info *info; 750 struct sc_info *parent; 751 int dir; 752 int num; 753 int cs, cclk, cdti; 754 }; 755 756 static void 757 envy24_gpio_i2c_ctl(void *codec, unsigned int scl, unsigned int sda) 758 { 759 u_int32_t data = 0; 760 struct envy24_delta_ak4524_codec *ptr = codec; 761 #if(0) 762 device_printf(ptr->parent->dev, "--> %d, %d\n", scl, sda); 763 #endif 764 data = envy24_gpiord(ptr->parent); 765 data &= ~(SDA_GPIO | SCL_GPIO); 766 if (scl) data += SCL_GPIO; 767 if (sda) data += SDA_GPIO; 768 envy24_gpiowr(ptr->parent, data); 769 return; 770 } 771 772 static void 773 i2c_wrbit(void *codec, void (*ctrl)(void*, unsigned int, unsigned int), int bit) 774 { 775 struct envy24_delta_ak4524_codec *ptr = codec; 776 unsigned int sda; 777 778 if (bit) 779 sda = 1; 780 else 781 sda = 0; 782 783 ctrl(ptr, 0, sda); 784 DELAY(I2C_DELAY); 785 ctrl(ptr, 1, sda); 786 DELAY(I2C_DELAY); 787 ctrl(ptr, 0, sda); 788 DELAY(I2C_DELAY); 789 } 790 791 static void 792 i2c_start(void *codec, void (*ctrl)(void*, unsigned int, unsigned int)) 793 { 794 struct envy24_delta_ak4524_codec *ptr = codec; 795 796 ctrl(ptr, 1, 1); 797 DELAY(I2C_DELAY); 798 ctrl(ptr, 1, 0); 799 DELAY(I2C_DELAY); 800 ctrl(ptr, 0, 0); 801 DELAY(I2C_DELAY); 802 } 803 804 static void 805 i2c_stop(void *codec, void (*ctrl)(void*, unsigned int, unsigned int)) 806 { 807 struct envy24_delta_ak4524_codec *ptr = codec; 808 809 ctrl(ptr, 0, 0); 810 DELAY(I2C_DELAY); 811 ctrl(ptr, 1, 0); 812 DELAY(I2C_DELAY); 813 ctrl(ptr, 1, 1); 814 DELAY(I2C_DELAY); 815 } 816 817 static void 818 i2c_ack(void *codec, void (*ctrl)(void*, unsigned int, unsigned int)) 819 { 820 struct envy24_delta_ak4524_codec *ptr = codec; 821 822 ctrl(ptr, 0, 1); 823 DELAY(I2C_DELAY); 824 ctrl(ptr, 1, 1); 825 DELAY(I2C_DELAY); 826 /* dummy, need routine to change gpio direction */ 827 ctrl(ptr, 0, 1); 828 DELAY(I2C_DELAY); 829 } 830 831 static void 832 i2c_wr(void *codec, void (*ctrl)(void*, unsigned int, unsigned int), u_int32_t dev, int reg, u_int8_t val) 833 { 834 struct envy24_delta_ak4524_codec *ptr = codec; 835 int mask; 836 837 i2c_start(ptr, ctrl); 838 839 for (mask = 0x80; mask != 0; mask >>= 1) 840 i2c_wrbit(ptr, ctrl, dev & mask); 841 i2c_ack(ptr, ctrl); 842 843 if (reg != 0xff) { 844 for (mask = 0x80; mask != 0; mask >>= 1) 845 i2c_wrbit(ptr, ctrl, reg & mask); 846 i2c_ack(ptr, ctrl); 847 } 848 849 for (mask = 0x80; mask != 0; mask >>= 1) 850 i2c_wrbit(ptr, ctrl, val & mask); 851 i2c_ack(ptr, ctrl); 852 853 i2c_stop(ptr, ctrl); 854 } 855 856 /* -------------------------------------------------------------------- */ 857 858 /* M-Audio Delta series AK4524 access interface routine */ 859 860 static void 861 envy24_delta_ak4524_ctl(void *codec, unsigned int cs, unsigned int cclk, unsigned int cdti) 862 { 863 u_int32_t data = 0; 864 struct envy24_delta_ak4524_codec *ptr = codec; 865 866 #if(0) 867 device_printf(ptr->parent->dev, "--> %d, %d, %d\n", cs, cclk, cdti); 868 #endif 869 data = envy24_gpiord(ptr->parent); 870 data &= ~(ptr->cs | ptr->cclk | ptr->cdti); 871 if (cs) data += ptr->cs; 872 if (cclk) data += ptr->cclk; 873 if (cdti) data += ptr->cdti; 874 envy24_gpiowr(ptr->parent, data); 875 return; 876 } 877 878 static void * 879 envy24_delta_ak4524_create(device_t dev, void *info, int dir, int num) 880 { 881 struct sc_info *sc = info; 882 struct envy24_delta_ak4524_codec *buff = NULL; 883 884 #if(0) 885 device_printf(sc->dev, "envy24_delta_ak4524_create(dev, sc, %d, %d)\n", dir, num); 886 #endif 887 888 buff = malloc(sizeof(*buff), M_ENVY24, M_NOWAIT); 889 if (buff == NULL) 890 return NULL; 891 892 if (dir == PCMDIR_REC && sc->adc[num] != NULL) 893 buff->info = ((struct envy24_delta_ak4524_codec *)sc->adc[num])->info; 894 else if (dir == PCMDIR_PLAY && sc->dac[num] != NULL) 895 buff->info = ((struct envy24_delta_ak4524_codec *)sc->dac[num])->info; 896 else 897 buff->info = spicds_create(dev, buff, num, envy24_delta_ak4524_ctl); 898 if (buff->info == NULL) { 899 free(buff, M_ENVY24); 900 return NULL; 901 } 902 903 buff->parent = sc; 904 buff->dir = dir; 905 buff->num = num; 906 907 return (void *)buff; 908 } 909 910 static void 911 envy24_delta_ak4524_destroy(void *codec) 912 { 913 struct envy24_delta_ak4524_codec *ptr = codec; 914 if (ptr == NULL) 915 return; 916 #if(0) 917 device_printf(ptr->parent->dev, "envy24_delta_ak4524_destroy()\n"); 918 #endif 919 920 if (ptr->dir == PCMDIR_PLAY) { 921 if (ptr->parent->dac[ptr->num] != NULL) 922 spicds_destroy(ptr->info); 923 } 924 else { 925 if (ptr->parent->adc[ptr->num] != NULL) 926 spicds_destroy(ptr->info); 927 } 928 929 free(codec, M_ENVY24); 930 } 931 932 static void 933 envy24_delta_ak4524_init(void *codec) 934 { 935 #if 0 936 u_int32_t gpiomask, gpiodir; 937 #endif 938 struct envy24_delta_ak4524_codec *ptr = codec; 939 if (ptr == NULL) 940 return; 941 #if(0) 942 device_printf(ptr->parent->dev, "envy24_delta_ak4524_init()\n"); 943 #endif 944 945 /* 946 gpiomask = envy24_gpiogetmask(ptr->parent); 947 gpiomask &= ~(ENVY24_GPIO_AK4524_CDTI | ENVY24_GPIO_AK4524_CCLK | ENVY24_GPIO_AK4524_CS0 | ENVY24_GPIO_AK4524_CS1); 948 envy24_gpiosetmask(ptr->parent, gpiomask); 949 gpiodir = envy24_gpiogetdir(ptr->parent); 950 gpiodir |= ENVY24_GPIO_AK4524_CDTI | ENVY24_GPIO_AK4524_CCLK | ENVY24_GPIO_AK4524_CS0 | ENVY24_GPIO_AK4524_CS1; 951 envy24_gpiosetdir(ptr->parent, gpiodir); 952 */ 953 ptr->cs = ptr->parent->cfg->cs; 954 #if 0 955 envy24_gpiosetmask(ptr->parent, ENVY24_GPIO_CS8414_STATUS); 956 envy24_gpiosetdir(ptr->parent, ~ENVY24_GPIO_CS8414_STATUS); 957 if (ptr->num == 0) 958 ptr->cs = ENVY24_GPIO_AK4524_CS0; 959 else 960 ptr->cs = ENVY24_GPIO_AK4524_CS1; 961 ptr->cclk = ENVY24_GPIO_AK4524_CCLK; 962 #endif 963 ptr->cclk = ptr->parent->cfg->cclk; 964 ptr->cdti = ptr->parent->cfg->cdti; 965 spicds_settype(ptr->info, ptr->parent->cfg->type); 966 spicds_setcif(ptr->info, ptr->parent->cfg->cif); 967 spicds_setformat(ptr->info, 968 AK452X_FORMAT_I2S | AK452X_FORMAT_256FSN | AK452X_FORMAT_1X); 969 spicds_setdvc(ptr->info, AK452X_DVC_DEMOFF); 970 /* for the time being, init only first codec */ 971 if (ptr->num == 0) 972 spicds_init(ptr->info); 973 974 /* 6fire rear input init test, set ptr->num to 1 for test */ 975 if (ptr->parent->cfg->subvendor == 0x153b && \ 976 ptr->parent->cfg->subdevice == 0x1138 && ptr->num == 100) { 977 ptr->cs = 0x02; 978 spicds_init(ptr->info); 979 device_printf(ptr->parent->dev, "6fire rear input init\n"); 980 i2c_wr(ptr, envy24_gpio_i2c_ctl, \ 981 PCA9554_I2CDEV, PCA9554_DIR, 0x80); 982 i2c_wr(ptr, envy24_gpio_i2c_ctl, \ 983 PCA9554_I2CDEV, PCA9554_OUT, 0x02); 984 } 985 } 986 987 static void 988 envy24_delta_ak4524_reinit(void *codec) 989 { 990 struct envy24_delta_ak4524_codec *ptr = codec; 991 if (ptr == NULL) 992 return; 993 #if(0) 994 device_printf(ptr->parent->dev, "envy24_delta_ak4524_reinit()\n"); 995 #endif 996 997 spicds_reinit(ptr->info); 998 } 999 1000 static void 1001 envy24_delta_ak4524_setvolume(void *codec, int dir, unsigned int left, unsigned int right) 1002 { 1003 struct envy24_delta_ak4524_codec *ptr = codec; 1004 if (ptr == NULL) 1005 return; 1006 #if(0) 1007 device_printf(ptr->parent->dev, "envy24_delta_ak4524_set()\n"); 1008 #endif 1009 1010 spicds_set(ptr->info, dir, left, right); 1011 } 1012 1013 /* 1014 There is no need for AK452[48] codec to set sample rate 1015 static void 1016 envy24_delta_ak4524_setrate(struct envy24_delta_ak4524_codec *codec, int which, int rate) 1017 { 1018 } 1019 */ 1020 1021 /* -------------------------------------------------------------------- */ 1022 1023 /* hardware access routeines */ 1024 1025 static struct { 1026 u_int32_t speed; 1027 u_int32_t code; 1028 } envy24_speedtab[] = { 1029 {48000, ENVY24_MT_RATE_48000}, 1030 {24000, ENVY24_MT_RATE_24000}, 1031 {12000, ENVY24_MT_RATE_12000}, 1032 {9600, ENVY24_MT_RATE_9600}, 1033 {32000, ENVY24_MT_RATE_32000}, 1034 {16000, ENVY24_MT_RATE_16000}, 1035 {8000, ENVY24_MT_RATE_8000}, 1036 {96000, ENVY24_MT_RATE_96000}, 1037 {64000, ENVY24_MT_RATE_64000}, 1038 {44100, ENVY24_MT_RATE_44100}, 1039 {22050, ENVY24_MT_RATE_22050}, 1040 {11025, ENVY24_MT_RATE_11025}, 1041 {88200, ENVY24_MT_RATE_88200}, 1042 {0, 0x10} 1043 }; 1044 1045 static int 1046 envy24_setspeed(struct sc_info *sc, u_int32_t speed) { 1047 u_int32_t code; 1048 int i = 0; 1049 1050 #if(0) 1051 device_printf(sc->dev, "envy24_setspeed(sc, %d)\n", speed); 1052 #endif 1053 if (speed == 0) { 1054 code = ENVY24_MT_RATE_SPDIF; /* external master clock */ 1055 envy24_slavecd(sc); 1056 } 1057 else { 1058 for (i = 0; envy24_speedtab[i].speed != 0; i++) { 1059 if (envy24_speedtab[i].speed == speed) 1060 break; 1061 } 1062 code = envy24_speedtab[i].code; 1063 } 1064 #if(0) 1065 device_printf(sc->dev, "envy24_setspeed(): speed %d/code 0x%04x\n", envy24_speedtab[i].speed, code); 1066 #endif 1067 if (code < 0x10) { 1068 envy24_wrmt(sc, ENVY24_MT_RATE, code, 1); 1069 code = envy24_rdmt(sc, ENVY24_MT_RATE, 1); 1070 code &= ENVY24_MT_RATE_MASK; 1071 for (i = 0; envy24_speedtab[i].code < 0x10; i++) { 1072 if (envy24_speedtab[i].code == code) 1073 break; 1074 } 1075 speed = envy24_speedtab[i].speed; 1076 } 1077 else 1078 speed = 0; 1079 1080 #if(0) 1081 device_printf(sc->dev, "envy24_setspeed(): return %d\n", speed); 1082 #endif 1083 return speed; 1084 } 1085 1086 static void 1087 envy24_setvolume(struct sc_info *sc, unsigned ch) 1088 { 1089 #if(0) 1090 device_printf(sc->dev, "envy24_setvolume(sc, %d)\n", ch); 1091 #endif 1092 if (sc->cfg->subvendor==0x153b && sc->cfg->subdevice==0x1138 ) { 1093 envy24_wrmt(sc, ENVY24_MT_VOLIDX, 16, 1); 1094 envy24_wrmt(sc, ENVY24_MT_VOLUME, 0x7f7f, 2); 1095 envy24_wrmt(sc, ENVY24_MT_VOLIDX, 17, 1); 1096 envy24_wrmt(sc, ENVY24_MT_VOLUME, 0x7f7f, 2); 1097 } 1098 1099 envy24_wrmt(sc, ENVY24_MT_VOLIDX, ch * 2, 1); 1100 envy24_wrmt(sc, ENVY24_MT_VOLUME, 0x7f00 | sc->left[ch], 2); 1101 envy24_wrmt(sc, ENVY24_MT_VOLIDX, ch * 2 + 1, 1); 1102 envy24_wrmt(sc, ENVY24_MT_VOLUME, (sc->right[ch] << 8) | 0x7f, 2); 1103 } 1104 1105 static void 1106 envy24_mutevolume(struct sc_info *sc, unsigned ch) 1107 { 1108 u_int32_t vol; 1109 1110 #if(0) 1111 device_printf(sc->dev, "envy24_mutevolume(sc, %d)\n", ch); 1112 #endif 1113 vol = ENVY24_VOL_MUTE << 8 | ENVY24_VOL_MUTE; 1114 envy24_wrmt(sc, ENVY24_MT_VOLIDX, ch * 2, 1); 1115 envy24_wrmt(sc, ENVY24_MT_VOLUME, vol, 2); 1116 envy24_wrmt(sc, ENVY24_MT_VOLIDX, ch * 2 + 1, 1); 1117 envy24_wrmt(sc, ENVY24_MT_VOLUME, vol, 2); 1118 } 1119 1120 static u_int32_t 1121 envy24_gethwptr(struct sc_info *sc, int dir) 1122 { 1123 int unit, regno; 1124 u_int32_t ptr, rtn; 1125 1126 #if(0) 1127 device_printf(sc->dev, "envy24_gethwptr(sc, %d)\n", dir); 1128 #endif 1129 if (dir == PCMDIR_PLAY) { 1130 rtn = sc->psize / 4; 1131 unit = ENVY24_PLAY_BUFUNIT / 4; 1132 regno = ENVY24_MT_PCNT; 1133 } 1134 else { 1135 rtn = sc->rsize / 4; 1136 unit = ENVY24_REC_BUFUNIT / 4; 1137 regno = ENVY24_MT_RCNT; 1138 } 1139 1140 ptr = envy24_rdmt(sc, regno, 2); 1141 rtn -= (ptr + 1); 1142 rtn /= unit; 1143 1144 #if(0) 1145 device_printf(sc->dev, "envy24_gethwptr(): return %d\n", rtn); 1146 #endif 1147 return rtn; 1148 } 1149 1150 static void 1151 envy24_updintr(struct sc_info *sc, int dir) 1152 { 1153 int regptr, regintr; 1154 u_int32_t mask, intr; 1155 u_int32_t ptr, size, cnt; 1156 u_int16_t blk; 1157 1158 #if(0) 1159 device_printf(sc->dev, "envy24_updintr(sc, %d)\n", dir); 1160 #endif 1161 if (dir == PCMDIR_PLAY) { 1162 blk = sc->blk[0]; 1163 size = sc->psize / 4; 1164 regptr = ENVY24_MT_PCNT; 1165 regintr = ENVY24_MT_PTERM; 1166 mask = ~ENVY24_MT_INT_PMASK; 1167 } 1168 else { 1169 blk = sc->blk[1]; 1170 size = sc->rsize / 4; 1171 regptr = ENVY24_MT_RCNT; 1172 regintr = ENVY24_MT_RTERM; 1173 mask = ~ENVY24_MT_INT_RMASK; 1174 } 1175 1176 ptr = size - envy24_rdmt(sc, regptr, 2) - 1; 1177 /* 1178 cnt = blk - ptr % blk - 1; 1179 if (cnt == 0) 1180 cnt = blk - 1; 1181 */ 1182 cnt = blk - 1; 1183 #if(0) 1184 device_printf(sc->dev, "envy24_updintr():ptr = %d, blk = %d, cnt = %d\n", ptr, blk, cnt); 1185 #endif 1186 envy24_wrmt(sc, regintr, cnt, 2); 1187 intr = envy24_rdmt(sc, ENVY24_MT_INT, 1); 1188 #if(0) 1189 device_printf(sc->dev, "envy24_updintr():intr = 0x%02x, mask = 0x%02x\n", intr, mask); 1190 #endif 1191 envy24_wrmt(sc, ENVY24_MT_INT, intr & mask, 1); 1192 #if(0) 1193 device_printf(sc->dev, "envy24_updintr():INT-->0x%02x\n", 1194 envy24_rdmt(sc, ENVY24_MT_INT, 1)); 1195 #endif 1196 1197 return; 1198 } 1199 1200 #if 0 1201 static void 1202 envy24_maskintr(struct sc_info *sc, int dir) 1203 { 1204 u_int32_t mask, intr; 1205 1206 #if(0) 1207 device_printf(sc->dev, "envy24_maskintr(sc, %d)\n", dir); 1208 #endif 1209 if (dir == PCMDIR_PLAY) 1210 mask = ENVY24_MT_INT_PMASK; 1211 else 1212 mask = ENVY24_MT_INT_RMASK; 1213 intr = envy24_rdmt(sc, ENVY24_MT_INT, 1); 1214 envy24_wrmt(sc, ENVY24_MT_INT, intr | mask, 1); 1215 1216 return; 1217 } 1218 #endif 1219 1220 static int 1221 envy24_checkintr(struct sc_info *sc, int dir) 1222 { 1223 u_int32_t mask, stat, intr, rtn; 1224 1225 #if(0) 1226 device_printf(sc->dev, "envy24_checkintr(sc, %d)\n", dir); 1227 #endif 1228 intr = envy24_rdmt(sc, ENVY24_MT_INT, 1); 1229 if (dir == PCMDIR_PLAY) { 1230 if ((rtn = intr & ENVY24_MT_INT_PSTAT) != 0) { 1231 mask = ~ENVY24_MT_INT_RSTAT; 1232 stat = ENVY24_MT_INT_PSTAT | ENVY24_MT_INT_PMASK; 1233 envy24_wrmt(sc, ENVY24_MT_INT, (intr & mask) | stat, 1); 1234 } 1235 } 1236 else { 1237 if ((rtn = intr & ENVY24_MT_INT_RSTAT) != 0) { 1238 mask = ~ENVY24_MT_INT_PSTAT; 1239 stat = ENVY24_MT_INT_RSTAT | ENVY24_MT_INT_RMASK; 1240 envy24_wrmt(sc, ENVY24_MT_INT, (intr & mask) | stat, 1); 1241 } 1242 } 1243 1244 return rtn; 1245 } 1246 1247 static void 1248 envy24_start(struct sc_info *sc, int dir) 1249 { 1250 u_int32_t stat, sw; 1251 1252 #if(0) 1253 device_printf(sc->dev, "envy24_start(sc, %d)\n", dir); 1254 #endif 1255 if (dir == PCMDIR_PLAY) 1256 sw = ENVY24_MT_PCTL_PSTART; 1257 else 1258 sw = ENVY24_MT_PCTL_RSTART; 1259 1260 stat = envy24_rdmt(sc, ENVY24_MT_PCTL, 1); 1261 envy24_wrmt(sc, ENVY24_MT_PCTL, stat | sw, 1); 1262 #if(0) 1263 DELAY(100); 1264 device_printf(sc->dev, "PADDR:0x%08x\n", envy24_rdmt(sc, ENVY24_MT_PADDR, 4)); 1265 device_printf(sc->dev, "PCNT:%ld\n", envy24_rdmt(sc, ENVY24_MT_PCNT, 2)); 1266 #endif 1267 1268 return; 1269 } 1270 1271 static void 1272 envy24_stop(struct sc_info *sc, int dir) 1273 { 1274 u_int32_t stat, sw; 1275 1276 #if(0) 1277 device_printf(sc->dev, "envy24_stop(sc, %d)\n", dir); 1278 #endif 1279 if (dir == PCMDIR_PLAY) 1280 sw = ~ENVY24_MT_PCTL_PSTART; 1281 else 1282 sw = ~ENVY24_MT_PCTL_RSTART; 1283 1284 stat = envy24_rdmt(sc, ENVY24_MT_PCTL, 1); 1285 envy24_wrmt(sc, ENVY24_MT_PCTL, stat & sw, 1); 1286 1287 return; 1288 } 1289 1290 static int 1291 envy24_route(struct sc_info *sc, int dac, int class, int adc, int rev) 1292 { 1293 u_int32_t reg, mask; 1294 u_int32_t left, right; 1295 1296 #if(0) 1297 device_printf(sc->dev, "envy24_route(sc, %d, %d, %d, %d)\n", 1298 dac, class, adc, rev); 1299 #endif 1300 /* parameter pattern check */ 1301 if (dac < 0 || ENVY24_ROUTE_DAC_SPDIF < dac) 1302 return -1; 1303 if (class == ENVY24_ROUTE_CLASS_MIX && 1304 (dac != ENVY24_ROUTE_DAC_1 && dac != ENVY24_ROUTE_DAC_SPDIF)) 1305 return -1; 1306 if (rev) { 1307 left = ENVY24_ROUTE_RIGHT; 1308 right = ENVY24_ROUTE_LEFT; 1309 } 1310 else { 1311 left = ENVY24_ROUTE_LEFT; 1312 right = ENVY24_ROUTE_RIGHT; 1313 } 1314 1315 if (dac == ENVY24_ROUTE_DAC_SPDIF) { 1316 reg = class | class << 2 | 1317 ((adc << 1 | left) | left << 3) << 8 | 1318 ((adc << 1 | right) | right << 3) << 12; 1319 #if(0) 1320 device_printf(sc->dev, "envy24_route(): MT_SPDOUT-->0x%04x\n", reg); 1321 #endif 1322 envy24_wrmt(sc, ENVY24_MT_SPDOUT, reg, 2); 1323 } 1324 else { 1325 mask = ~(0x0303 << dac * 2); 1326 reg = envy24_rdmt(sc, ENVY24_MT_PSDOUT, 2); 1327 reg = (reg & mask) | ((class | class << 8) << dac * 2); 1328 #if(0) 1329 device_printf(sc->dev, "envy24_route(): MT_PSDOUT-->0x%04x\n", reg); 1330 #endif 1331 envy24_wrmt(sc, ENVY24_MT_PSDOUT, reg, 2); 1332 mask = ~(0xff << dac * 8); 1333 reg = envy24_rdmt(sc, ENVY24_MT_RECORD, 4); 1334 reg = (reg & mask) | 1335 (((adc << 1 | left) | left << 3) | 1336 ((adc << 1 | right) | right << 3) << 4) << dac * 8; 1337 #if(0) 1338 device_printf(sc->dev, "envy24_route(): MT_RECORD-->0x%08x\n", reg); 1339 #endif 1340 envy24_wrmt(sc, ENVY24_MT_RECORD, reg, 4); 1341 1342 /* 6fire rear input init test */ 1343 envy24_wrmt(sc, ENVY24_MT_RECORD, 0x00, 4); 1344 } 1345 1346 return 0; 1347 } 1348 1349 /* -------------------------------------------------------------------- */ 1350 1351 /* buffer copy routines */ 1352 static void 1353 envy24_p32sl(struct sc_chinfo *ch) 1354 { 1355 int length; 1356 sample32_t *dmabuf; 1357 u_int32_t *data; 1358 int src, dst, ssize, dsize, slot; 1359 int i; 1360 1361 length = sndbuf_getready(ch->buffer) / 8; 1362 dmabuf = ch->parent->pbuf; 1363 data = (u_int32_t *)ch->data; 1364 src = sndbuf_getreadyptr(ch->buffer) / 4; 1365 dst = src / 2 + ch->offset; 1366 ssize = ch->size / 4; 1367 dsize = ch->size / 8; 1368 slot = ch->num * 2; 1369 1370 for (i = 0; i < length; i++) { 1371 dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = data[src]; 1372 dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = data[src + 1]; 1373 dst++; 1374 dst %= dsize; 1375 src += 2; 1376 src %= ssize; 1377 } 1378 1379 return; 1380 } 1381 1382 static void 1383 envy24_p16sl(struct sc_chinfo *ch) 1384 { 1385 int length; 1386 sample32_t *dmabuf; 1387 u_int16_t *data; 1388 int src, dst, ssize, dsize, slot; 1389 int i; 1390 1391 #if(0) 1392 device_printf(ch->parent->dev, "envy24_p16sl()\n"); 1393 #endif 1394 length = sndbuf_getready(ch->buffer) / 4; 1395 dmabuf = ch->parent->pbuf; 1396 data = (u_int16_t *)ch->data; 1397 src = sndbuf_getreadyptr(ch->buffer) / 2; 1398 dst = src / 2 + ch->offset; 1399 ssize = ch->size / 2; 1400 dsize = ch->size / 4; 1401 slot = ch->num * 2; 1402 #if(0) 1403 device_printf(ch->parent->dev, "envy24_p16sl():%lu-->%lu(%lu)\n", src, dst, length); 1404 #endif 1405 1406 for (i = 0; i < length; i++) { 1407 dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = (u_int32_t)data[src] << 16; 1408 dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = (u_int32_t)data[src + 1] << 16; 1409 #if(0) 1410 if (i < 16) { 1411 printf("%08x", dmabuf[dst * ENVY24_PLAY_CHNUM + slot]); 1412 printf("%08x", dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1]); 1413 } 1414 #endif 1415 dst++; 1416 dst %= dsize; 1417 src += 2; 1418 src %= ssize; 1419 } 1420 #if(0) 1421 printf("\n"); 1422 #endif 1423 1424 return; 1425 } 1426 1427 static void 1428 envy24_p8u(struct sc_chinfo *ch) 1429 { 1430 int length; 1431 sample32_t *dmabuf; 1432 u_int8_t *data; 1433 int src, dst, ssize, dsize, slot; 1434 int i; 1435 1436 length = sndbuf_getready(ch->buffer) / 2; 1437 dmabuf = ch->parent->pbuf; 1438 data = (u_int8_t *)ch->data; 1439 src = sndbuf_getreadyptr(ch->buffer); 1440 dst = src / 2 + ch->offset; 1441 ssize = ch->size; 1442 dsize = ch->size / 4; 1443 slot = ch->num * 2; 1444 1445 for (i = 0; i < length; i++) { 1446 dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = ((u_int32_t)data[src] ^ 0x80) << 24; 1447 dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = ((u_int32_t)data[src + 1] ^ 0x80) << 24; 1448 dst++; 1449 dst %= dsize; 1450 src += 2; 1451 src %= ssize; 1452 } 1453 1454 return; 1455 } 1456 1457 static void 1458 envy24_r32sl(struct sc_chinfo *ch) 1459 { 1460 int length; 1461 sample32_t *dmabuf; 1462 u_int32_t *data; 1463 int src, dst, ssize, dsize, slot; 1464 int i; 1465 1466 length = sndbuf_getfree(ch->buffer) / 8; 1467 dmabuf = ch->parent->rbuf; 1468 data = (u_int32_t *)ch->data; 1469 dst = sndbuf_getfreeptr(ch->buffer) / 4; 1470 src = dst / 2 + ch->offset; 1471 dsize = ch->size / 4; 1472 ssize = ch->size / 8; 1473 slot = (ch->num - ENVY24_CHAN_REC_ADC1) * 2; 1474 1475 for (i = 0; i < length; i++) { 1476 data[dst] = dmabuf[src * ENVY24_REC_CHNUM + slot].buffer; 1477 data[dst + 1] = dmabuf[src * ENVY24_REC_CHNUM + slot + 1].buffer; 1478 dst += 2; 1479 dst %= dsize; 1480 src++; 1481 src %= ssize; 1482 } 1483 1484 return; 1485 } 1486 1487 static void 1488 envy24_r16sl(struct sc_chinfo *ch) 1489 { 1490 int length; 1491 sample32_t *dmabuf; 1492 u_int16_t *data; 1493 int src, dst, ssize, dsize, slot; 1494 int i; 1495 1496 length = sndbuf_getfree(ch->buffer) / 4; 1497 dmabuf = ch->parent->rbuf; 1498 data = (u_int16_t *)ch->data; 1499 dst = sndbuf_getfreeptr(ch->buffer) / 2; 1500 src = dst / 2 + ch->offset; 1501 dsize = ch->size / 2; 1502 ssize = ch->size / 8; 1503 slot = (ch->num - ENVY24_CHAN_REC_ADC1) * 2; 1504 1505 for (i = 0; i < length; i++) { 1506 data[dst] = dmabuf[src * ENVY24_REC_CHNUM + slot].buffer; 1507 data[dst + 1] = dmabuf[src * ENVY24_REC_CHNUM + slot + 1].buffer; 1508 dst += 2; 1509 dst %= dsize; 1510 src++; 1511 src %= ssize; 1512 } 1513 1514 return; 1515 } 1516 1517 /* -------------------------------------------------------------------- */ 1518 1519 /* channel interface */ 1520 static void * 1521 envy24chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) 1522 { 1523 struct sc_info *sc = (struct sc_info *)devinfo; 1524 struct sc_chinfo *ch; 1525 unsigned num; 1526 1527 #if(0) 1528 device_printf(sc->dev, "envy24chan_init(obj, devinfo, b, c, %d)\n", dir); 1529 #endif 1530 snd_mtxlock(sc->lock); 1531 if ((sc->chnum > ENVY24_CHAN_PLAY_SPDIF && dir != PCMDIR_REC) || 1532 (sc->chnum < ENVY24_CHAN_REC_ADC1 && dir != PCMDIR_PLAY)) { 1533 snd_mtxunlock(sc->lock); 1534 return NULL; 1535 } 1536 num = sc->chnum; 1537 1538 ch = &sc->chan[num]; 1539 ch->size = 8 * ENVY24_SAMPLE_NUM; 1540 ch->data = malloc(ch->size, M_ENVY24, M_NOWAIT); 1541 if (ch->data == NULL) { 1542 ch->size = 0; 1543 ch = NULL; 1544 } 1545 else { 1546 ch->buffer = b; 1547 ch->channel = c; 1548 ch->parent = sc; 1549 ch->dir = dir; 1550 /* set channel map */ 1551 ch->num = envy24_chanmap[num]; 1552 snd_mtxunlock(sc->lock); 1553 sndbuf_setup(ch->buffer, ch->data, ch->size); 1554 snd_mtxlock(sc->lock); 1555 /* these 2 values are dummy */ 1556 ch->unit = 4; 1557 ch->blk = 10240; 1558 } 1559 snd_mtxunlock(sc->lock); 1560 1561 return ch; 1562 } 1563 1564 static int 1565 envy24chan_free(kobj_t obj, void *data) 1566 { 1567 struct sc_chinfo *ch = data; 1568 struct sc_info *sc = ch->parent; 1569 1570 #if(0) 1571 device_printf(sc->dev, "envy24chan_free()\n"); 1572 #endif 1573 snd_mtxlock(sc->lock); 1574 if (ch->data != NULL) { 1575 free(ch->data, M_ENVY24); 1576 ch->data = NULL; 1577 } 1578 snd_mtxunlock(sc->lock); 1579 1580 return 0; 1581 } 1582 1583 static int 1584 envy24chan_setformat(kobj_t obj, void *data, u_int32_t format) 1585 { 1586 struct sc_chinfo *ch = data; 1587 struct sc_info *sc = ch->parent; 1588 struct envy24_emldma *emltab; 1589 /* unsigned int bcnt, bsize; */ 1590 int i; 1591 1592 #if(0) 1593 device_printf(sc->dev, "envy24chan_setformat(obj, data, 0x%08x)\n", format); 1594 #endif 1595 snd_mtxlock(sc->lock); 1596 /* check and get format related information */ 1597 if (ch->dir == PCMDIR_PLAY) 1598 emltab = envy24_pemltab; 1599 else 1600 emltab = envy24_remltab; 1601 if (emltab == NULL) { 1602 snd_mtxunlock(sc->lock); 1603 return -1; 1604 } 1605 for (i = 0; emltab[i].format != 0; i++) 1606 if (emltab[i].format == format) 1607 break; 1608 if (emltab[i].format == 0) { 1609 snd_mtxunlock(sc->lock); 1610 return -1; 1611 } 1612 1613 /* set format information */ 1614 ch->format = format; 1615 ch->emldma = emltab[i].emldma; 1616 if (ch->unit > emltab[i].unit) 1617 ch->blk *= ch->unit / emltab[i].unit; 1618 else 1619 ch->blk /= emltab[i].unit / ch->unit; 1620 ch->unit = emltab[i].unit; 1621 1622 /* set channel buffer information */ 1623 ch->size = ch->unit * ENVY24_SAMPLE_NUM; 1624 #if 0 1625 if (ch->dir == PCMDIR_PLAY) 1626 bsize = ch->blk * 4 / ENVY24_PLAY_BUFUNIT; 1627 else 1628 bsize = ch->blk * 4 / ENVY24_REC_BUFUNIT; 1629 bsize *= ch->unit; 1630 bcnt = ch->size / bsize; 1631 sndbuf_resize(ch->buffer, bcnt, bsize); 1632 #endif 1633 snd_mtxunlock(sc->lock); 1634 1635 #if(0) 1636 device_printf(sc->dev, "envy24chan_setformat(): return 0x%08x\n", 0); 1637 #endif 1638 return 0; 1639 } 1640 1641 /* 1642 IMPLEMENT NOTICE: In this driver, setspeed function only do setting 1643 of speed information value. And real hardware speed setting is done 1644 at start triggered(see envy24chan_trigger()). So, at this function 1645 is called, any value that ENVY24 can use is able to set. But, at 1646 start triggerd, some other channel is running, and that channel's 1647 speed isn't same with, then trigger function will fail. 1648 */ 1649 static int 1650 envy24chan_setspeed(kobj_t obj, void *data, u_int32_t speed) 1651 { 1652 struct sc_chinfo *ch = data; 1653 u_int32_t val, prev; 1654 int i; 1655 1656 #if(0) 1657 device_printf(ch->parent->dev, "envy24chan_setspeed(obj, data, %d)\n", speed); 1658 #endif 1659 prev = 0x7fffffff; 1660 for (i = 0; (val = envy24_speed[i]) != 0; i++) { 1661 if (abs(val - speed) < abs(prev - speed)) 1662 prev = val; 1663 else 1664 break; 1665 } 1666 ch->speed = prev; 1667 1668 #if(0) 1669 device_printf(ch->parent->dev, "envy24chan_setspeed(): return %d\n", ch->speed); 1670 #endif 1671 return ch->speed; 1672 } 1673 1674 static int 1675 envy24chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) 1676 { 1677 struct sc_chinfo *ch = data; 1678 /* struct sc_info *sc = ch->parent; */ 1679 u_int32_t size, prev; 1680 unsigned int bcnt, bsize; 1681 1682 #if(0) 1683 device_printf(sc->dev, "envy24chan_setblocksize(obj, data, %d)\n", blocksize); 1684 #endif 1685 prev = 0x7fffffff; 1686 /* snd_mtxlock(sc->lock); */ 1687 for (size = ch->size / 2; size > 0; size /= 2) { 1688 if (abs(size - blocksize) < abs(prev - blocksize)) 1689 prev = size; 1690 else 1691 break; 1692 } 1693 1694 ch->blk = prev / ch->unit; 1695 if (ch->dir == PCMDIR_PLAY) 1696 ch->blk *= ENVY24_PLAY_BUFUNIT / 4; 1697 else 1698 ch->blk *= ENVY24_REC_BUFUNIT / 4; 1699 /* set channel buffer information */ 1700 /* ch->size = ch->unit * ENVY24_SAMPLE_NUM; */ 1701 if (ch->dir == PCMDIR_PLAY) 1702 bsize = ch->blk * 4 / ENVY24_PLAY_BUFUNIT; 1703 else 1704 bsize = ch->blk * 4 / ENVY24_REC_BUFUNIT; 1705 bsize *= ch->unit; 1706 bcnt = ch->size / bsize; 1707 sndbuf_resize(ch->buffer, bcnt, bsize); 1708 /* snd_mtxunlock(sc->lock); */ 1709 1710 #if(0) 1711 device_printf(sc->dev, "envy24chan_setblocksize(): return %d\n", prev); 1712 #endif 1713 return prev; 1714 } 1715 1716 /* semantic note: must start at beginning of buffer */ 1717 static int 1718 envy24chan_trigger(kobj_t obj, void *data, int go) 1719 { 1720 struct sc_chinfo *ch = data; 1721 struct sc_info *sc = ch->parent; 1722 u_int32_t ptr; 1723 int slot; 1724 #if 0 1725 int i; 1726 1727 device_printf(sc->dev, "envy24chan_trigger(obj, data, %d)\n", go); 1728 #endif 1729 snd_mtxlock(sc->lock); 1730 if (ch->dir == PCMDIR_PLAY) 1731 slot = 0; 1732 else 1733 slot = 1; 1734 switch (go) { 1735 case PCMTRIG_START: 1736 #if(0) 1737 device_printf(sc->dev, "envy24chan_trigger(): start\n"); 1738 #endif 1739 /* check or set channel speed */ 1740 if (sc->run[0] == 0 && sc->run[1] == 0) { 1741 sc->speed = envy24_setspeed(sc, ch->speed); 1742 sc->caps[0].minspeed = sc->caps[0].maxspeed = sc->speed; 1743 sc->caps[1].minspeed = sc->caps[1].maxspeed = sc->speed; 1744 } 1745 else if (ch->speed != 0 && ch->speed != sc->speed) 1746 return -1; 1747 if (ch->speed == 0) 1748 ch->channel->speed = sc->speed; 1749 /* start or enable channel */ 1750 sc->run[slot]++; 1751 if (sc->run[slot] == 1) { 1752 /* first channel */ 1753 ch->offset = 0; 1754 sc->blk[slot] = ch->blk; 1755 } 1756 else { 1757 ptr = envy24_gethwptr(sc, ch->dir); 1758 ch->offset = ((ptr / ch->blk + 1) * ch->blk % 1759 (ch->size / 4)) * 4 / ch->unit; 1760 if (ch->blk < sc->blk[slot]) 1761 sc->blk[slot] = ch->blk; 1762 } 1763 if (ch->dir == PCMDIR_PLAY) { 1764 ch->emldma(ch); 1765 envy24_setvolume(sc, ch->num); 1766 } 1767 envy24_updintr(sc, ch->dir); 1768 if (sc->run[slot] == 1) 1769 envy24_start(sc, ch->dir); 1770 ch->run = 1; 1771 break; 1772 case PCMTRIG_EMLDMAWR: 1773 #if(0) 1774 device_printf(sc->dev, "envy24chan_trigger(): emldmawr\n"); 1775 #endif 1776 if (ch->run != 1) 1777 return -1; 1778 ch->emldma(ch); 1779 break; 1780 case PCMTRIG_EMLDMARD: 1781 #if(0) 1782 device_printf(sc->dev, "envy24chan_trigger(): emldmard\n"); 1783 #endif 1784 if (ch->run != 1) 1785 return -1; 1786 ch->emldma(ch); 1787 break; 1788 case PCMTRIG_ABORT: 1789 if (ch->run) { 1790 #if(0) 1791 device_printf(sc->dev, "envy24chan_trigger(): abort\n"); 1792 #endif 1793 ch->run = 0; 1794 sc->run[slot]--; 1795 if (ch->dir == PCMDIR_PLAY) 1796 envy24_mutevolume(sc, ch->num); 1797 if (sc->run[slot] == 0) { 1798 envy24_stop(sc, ch->dir); 1799 sc->intr[slot] = 0; 1800 } 1801 #if 0 1802 else if (ch->blk == sc->blk[slot]) { 1803 sc->blk[slot] = ENVY24_SAMPLE_NUM / 2; 1804 for (i = 0; i < ENVY24_CHAN_NUM; i++) { 1805 if (sc->chan[i].dir == ch->dir && 1806 sc->chan[i].run == 1 && 1807 sc->chan[i].blk < sc->blk[slot]) 1808 sc->blk[slot] = sc->chan[i].blk; 1809 } 1810 if (ch->blk != sc->blk[slot]) 1811 envy24_updintr(sc, ch->dir); 1812 } 1813 #endif 1814 } 1815 break; 1816 } 1817 snd_mtxunlock(sc->lock); 1818 1819 return 0; 1820 } 1821 1822 static int 1823 envy24chan_getptr(kobj_t obj, void *data) 1824 { 1825 struct sc_chinfo *ch = data; 1826 struct sc_info *sc = ch->parent; 1827 u_int32_t ptr; 1828 int rtn; 1829 1830 #if(0) 1831 device_printf(sc->dev, "envy24chan_getptr()\n"); 1832 #endif 1833 snd_mtxlock(sc->lock); 1834 ptr = envy24_gethwptr(sc, ch->dir); 1835 rtn = ptr * ch->unit; 1836 snd_mtxunlock(sc->lock); 1837 1838 #if(0) 1839 device_printf(sc->dev, "envy24chan_getptr(): return %d\n", 1840 rtn); 1841 #endif 1842 return rtn; 1843 } 1844 1845 static struct pcmchan_caps * 1846 envy24chan_getcaps(kobj_t obj, void *data) 1847 { 1848 struct sc_chinfo *ch = data; 1849 struct sc_info *sc = ch->parent; 1850 struct pcmchan_caps *rtn; 1851 1852 #if(0) 1853 device_printf(sc->dev, "envy24chan_getcaps()\n"); 1854 #endif 1855 snd_mtxlock(sc->lock); 1856 if (ch->dir == PCMDIR_PLAY) { 1857 if (sc->run[0] == 0) 1858 rtn = &envy24_playcaps; 1859 else 1860 rtn = &sc->caps[0]; 1861 } 1862 else { 1863 if (sc->run[1] == 0) 1864 rtn = &envy24_reccaps; 1865 else 1866 rtn = &sc->caps[1]; 1867 } 1868 snd_mtxunlock(sc->lock); 1869 1870 return rtn; 1871 } 1872 1873 static kobj_method_t envy24chan_methods[] = { 1874 KOBJMETHOD(channel_init, envy24chan_init), 1875 KOBJMETHOD(channel_free, envy24chan_free), 1876 KOBJMETHOD(channel_setformat, envy24chan_setformat), 1877 KOBJMETHOD(channel_setspeed, envy24chan_setspeed), 1878 KOBJMETHOD(channel_setblocksize, envy24chan_setblocksize), 1879 KOBJMETHOD(channel_trigger, envy24chan_trigger), 1880 KOBJMETHOD(channel_getptr, envy24chan_getptr), 1881 KOBJMETHOD(channel_getcaps, envy24chan_getcaps), 1882 { 0, 0 } 1883 }; 1884 CHANNEL_DECLARE(envy24chan); 1885 1886 /* -------------------------------------------------------------------- */ 1887 1888 /* mixer interface */ 1889 1890 static int 1891 envy24mixer_init(struct snd_mixer *m) 1892 { 1893 struct sc_info *sc = mix_getdevinfo(m); 1894 1895 #if(0) 1896 device_printf(sc->dev, "envy24mixer_init()\n"); 1897 #endif 1898 if (sc == NULL) 1899 return -1; 1900 1901 /* set volume control rate */ 1902 snd_mtxlock(sc->lock); 1903 envy24_wrmt(sc, ENVY24_MT_VOLRATE, 0x30, 1); /* 0x30 is default value */ 1904 1905 mix_setdevs(m, ENVY24_MIX_MASK); 1906 mix_setrecdevs(m, ENVY24_MIX_REC_MASK); 1907 snd_mtxunlock(sc->lock); 1908 1909 return 0; 1910 } 1911 1912 static int 1913 envy24mixer_reinit(struct snd_mixer *m) 1914 { 1915 struct sc_info *sc = mix_getdevinfo(m); 1916 1917 if (sc == NULL) 1918 return -1; 1919 #if(0) 1920 device_printf(sc->dev, "envy24mixer_reinit()\n"); 1921 #endif 1922 1923 return 0; 1924 } 1925 1926 static int 1927 envy24mixer_uninit(struct snd_mixer *m) 1928 { 1929 struct sc_info *sc = mix_getdevinfo(m); 1930 1931 if (sc == NULL) 1932 return -1; 1933 #if(0) 1934 device_printf(sc->dev, "envy24mixer_uninit()\n"); 1935 #endif 1936 1937 return 0; 1938 } 1939 1940 static int 1941 envy24mixer_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) 1942 { 1943 struct sc_info *sc = mix_getdevinfo(m); 1944 int ch = envy24_mixmap[dev]; 1945 int hwch; 1946 int i; 1947 1948 if (sc == NULL) 1949 return -1; 1950 if (dev == 0 && sc->cfg->codec->setvolume == NULL) 1951 return -1; 1952 if (dev != 0 && ch == -1) 1953 return -1; 1954 hwch = envy24_chanmap[ch]; 1955 #if(0) 1956 device_printf(sc->dev, "envy24mixer_set(m, %d, %d, %d)\n", 1957 dev, left, right); 1958 #endif 1959 1960 snd_mtxlock(sc->lock); 1961 if (dev == 0) { 1962 for (i = 0; i < sc->dacn; i++) { 1963 sc->cfg->codec->setvolume(sc->dac[i], PCMDIR_PLAY, left, right); 1964 } 1965 } 1966 else { 1967 /* set volume value for hardware */ 1968 if ((sc->left[hwch] = 100 - left) > ENVY24_VOL_MIN) 1969 sc->left[hwch] = ENVY24_VOL_MUTE; 1970 if ((sc->right[hwch] = 100 - right) > ENVY24_VOL_MIN) 1971 sc->right[hwch] = ENVY24_VOL_MUTE; 1972 1973 /* set volume for record channel and running play channel */ 1974 if (hwch > ENVY24_CHAN_PLAY_SPDIF || sc->chan[ch].run) 1975 envy24_setvolume(sc, hwch); 1976 } 1977 snd_mtxunlock(sc->lock); 1978 1979 return right << 8 | left; 1980 } 1981 1982 static u_int32_t 1983 envy24mixer_setrecsrc(struct snd_mixer *m, u_int32_t src) 1984 { 1985 struct sc_info *sc = mix_getdevinfo(m); 1986 int ch = envy24_mixmap[src]; 1987 #if(0) 1988 device_printf(sc->dev, "envy24mixer_setrecsrc(m, %d)\n", src); 1989 #endif 1990 1991 if (ch > ENVY24_CHAN_PLAY_SPDIF) 1992 sc->src = ch; 1993 return src; 1994 } 1995 1996 static kobj_method_t envy24mixer_methods[] = { 1997 KOBJMETHOD(mixer_init, envy24mixer_init), 1998 KOBJMETHOD(mixer_reinit, envy24mixer_reinit), 1999 KOBJMETHOD(mixer_uninit, envy24mixer_uninit), 2000 KOBJMETHOD(mixer_set, envy24mixer_set), 2001 KOBJMETHOD(mixer_setrecsrc, envy24mixer_setrecsrc), 2002 { 0, 0 } 2003 }; 2004 MIXER_DECLARE(envy24mixer); 2005 2006 /* -------------------------------------------------------------------- */ 2007 2008 /* The interrupt handler */ 2009 static void 2010 envy24_intr(void *p) 2011 { 2012 struct sc_info *sc = (struct sc_info *)p; 2013 struct sc_chinfo *ch; 2014 u_int32_t ptr, dsize, feed; 2015 int i; 2016 2017 #if(0) 2018 device_printf(sc->dev, "envy24_intr()\n"); 2019 #endif 2020 snd_mtxlock(sc->lock); 2021 if (envy24_checkintr(sc, PCMDIR_PLAY)) { 2022 #if(0) 2023 device_printf(sc->dev, "envy24_intr(): play\n"); 2024 #endif 2025 dsize = sc->psize / 4; 2026 ptr = dsize - envy24_rdmt(sc, ENVY24_MT_PCNT, 2) - 1; 2027 #if(0) 2028 device_printf(sc->dev, "envy24_intr(): ptr = %d-->", ptr); 2029 #endif 2030 ptr -= ptr % sc->blk[0]; 2031 feed = (ptr + dsize - sc->intr[0]) % dsize; 2032 #if(0) 2033 printf("%d intr = %d feed = %d\n", ptr, sc->intr[0], feed); 2034 #endif 2035 for (i = ENVY24_CHAN_PLAY_DAC1; i <= ENVY24_CHAN_PLAY_SPDIF; i++) { 2036 ch = &sc->chan[i]; 2037 #if(0) 2038 if (ch->run) 2039 device_printf(sc->dev, "envy24_intr(): chan[%d].blk = %d\n", i, ch->blk); 2040 #endif 2041 if (ch->run && ch->blk <= feed) { 2042 snd_mtxunlock(sc->lock); 2043 chn_intr(ch->channel); 2044 snd_mtxlock(sc->lock); 2045 } 2046 } 2047 sc->intr[0] = ptr; 2048 envy24_updintr(sc, PCMDIR_PLAY); 2049 } 2050 if (envy24_checkintr(sc, PCMDIR_REC)) { 2051 #if(0) 2052 device_printf(sc->dev, "envy24_intr(): rec\n"); 2053 #endif 2054 dsize = sc->rsize / 4; 2055 ptr = dsize - envy24_rdmt(sc, ENVY24_MT_RCNT, 2) - 1; 2056 ptr -= ptr % sc->blk[1]; 2057 feed = (ptr + dsize - sc->intr[1]) % dsize; 2058 for (i = ENVY24_CHAN_REC_ADC1; i <= ENVY24_CHAN_REC_SPDIF; i++) { 2059 ch = &sc->chan[i]; 2060 if (ch->run && ch->blk <= feed) { 2061 snd_mtxunlock(sc->lock); 2062 chn_intr(ch->channel); 2063 snd_mtxlock(sc->lock); 2064 } 2065 } 2066 sc->intr[1] = ptr; 2067 envy24_updintr(sc, PCMDIR_REC); 2068 } 2069 snd_mtxunlock(sc->lock); 2070 2071 return; 2072 } 2073 2074 /* 2075 * Probe and attach the card 2076 */ 2077 2078 static int 2079 envy24_pci_probe(device_t dev) 2080 { 2081 u_int16_t sv, sd; 2082 int i; 2083 2084 #if(0) 2085 printf("envy24_pci_probe()\n"); 2086 #endif 2087 if (pci_get_device(dev) == PCID_ENVY24 && 2088 pci_get_vendor(dev) == PCIV_ENVY24) { 2089 sv = pci_get_subvendor(dev); 2090 sd = pci_get_subdevice(dev); 2091 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++) { 2092 if (cfg_table[i].subvendor == sv && 2093 cfg_table[i].subdevice == sd) { 2094 break; 2095 } 2096 } 2097 device_set_desc(dev, cfg_table[i].name); 2098 #if(0) 2099 printf("envy24_pci_probe(): return 0\n"); 2100 #endif 2101 return 0; 2102 } 2103 else { 2104 #if(0) 2105 printf("envy24_pci_probe(): return ENXIO\n"); 2106 #endif 2107 return ENXIO; 2108 } 2109 } 2110 2111 static void 2112 envy24_dmapsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error) 2113 { 2114 /* struct sc_info *sc = (struct sc_info *)arg; */ 2115 2116 #if(0) 2117 device_printf(sc->dev, "envy24_dmapsetmap()\n"); 2118 if (bootverbose) { 2119 printf("envy24(play): setmap %lx, %lx; ", 2120 (unsigned long)segs->ds_addr, 2121 (unsigned long)segs->ds_len); 2122 printf("%p -> %lx\n", sc->pmap, (unsigned long)vtophys(sc->pmap)); 2123 } 2124 #endif 2125 } 2126 2127 static void 2128 envy24_dmarsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error) 2129 { 2130 /* struct sc_info *sc = (struct sc_info *)arg; */ 2131 2132 #if(0) 2133 device_printf(sc->dev, "envy24_dmarsetmap()\n"); 2134 if (bootverbose) { 2135 printf("envy24(record): setmap %lx, %lx; ", 2136 (unsigned long)segs->ds_addr, 2137 (unsigned long)segs->ds_len); 2138 printf("%p -> %lx\n", sc->rmap, (unsigned long)vtophys(sc->pmap)); 2139 } 2140 #endif 2141 } 2142 2143 static void 2144 envy24_dmafree(struct sc_info *sc) 2145 { 2146 #if(0) 2147 device_printf(sc->dev, "envy24_dmafree():"); 2148 if (sc->rmap) printf(" sc->rmap(0x%08x)", (u_int32_t)sc->rmap); 2149 else printf(" sc->rmap(null)"); 2150 if (sc->pmap) printf(" sc->pmap(0x%08x)", (u_int32_t)sc->pmap); 2151 else printf(" sc->pmap(null)"); 2152 if (sc->rbuf) printf(" sc->rbuf(0x%08x)", (u_int32_t)sc->rbuf); 2153 else printf(" sc->rbuf(null)"); 2154 if (sc->pbuf) printf(" sc->pbuf(0x%08x)\n", (u_int32_t)sc->pbuf); 2155 else printf(" sc->pbuf(null)\n"); 2156 #endif 2157 #if(0) 2158 if (sc->rmap) 2159 bus_dmamap_unload(sc->dmat, sc->rmap); 2160 if (sc->pmap) 2161 bus_dmamap_unload(sc->dmat, sc->pmap); 2162 if (sc->rbuf) 2163 bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap); 2164 if (sc->pbuf) 2165 bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap); 2166 #else 2167 bus_dmamap_unload(sc->dmat, sc->rmap); 2168 bus_dmamap_unload(sc->dmat, sc->pmap); 2169 bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap); 2170 bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap); 2171 #endif 2172 2173 sc->rmap = sc->pmap = NULL; 2174 sc->pbuf = NULL; 2175 sc->rbuf = NULL; 2176 2177 return; 2178 } 2179 2180 static int 2181 envy24_dmainit(struct sc_info *sc) 2182 { 2183 u_int32_t addr; 2184 2185 #if(0) 2186 device_printf(sc->dev, "envy24_dmainit()\n"); 2187 #endif 2188 /* init values */ 2189 sc->psize = ENVY24_PLAY_BUFUNIT * ENVY24_SAMPLE_NUM; 2190 sc->rsize = ENVY24_REC_BUFUNIT * ENVY24_SAMPLE_NUM; 2191 sc->pbuf = NULL; 2192 sc->rbuf = NULL; 2193 sc->pmap = sc->rmap = NULL; 2194 sc->blk[0] = sc->blk[1] = 0; 2195 2196 /* allocate DMA buffer */ 2197 #if(0) 2198 device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_alloc(): sc->pbuf\n"); 2199 #endif 2200 if (bus_dmamem_alloc(sc->dmat, (void **)&sc->pbuf, BUS_DMA_NOWAIT, &sc->pmap)) 2201 goto bad; 2202 #if(0) 2203 device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_alloc(): sc->rbuf\n"); 2204 #endif 2205 if (bus_dmamem_alloc(sc->dmat, (void **)&sc->rbuf, BUS_DMA_NOWAIT, &sc->rmap)) 2206 goto bad; 2207 #if(0) 2208 device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_load(): sc->pmap\n"); 2209 #endif 2210 if (bus_dmamap_load(sc->dmat, sc->pmap, sc->pbuf, sc->psize, envy24_dmapsetmap, sc, 0)) 2211 goto bad; 2212 #if(0) 2213 device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_load(): sc->rmap\n"); 2214 #endif 2215 if (bus_dmamap_load(sc->dmat, sc->rmap, sc->rbuf, sc->rsize, envy24_dmarsetmap, sc, 0)) 2216 goto bad; 2217 bzero(sc->pbuf, sc->psize); 2218 bzero(sc->rbuf, sc->rsize); 2219 2220 /* set values to register */ 2221 addr = vtophys(sc->pbuf); 2222 #if(0) 2223 device_printf(sc->dev, "pbuf(0x%08x)\n", addr); 2224 #endif 2225 envy24_wrmt(sc, ENVY24_MT_PADDR, addr, 4); 2226 #if(0) 2227 device_printf(sc->dev, "PADDR-->(0x%08x)\n", envy24_rdmt(sc, ENVY24_MT_PADDR, 4)); 2228 device_printf(sc->dev, "psize(%ld)\n", sc->psize / 4 - 1); 2229 #endif 2230 envy24_wrmt(sc, ENVY24_MT_PCNT, sc->psize / 4 - 1, 2); 2231 #if(0) 2232 device_printf(sc->dev, "PCNT-->(%ld)\n", envy24_rdmt(sc, ENVY24_MT_PCNT, 2)); 2233 #endif 2234 addr = vtophys(sc->rbuf); 2235 envy24_wrmt(sc, ENVY24_MT_RADDR, addr, 4); 2236 envy24_wrmt(sc, ENVY24_MT_RCNT, sc->rsize / 4 - 1, 2); 2237 2238 return 0; 2239 bad: 2240 envy24_dmafree(sc); 2241 return ENOSPC; 2242 } 2243 2244 static void 2245 envy24_putcfg(struct sc_info *sc) 2246 { 2247 device_printf(sc->dev, "system configuration\n"); 2248 printf(" SubVendorID: 0x%04x, SubDeviceID: 0x%04x\n", 2249 sc->cfg->subvendor, sc->cfg->subdevice); 2250 printf(" XIN2 Clock Source: "); 2251 switch (sc->cfg->scfg & PCIM_SCFG_XIN2) { 2252 case 0x00: 2253 printf("22.5792MHz(44.1kHz*512)\n"); 2254 break; 2255 case 0x40: 2256 printf("16.9344MHz(44.1kHz*384)\n"); 2257 break; 2258 case 0x80: 2259 printf("from external clock synthesizer chip\n"); 2260 break; 2261 default: 2262 printf("illeagal system setting\n"); 2263 } 2264 printf(" MPU-401 UART(s) #: "); 2265 if (sc->cfg->scfg & PCIM_SCFG_MPU) 2266 printf("2\n"); 2267 else 2268 printf("1\n"); 2269 printf(" AC'97 codec: "); 2270 if (sc->cfg->scfg & PCIM_SCFG_AC97) 2271 printf("not exist\n"); 2272 else 2273 printf("exist\n"); 2274 printf(" ADC #: "); 2275 printf("%d\n", sc->adcn); 2276 printf(" DAC #: "); 2277 printf("%d\n", sc->dacn); 2278 printf(" Multi-track converter type: "); 2279 if ((sc->cfg->acl & PCIM_ACL_MTC) == 0) { 2280 printf("AC'97(SDATA_OUT:"); 2281 if (sc->cfg->acl & PCIM_ACL_OMODE) 2282 printf("packed"); 2283 else 2284 printf("split"); 2285 printf("|SDATA_IN:"); 2286 if (sc->cfg->acl & PCIM_ACL_IMODE) 2287 printf("packed"); 2288 else 2289 printf("split"); 2290 printf(")\n"); 2291 } 2292 else { 2293 printf("I2S("); 2294 if (sc->cfg->i2s & PCIM_I2S_VOL) 2295 printf("with volume, "); 2296 if (sc->cfg->i2s & PCIM_I2S_96KHZ) 2297 printf("96KHz support, "); 2298 switch (sc->cfg->i2s & PCIM_I2S_RES) { 2299 case PCIM_I2S_16BIT: 2300 printf("16bit resolution, "); 2301 break; 2302 case PCIM_I2S_18BIT: 2303 printf("18bit resolution, "); 2304 break; 2305 case PCIM_I2S_20BIT: 2306 printf("20bit resolution, "); 2307 break; 2308 case PCIM_I2S_24BIT: 2309 printf("24bit resolution, "); 2310 break; 2311 } 2312 printf("ID#0x%x)\n", sc->cfg->i2s & PCIM_I2S_ID); 2313 } 2314 printf(" S/PDIF(IN/OUT): "); 2315 if (sc->cfg->spdif & PCIM_SPDIF_IN) 2316 printf("1/"); 2317 else 2318 printf("0/"); 2319 if (sc->cfg->spdif & PCIM_SPDIF_OUT) 2320 printf("1 "); 2321 else 2322 printf("0 "); 2323 if (sc->cfg->spdif & (PCIM_SPDIF_IN | PCIM_SPDIF_OUT)) 2324 printf("ID# 0x%02x\n", (sc->cfg->spdif & PCIM_SPDIF_ID) >> 2); 2325 printf(" GPIO(mask/dir/state): 0x%02x/0x%02x/0x%02x\n", 2326 sc->cfg->gpiomask, sc->cfg->gpiodir, sc->cfg->gpiostate); 2327 } 2328 2329 static int 2330 envy24_init(struct sc_info *sc) 2331 { 2332 u_int32_t data; 2333 #if(0) 2334 int rtn; 2335 #endif 2336 int i; 2337 u_int32_t sv, sd; 2338 2339 2340 #if(0) 2341 device_printf(sc->dev, "envy24_init()\n"); 2342 #endif 2343 2344 /* reset chip */ 2345 envy24_wrcs(sc, ENVY24_CCS_CTL, ENVY24_CCS_CTL_RESET | ENVY24_CCS_CTL_NATIVE, 1); 2346 DELAY(200); 2347 envy24_wrcs(sc, ENVY24_CCS_CTL, ENVY24_CCS_CTL_NATIVE, 1); 2348 DELAY(200); 2349 2350 /* legacy hardware disable */ 2351 data = pci_read_config(sc->dev, PCIR_LAC, 2); 2352 data |= PCIM_LAC_DISABLE; 2353 pci_write_config(sc->dev, PCIR_LAC, data, 2); 2354 2355 /* check system configuration */ 2356 sc->cfg = NULL; 2357 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++) { 2358 /* 1st: search configuration from table */ 2359 sv = pci_get_subvendor(sc->dev); 2360 sd = pci_get_subdevice(sc->dev); 2361 if (sv == cfg_table[i].subvendor && sd == cfg_table[i].subdevice) { 2362 #if(0) 2363 device_printf(sc->dev, "Set configuration from table\n"); 2364 #endif 2365 sc->cfg = &cfg_table[i]; 2366 break; 2367 } 2368 } 2369 if (sc->cfg == NULL) { 2370 /* 2nd: read configuration from table */ 2371 sc->cfg = envy24_rom2cfg(sc); 2372 } 2373 sc->adcn = ((sc->cfg->scfg & PCIM_SCFG_ADC) >> 2) + 1; 2374 sc->dacn = (sc->cfg->scfg & PCIM_SCFG_DAC) + 1; 2375 2376 if (1 /* bootverbose */) { 2377 envy24_putcfg(sc); 2378 } 2379 2380 /* set system configuration */ 2381 pci_write_config(sc->dev, PCIR_SCFG, sc->cfg->scfg, 1); 2382 pci_write_config(sc->dev, PCIR_ACL, sc->cfg->acl, 1); 2383 pci_write_config(sc->dev, PCIR_I2S, sc->cfg->i2s, 1); 2384 pci_write_config(sc->dev, PCIR_SPDIF, sc->cfg->spdif, 1); 2385 envy24_gpiosetmask(sc, sc->cfg->gpiomask); 2386 envy24_gpiosetdir(sc, sc->cfg->gpiodir); 2387 envy24_gpiowr(sc, sc->cfg->gpiostate); 2388 for (i = 0; i < sc->adcn; i++) { 2389 sc->adc[i] = sc->cfg->codec->create(sc->dev, sc, PCMDIR_REC, i); 2390 sc->cfg->codec->init(sc->adc[i]); 2391 } 2392 for (i = 0; i < sc->dacn; i++) { 2393 sc->dac[i] = sc->cfg->codec->create(sc->dev, sc, PCMDIR_PLAY, i); 2394 sc->cfg->codec->init(sc->dac[i]); 2395 } 2396 2397 /* initialize DMA buffer */ 2398 #if(0) 2399 device_printf(sc->dev, "envy24_init(): initialize DMA buffer\n"); 2400 #endif 2401 if (envy24_dmainit(sc)) 2402 return ENOSPC; 2403 2404 /* initialize status */ 2405 sc->run[0] = sc->run[1] = 0; 2406 sc->intr[0] = sc->intr[1] = 0; 2407 sc->speed = 0; 2408 sc->caps[0].fmtlist = envy24_playfmt; 2409 sc->caps[1].fmtlist = envy24_recfmt; 2410 2411 /* set channel router */ 2412 envy24_route(sc, ENVY24_ROUTE_DAC_1, ENVY24_ROUTE_CLASS_MIX, 0, 0); 2413 envy24_route(sc, ENVY24_ROUTE_DAC_SPDIF, ENVY24_ROUTE_CLASS_DMA, 0, 0); 2414 /* envy24_route(sc, ENVY24_ROUTE_DAC_SPDIF, ENVY24_ROUTE_CLASS_MIX, 0, 0); */ 2415 2416 /* set macro interrupt mask */ 2417 data = envy24_rdcs(sc, ENVY24_CCS_IMASK, 1); 2418 envy24_wrcs(sc, ENVY24_CCS_IMASK, data & ~ENVY24_CCS_IMASK_PMT, 1); 2419 data = envy24_rdcs(sc, ENVY24_CCS_IMASK, 1); 2420 #if(0) 2421 device_printf(sc->dev, "envy24_init(): CCS_IMASK-->0x%02x\n", data); 2422 #endif 2423 2424 return 0; 2425 } 2426 2427 static int 2428 envy24_alloc_resource(struct sc_info *sc) 2429 { 2430 /* allocate I/O port resource */ 2431 sc->csid = PCIR_CCS; 2432 sc->cs = bus_alloc_resource(sc->dev, SYS_RES_IOPORT, 2433 &sc->csid, 0, ~0, 1, RF_ACTIVE); 2434 sc->ddmaid = PCIR_DDMA; 2435 sc->ddma = bus_alloc_resource(sc->dev, SYS_RES_IOPORT, 2436 &sc->ddmaid, 0, ~0, 1, RF_ACTIVE); 2437 sc->dsid = PCIR_DS; 2438 sc->ds = bus_alloc_resource(sc->dev, SYS_RES_IOPORT, 2439 &sc->dsid, 0, ~0, 1, RF_ACTIVE); 2440 sc->mtid = PCIR_MT; 2441 sc->mt = bus_alloc_resource(sc->dev, SYS_RES_IOPORT, 2442 &sc->mtid, 0, ~0, 1, RF_ACTIVE); 2443 if (!sc->cs || !sc->ddma || !sc->ds || !sc->mt) { 2444 device_printf(sc->dev, "unable to map IO port space\n"); 2445 return ENXIO; 2446 } 2447 sc->cst = rman_get_bustag(sc->cs); 2448 sc->csh = rman_get_bushandle(sc->cs); 2449 sc->ddmat = rman_get_bustag(sc->ddma); 2450 sc->ddmah = rman_get_bushandle(sc->ddma); 2451 sc->dst = rman_get_bustag(sc->ds); 2452 sc->dsh = rman_get_bushandle(sc->ds); 2453 sc->mtt = rman_get_bustag(sc->mt); 2454 sc->mth = rman_get_bushandle(sc->mt); 2455 #if(0) 2456 device_printf(sc->dev, 2457 "IO port register values\nCCS: 0x%lx\nDDMA: 0x%lx\nDS: 0x%lx\nMT: 0x%lx\n", 2458 pci_read_config(sc->dev, PCIR_CCS, 4), 2459 pci_read_config(sc->dev, PCIR_DDMA, 4), 2460 pci_read_config(sc->dev, PCIR_DS, 4), 2461 pci_read_config(sc->dev, PCIR_MT, 4)); 2462 #endif 2463 2464 /* allocate interrupt resource */ 2465 sc->irqid = 0; 2466 sc->irq = bus_alloc_resource(sc->dev, SYS_RES_IRQ, &sc->irqid, 2467 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); 2468 if (!sc->irq || 2469 snd_setup_intr(sc->dev, sc->irq, INTR_MPSAFE, envy24_intr, sc, &sc->ih)) { 2470 device_printf(sc->dev, "unable to map interrupt\n"); 2471 return ENXIO; 2472 } 2473 2474 /* allocate DMA resource */ 2475 if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(sc->dev), 2476 /*alignment*/4, 2477 /*boundary*/0, 2478 /*lowaddr*/BUS_SPACE_MAXADDR_ENVY24, 2479 /*highaddr*/BUS_SPACE_MAXADDR_ENVY24, 2480 /*filter*/NULL, /*filterarg*/NULL, 2481 /*maxsize*/BUS_SPACE_MAXSIZE_ENVY24, 2482 /*nsegments*/1, /*maxsegsz*/0x3ffff, 2483 /*flags*/0, /*lockfunc*/busdma_lock_mutex, 2484 /*lockarg*/&Giant, &sc->dmat) != 0) { 2485 device_printf(sc->dev, "unable to create dma tag\n"); 2486 return ENXIO; 2487 } 2488 2489 return 0; 2490 } 2491 2492 static int 2493 envy24_pci_attach(device_t dev) 2494 { 2495 u_int32_t data; 2496 struct sc_info *sc; 2497 char status[SND_STATUSLEN]; 2498 int err = 0; 2499 int i; 2500 2501 #if(0) 2502 device_printf(dev, "envy24_pci_attach()\n"); 2503 #endif 2504 /* get sc_info data area */ 2505 if ((sc = malloc(sizeof(*sc), M_ENVY24, M_NOWAIT)) == NULL) { 2506 device_printf(dev, "cannot allocate softc\n"); 2507 return ENXIO; 2508 } 2509 2510 bzero(sc, sizeof(*sc)); 2511 sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_envy24 softc"); 2512 sc->dev = dev; 2513 2514 /* initialize PCI interface */ 2515 data = pci_read_config(dev, PCIR_COMMAND, 2); 2516 data |= (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN); 2517 pci_write_config(dev, PCIR_COMMAND, data, 2); 2518 data = pci_read_config(dev, PCIR_COMMAND, 2); 2519 2520 /* allocate resources */ 2521 err = envy24_alloc_resource(sc); 2522 if (err) { 2523 device_printf(dev, "unable to allocate system resources\n"); 2524 goto bad; 2525 } 2526 2527 /* initialize card */ 2528 err = envy24_init(sc); 2529 if (err) { 2530 device_printf(dev, "unable to initialize the card\n"); 2531 goto bad; 2532 } 2533 2534 /* set multi track mixer */ 2535 mixer_init(dev, &envy24mixer_class, sc); 2536 2537 /* set channel information */ 2538 err = pcm_register(dev, sc, 5, 2 + sc->adcn); 2539 if (err) 2540 goto bad; 2541 sc->chnum = 0; 2542 for (i = 0; i < 5; i++) { 2543 pcm_addchan(dev, PCMDIR_PLAY, &envy24chan_class, sc); 2544 sc->chnum++; 2545 } 2546 for (i = 0; i < 2 + sc->adcn; i++) { 2547 pcm_addchan(dev, PCMDIR_REC, &envy24chan_class, sc); 2548 sc->chnum++; 2549 } 2550 2551 /* set status iformation */ 2552 snprintf(status, SND_STATUSLEN, 2553 "at io 0x%lx:%ld,0x%lx:%ld,0x%lx:%ld,0x%lx:%ld irq %ld", 2554 rman_get_start(sc->cs), 2555 rman_get_end(sc->cs) - rman_get_start(sc->cs) + 1, 2556 rman_get_start(sc->ddma), 2557 rman_get_end(sc->ddma) - rman_get_start(sc->ddma) + 1, 2558 rman_get_start(sc->ds), 2559 rman_get_end(sc->ds) - rman_get_start(sc->ds) + 1, 2560 rman_get_start(sc->mt), 2561 rman_get_end(sc->mt) - rman_get_start(sc->mt) + 1, 2562 rman_get_start(sc->irq)); 2563 pcm_setstatus(dev, status); 2564 2565 return 0; 2566 2567 bad: 2568 if (sc->ih) 2569 bus_teardown_intr(dev, sc->irq, sc->ih); 2570 if (sc->irq) 2571 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); 2572 envy24_dmafree(sc); 2573 if (sc->dmat) 2574 bus_dma_tag_destroy(sc->dmat); 2575 if (sc->cfg->codec->destroy != NULL) { 2576 for (i = 0; i < sc->adcn; i++) 2577 sc->cfg->codec->destroy(sc->adc[i]); 2578 for (i = 0; i < sc->dacn; i++) 2579 sc->cfg->codec->destroy(sc->dac[i]); 2580 } 2581 envy24_cfgfree(sc->cfg); 2582 if (sc->cs) 2583 bus_release_resource(dev, SYS_RES_IOPORT, sc->csid, sc->cs); 2584 if (sc->ddma) 2585 bus_release_resource(dev, SYS_RES_IOPORT, sc->ddmaid, sc->ddma); 2586 if (sc->ds) 2587 bus_release_resource(dev, SYS_RES_IOPORT, sc->dsid, sc->ds); 2588 if (sc->mt) 2589 bus_release_resource(dev, SYS_RES_IOPORT, sc->mtid, sc->mt); 2590 if (sc->lock) 2591 snd_mtxfree(sc->lock); 2592 free(sc, M_ENVY24); 2593 return err; 2594 } 2595 2596 static int 2597 envy24_pci_detach(device_t dev) 2598 { 2599 struct sc_info *sc; 2600 int r; 2601 int i; 2602 2603 #if(0) 2604 device_printf(dev, "envy24_pci_detach()\n"); 2605 #endif 2606 sc = pcm_getdevinfo(dev); 2607 if (sc == NULL) 2608 return 0; 2609 r = pcm_unregister(dev); 2610 if (r) 2611 return r; 2612 2613 envy24_dmafree(sc); 2614 if (sc->cfg->codec->destroy != NULL) { 2615 for (i = 0; i < sc->adcn; i++) 2616 sc->cfg->codec->destroy(sc->adc[i]); 2617 for (i = 0; i < sc->dacn; i++) 2618 sc->cfg->codec->destroy(sc->dac[i]); 2619 } 2620 envy24_cfgfree(sc->cfg); 2621 bus_dma_tag_destroy(sc->dmat); 2622 bus_teardown_intr(dev, sc->irq, sc->ih); 2623 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); 2624 bus_release_resource(dev, SYS_RES_IOPORT, sc->csid, sc->cs); 2625 bus_release_resource(dev, SYS_RES_IOPORT, sc->ddmaid, sc->ddma); 2626 bus_release_resource(dev, SYS_RES_IOPORT, sc->dsid, sc->ds); 2627 bus_release_resource(dev, SYS_RES_IOPORT, sc->mtid, sc->mt); 2628 snd_mtxfree(sc->lock); 2629 free(sc, M_ENVY24); 2630 return 0; 2631 } 2632 2633 static device_method_t envy24_methods[] = { 2634 /* Device interface */ 2635 DEVMETHOD(device_probe, envy24_pci_probe), 2636 DEVMETHOD(device_attach, envy24_pci_attach), 2637 DEVMETHOD(device_detach, envy24_pci_detach), 2638 { 0, 0 } 2639 }; 2640 2641 static driver_t envy24_driver = { 2642 "pcm", 2643 envy24_methods, 2644 #if __FreeBSD_version > 500000 2645 PCM_SOFTC_SIZE, 2646 #else 2647 sizeof(struct snddev_info), 2648 #endif 2649 }; 2650 2651 DRIVER_MODULE(snd_envy24, pci, envy24_driver, pcm_devclass, 0, 0); 2652 MODULE_DEPEND(snd_envy24, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 2653 MODULE_DEPEND(snd_envy24, snd_spicds, 1, 1, 1); 2654 MODULE_VERSION(snd_envy24, 1); 2655