1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 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 regintr; 1206 u_int32_t mask, intr; 1207 u_int32_t 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 regintr = ENVY24_MT_PTERM; 1216 mask = ~ENVY24_MT_INT_PMASK; 1217 } 1218 else { 1219 blk = sc->blk[1]; 1220 regintr = ENVY24_MT_RTERM; 1221 mask = ~ENVY24_MT_INT_RMASK; 1222 } 1223 1224 cnt = blk - 1; 1225 #if(0) 1226 device_printf(sc->dev, "envy24_updintr():blk = %d, cnt = %d\n", blk, cnt); 1227 #endif 1228 envy24_wrmt(sc, regintr, cnt, 2); 1229 intr = envy24_rdmt(sc, ENVY24_MT_INT, 1); 1230 #if(0) 1231 device_printf(sc->dev, "envy24_updintr():intr = 0x%02x, mask = 0x%02x\n", intr, mask); 1232 #endif 1233 envy24_wrmt(sc, ENVY24_MT_INT, intr & mask, 1); 1234 #if(0) 1235 device_printf(sc->dev, "envy24_updintr():INT-->0x%02x\n", 1236 envy24_rdmt(sc, ENVY24_MT_INT, 1)); 1237 #endif 1238 1239 return; 1240 } 1241 1242 #if 0 1243 static void 1244 envy24_maskintr(struct sc_info *sc, int dir) 1245 { 1246 u_int32_t mask, intr; 1247 1248 #if(0) 1249 device_printf(sc->dev, "envy24_maskintr(sc, %d)\n", dir); 1250 #endif 1251 if (dir == PCMDIR_PLAY) 1252 mask = ENVY24_MT_INT_PMASK; 1253 else 1254 mask = ENVY24_MT_INT_RMASK; 1255 intr = envy24_rdmt(sc, ENVY24_MT_INT, 1); 1256 envy24_wrmt(sc, ENVY24_MT_INT, intr | mask, 1); 1257 1258 return; 1259 } 1260 #endif 1261 1262 static int 1263 envy24_checkintr(struct sc_info *sc, int dir) 1264 { 1265 u_int32_t mask, stat, intr, rtn; 1266 1267 #if(0) 1268 device_printf(sc->dev, "envy24_checkintr(sc, %d)\n", dir); 1269 #endif 1270 intr = envy24_rdmt(sc, ENVY24_MT_INT, 1); 1271 if (dir == PCMDIR_PLAY) { 1272 if ((rtn = intr & ENVY24_MT_INT_PSTAT) != 0) { 1273 mask = ~ENVY24_MT_INT_RSTAT; 1274 stat = ENVY24_MT_INT_PSTAT | ENVY24_MT_INT_PMASK; 1275 envy24_wrmt(sc, ENVY24_MT_INT, (intr & mask) | stat, 1); 1276 } 1277 } 1278 else { 1279 if ((rtn = intr & ENVY24_MT_INT_RSTAT) != 0) { 1280 mask = ~ENVY24_MT_INT_PSTAT; 1281 stat = ENVY24_MT_INT_RSTAT | ENVY24_MT_INT_RMASK; 1282 envy24_wrmt(sc, ENVY24_MT_INT, (intr & mask) | stat, 1); 1283 } 1284 } 1285 1286 return rtn; 1287 } 1288 1289 static void 1290 envy24_start(struct sc_info *sc, int dir) 1291 { 1292 u_int32_t stat, sw; 1293 1294 #if(0) 1295 device_printf(sc->dev, "envy24_start(sc, %d)\n", dir); 1296 #endif 1297 if (dir == PCMDIR_PLAY) 1298 sw = ENVY24_MT_PCTL_PSTART; 1299 else 1300 sw = ENVY24_MT_PCTL_RSTART; 1301 1302 stat = envy24_rdmt(sc, ENVY24_MT_PCTL, 1); 1303 envy24_wrmt(sc, ENVY24_MT_PCTL, stat | sw, 1); 1304 #if(0) 1305 DELAY(100); 1306 device_printf(sc->dev, "PADDR:0x%08x\n", envy24_rdmt(sc, ENVY24_MT_PADDR, 4)); 1307 device_printf(sc->dev, "PCNT:%ld\n", envy24_rdmt(sc, ENVY24_MT_PCNT, 2)); 1308 #endif 1309 1310 return; 1311 } 1312 1313 static void 1314 envy24_stop(struct sc_info *sc, int dir) 1315 { 1316 u_int32_t stat, sw; 1317 1318 #if(0) 1319 device_printf(sc->dev, "envy24_stop(sc, %d)\n", dir); 1320 #endif 1321 if (dir == PCMDIR_PLAY) 1322 sw = ~ENVY24_MT_PCTL_PSTART; 1323 else 1324 sw = ~ENVY24_MT_PCTL_RSTART; 1325 1326 stat = envy24_rdmt(sc, ENVY24_MT_PCTL, 1); 1327 envy24_wrmt(sc, ENVY24_MT_PCTL, stat & sw, 1); 1328 1329 return; 1330 } 1331 1332 static int 1333 envy24_route(struct sc_info *sc, int dac, int class, int adc, int rev) 1334 { 1335 u_int32_t reg, mask; 1336 u_int32_t left, right; 1337 1338 #if(0) 1339 device_printf(sc->dev, "envy24_route(sc, %d, %d, %d, %d)\n", 1340 dac, class, adc, rev); 1341 #endif 1342 /* parameter pattern check */ 1343 if (dac < 0 || ENVY24_ROUTE_DAC_SPDIF < dac) 1344 return -1; 1345 if (class == ENVY24_ROUTE_CLASS_MIX && 1346 (dac != ENVY24_ROUTE_DAC_1 && dac != ENVY24_ROUTE_DAC_SPDIF)) 1347 return -1; 1348 if (rev) { 1349 left = ENVY24_ROUTE_RIGHT; 1350 right = ENVY24_ROUTE_LEFT; 1351 } 1352 else { 1353 left = ENVY24_ROUTE_LEFT; 1354 right = ENVY24_ROUTE_RIGHT; 1355 } 1356 1357 if (dac == ENVY24_ROUTE_DAC_SPDIF) { 1358 reg = class | class << 2 | 1359 ((adc << 1 | left) | left << 3) << 8 | 1360 ((adc << 1 | right) | right << 3) << 12; 1361 #if(0) 1362 device_printf(sc->dev, "envy24_route(): MT_SPDOUT-->0x%04x\n", reg); 1363 #endif 1364 envy24_wrmt(sc, ENVY24_MT_SPDOUT, reg, 2); 1365 } 1366 else { 1367 mask = ~(0x0303 << dac * 2); 1368 reg = envy24_rdmt(sc, ENVY24_MT_PSDOUT, 2); 1369 reg = (reg & mask) | ((class | class << 8) << dac * 2); 1370 #if(0) 1371 device_printf(sc->dev, "envy24_route(): MT_PSDOUT-->0x%04x\n", reg); 1372 #endif 1373 envy24_wrmt(sc, ENVY24_MT_PSDOUT, reg, 2); 1374 mask = ~(0xff << dac * 8); 1375 reg = envy24_rdmt(sc, ENVY24_MT_RECORD, 4); 1376 reg = (reg & mask) | 1377 (((adc << 1 | left) | left << 3) | 1378 ((adc << 1 | right) | right << 3) << 4) << dac * 8; 1379 #if(0) 1380 device_printf(sc->dev, "envy24_route(): MT_RECORD-->0x%08x\n", reg); 1381 #endif 1382 envy24_wrmt(sc, ENVY24_MT_RECORD, reg, 4); 1383 1384 /* 6fire rear input init test */ 1385 envy24_wrmt(sc, ENVY24_MT_RECORD, 0x00, 4); 1386 } 1387 1388 return 0; 1389 } 1390 1391 /* -------------------------------------------------------------------- */ 1392 1393 /* buffer copy routines */ 1394 static void 1395 envy24_p32sl(struct sc_chinfo *ch) 1396 { 1397 int length; 1398 sample32_t *dmabuf; 1399 u_int32_t *data; 1400 int src, dst, ssize, dsize, slot; 1401 int i; 1402 1403 length = sndbuf_getready(ch->buffer) / 8; 1404 dmabuf = ch->parent->pbuf; 1405 data = (u_int32_t *)ch->data; 1406 src = sndbuf_getreadyptr(ch->buffer) / 4; 1407 dst = src / 2 + ch->offset; 1408 ssize = ch->size / 4; 1409 dsize = ch->size / 8; 1410 slot = ch->num * 2; 1411 1412 for (i = 0; i < length; i++) { 1413 dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = data[src]; 1414 dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = data[src + 1]; 1415 dst++; 1416 dst %= dsize; 1417 src += 2; 1418 src %= ssize; 1419 } 1420 1421 return; 1422 } 1423 1424 static void 1425 envy24_p16sl(struct sc_chinfo *ch) 1426 { 1427 int length; 1428 sample32_t *dmabuf; 1429 u_int16_t *data; 1430 int src, dst, ssize, dsize, slot; 1431 int i; 1432 1433 #if(0) 1434 device_printf(ch->parent->dev, "envy24_p16sl()\n"); 1435 #endif 1436 length = sndbuf_getready(ch->buffer) / 4; 1437 dmabuf = ch->parent->pbuf; 1438 data = (u_int16_t *)ch->data; 1439 src = sndbuf_getreadyptr(ch->buffer) / 2; 1440 dst = src / 2 + ch->offset; 1441 ssize = ch->size / 2; 1442 dsize = ch->size / 4; 1443 slot = ch->num * 2; 1444 #if(0) 1445 device_printf(ch->parent->dev, "envy24_p16sl():%lu-->%lu(%lu)\n", src, dst, length); 1446 #endif 1447 1448 for (i = 0; i < length; i++) { 1449 dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = (u_int32_t)data[src] << 16; 1450 dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = (u_int32_t)data[src + 1] << 16; 1451 #if(0) 1452 if (i < 16) { 1453 printf("%08x", dmabuf[dst * ENVY24_PLAY_CHNUM + slot]); 1454 printf("%08x", dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1]); 1455 } 1456 #endif 1457 dst++; 1458 dst %= dsize; 1459 src += 2; 1460 src %= ssize; 1461 } 1462 #if(0) 1463 printf("\n"); 1464 #endif 1465 1466 return; 1467 } 1468 1469 static void 1470 envy24_p8u(struct sc_chinfo *ch) 1471 { 1472 int length; 1473 sample32_t *dmabuf; 1474 u_int8_t *data; 1475 int src, dst, ssize, dsize, slot; 1476 int i; 1477 1478 length = sndbuf_getready(ch->buffer) / 2; 1479 dmabuf = ch->parent->pbuf; 1480 data = (u_int8_t *)ch->data; 1481 src = sndbuf_getreadyptr(ch->buffer); 1482 dst = src / 2 + ch->offset; 1483 ssize = ch->size; 1484 dsize = ch->size / 4; 1485 slot = ch->num * 2; 1486 1487 for (i = 0; i < length; i++) { 1488 dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = ((u_int32_t)data[src] ^ 0x80) << 24; 1489 dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = ((u_int32_t)data[src + 1] ^ 0x80) << 24; 1490 dst++; 1491 dst %= dsize; 1492 src += 2; 1493 src %= ssize; 1494 } 1495 1496 return; 1497 } 1498 1499 static void 1500 envy24_r32sl(struct sc_chinfo *ch) 1501 { 1502 int length; 1503 sample32_t *dmabuf; 1504 u_int32_t *data; 1505 int src, dst, ssize, dsize, slot; 1506 int i; 1507 1508 length = sndbuf_getfree(ch->buffer) / 8; 1509 dmabuf = ch->parent->rbuf; 1510 data = (u_int32_t *)ch->data; 1511 dst = sndbuf_getfreeptr(ch->buffer) / 4; 1512 src = dst / 2 + ch->offset; 1513 dsize = ch->size / 4; 1514 ssize = ch->size / 8; 1515 slot = (ch->num - ENVY24_CHAN_REC_ADC1) * 2; 1516 1517 for (i = 0; i < length; i++) { 1518 data[dst] = dmabuf[src * ENVY24_REC_CHNUM + slot].buffer; 1519 data[dst + 1] = dmabuf[src * ENVY24_REC_CHNUM + slot + 1].buffer; 1520 dst += 2; 1521 dst %= dsize; 1522 src++; 1523 src %= ssize; 1524 } 1525 1526 return; 1527 } 1528 1529 static void 1530 envy24_r16sl(struct sc_chinfo *ch) 1531 { 1532 int length; 1533 sample32_t *dmabuf; 1534 u_int16_t *data; 1535 int src, dst, ssize, dsize, slot; 1536 int i; 1537 1538 length = sndbuf_getfree(ch->buffer) / 4; 1539 dmabuf = ch->parent->rbuf; 1540 data = (u_int16_t *)ch->data; 1541 dst = sndbuf_getfreeptr(ch->buffer) / 2; 1542 src = dst / 2 + ch->offset; 1543 dsize = ch->size / 2; 1544 ssize = ch->size / 8; 1545 slot = (ch->num - ENVY24_CHAN_REC_ADC1) * 2; 1546 1547 for (i = 0; i < length; i++) { 1548 data[dst] = dmabuf[src * ENVY24_REC_CHNUM + slot].buffer; 1549 data[dst + 1] = dmabuf[src * ENVY24_REC_CHNUM + slot + 1].buffer; 1550 dst += 2; 1551 dst %= dsize; 1552 src++; 1553 src %= ssize; 1554 } 1555 1556 return; 1557 } 1558 1559 /* -------------------------------------------------------------------- */ 1560 1561 /* channel interface */ 1562 static void * 1563 envy24chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) 1564 { 1565 struct sc_info *sc = (struct sc_info *)devinfo; 1566 struct sc_chinfo *ch; 1567 unsigned num; 1568 1569 #if(0) 1570 device_printf(sc->dev, "envy24chan_init(obj, devinfo, b, c, %d)\n", dir); 1571 #endif 1572 snd_mtxlock(sc->lock); 1573 if ((sc->chnum > ENVY24_CHAN_PLAY_SPDIF && dir != PCMDIR_REC) || 1574 (sc->chnum < ENVY24_CHAN_REC_ADC1 && dir != PCMDIR_PLAY)) { 1575 snd_mtxunlock(sc->lock); 1576 return NULL; 1577 } 1578 num = sc->chnum; 1579 1580 ch = &sc->chan[num]; 1581 ch->size = 8 * ENVY24_SAMPLE_NUM; 1582 ch->data = malloc(ch->size, M_ENVY24, M_NOWAIT); 1583 if (ch->data == NULL) { 1584 ch->size = 0; 1585 ch = NULL; 1586 } 1587 else { 1588 ch->buffer = b; 1589 ch->channel = c; 1590 ch->parent = sc; 1591 ch->dir = dir; 1592 /* set channel map */ 1593 ch->num = envy24_chanmap[num]; 1594 snd_mtxunlock(sc->lock); 1595 sndbuf_setup(ch->buffer, ch->data, ch->size); 1596 snd_mtxlock(sc->lock); 1597 /* these 2 values are dummy */ 1598 ch->unit = 4; 1599 ch->blk = 10240; 1600 } 1601 snd_mtxunlock(sc->lock); 1602 1603 return ch; 1604 } 1605 1606 static int 1607 envy24chan_free(kobj_t obj, void *data) 1608 { 1609 struct sc_chinfo *ch = data; 1610 struct sc_info *sc = ch->parent; 1611 1612 #if(0) 1613 device_printf(sc->dev, "envy24chan_free()\n"); 1614 #endif 1615 snd_mtxlock(sc->lock); 1616 if (ch->data != NULL) { 1617 free(ch->data, M_ENVY24); 1618 ch->data = NULL; 1619 } 1620 snd_mtxunlock(sc->lock); 1621 1622 return 0; 1623 } 1624 1625 static int 1626 envy24chan_setformat(kobj_t obj, void *data, u_int32_t format) 1627 { 1628 struct sc_chinfo *ch = data; 1629 struct sc_info *sc = ch->parent; 1630 struct envy24_emldma *emltab; 1631 /* unsigned int bcnt, bsize; */ 1632 int i; 1633 1634 #if(0) 1635 device_printf(sc->dev, "envy24chan_setformat(obj, data, 0x%08x)\n", format); 1636 #endif 1637 snd_mtxlock(sc->lock); 1638 /* check and get format related information */ 1639 if (ch->dir == PCMDIR_PLAY) 1640 emltab = envy24_pemltab; 1641 else 1642 emltab = envy24_remltab; 1643 if (emltab == NULL) { 1644 snd_mtxunlock(sc->lock); 1645 return -1; 1646 } 1647 for (i = 0; emltab[i].format != 0; i++) 1648 if (emltab[i].format == format) 1649 break; 1650 if (emltab[i].format == 0) { 1651 snd_mtxunlock(sc->lock); 1652 return -1; 1653 } 1654 1655 /* set format information */ 1656 ch->format = format; 1657 ch->emldma = emltab[i].emldma; 1658 if (ch->unit > emltab[i].unit) 1659 ch->blk *= ch->unit / emltab[i].unit; 1660 else 1661 ch->blk /= emltab[i].unit / ch->unit; 1662 ch->unit = emltab[i].unit; 1663 1664 /* set channel buffer information */ 1665 ch->size = ch->unit * ENVY24_SAMPLE_NUM; 1666 #if 0 1667 if (ch->dir == PCMDIR_PLAY) 1668 bsize = ch->blk * 4 / ENVY24_PLAY_BUFUNIT; 1669 else 1670 bsize = ch->blk * 4 / ENVY24_REC_BUFUNIT; 1671 bsize *= ch->unit; 1672 bcnt = ch->size / bsize; 1673 sndbuf_resize(ch->buffer, bcnt, bsize); 1674 #endif 1675 snd_mtxunlock(sc->lock); 1676 1677 #if(0) 1678 device_printf(sc->dev, "envy24chan_setformat(): return 0x%08x\n", 0); 1679 #endif 1680 return 0; 1681 } 1682 1683 /* 1684 IMPLEMENT NOTICE: In this driver, setspeed function only do setting 1685 of speed information value. And real hardware speed setting is done 1686 at start triggered(see envy24chan_trigger()). So, at this function 1687 is called, any value that ENVY24 can use is able to set. But, at 1688 start triggerd, some other channel is running, and that channel's 1689 speed isn't same with, then trigger function will fail. 1690 */ 1691 static u_int32_t 1692 envy24chan_setspeed(kobj_t obj, void *data, u_int32_t speed) 1693 { 1694 struct sc_chinfo *ch = data; 1695 u_int32_t val, prev; 1696 int i; 1697 1698 #if(0) 1699 device_printf(ch->parent->dev, "envy24chan_setspeed(obj, data, %d)\n", speed); 1700 #endif 1701 prev = 0x7fffffff; 1702 for (i = 0; (val = envy24_speed[i]) != 0; i++) { 1703 if (abs(val - speed) < abs(prev - speed)) 1704 prev = val; 1705 else 1706 break; 1707 } 1708 ch->speed = prev; 1709 1710 #if(0) 1711 device_printf(ch->parent->dev, "envy24chan_setspeed(): return %d\n", ch->speed); 1712 #endif 1713 return ch->speed; 1714 } 1715 1716 static u_int32_t 1717 envy24chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) 1718 { 1719 struct sc_chinfo *ch = data; 1720 /* struct sc_info *sc = ch->parent; */ 1721 u_int32_t size, prev; 1722 unsigned int bcnt, bsize; 1723 1724 #if(0) 1725 device_printf(sc->dev, "envy24chan_setblocksize(obj, data, %d)\n", blocksize); 1726 #endif 1727 prev = 0x7fffffff; 1728 /* snd_mtxlock(sc->lock); */ 1729 for (size = ch->size / 2; size > 0; size /= 2) { 1730 if (abs(size - blocksize) < abs(prev - blocksize)) 1731 prev = size; 1732 else 1733 break; 1734 } 1735 1736 ch->blk = prev / ch->unit; 1737 if (ch->dir == PCMDIR_PLAY) 1738 ch->blk *= ENVY24_PLAY_BUFUNIT / 4; 1739 else 1740 ch->blk *= ENVY24_REC_BUFUNIT / 4; 1741 /* set channel buffer information */ 1742 /* ch->size = ch->unit * ENVY24_SAMPLE_NUM; */ 1743 if (ch->dir == PCMDIR_PLAY) 1744 bsize = ch->blk * 4 / ENVY24_PLAY_BUFUNIT; 1745 else 1746 bsize = ch->blk * 4 / ENVY24_REC_BUFUNIT; 1747 bsize *= ch->unit; 1748 bcnt = ch->size / bsize; 1749 sndbuf_resize(ch->buffer, bcnt, bsize); 1750 /* snd_mtxunlock(sc->lock); */ 1751 1752 #if(0) 1753 device_printf(sc->dev, "envy24chan_setblocksize(): return %d\n", prev); 1754 #endif 1755 return prev; 1756 } 1757 1758 /* semantic note: must start at beginning of buffer */ 1759 static int 1760 envy24chan_trigger(kobj_t obj, void *data, int go) 1761 { 1762 struct sc_chinfo *ch = data; 1763 struct sc_info *sc = ch->parent; 1764 u_int32_t ptr; 1765 int slot; 1766 int error = 0; 1767 #if 0 1768 int i; 1769 1770 device_printf(sc->dev, "envy24chan_trigger(obj, data, %d)\n", go); 1771 #endif 1772 snd_mtxlock(sc->lock); 1773 if (ch->dir == PCMDIR_PLAY) 1774 slot = 0; 1775 else 1776 slot = 1; 1777 switch (go) { 1778 case PCMTRIG_START: 1779 #if(0) 1780 device_printf(sc->dev, "envy24chan_trigger(): start\n"); 1781 #endif 1782 /* check or set channel speed */ 1783 if (sc->run[0] == 0 && sc->run[1] == 0) { 1784 sc->speed = envy24_setspeed(sc, ch->speed); 1785 sc->caps[0].minspeed = sc->caps[0].maxspeed = sc->speed; 1786 sc->caps[1].minspeed = sc->caps[1].maxspeed = sc->speed; 1787 } 1788 else if (ch->speed != 0 && ch->speed != sc->speed) { 1789 error = -1; 1790 goto fail; 1791 } 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 error = -1; 1823 goto fail; 1824 } 1825 ch->emldma(ch); 1826 break; 1827 case PCMTRIG_EMLDMARD: 1828 #if(0) 1829 device_printf(sc->dev, "envy24chan_trigger(): emldmard\n"); 1830 #endif 1831 if (ch->run != 1) { 1832 error = -1; 1833 goto fail; 1834 } 1835 ch->emldma(ch); 1836 break; 1837 case PCMTRIG_ABORT: 1838 if (ch->run) { 1839 #if(0) 1840 device_printf(sc->dev, "envy24chan_trigger(): abort\n"); 1841 #endif 1842 ch->run = 0; 1843 sc->run[slot]--; 1844 if (ch->dir == PCMDIR_PLAY) 1845 envy24_mutevolume(sc, ch->num); 1846 if (sc->run[slot] == 0) { 1847 envy24_stop(sc, ch->dir); 1848 sc->intr[slot] = 0; 1849 } 1850 #if 0 1851 else if (ch->blk == sc->blk[slot]) { 1852 sc->blk[slot] = ENVY24_SAMPLE_NUM / 2; 1853 for (i = 0; i < ENVY24_CHAN_NUM; i++) { 1854 if (sc->chan[i].dir == ch->dir && 1855 sc->chan[i].run == 1 && 1856 sc->chan[i].blk < sc->blk[slot]) 1857 sc->blk[slot] = sc->chan[i].blk; 1858 } 1859 if (ch->blk != sc->blk[slot]) 1860 envy24_updintr(sc, ch->dir); 1861 } 1862 #endif 1863 } 1864 break; 1865 } 1866 fail: 1867 snd_mtxunlock(sc->lock); 1868 return (error); 1869 } 1870 1871 static u_int32_t 1872 envy24chan_getptr(kobj_t obj, void *data) 1873 { 1874 struct sc_chinfo *ch = data; 1875 struct sc_info *sc = ch->parent; 1876 u_int32_t ptr, rtn; 1877 1878 #if(0) 1879 device_printf(sc->dev, "envy24chan_getptr()\n"); 1880 #endif 1881 snd_mtxlock(sc->lock); 1882 ptr = envy24_gethwptr(sc, ch->dir); 1883 rtn = ptr * ch->unit; 1884 snd_mtxunlock(sc->lock); 1885 1886 #if(0) 1887 device_printf(sc->dev, "envy24chan_getptr(): return %d\n", 1888 rtn); 1889 #endif 1890 return rtn; 1891 } 1892 1893 static struct pcmchan_caps * 1894 envy24chan_getcaps(kobj_t obj, void *data) 1895 { 1896 struct sc_chinfo *ch = data; 1897 struct sc_info *sc = ch->parent; 1898 struct pcmchan_caps *rtn; 1899 1900 #if(0) 1901 device_printf(sc->dev, "envy24chan_getcaps()\n"); 1902 #endif 1903 snd_mtxlock(sc->lock); 1904 if (ch->dir == PCMDIR_PLAY) { 1905 if (sc->run[0] == 0) 1906 rtn = &envy24_playcaps; 1907 else 1908 rtn = &sc->caps[0]; 1909 } 1910 else { 1911 if (sc->run[1] == 0) 1912 rtn = &envy24_reccaps; 1913 else 1914 rtn = &sc->caps[1]; 1915 } 1916 snd_mtxunlock(sc->lock); 1917 1918 return rtn; 1919 } 1920 1921 static kobj_method_t envy24chan_methods[] = { 1922 KOBJMETHOD(channel_init, envy24chan_init), 1923 KOBJMETHOD(channel_free, envy24chan_free), 1924 KOBJMETHOD(channel_setformat, envy24chan_setformat), 1925 KOBJMETHOD(channel_setspeed, envy24chan_setspeed), 1926 KOBJMETHOD(channel_setblocksize, envy24chan_setblocksize), 1927 KOBJMETHOD(channel_trigger, envy24chan_trigger), 1928 KOBJMETHOD(channel_getptr, envy24chan_getptr), 1929 KOBJMETHOD(channel_getcaps, envy24chan_getcaps), 1930 KOBJMETHOD_END 1931 }; 1932 CHANNEL_DECLARE(envy24chan); 1933 1934 /* -------------------------------------------------------------------- */ 1935 1936 /* mixer interface */ 1937 1938 static int 1939 envy24mixer_init(struct snd_mixer *m) 1940 { 1941 struct sc_info *sc = mix_getdevinfo(m); 1942 1943 #if(0) 1944 device_printf(sc->dev, "envy24mixer_init()\n"); 1945 #endif 1946 if (sc == NULL) 1947 return -1; 1948 1949 /* set volume control rate */ 1950 snd_mtxlock(sc->lock); 1951 envy24_wrmt(sc, ENVY24_MT_VOLRATE, 0x30, 1); /* 0x30 is default value */ 1952 1953 mix_setdevs(m, ENVY24_MIX_MASK); 1954 mix_setrecdevs(m, ENVY24_MIX_REC_MASK); 1955 snd_mtxunlock(sc->lock); 1956 1957 return 0; 1958 } 1959 1960 static int 1961 envy24mixer_reinit(struct snd_mixer *m) 1962 { 1963 struct sc_info *sc = mix_getdevinfo(m); 1964 1965 if (sc == NULL) 1966 return -1; 1967 #if(0) 1968 device_printf(sc->dev, "envy24mixer_reinit()\n"); 1969 #endif 1970 1971 return 0; 1972 } 1973 1974 static int 1975 envy24mixer_uninit(struct snd_mixer *m) 1976 { 1977 struct sc_info *sc = mix_getdevinfo(m); 1978 1979 if (sc == NULL) 1980 return -1; 1981 #if(0) 1982 device_printf(sc->dev, "envy24mixer_uninit()\n"); 1983 #endif 1984 1985 return 0; 1986 } 1987 1988 static int 1989 envy24mixer_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) 1990 { 1991 struct sc_info *sc = mix_getdevinfo(m); 1992 int ch = envy24_mixmap[dev]; 1993 int hwch; 1994 int i; 1995 1996 if (sc == NULL) 1997 return -1; 1998 if (dev == 0 && sc->cfg->codec->setvolume == NULL) 1999 return -1; 2000 if (dev != 0 && ch == -1) 2001 return -1; 2002 hwch = envy24_chanmap[ch]; 2003 #if(0) 2004 device_printf(sc->dev, "envy24mixer_set(m, %d, %d, %d)\n", 2005 dev, left, right); 2006 #endif 2007 2008 snd_mtxlock(sc->lock); 2009 if (dev == 0) { 2010 for (i = 0; i < sc->dacn; i++) { 2011 sc->cfg->codec->setvolume(sc->dac[i], PCMDIR_PLAY, left, right); 2012 } 2013 } 2014 else { 2015 /* set volume value for hardware */ 2016 if ((sc->left[hwch] = 100 - left) > ENVY24_VOL_MIN) 2017 sc->left[hwch] = ENVY24_VOL_MUTE; 2018 if ((sc->right[hwch] = 100 - right) > ENVY24_VOL_MIN) 2019 sc->right[hwch] = ENVY24_VOL_MUTE; 2020 2021 /* set volume for record channel and running play channel */ 2022 if (hwch > ENVY24_CHAN_PLAY_SPDIF || sc->chan[ch].run) 2023 envy24_setvolume(sc, hwch); 2024 } 2025 snd_mtxunlock(sc->lock); 2026 2027 return right << 8 | left; 2028 } 2029 2030 static u_int32_t 2031 envy24mixer_setrecsrc(struct snd_mixer *m, u_int32_t src) 2032 { 2033 struct sc_info *sc = mix_getdevinfo(m); 2034 int ch = envy24_mixmap[src]; 2035 #if(0) 2036 device_printf(sc->dev, "envy24mixer_setrecsrc(m, %d)\n", src); 2037 #endif 2038 2039 if (ch > ENVY24_CHAN_PLAY_SPDIF) 2040 sc->src = ch; 2041 return src; 2042 } 2043 2044 static kobj_method_t envy24mixer_methods[] = { 2045 KOBJMETHOD(mixer_init, envy24mixer_init), 2046 KOBJMETHOD(mixer_reinit, envy24mixer_reinit), 2047 KOBJMETHOD(mixer_uninit, envy24mixer_uninit), 2048 KOBJMETHOD(mixer_set, envy24mixer_set), 2049 KOBJMETHOD(mixer_setrecsrc, envy24mixer_setrecsrc), 2050 KOBJMETHOD_END 2051 }; 2052 MIXER_DECLARE(envy24mixer); 2053 2054 /* -------------------------------------------------------------------- */ 2055 2056 /* The interrupt handler */ 2057 static void 2058 envy24_intr(void *p) 2059 { 2060 struct sc_info *sc = (struct sc_info *)p; 2061 struct sc_chinfo *ch; 2062 u_int32_t ptr, dsize, feed; 2063 int i; 2064 2065 #if(0) 2066 device_printf(sc->dev, "envy24_intr()\n"); 2067 #endif 2068 snd_mtxlock(sc->lock); 2069 if (envy24_checkintr(sc, PCMDIR_PLAY)) { 2070 #if(0) 2071 device_printf(sc->dev, "envy24_intr(): play\n"); 2072 #endif 2073 dsize = sc->psize / 4; 2074 ptr = dsize - envy24_rdmt(sc, ENVY24_MT_PCNT, 2) - 1; 2075 #if(0) 2076 device_printf(sc->dev, "envy24_intr(): ptr = %d-->", ptr); 2077 #endif 2078 ptr -= ptr % sc->blk[0]; 2079 feed = (ptr + dsize - sc->intr[0]) % dsize; 2080 #if(0) 2081 printf("%d intr = %d feed = %d\n", ptr, sc->intr[0], feed); 2082 #endif 2083 for (i = ENVY24_CHAN_PLAY_DAC1; i <= ENVY24_CHAN_PLAY_SPDIF; i++) { 2084 ch = &sc->chan[i]; 2085 #if(0) 2086 if (ch->run) 2087 device_printf(sc->dev, "envy24_intr(): chan[%d].blk = %d\n", i, ch->blk); 2088 #endif 2089 if (ch->run && ch->blk <= feed) { 2090 snd_mtxunlock(sc->lock); 2091 chn_intr(ch->channel); 2092 snd_mtxlock(sc->lock); 2093 } 2094 } 2095 sc->intr[0] = ptr; 2096 envy24_updintr(sc, PCMDIR_PLAY); 2097 } 2098 if (envy24_checkintr(sc, PCMDIR_REC)) { 2099 #if(0) 2100 device_printf(sc->dev, "envy24_intr(): rec\n"); 2101 #endif 2102 dsize = sc->rsize / 4; 2103 ptr = dsize - envy24_rdmt(sc, ENVY24_MT_RCNT, 2) - 1; 2104 ptr -= ptr % sc->blk[1]; 2105 feed = (ptr + dsize - sc->intr[1]) % dsize; 2106 for (i = ENVY24_CHAN_REC_ADC1; i <= ENVY24_CHAN_REC_SPDIF; i++) { 2107 ch = &sc->chan[i]; 2108 if (ch->run && ch->blk <= feed) { 2109 snd_mtxunlock(sc->lock); 2110 chn_intr(ch->channel); 2111 snd_mtxlock(sc->lock); 2112 } 2113 } 2114 sc->intr[1] = ptr; 2115 envy24_updintr(sc, PCMDIR_REC); 2116 } 2117 snd_mtxunlock(sc->lock); 2118 2119 return; 2120 } 2121 2122 /* 2123 * Probe and attach the card 2124 */ 2125 2126 static int 2127 envy24_pci_probe(device_t dev) 2128 { 2129 u_int16_t sv, sd; 2130 int i; 2131 2132 #if(0) 2133 printf("envy24_pci_probe()\n"); 2134 #endif 2135 if (pci_get_device(dev) == PCID_ENVY24 && 2136 pci_get_vendor(dev) == PCIV_ENVY24) { 2137 sv = pci_get_subvendor(dev); 2138 sd = pci_get_subdevice(dev); 2139 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++) { 2140 if (cfg_table[i].subvendor == sv && 2141 cfg_table[i].subdevice == sd) { 2142 break; 2143 } 2144 } 2145 device_set_desc(dev, cfg_table[i].name); 2146 #if(0) 2147 printf("envy24_pci_probe(): return 0\n"); 2148 #endif 2149 return 0; 2150 } 2151 else { 2152 #if(0) 2153 printf("envy24_pci_probe(): return ENXIO\n"); 2154 #endif 2155 return ENXIO; 2156 } 2157 } 2158 2159 static void 2160 envy24_dmapsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error) 2161 { 2162 struct sc_info *sc = (struct sc_info *)arg; 2163 2164 sc->paddr = segs->ds_addr; 2165 #if(0) 2166 device_printf(sc->dev, "envy24_dmapsetmap()\n"); 2167 if (bootverbose) { 2168 printf("envy24(play): setmap %lx, %lx; ", 2169 (unsigned long)segs->ds_addr, 2170 (unsigned long)segs->ds_len); 2171 printf("%p -> %lx\n", sc->pmap, sc->paddr); 2172 } 2173 #endif 2174 } 2175 2176 static void 2177 envy24_dmarsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error) 2178 { 2179 struct sc_info *sc = (struct sc_info *)arg; 2180 2181 sc->raddr = segs->ds_addr; 2182 #if(0) 2183 device_printf(sc->dev, "envy24_dmarsetmap()\n"); 2184 if (bootverbose) { 2185 printf("envy24(record): setmap %lx, %lx; ", 2186 (unsigned long)segs->ds_addr, 2187 (unsigned long)segs->ds_len); 2188 printf("%p -> %lx\n", sc->rmap, sc->raddr); 2189 } 2190 #endif 2191 } 2192 2193 static void 2194 envy24_dmafree(struct sc_info *sc) 2195 { 2196 #if(0) 2197 device_printf(sc->dev, "envy24_dmafree():"); 2198 printf(" sc->raddr(0x%08x)", (u_int32_t)sc->raddr); 2199 printf(" sc->paddr(0x%08x)", (u_int32_t)sc->paddr); 2200 if (sc->rbuf) printf(" sc->rbuf(0x%08x)", (u_int32_t)sc->rbuf); 2201 else printf(" sc->rbuf(null)"); 2202 if (sc->pbuf) printf(" sc->pbuf(0x%08x)\n", (u_int32_t)sc->pbuf); 2203 else printf(" sc->pbuf(null)\n"); 2204 #endif 2205 #if(0) 2206 if (sc->raddr) 2207 bus_dmamap_unload(sc->dmat, sc->rmap); 2208 if (sc->paddr) 2209 bus_dmamap_unload(sc->dmat, sc->pmap); 2210 if (sc->rbuf) 2211 bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap); 2212 if (sc->pbuf) 2213 bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap); 2214 #else 2215 bus_dmamap_unload(sc->dmat, sc->rmap); 2216 bus_dmamap_unload(sc->dmat, sc->pmap); 2217 bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap); 2218 bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap); 2219 #endif 2220 2221 sc->raddr = sc->paddr = 0; 2222 sc->pbuf = NULL; 2223 sc->rbuf = NULL; 2224 2225 return; 2226 } 2227 2228 static int 2229 envy24_dmainit(struct sc_info *sc) 2230 { 2231 2232 #if(0) 2233 device_printf(sc->dev, "envy24_dmainit()\n"); 2234 #endif 2235 /* init values */ 2236 sc->psize = ENVY24_PLAY_BUFUNIT * ENVY24_SAMPLE_NUM; 2237 sc->rsize = ENVY24_REC_BUFUNIT * ENVY24_SAMPLE_NUM; 2238 sc->pbuf = NULL; 2239 sc->rbuf = NULL; 2240 sc->paddr = sc->raddr = 0; 2241 sc->blk[0] = sc->blk[1] = 0; 2242 2243 /* allocate DMA buffer */ 2244 #if(0) 2245 device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_alloc(): sc->pbuf\n"); 2246 #endif 2247 if (bus_dmamem_alloc(sc->dmat, (void **)&sc->pbuf, BUS_DMA_NOWAIT, &sc->pmap)) 2248 goto bad; 2249 #if(0) 2250 device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_alloc(): sc->rbuf\n"); 2251 #endif 2252 if (bus_dmamem_alloc(sc->dmat, (void **)&sc->rbuf, BUS_DMA_NOWAIT, &sc->rmap)) 2253 goto bad; 2254 #if(0) 2255 device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_load(): sc->pmap\n"); 2256 #endif 2257 if (bus_dmamap_load(sc->dmat, sc->pmap, sc->pbuf, sc->psize, 2258 envy24_dmapsetmap, sc, BUS_DMA_NOWAIT)) 2259 goto bad; 2260 #if(0) 2261 device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_load(): sc->rmap\n"); 2262 #endif 2263 if (bus_dmamap_load(sc->dmat, sc->rmap, sc->rbuf, sc->rsize, 2264 envy24_dmarsetmap, sc, BUS_DMA_NOWAIT)) 2265 goto bad; 2266 bzero(sc->pbuf, sc->psize); 2267 bzero(sc->rbuf, sc->rsize); 2268 2269 /* set values to register */ 2270 #if(0) 2271 device_printf(sc->dev, "paddr(0x%08x)\n", sc->paddr); 2272 #endif 2273 envy24_wrmt(sc, ENVY24_MT_PADDR, sc->paddr, 4); 2274 #if(0) 2275 device_printf(sc->dev, "PADDR-->(0x%08x)\n", envy24_rdmt(sc, ENVY24_MT_PADDR, 4)); 2276 device_printf(sc->dev, "psize(%ld)\n", sc->psize / 4 - 1); 2277 #endif 2278 envy24_wrmt(sc, ENVY24_MT_PCNT, sc->psize / 4 - 1, 2); 2279 #if(0) 2280 device_printf(sc->dev, "PCNT-->(%ld)\n", envy24_rdmt(sc, ENVY24_MT_PCNT, 2)); 2281 #endif 2282 envy24_wrmt(sc, ENVY24_MT_RADDR, sc->raddr, 4); 2283 envy24_wrmt(sc, ENVY24_MT_RCNT, sc->rsize / 4 - 1, 2); 2284 2285 return 0; 2286 bad: 2287 envy24_dmafree(sc); 2288 return ENOSPC; 2289 } 2290 2291 static void 2292 envy24_putcfg(struct sc_info *sc) 2293 { 2294 device_printf(sc->dev, "system configuration\n"); 2295 printf(" SubVendorID: 0x%04x, SubDeviceID: 0x%04x\n", 2296 sc->cfg->subvendor, sc->cfg->subdevice); 2297 printf(" XIN2 Clock Source: "); 2298 switch (sc->cfg->scfg & PCIM_SCFG_XIN2) { 2299 case 0x00: 2300 printf("22.5792MHz(44.1kHz*512)\n"); 2301 break; 2302 case 0x40: 2303 printf("16.9344MHz(44.1kHz*384)\n"); 2304 break; 2305 case 0x80: 2306 printf("from external clock synthesizer chip\n"); 2307 break; 2308 default: 2309 printf("illegal system setting\n"); 2310 } 2311 printf(" MPU-401 UART(s) #: "); 2312 if (sc->cfg->scfg & PCIM_SCFG_MPU) 2313 printf("2\n"); 2314 else 2315 printf("1\n"); 2316 printf(" AC'97 codec: "); 2317 if (sc->cfg->scfg & PCIM_SCFG_AC97) 2318 printf("not exist\n"); 2319 else 2320 printf("exist\n"); 2321 printf(" ADC #: "); 2322 printf("%d\n", sc->adcn); 2323 printf(" DAC #: "); 2324 printf("%d\n", sc->dacn); 2325 printf(" Multi-track converter type: "); 2326 if ((sc->cfg->acl & PCIM_ACL_MTC) == 0) { 2327 printf("AC'97(SDATA_OUT:"); 2328 if (sc->cfg->acl & PCIM_ACL_OMODE) 2329 printf("packed"); 2330 else 2331 printf("split"); 2332 printf("|SDATA_IN:"); 2333 if (sc->cfg->acl & PCIM_ACL_IMODE) 2334 printf("packed"); 2335 else 2336 printf("split"); 2337 printf(")\n"); 2338 } 2339 else { 2340 printf("I2S("); 2341 if (sc->cfg->i2s & PCIM_I2S_VOL) 2342 printf("with volume, "); 2343 if (sc->cfg->i2s & PCIM_I2S_96KHZ) 2344 printf("96KHz support, "); 2345 switch (sc->cfg->i2s & PCIM_I2S_RES) { 2346 case PCIM_I2S_16BIT: 2347 printf("16bit resolution, "); 2348 break; 2349 case PCIM_I2S_18BIT: 2350 printf("18bit resolution, "); 2351 break; 2352 case PCIM_I2S_20BIT: 2353 printf("20bit resolution, "); 2354 break; 2355 case PCIM_I2S_24BIT: 2356 printf("24bit resolution, "); 2357 break; 2358 } 2359 printf("ID#0x%x)\n", sc->cfg->i2s & PCIM_I2S_ID); 2360 } 2361 printf(" S/PDIF(IN/OUT): "); 2362 if (sc->cfg->spdif & PCIM_SPDIF_IN) 2363 printf("1/"); 2364 else 2365 printf("0/"); 2366 if (sc->cfg->spdif & PCIM_SPDIF_OUT) 2367 printf("1 "); 2368 else 2369 printf("0 "); 2370 if (sc->cfg->spdif & (PCIM_SPDIF_IN | PCIM_SPDIF_OUT)) 2371 printf("ID# 0x%02x\n", (sc->cfg->spdif & PCIM_SPDIF_ID) >> 2); 2372 printf(" GPIO(mask/dir/state): 0x%02x/0x%02x/0x%02x\n", 2373 sc->cfg->gpiomask, sc->cfg->gpiodir, sc->cfg->gpiostate); 2374 } 2375 2376 static int 2377 envy24_init(struct sc_info *sc) 2378 { 2379 u_int32_t data; 2380 #if(0) 2381 int rtn; 2382 #endif 2383 int i; 2384 u_int32_t sv, sd; 2385 2386 #if(0) 2387 device_printf(sc->dev, "envy24_init()\n"); 2388 #endif 2389 2390 /* reset chip */ 2391 envy24_wrcs(sc, ENVY24_CCS_CTL, ENVY24_CCS_CTL_RESET | ENVY24_CCS_CTL_NATIVE, 1); 2392 DELAY(200); 2393 envy24_wrcs(sc, ENVY24_CCS_CTL, ENVY24_CCS_CTL_NATIVE, 1); 2394 DELAY(200); 2395 2396 /* legacy hardware disable */ 2397 data = pci_read_config(sc->dev, PCIR_LAC, 2); 2398 data |= PCIM_LAC_DISABLE; 2399 pci_write_config(sc->dev, PCIR_LAC, data, 2); 2400 2401 /* check system configuration */ 2402 sc->cfg = NULL; 2403 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++) { 2404 /* 1st: search configuration from table */ 2405 sv = pci_get_subvendor(sc->dev); 2406 sd = pci_get_subdevice(sc->dev); 2407 if (sv == cfg_table[i].subvendor && sd == cfg_table[i].subdevice) { 2408 #if(0) 2409 device_printf(sc->dev, "Set configuration from table\n"); 2410 #endif 2411 sc->cfg = &cfg_table[i]; 2412 break; 2413 } 2414 } 2415 if (sc->cfg == NULL) { 2416 /* 2nd: read configuration from table */ 2417 sc->cfg = envy24_rom2cfg(sc); 2418 } 2419 sc->adcn = ((sc->cfg->scfg & PCIM_SCFG_ADC) >> 2) + 1; 2420 sc->dacn = (sc->cfg->scfg & PCIM_SCFG_DAC) + 1; 2421 2422 if (1 /* bootverbose */) { 2423 envy24_putcfg(sc); 2424 } 2425 2426 /* set system configuration */ 2427 pci_write_config(sc->dev, PCIR_SCFG, sc->cfg->scfg, 1); 2428 pci_write_config(sc->dev, PCIR_ACL, sc->cfg->acl, 1); 2429 pci_write_config(sc->dev, PCIR_I2S, sc->cfg->i2s, 1); 2430 pci_write_config(sc->dev, PCIR_SPDIF, sc->cfg->spdif, 1); 2431 envy24_gpiosetmask(sc, sc->cfg->gpiomask); 2432 envy24_gpiosetdir(sc, sc->cfg->gpiodir); 2433 envy24_gpiowr(sc, sc->cfg->gpiostate); 2434 for (i = 0; i < sc->adcn; i++) { 2435 sc->adc[i] = sc->cfg->codec->create(sc->dev, sc, PCMDIR_REC, i); 2436 sc->cfg->codec->init(sc->adc[i]); 2437 } 2438 for (i = 0; i < sc->dacn; i++) { 2439 sc->dac[i] = sc->cfg->codec->create(sc->dev, sc, PCMDIR_PLAY, i); 2440 sc->cfg->codec->init(sc->dac[i]); 2441 } 2442 2443 /* initialize DMA buffer */ 2444 #if(0) 2445 device_printf(sc->dev, "envy24_init(): initialize DMA buffer\n"); 2446 #endif 2447 if (envy24_dmainit(sc)) 2448 return ENOSPC; 2449 2450 /* initialize status */ 2451 sc->run[0] = sc->run[1] = 0; 2452 sc->intr[0] = sc->intr[1] = 0; 2453 sc->speed = 0; 2454 sc->caps[0].fmtlist = envy24_playfmt; 2455 sc->caps[1].fmtlist = envy24_recfmt; 2456 2457 /* set channel router */ 2458 envy24_route(sc, ENVY24_ROUTE_DAC_1, ENVY24_ROUTE_CLASS_MIX, 0, 0); 2459 envy24_route(sc, ENVY24_ROUTE_DAC_SPDIF, ENVY24_ROUTE_CLASS_DMA, 0, 0); 2460 /* envy24_route(sc, ENVY24_ROUTE_DAC_SPDIF, ENVY24_ROUTE_CLASS_MIX, 0, 0); */ 2461 2462 /* set macro interrupt mask */ 2463 data = envy24_rdcs(sc, ENVY24_CCS_IMASK, 1); 2464 envy24_wrcs(sc, ENVY24_CCS_IMASK, data & ~ENVY24_CCS_IMASK_PMT, 1); 2465 data = envy24_rdcs(sc, ENVY24_CCS_IMASK, 1); 2466 #if(0) 2467 device_printf(sc->dev, "envy24_init(): CCS_IMASK-->0x%02x\n", data); 2468 #endif 2469 2470 return 0; 2471 } 2472 2473 static int 2474 envy24_alloc_resource(struct sc_info *sc) 2475 { 2476 /* allocate I/O port resource */ 2477 sc->csid = PCIR_CCS; 2478 sc->cs = bus_alloc_resource_any(sc->dev, SYS_RES_IOPORT, 2479 &sc->csid, RF_ACTIVE); 2480 sc->ddmaid = PCIR_DDMA; 2481 sc->ddma = bus_alloc_resource_any(sc->dev, SYS_RES_IOPORT, 2482 &sc->ddmaid, RF_ACTIVE); 2483 sc->dsid = PCIR_DS; 2484 sc->ds = bus_alloc_resource_any(sc->dev, SYS_RES_IOPORT, 2485 &sc->dsid, RF_ACTIVE); 2486 sc->mtid = PCIR_MT; 2487 sc->mt = bus_alloc_resource_any(sc->dev, SYS_RES_IOPORT, 2488 &sc->mtid, RF_ACTIVE); 2489 if (!sc->cs || !sc->ddma || !sc->ds || !sc->mt) { 2490 device_printf(sc->dev, "unable to map IO port space\n"); 2491 return ENXIO; 2492 } 2493 sc->cst = rman_get_bustag(sc->cs); 2494 sc->csh = rman_get_bushandle(sc->cs); 2495 sc->ddmat = rman_get_bustag(sc->ddma); 2496 sc->ddmah = rman_get_bushandle(sc->ddma); 2497 sc->dst = rman_get_bustag(sc->ds); 2498 sc->dsh = rman_get_bushandle(sc->ds); 2499 sc->mtt = rman_get_bustag(sc->mt); 2500 sc->mth = rman_get_bushandle(sc->mt); 2501 #if(0) 2502 device_printf(sc->dev, 2503 "IO port register values\nCCS: 0x%lx\nDDMA: 0x%lx\nDS: 0x%lx\nMT: 0x%lx\n", 2504 pci_read_config(sc->dev, PCIR_CCS, 4), 2505 pci_read_config(sc->dev, PCIR_DDMA, 4), 2506 pci_read_config(sc->dev, PCIR_DS, 4), 2507 pci_read_config(sc->dev, PCIR_MT, 4)); 2508 #endif 2509 2510 /* allocate interrupt resource */ 2511 sc->irqid = 0; 2512 sc->irq = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, &sc->irqid, 2513 RF_ACTIVE | RF_SHAREABLE); 2514 if (!sc->irq || 2515 snd_setup_intr(sc->dev, sc->irq, INTR_MPSAFE, envy24_intr, sc, &sc->ih)) { 2516 device_printf(sc->dev, "unable to map interrupt\n"); 2517 return ENXIO; 2518 } 2519 2520 /* allocate DMA resource */ 2521 if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(sc->dev), 2522 /*alignment*/4, 2523 /*boundary*/0, 2524 /*lowaddr*/BUS_SPACE_MAXADDR_ENVY24, 2525 /*highaddr*/BUS_SPACE_MAXADDR_ENVY24, 2526 /*filter*/NULL, /*filterarg*/NULL, 2527 /*maxsize*/BUS_SPACE_MAXSIZE_ENVY24, 2528 /*nsegments*/1, /*maxsegsz*/0x3ffff, 2529 /*flags*/0, /*lockfunc*/NULL, /*lockarg*/NULL, 2530 &sc->dmat) != 0) { 2531 device_printf(sc->dev, "unable to create dma tag\n"); 2532 return ENXIO; 2533 } 2534 2535 return 0; 2536 } 2537 2538 static int 2539 envy24_pci_attach(device_t dev) 2540 { 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 pci_enable_busmaster(dev); 2561 2562 /* allocate resources */ 2563 err = envy24_alloc_resource(sc); 2564 if (err) { 2565 device_printf(dev, "unable to allocate system resources\n"); 2566 goto bad; 2567 } 2568 2569 /* initialize card */ 2570 err = envy24_init(sc); 2571 if (err) { 2572 device_printf(dev, "unable to initialize the card\n"); 2573 goto bad; 2574 } 2575 2576 /* set multi track mixer */ 2577 mixer_init(dev, &envy24mixer_class, sc); 2578 2579 /* set channel information */ 2580 err = pcm_register(dev, sc, 5, 2 + sc->adcn); 2581 if (err) 2582 goto bad; 2583 sc->chnum = 0; 2584 for (i = 0; i < 5; i++) { 2585 pcm_addchan(dev, PCMDIR_PLAY, &envy24chan_class, sc); 2586 sc->chnum++; 2587 } 2588 for (i = 0; i < 2 + sc->adcn; i++) { 2589 pcm_addchan(dev, PCMDIR_REC, &envy24chan_class, sc); 2590 sc->chnum++; 2591 } 2592 2593 /* set status iformation */ 2594 snprintf(status, SND_STATUSLEN, 2595 "at io 0x%jx:%jd,0x%jx:%jd,0x%jx:%jd,0x%jx:%jd irq %jd", 2596 rman_get_start(sc->cs), 2597 rman_get_end(sc->cs) - rman_get_start(sc->cs) + 1, 2598 rman_get_start(sc->ddma), 2599 rman_get_end(sc->ddma) - rman_get_start(sc->ddma) + 1, 2600 rman_get_start(sc->ds), 2601 rman_get_end(sc->ds) - rman_get_start(sc->ds) + 1, 2602 rman_get_start(sc->mt), 2603 rman_get_end(sc->mt) - rman_get_start(sc->mt) + 1, 2604 rman_get_start(sc->irq)); 2605 pcm_setstatus(dev, status); 2606 2607 return 0; 2608 2609 bad: 2610 if (sc->ih) 2611 bus_teardown_intr(dev, sc->irq, sc->ih); 2612 if (sc->irq) 2613 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); 2614 envy24_dmafree(sc); 2615 if (sc->dmat) 2616 bus_dma_tag_destroy(sc->dmat); 2617 if (sc->cfg->codec->destroy != NULL) { 2618 for (i = 0; i < sc->adcn; i++) 2619 sc->cfg->codec->destroy(sc->adc[i]); 2620 for (i = 0; i < sc->dacn; i++) 2621 sc->cfg->codec->destroy(sc->dac[i]); 2622 } 2623 envy24_cfgfree(sc->cfg); 2624 if (sc->cs) 2625 bus_release_resource(dev, SYS_RES_IOPORT, sc->csid, sc->cs); 2626 if (sc->ddma) 2627 bus_release_resource(dev, SYS_RES_IOPORT, sc->ddmaid, sc->ddma); 2628 if (sc->ds) 2629 bus_release_resource(dev, SYS_RES_IOPORT, sc->dsid, sc->ds); 2630 if (sc->mt) 2631 bus_release_resource(dev, SYS_RES_IOPORT, sc->mtid, sc->mt); 2632 if (sc->lock) 2633 snd_mtxfree(sc->lock); 2634 free(sc, M_ENVY24); 2635 return err; 2636 } 2637 2638 static int 2639 envy24_pci_detach(device_t dev) 2640 { 2641 struct sc_info *sc; 2642 int r; 2643 int i; 2644 2645 #if(0) 2646 device_printf(dev, "envy24_pci_detach()\n"); 2647 #endif 2648 sc = pcm_getdevinfo(dev); 2649 if (sc == NULL) 2650 return 0; 2651 r = pcm_unregister(dev); 2652 if (r) 2653 return r; 2654 2655 envy24_dmafree(sc); 2656 if (sc->cfg->codec->destroy != NULL) { 2657 for (i = 0; i < sc->adcn; i++) 2658 sc->cfg->codec->destroy(sc->adc[i]); 2659 for (i = 0; i < sc->dacn; i++) 2660 sc->cfg->codec->destroy(sc->dac[i]); 2661 } 2662 envy24_cfgfree(sc->cfg); 2663 bus_dma_tag_destroy(sc->dmat); 2664 bus_teardown_intr(dev, sc->irq, sc->ih); 2665 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); 2666 bus_release_resource(dev, SYS_RES_IOPORT, sc->csid, sc->cs); 2667 bus_release_resource(dev, SYS_RES_IOPORT, sc->ddmaid, sc->ddma); 2668 bus_release_resource(dev, SYS_RES_IOPORT, sc->dsid, sc->ds); 2669 bus_release_resource(dev, SYS_RES_IOPORT, sc->mtid, sc->mt); 2670 snd_mtxfree(sc->lock); 2671 free(sc, M_ENVY24); 2672 return 0; 2673 } 2674 2675 static device_method_t envy24_methods[] = { 2676 /* Device interface */ 2677 DEVMETHOD(device_probe, envy24_pci_probe), 2678 DEVMETHOD(device_attach, envy24_pci_attach), 2679 DEVMETHOD(device_detach, envy24_pci_detach), 2680 { 0, 0 } 2681 }; 2682 2683 static driver_t envy24_driver = { 2684 "pcm", 2685 envy24_methods, 2686 PCM_SOFTC_SIZE, 2687 }; 2688 2689 DRIVER_MODULE(snd_envy24, pci, envy24_driver, 0, 0); 2690 MODULE_DEPEND(snd_envy24, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 2691 MODULE_DEPEND(snd_envy24, snd_spicds, 1, 1, 1); 2692 MODULE_VERSION(snd_envy24, 1); 2693