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