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