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