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