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