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