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