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