1 /* 2 * Copyright (c) 2006 Konstantin Dimitrov <kosio.dimitrov@gmail.com> 3 * Copyright (c) 2001 Katsurajima Naoto <raven@katsurajima.seya.yokohama.jp> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 */ 28 29 /* 30 * Konstantin Dimitrov's thanks list: 31 * 32 * A huge thanks goes to Spas Filipov for his friendship, support and his 33 * generous gift - an 'Audiotrak Prodigy HD2' audio card! I also want to 34 * thank Keiichi Iwasaki and his parents, because they helped Spas to get 35 * the card from Japan! Having hardware sample of Prodigy HD2 made adding 36 * support for that great card very easy and real fun and pleasure. 37 * 38 */ 39 40 #include <dev/sound/pcm/sound.h> 41 #include <dev/sound/pcm/ac97.h> 42 #include <dev/sound/pci/spicds.h> 43 #include <dev/sound/pci/envy24ht.h> 44 45 #include <dev/pci/pcireg.h> 46 #include <dev/pci/pcivar.h> 47 48 #include "mixer_if.h" 49 50 SND_DECLARE_FILE("$FreeBSD$"); 51 52 MALLOC_DEFINE(M_ENVY24HT, "envy24ht", "envy24ht audio"); 53 54 /* -------------------------------------------------------------------- */ 55 56 struct sc_info; 57 58 #define ENVY24HT_PLAY_CHNUM 8 59 #define ENVY24HT_REC_CHNUM 2 60 #define ENVY24HT_PLAY_BUFUNIT (4 /* byte/sample */ * 8 /* channel */) 61 #define ENVY24HT_REC_BUFUNIT (4 /* byte/sample */ * 2 /* channel */) 62 #define ENVY24HT_SAMPLE_NUM 4096 63 64 #define ENVY24HT_TIMEOUT 1000 65 66 #define ENVY24HT_DEFAULT_FORMAT (AFMT_STEREO | AFMT_S16_LE) 67 68 #define ENVY24HT_NAMELEN 32 69 70 struct envy24ht_sample { 71 volatile u_int32_t buffer; 72 }; 73 74 typedef struct envy24ht_sample sample32_t; 75 76 /* channel registers */ 77 struct sc_chinfo { 78 struct snd_dbuf *buffer; 79 struct pcm_channel *channel; 80 struct sc_info *parent; 81 int dir; 82 unsigned num; /* hw channel number */ 83 84 /* channel information */ 85 u_int32_t format; 86 u_int32_t speed; 87 u_int32_t blk; /* hw block size(dword) */ 88 89 /* format conversion structure */ 90 u_int8_t *data; 91 unsigned int size; /* data buffer size(byte) */ 92 int unit; /* sample size(byte) */ 93 unsigned int offset; /* samples number offset */ 94 void (*emldma)(struct sc_chinfo *); 95 96 /* flags */ 97 int run; 98 }; 99 100 /* codec interface entrys */ 101 struct codec_entry { 102 void *(*create)(device_t dev, void *devinfo, int dir, int num); 103 void (*destroy)(void *codec); 104 void (*init)(void *codec); 105 void (*reinit)(void *codec); 106 void (*setvolume)(void *codec, int dir, unsigned int left, unsigned int right); 107 void (*setrate)(void *codec, int which, int rate); 108 }; 109 110 /* system configuration information */ 111 struct cfg_info { 112 char *name; 113 u_int16_t subvendor, subdevice; 114 u_int8_t scfg, acl, i2s, spdif; 115 u_int32_t gpiomask, gpiostate, gpiodir; 116 u_int32_t cdti, cclk, cs; 117 u_int8_t cif, type, free; 118 struct codec_entry *codec; 119 }; 120 121 /* device private data */ 122 struct sc_info { 123 device_t dev; 124 struct mtx *lock; 125 126 /* Control/Status registor */ 127 struct resource *cs; 128 int csid; 129 bus_space_tag_t cst; 130 bus_space_handle_t csh; 131 /* MultiTrack registor */ 132 struct resource *mt; 133 int mtid; 134 bus_space_tag_t mtt; 135 bus_space_handle_t mth; 136 /* DMA tag */ 137 bus_dma_tag_t dmat; 138 /* IRQ resource */ 139 struct resource *irq; 140 int irqid; 141 void *ih; 142 143 /* system configuration data */ 144 struct cfg_info *cfg; 145 146 /* ADC/DAC number and info */ 147 int adcn, dacn; 148 void *adc[4], *dac[4]; 149 150 /* mixer control data */ 151 u_int32_t src; 152 u_int8_t left[ENVY24HT_CHAN_NUM]; 153 u_int8_t right[ENVY24HT_CHAN_NUM]; 154 155 /* Play/Record DMA fifo */ 156 sample32_t *pbuf; 157 sample32_t *rbuf; 158 u_int32_t psize, rsize; /* DMA buffer size(byte) */ 159 u_int16_t blk[2]; /* transfer check blocksize(dword) */ 160 bus_dmamap_t pmap, rmap; 161 162 /* current status */ 163 u_int32_t speed; 164 int run[2]; 165 u_int16_t intr[2]; 166 struct pcmchan_caps caps[2]; 167 168 /* channel info table */ 169 unsigned chnum; 170 struct sc_chinfo chan[11]; 171 }; 172 173 /* -------------------------------------------------------------------- */ 174 175 /* 176 * prototypes 177 */ 178 179 /* DMA emulator */ 180 static void envy24ht_p8u(struct sc_chinfo *); 181 static void envy24ht_p16sl(struct sc_chinfo *); 182 static void envy24ht_p32sl(struct sc_chinfo *); 183 static void envy24ht_r16sl(struct sc_chinfo *); 184 static void envy24ht_r32sl(struct sc_chinfo *); 185 186 /* channel interface */ 187 static void *envy24htchan_init(kobj_t, void *, struct snd_dbuf *, struct pcm_channel *, int); 188 static int envy24htchan_setformat(kobj_t, void *, u_int32_t); 189 static int envy24htchan_setspeed(kobj_t, void *, u_int32_t); 190 static int envy24htchan_setblocksize(kobj_t, void *, u_int32_t); 191 static int envy24htchan_trigger(kobj_t, void *, int); 192 static int envy24htchan_getptr(kobj_t, void *); 193 static struct pcmchan_caps *envy24htchan_getcaps(kobj_t, void *); 194 195 /* mixer interface */ 196 static int envy24htmixer_init(struct snd_mixer *); 197 static int envy24htmixer_reinit(struct snd_mixer *); 198 static int envy24htmixer_uninit(struct snd_mixer *); 199 static int envy24htmixer_set(struct snd_mixer *, unsigned, unsigned, unsigned); 200 static u_int32_t envy24htmixer_setrecsrc(struct snd_mixer *, u_int32_t); 201 202 /* SPI codec access interface */ 203 static void *envy24ht_spi_create(device_t, void *, int, int); 204 static void envy24ht_spi_destroy(void *); 205 static void envy24ht_spi_init(void *); 206 static void envy24ht_spi_reinit(void *); 207 static void envy24ht_spi_setvolume(void *, int, unsigned int, unsigned int); 208 209 /* -------------------------------------------------------------------- */ 210 211 /* 212 system constant tables 213 */ 214 215 /* API -> hardware channel map */ 216 static unsigned envy24ht_chanmap[ENVY24HT_CHAN_NUM] = { 217 ENVY24HT_CHAN_PLAY_DAC1, /* 1 */ 218 ENVY24HT_CHAN_PLAY_DAC2, /* 2 */ 219 ENVY24HT_CHAN_PLAY_DAC3, /* 3 */ 220 ENVY24HT_CHAN_PLAY_DAC4, /* 4 */ 221 ENVY24HT_CHAN_PLAY_SPDIF, /* 0 */ 222 ENVY24HT_CHAN_REC_MIX, /* 5 */ 223 ENVY24HT_CHAN_REC_SPDIF, /* 6 */ 224 ENVY24HT_CHAN_REC_ADC1, /* 7 */ 225 ENVY24HT_CHAN_REC_ADC2, /* 8 */ 226 ENVY24HT_CHAN_REC_ADC3, /* 9 */ 227 ENVY24HT_CHAN_REC_ADC4, /* 10 */ 228 }; 229 230 /* mixer -> API channel map. see above */ 231 static int envy24ht_mixmap[] = { 232 -1, /* Master output level. It is depend on codec support */ 233 -1, /* Treble level of all output channels */ 234 -1, /* Bass level of all output channels */ 235 -1, /* Volume of synthesier input */ 236 0, /* Output level for the audio device */ 237 -1, /* Output level for the PC speaker */ 238 7, /* line in jack */ 239 -1, /* microphone jack */ 240 -1, /* CD audio input */ 241 -1, /* Recording monitor */ 242 1, /* alternative codec */ 243 -1, /* global recording level */ 244 -1, /* Input gain */ 245 -1, /* Output gain */ 246 8, /* Input source 1 */ 247 9, /* Input source 2 */ 248 10, /* Input source 3 */ 249 6, /* Digital (input) 1 */ 250 -1, /* Digital (input) 2 */ 251 -1, /* Digital (input) 3 */ 252 -1, /* Phone input */ 253 -1, /* Phone output */ 254 -1, /* Video/TV (audio) in */ 255 -1, /* Radio in */ 256 -1, /* Monitor volume */ 257 }; 258 259 /* variable rate audio */ 260 static u_int32_t envy24ht_speed[] = { 261 192000, 176400, 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 262 12000, 11025, 9600, 8000, 0 263 }; 264 265 /* known boards configuration */ 266 static struct codec_entry spi_codec = { 267 envy24ht_spi_create, 268 envy24ht_spi_destroy, 269 envy24ht_spi_init, 270 envy24ht_spi_reinit, 271 envy24ht_spi_setvolume, 272 NULL, /* setrate */ 273 }; 274 275 static struct cfg_info cfg_table[] = { 276 { 277 "Envy24HT audio (Terratec Aureon 7.1 Space)", 278 0x153b, 0x1145, 279 0x0b, 0x80, 0xfc, 0xc3, 280 0x21efff, 0x7fffff, 0x5e1000, 281 0x40000, 0x80000, 0x1000, 0x00, 0x02, 282 0, 283 &spi_codec, 284 }, 285 { 286 "Envy24HT audio (Terratec Aureon 5.1 Sky)", 287 0x153b, 0x1147, 288 0x0a, 0x80, 0xfc, 0xc3, 289 0x21efff, 0x7fffff, 0x5e1000, 290 0x40000, 0x80000, 0x1000, 0x00, 0x02, 291 0, 292 &spi_codec, 293 }, 294 { 295 "Envy24HT audio (Terratec Aureon 7.1 Universe)", 296 0x153b, 0x1153, 297 0x0b, 0x80, 0xfc, 0xc3, 298 0x21efff, 0x7fffff, 0x5e1000, 299 0x40000, 0x80000, 0x1000, 0x00, 0x02, 300 0, 301 &spi_codec, 302 }, 303 { 304 "Envy24HT audio (AudioTrak Prodigy 7.1)", 305 0x4933, 0x4553, 306 0x0b, 0x80, 0xfc, 0xc3, 307 0x21efff, 0x7fffff, 0x5e1000, 308 0x40000, 0x80000, 0x1000, 0x00, 0x02, 309 0, 310 &spi_codec, 311 }, 312 { 313 "Envy24HT audio (Terratec PHASE 28)", 314 0x153b, 0x1149, 315 0x0b, 0x80, 0xfc, 0xc3, 316 0x21efff, 0x7fffff, 0x5e1000, 317 0x40000, 0x80000, 0x1000, 0x00, 0x02, 318 0, 319 &spi_codec, 320 }, 321 { 322 "Envy24HT-S audio (Terratec PHASE 22)", 323 0x153b, 0x1150, 324 0x10, 0x80, 0xf0, 0xc3, 325 0x7ffbc7, 0x7fffff, 0x438, 326 0x20, 0x10, 0x400, 0x00, 0x00, 327 0, 328 &spi_codec, 329 }, 330 { 331 "Envy24HT audio (AudioTrak Prodigy 7.1 LT)", 332 0x3132, 0x4154, 333 0x4b, 0x80, 0xfc, 0xc3, 334 0x7ff8ff, 0x7fffff, 0x700, 335 0x400, 0x200, 0x100, 0x00, 0x02, 336 0, 337 &spi_codec, 338 }, 339 { 340 "Envy24HT audio (AudioTrak Prodigy 7.1 XT)", 341 0x3136, 0x4154, 342 0x4b, 0x80, 0xfc, 0xc3, 343 0x7ff8ff, 0x7fffff, 0x700, 344 0x400, 0x200, 0x100, 0x00, 0x02, 345 0, 346 &spi_codec, 347 }, 348 { 349 "Envy24HT audio (M-Audio Revolution 7.1)", 350 0x1412, 0x3630, 351 0x43, 0x80, 0xf8, 0xc1, 352 0x3fff85, 0x72, 0x4000fa, 353 0x08, 0x02, 0x20, 0x00, 0x04, 354 0, 355 &spi_codec, 356 }, 357 { 358 "Envy24GT audio (M-Audio Revolution 5.1)", 359 0x1412, 0x3631, 360 0x42, 0x80, 0xf8, 0xc1, 361 0x3fff85, 0x72, 0x4000fa, 362 0x08, 0x02, 0x10, 0x00, 0x03, 363 0, 364 &spi_codec, 365 }, 366 { 367 "Envy24HT audio (M-Audio Audiophile 192)", 368 0x1412, 0x3632, 369 0x68, 0x80, 0xf8, 0xc3, 370 0x45, 0x4000b5, 0x7fffba, 371 0x08, 0x02, 0x10, 0x00, 0x03, 372 0, 373 &spi_codec, 374 }, 375 { 376 "Envy24HT audio (AudioTrak Prodigy HD2)", 377 0x3137, 0x4154, 378 0x68, 0x80, 0x78, 0xc3, 379 0xfff8ff, 0x200700, 0xdfffff, 380 0x400, 0x200, 0x100, 0x00, 0x05, 381 0, 382 &spi_codec, 383 }, 384 { 385 "Envy24HT audio (ESI Juli@)", 386 0x3031, 0x4553, 387 0x20, 0x80, 0xf8, 0xc3, 388 0x7fff9f, 0x8016, 0x7fff9f, 389 0x08, 0x02, 0x10, 0x00, 0x03, 390 0, 391 &spi_codec, 392 }, 393 { 394 "Envy24HT audio (Generic)", 395 0, 0, 396 0x0b, 0x80, 0xfc, 0xc3, 397 0x21efff, 0x7fffff, 0x5e1000, 398 0x40000, 0x80000, 0x1000, 0x00, 0x02, 399 0, 400 &spi_codec, /* default codec routines */ 401 } 402 }; 403 404 static u_int32_t envy24ht_recfmt[] = { 405 AFMT_STEREO | AFMT_S16_LE, 406 AFMT_STEREO | AFMT_S32_LE, 407 0 408 }; 409 static struct pcmchan_caps envy24ht_reccaps = {8000, 96000, envy24ht_recfmt, 0}; 410 411 static u_int32_t envy24ht_playfmt[] = { 412 AFMT_STEREO | AFMT_U8, 413 AFMT_STEREO | AFMT_S16_LE, 414 AFMT_STEREO | AFMT_S32_LE, 415 0 416 }; 417 418 static struct pcmchan_caps envy24ht_playcaps = {8000, 192000, envy24ht_playfmt, 0}; 419 420 struct envy24ht_emldma { 421 u_int32_t format; 422 void (*emldma)(struct sc_chinfo *); 423 int unit; 424 }; 425 426 static struct envy24ht_emldma envy24ht_pemltab[] = { 427 {AFMT_STEREO | AFMT_U8, envy24ht_p8u, 2}, 428 {AFMT_STEREO | AFMT_S16_LE, envy24ht_p16sl, 4}, 429 {AFMT_STEREO | AFMT_S32_LE, envy24ht_p32sl, 8}, 430 {0, NULL, 0} 431 }; 432 433 static struct envy24ht_emldma envy24ht_remltab[] = { 434 {AFMT_STEREO | AFMT_S16_LE, envy24ht_r16sl, 4}, 435 {AFMT_STEREO | AFMT_S32_LE, envy24ht_r32sl, 8}, 436 {0, NULL, 0} 437 }; 438 439 /* -------------------------------------------------------------------- */ 440 441 /* common routines */ 442 static u_int32_t 443 envy24ht_rdcs(struct sc_info *sc, int regno, int size) 444 { 445 switch (size) { 446 case 1: 447 return bus_space_read_1(sc->cst, sc->csh, regno); 448 case 2: 449 return bus_space_read_2(sc->cst, sc->csh, regno); 450 case 4: 451 return bus_space_read_4(sc->cst, sc->csh, regno); 452 default: 453 return 0xffffffff; 454 } 455 } 456 457 static void 458 envy24ht_wrcs(struct sc_info *sc, int regno, u_int32_t data, int size) 459 { 460 switch (size) { 461 case 1: 462 bus_space_write_1(sc->cst, sc->csh, regno, data); 463 break; 464 case 2: 465 bus_space_write_2(sc->cst, sc->csh, regno, data); 466 break; 467 case 4: 468 bus_space_write_4(sc->cst, sc->csh, regno, data); 469 break; 470 } 471 } 472 473 static u_int32_t 474 envy24ht_rdmt(struct sc_info *sc, int regno, int size) 475 { 476 switch (size) { 477 case 1: 478 return bus_space_read_1(sc->mtt, sc->mth, regno); 479 case 2: 480 return bus_space_read_2(sc->mtt, sc->mth, regno); 481 case 4: 482 return bus_space_read_4(sc->mtt, sc->mth, regno); 483 default: 484 return 0xffffffff; 485 } 486 } 487 488 static void 489 envy24ht_wrmt(struct sc_info *sc, int regno, u_int32_t data, int size) 490 { 491 switch (size) { 492 case 1: 493 bus_space_write_1(sc->mtt, sc->mth, regno, data); 494 break; 495 case 2: 496 bus_space_write_2(sc->mtt, sc->mth, regno, data); 497 break; 498 case 4: 499 bus_space_write_4(sc->mtt, sc->mth, regno, data); 500 break; 501 } 502 } 503 504 /* -------------------------------------------------------------------- */ 505 506 /* I2C port/E2PROM access routines */ 507 508 static int 509 envy24ht_rdi2c(struct sc_info *sc, u_int32_t dev, u_int32_t addr) 510 { 511 u_int32_t data; 512 int i; 513 514 #if(0) 515 device_printf(sc->dev, "envy24ht_rdi2c(sc, 0x%02x, 0x%02x)\n", dev, addr); 516 #endif 517 for (i = 0; i < ENVY24HT_TIMEOUT; i++) { 518 data = envy24ht_rdcs(sc, ENVY24HT_CCS_I2CSTAT, 1); 519 if ((data & ENVY24HT_CCS_I2CSTAT_BSY) == 0) 520 break; 521 DELAY(32); /* 31.25kHz */ 522 } 523 if (i == ENVY24HT_TIMEOUT) { 524 return -1; 525 } 526 envy24ht_wrcs(sc, ENVY24HT_CCS_I2CADDR, addr, 1); 527 envy24ht_wrcs(sc, ENVY24HT_CCS_I2CDEV, 528 (dev & ENVY24HT_CCS_I2CDEV_ADDR) | ENVY24HT_CCS_I2CDEV_RD, 1); 529 for (i = 0; i < ENVY24HT_TIMEOUT; i++) { 530 data = envy24ht_rdcs(sc, ENVY24HT_CCS_I2CSTAT, 1); 531 if ((data & ENVY24HT_CCS_I2CSTAT_BSY) == 0) 532 break; 533 DELAY(32); /* 31.25kHz */ 534 } 535 if (i == ENVY24HT_TIMEOUT) { 536 return -1; 537 } 538 data = envy24ht_rdcs(sc, ENVY24HT_CCS_I2CDATA, 1); 539 540 #if(0) 541 device_printf(sc->dev, "envy24ht_rdi2c(): return 0x%x\n", data); 542 #endif 543 return (int)data; 544 } 545 546 static int 547 envy24ht_wri2c(struct sc_info *sc, u_int32_t dev, u_int32_t addr, u_int32_t data) 548 { 549 u_int32_t tmp; 550 int i; 551 552 #if(0) 553 device_printf(sc->dev, "envy24ht_rdi2c(sc, 0x%02x, 0x%02x)\n", dev, addr); 554 #endif 555 for (i = 0; i < ENVY24HT_TIMEOUT; i++) { 556 tmp = envy24ht_rdcs(sc, ENVY24HT_CCS_I2CSTAT, 1); 557 if ((tmp & ENVY24HT_CCS_I2CSTAT_BSY) == 0) 558 break; 559 DELAY(32); /* 31.25kHz */ 560 } 561 if (i == ENVY24HT_TIMEOUT) { 562 return -1; 563 } 564 envy24ht_wrcs(sc, ENVY24HT_CCS_I2CADDR, addr, 1); 565 envy24ht_wrcs(sc, ENVY24HT_CCS_I2CDATA, data, 1); 566 envy24ht_wrcs(sc, ENVY24HT_CCS_I2CDEV, 567 (dev & ENVY24HT_CCS_I2CDEV_ADDR) | ENVY24HT_CCS_I2CDEV_WR, 1); 568 for (i = 0; i < ENVY24HT_TIMEOUT; i++) { 569 data = envy24ht_rdcs(sc, ENVY24HT_CCS_I2CSTAT, 1); 570 if ((data & ENVY24HT_CCS_I2CSTAT_BSY) == 0) 571 break; 572 DELAY(32); /* 31.25kHz */ 573 } 574 if (i == ENVY24HT_TIMEOUT) { 575 return -1; 576 } 577 578 return 0; 579 } 580 581 static int 582 envy24ht_rdrom(struct sc_info *sc, u_int32_t addr) 583 { 584 u_int32_t data; 585 586 #if(0) 587 device_printf(sc->dev, "envy24ht_rdrom(sc, 0x%02x)\n", addr); 588 #endif 589 data = envy24ht_rdcs(sc, ENVY24HT_CCS_I2CSTAT, 1); 590 if ((data & ENVY24HT_CCS_I2CSTAT_ROM) == 0) { 591 #if(0) 592 device_printf(sc->dev, "envy24ht_rdrom(): E2PROM not presented\n"); 593 #endif 594 return -1; 595 } 596 597 return envy24ht_rdi2c(sc, ENVY24HT_CCS_I2CDEV_ROM, addr); 598 } 599 600 static struct cfg_info * 601 envy24ht_rom2cfg(struct sc_info *sc) 602 { 603 struct cfg_info *buff; 604 int size; 605 int i; 606 607 #if(0) 608 device_printf(sc->dev, "envy24ht_rom2cfg(sc)\n"); 609 #endif 610 size = envy24ht_rdrom(sc, ENVY24HT_E2PROM_SIZE); 611 if ((size < ENVY24HT_E2PROM_GPIOSTATE + 3) || (size == 0x78)) { 612 #if(0) 613 device_printf(sc->dev, "envy24ht_rom2cfg(): ENVY24HT_E2PROM_SIZE-->%d\n", size); 614 #endif 615 buff = malloc(sizeof(*buff), M_ENVY24HT, M_NOWAIT); 616 if (buff == NULL) { 617 #if(0) 618 device_printf(sc->dev, "envy24ht_rom2cfg(): malloc()\n"); 619 #endif 620 return NULL; 621 } 622 buff->free = 1; 623 624 /* no valid e2prom, using default values */ 625 buff->subvendor = envy24ht_rdrom(sc, ENVY24HT_E2PROM_SUBVENDOR) << 8; 626 buff->subvendor += envy24ht_rdrom(sc, ENVY24HT_E2PROM_SUBVENDOR + 1); 627 buff->subdevice = envy24ht_rdrom(sc, ENVY24HT_E2PROM_SUBDEVICE) << 8; 628 buff->subdevice += envy24ht_rdrom(sc, ENVY24HT_E2PROM_SUBDEVICE + 1); 629 buff->scfg = 0x0b; 630 buff->acl = 0x80; 631 buff->i2s = 0xfc; 632 buff->spdif = 0xc3; 633 buff->gpiomask = 0x21efff; 634 buff->gpiostate = 0x7fffff; 635 buff->gpiodir = 0x5e1000; 636 buff->cdti = 0x40000; 637 buff->cclk = 0x80000; 638 buff->cs = 0x1000; 639 buff->cif = 0x00; 640 buff->type = 0x02; 641 642 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; 643 i++) 644 if (cfg_table[i].subvendor == buff->subvendor && 645 cfg_table[i].subdevice == buff->subdevice) 646 break; 647 buff->name = cfg_table[i].name; 648 buff->codec = cfg_table[i].codec; 649 650 return buff; 651 #if 0 652 return NULL; 653 #endif 654 } 655 buff = malloc(sizeof(*buff), M_ENVY24HT, M_NOWAIT); 656 if (buff == NULL) { 657 #if(0) 658 device_printf(sc->dev, "envy24ht_rom2cfg(): malloc()\n"); 659 #endif 660 return NULL; 661 } 662 buff->free = 1; 663 664 buff->subvendor = envy24ht_rdrom(sc, ENVY24HT_E2PROM_SUBVENDOR) << 8; 665 buff->subvendor += envy24ht_rdrom(sc, ENVY24HT_E2PROM_SUBVENDOR + 1); 666 buff->subdevice = envy24ht_rdrom(sc, ENVY24HT_E2PROM_SUBDEVICE) << 8; 667 buff->subdevice += envy24ht_rdrom(sc, ENVY24HT_E2PROM_SUBDEVICE + 1); 668 buff->scfg = envy24ht_rdrom(sc, ENVY24HT_E2PROM_SCFG); 669 buff->acl = envy24ht_rdrom(sc, ENVY24HT_E2PROM_ACL); 670 buff->i2s = envy24ht_rdrom(sc, ENVY24HT_E2PROM_I2S); 671 buff->spdif = envy24ht_rdrom(sc, ENVY24HT_E2PROM_SPDIF); 672 buff->gpiomask = envy24ht_rdrom(sc, ENVY24HT_E2PROM_GPIOMASK) | \ 673 envy24ht_rdrom(sc, ENVY24HT_E2PROM_GPIOMASK + 1) << 8 | \ 674 envy24ht_rdrom(sc, ENVY24HT_E2PROM_GPIOMASK + 2) << 16; 675 buff->gpiostate = envy24ht_rdrom(sc, ENVY24HT_E2PROM_GPIOSTATE) | \ 676 envy24ht_rdrom(sc, ENVY24HT_E2PROM_GPIOSTATE + 1) << 8 | \ 677 envy24ht_rdrom(sc, ENVY24HT_E2PROM_GPIOSTATE + 2) << 16; 678 buff->gpiodir = envy24ht_rdrom(sc, ENVY24HT_E2PROM_GPIODIR) | \ 679 envy24ht_rdrom(sc, ENVY24HT_E2PROM_GPIODIR + 1) << 8 | \ 680 envy24ht_rdrom(sc, ENVY24HT_E2PROM_GPIODIR + 2) << 16; 681 682 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++) 683 if (cfg_table[i].subvendor == buff->subvendor && 684 cfg_table[i].subdevice == buff->subdevice) 685 break; 686 buff->name = cfg_table[i].name; 687 buff->codec = cfg_table[i].codec; 688 689 return buff; 690 } 691 692 static void 693 envy24ht_cfgfree(struct cfg_info *cfg) { 694 if (cfg == NULL) 695 return; 696 if (cfg->free) 697 free(cfg, M_ENVY24HT); 698 return; 699 } 700 701 /* -------------------------------------------------------------------- */ 702 703 /* AC'97 codec access routines */ 704 705 #if 0 706 static int 707 envy24ht_coldcd(struct sc_info *sc) 708 { 709 u_int32_t data; 710 int i; 711 712 #if(0) 713 device_printf(sc->dev, "envy24ht_coldcd()\n"); 714 #endif 715 envy24ht_wrmt(sc, ENVY24HT_MT_AC97CMD, ENVY24HT_MT_AC97CMD_CLD, 1); 716 DELAY(10); 717 envy24ht_wrmt(sc, ENVY24HT_MT_AC97CMD, 0, 1); 718 DELAY(1000); 719 for (i = 0; i < ENVY24HT_TIMEOUT; i++) { 720 data = envy24ht_rdmt(sc, ENVY24HT_MT_AC97CMD, 1); 721 if (data & ENVY24HT_MT_AC97CMD_RDY) { 722 return 0; 723 } 724 } 725 726 return -1; 727 } 728 729 static int 730 envy24ht_slavecd(struct sc_info *sc) 731 { 732 u_int32_t data; 733 int i; 734 735 #if(0) 736 device_printf(sc->dev, "envy24ht_slavecd()\n"); 737 #endif 738 envy24ht_wrmt(sc, ENVY24HT_MT_AC97CMD, 739 ENVY24HT_MT_AC97CMD_CLD | ENVY24HT_MT_AC97CMD_WRM, 1); 740 DELAY(10); 741 envy24ht_wrmt(sc, ENVY24HT_MT_AC97CMD, 0, 1); 742 DELAY(1000); 743 for (i = 0; i < ENVY24HT_TIMEOUT; i++) { 744 data = envy24ht_rdmt(sc, ENVY24HT_MT_AC97CMD, 1); 745 if (data & ENVY24HT_MT_AC97CMD_RDY) { 746 return 0; 747 } 748 } 749 750 return -1; 751 } 752 753 static int 754 envy24ht_rdcd(kobj_t obj, void *devinfo, int regno) 755 { 756 struct sc_info *sc = (struct sc_info *)devinfo; 757 u_int32_t data; 758 int i; 759 760 #if(0) 761 device_printf(sc->dev, "envy24ht_rdcd(obj, sc, 0x%02x)\n", regno); 762 #endif 763 envy24ht_wrmt(sc, ENVY24HT_MT_AC97IDX, (u_int32_t)regno, 1); 764 envy24ht_wrmt(sc, ENVY24HT_MT_AC97CMD, ENVY24HT_MT_AC97CMD_RD, 1); 765 for (i = 0; i < ENVY24HT_TIMEOUT; i++) { 766 data = envy24ht_rdmt(sc, ENVY24HT_MT_AC97CMD, 1); 767 if ((data & ENVY24HT_MT_AC97CMD_RD) == 0) 768 break; 769 } 770 data = envy24ht_rdmt(sc, ENVY24HT_MT_AC97DLO, 2); 771 772 #if(0) 773 device_printf(sc->dev, "envy24ht_rdcd(): return 0x%x\n", data); 774 #endif 775 return (int)data; 776 } 777 778 static int 779 envy24ht_wrcd(kobj_t obj, void *devinfo, int regno, u_int16_t data) 780 { 781 struct sc_info *sc = (struct sc_info *)devinfo; 782 u_int32_t cmd; 783 int i; 784 785 #if(0) 786 device_printf(sc->dev, "envy24ht_wrcd(obj, sc, 0x%02x, 0x%04x)\n", regno, data); 787 #endif 788 envy24ht_wrmt(sc, ENVY24HT_MT_AC97IDX, (u_int32_t)regno, 1); 789 envy24ht_wrmt(sc, ENVY24HT_MT_AC97DLO, (u_int32_t)data, 2); 790 envy24ht_wrmt(sc, ENVY24HT_MT_AC97CMD, ENVY24HT_MT_AC97CMD_WR, 1); 791 for (i = 0; i < ENVY24HT_TIMEOUT; i++) { 792 cmd = envy24ht_rdmt(sc, ENVY24HT_MT_AC97CMD, 1); 793 if ((cmd & ENVY24HT_MT_AC97CMD_WR) == 0) 794 break; 795 } 796 797 return 0; 798 } 799 800 static kobj_method_t envy24ht_ac97_methods[] = { 801 KOBJMETHOD(ac97_read, envy24ht_rdcd), 802 KOBJMETHOD(ac97_write, envy24ht_wrcd), 803 {0, 0} 804 }; 805 AC97_DECLARE(envy24ht_ac97); 806 #endif 807 808 /* -------------------------------------------------------------------- */ 809 810 /* GPIO access routines */ 811 812 static u_int32_t 813 envy24ht_gpiord(struct sc_info *sc) 814 { 815 if (sc->cfg->subvendor == 0x153b && sc->cfg->subdevice == 0x1150) 816 return envy24ht_rdcs(sc, ENVY24HT_CCS_GPIO_LDATA, 2); 817 else 818 return (envy24ht_rdcs(sc, ENVY24HT_CCS_GPIO_HDATA, 1) << 16 | envy24ht_rdcs(sc, ENVY24HT_CCS_GPIO_LDATA, 2)); 819 } 820 821 static void 822 envy24ht_gpiowr(struct sc_info *sc, u_int32_t data) 823 { 824 #if(0) 825 device_printf(sc->dev, "envy24ht_gpiowr(sc, 0x%02x)\n", data & 0x7FFFFF); 826 return; 827 #endif 828 envy24ht_wrcs(sc, ENVY24HT_CCS_GPIO_LDATA, data, 2); 829 if (sc->cfg->subdevice != 0x1150) 830 envy24ht_wrcs(sc, ENVY24HT_CCS_GPIO_HDATA, data >> 16, 1); 831 return; 832 } 833 834 #if 0 835 static u_int32_t 836 envy24ht_gpiogetmask(struct sc_info *sc) 837 { 838 return (envy24ht_rdcs(sc, ENVY24HT_CCS_GPIO_HMASK, 1) << 16 | envy24ht_rdcs(sc, ENVY24HT_CCS_GPIO_LMASK, 2)); 839 } 840 #endif 841 842 static void 843 envy24ht_gpiosetmask(struct sc_info *sc, u_int32_t mask) 844 { 845 envy24ht_wrcs(sc, ENVY24HT_CCS_GPIO_LMASK, mask, 2); 846 if (sc->cfg->subdevice != 0x1150) 847 envy24ht_wrcs(sc, ENVY24HT_CCS_GPIO_HMASK, mask >> 16, 1); 848 return; 849 } 850 851 #if 0 852 static u_int32_t 853 envy24ht_gpiogetdir(struct sc_info *sc) 854 { 855 return envy24ht_rdcs(sc, ENVY24HT_CCS_GPIO_CTLDIR, 4); 856 } 857 #endif 858 859 static void 860 envy24ht_gpiosetdir(struct sc_info *sc, u_int32_t dir) 861 { 862 if (sc->cfg->subvendor == 0x153b && sc->cfg->subdevice == 0x1150) 863 envy24ht_wrcs(sc, ENVY24HT_CCS_GPIO_CTLDIR, dir, 2); 864 else 865 envy24ht_wrcs(sc, ENVY24HT_CCS_GPIO_CTLDIR, dir, 4); 866 return; 867 } 868 869 /* -------------------------------------------------------------------- */ 870 871 /* SPI codec access interface routine */ 872 873 struct envy24ht_spi_codec { 874 struct spicds_info *info; 875 struct sc_info *parent; 876 int dir; 877 int num; 878 int cs, cclk, cdti; 879 }; 880 881 static void 882 envy24ht_spi_ctl(void *codec, unsigned int cs, unsigned int cclk, unsigned int cdti) 883 { 884 u_int32_t data = 0; 885 struct envy24ht_spi_codec *ptr = codec; 886 887 #if(0) 888 device_printf(ptr->parent->dev, "--> %d, %d, %d\n", cs, cclk, cdti); 889 #endif 890 data = envy24ht_gpiord(ptr->parent); 891 data &= ~(ptr->cs | ptr->cclk | ptr->cdti); 892 if (cs) data += ptr->cs; 893 if (cclk) data += ptr->cclk; 894 if (cdti) data += ptr->cdti; 895 envy24ht_gpiowr(ptr->parent, data); 896 return; 897 } 898 899 static void * 900 envy24ht_spi_create(device_t dev, void *info, int dir, int num) 901 { 902 struct sc_info *sc = info; 903 struct envy24ht_spi_codec *buff = NULL; 904 905 #if(0) 906 device_printf(sc->dev, "envy24ht_spi_create(dev, sc, %d, %d)\n", dir, num); 907 #endif 908 909 buff = malloc(sizeof(*buff), M_ENVY24HT, M_NOWAIT); 910 if (buff == NULL) 911 return NULL; 912 913 if (dir == PCMDIR_REC && sc->adc[num] != NULL) 914 buff->info = ((struct envy24ht_spi_codec *)sc->adc[num])->info; 915 else if (dir == PCMDIR_PLAY && sc->dac[num] != NULL) 916 buff->info = ((struct envy24ht_spi_codec *)sc->dac[num])->info; 917 else 918 buff->info = spicds_create(dev, buff, num, envy24ht_spi_ctl); 919 if (buff->info == NULL) { 920 free(buff, M_ENVY24HT); 921 return NULL; 922 } 923 924 buff->parent = sc; 925 buff->dir = dir; 926 buff->num = num; 927 928 return (void *)buff; 929 } 930 931 static void 932 envy24ht_spi_destroy(void *codec) 933 { 934 struct envy24ht_spi_codec *ptr = codec; 935 if (ptr == NULL) 936 return; 937 #if(0) 938 device_printf(ptr->parent->dev, "envy24ht_spi_destroy()\n"); 939 #endif 940 941 if (ptr->dir == PCMDIR_PLAY) { 942 if (ptr->parent->dac[ptr->num] != NULL) 943 spicds_destroy(ptr->info); 944 } 945 else { 946 if (ptr->parent->adc[ptr->num] != NULL) 947 spicds_destroy(ptr->info); 948 } 949 950 free(codec, M_ENVY24HT); 951 } 952 953 static void 954 envy24ht_spi_init(void *codec) 955 { 956 struct envy24ht_spi_codec *ptr = codec; 957 if (ptr == NULL) 958 return; 959 #if(0) 960 device_printf(ptr->parent->dev, "envy24ht_spicds_init()\n"); 961 #endif 962 ptr->cs = ptr->parent->cfg->cs; 963 ptr->cclk = ptr->parent->cfg->cclk; 964 ptr->cdti = ptr->parent->cfg->cdti; 965 spicds_settype(ptr->info, ptr->parent->cfg->type); 966 spicds_setcif(ptr->info, ptr->parent->cfg->cif); 967 if (ptr->parent->cfg->type == SPICDS_TYPE_AK4524 || \ 968 ptr->parent->cfg->type == SPICDS_TYPE_AK4528) { 969 spicds_setformat(ptr->info, 970 AK452X_FORMAT_I2S | AK452X_FORMAT_256FSN | AK452X_FORMAT_1X); 971 spicds_setdvc(ptr->info, AK452X_DVC_DEMOFF); 972 } 973 974 /* for the time being, init only first codec */ 975 if (ptr->num == 0) 976 spicds_init(ptr->info); 977 } 978 979 static void 980 envy24ht_spi_reinit(void *codec) 981 { 982 struct envy24ht_spi_codec *ptr = codec; 983 if (ptr == NULL) 984 return; 985 #if(0) 986 device_printf(ptr->parent->dev, "envy24ht_spi_reinit()\n"); 987 #endif 988 989 spicds_reinit(ptr->info); 990 } 991 992 static void 993 envy24ht_spi_setvolume(void *codec, int dir, unsigned int left, unsigned int right) 994 { 995 struct envy24ht_spi_codec *ptr = codec; 996 if (ptr == NULL) 997 return; 998 #if(0) 999 device_printf(ptr->parent->dev, "envy24ht_spi_set()\n"); 1000 #endif 1001 1002 spicds_set(ptr->info, dir, left, right); 1003 } 1004 1005 /* -------------------------------------------------------------------- */ 1006 1007 /* hardware access routeines */ 1008 1009 static struct { 1010 u_int32_t speed; 1011 u_int32_t code; 1012 } envy24ht_speedtab[] = { 1013 {48000, ENVY24HT_MT_RATE_48000}, 1014 {24000, ENVY24HT_MT_RATE_24000}, 1015 {12000, ENVY24HT_MT_RATE_12000}, 1016 {9600, ENVY24HT_MT_RATE_9600}, 1017 {32000, ENVY24HT_MT_RATE_32000}, 1018 {16000, ENVY24HT_MT_RATE_16000}, 1019 {8000, ENVY24HT_MT_RATE_8000}, 1020 {96000, ENVY24HT_MT_RATE_96000}, 1021 {192000, ENVY24HT_MT_RATE_192000}, 1022 {64000, ENVY24HT_MT_RATE_64000}, 1023 {44100, ENVY24HT_MT_RATE_44100}, 1024 {22050, ENVY24HT_MT_RATE_22050}, 1025 {11025, ENVY24HT_MT_RATE_11025}, 1026 {88200, ENVY24HT_MT_RATE_88200}, 1027 {176400, ENVY24HT_MT_RATE_176400}, 1028 {0, 0x10} 1029 }; 1030 1031 static int 1032 envy24ht_setspeed(struct sc_info *sc, u_int32_t speed) { 1033 u_int32_t code, i2sfmt; 1034 int i = 0; 1035 1036 #if(0) 1037 device_printf(sc->dev, "envy24ht_setspeed(sc, %d)\n", speed); 1038 if (speed == 0) { 1039 code = ENVY24HT_MT_RATE_SPDIF; /* external master clock */ 1040 envy24ht_slavecd(sc); 1041 } 1042 else { 1043 #endif 1044 for (i = 0; envy24ht_speedtab[i].speed != 0; i++) { 1045 if (envy24ht_speedtab[i].speed == speed) 1046 break; 1047 } 1048 code = envy24ht_speedtab[i].code; 1049 #if 0 1050 } 1051 device_printf(sc->dev, "envy24ht_setspeed(): speed %d/code 0x%04x\n", envy24ht_speedtab[i].speed, code); 1052 #endif 1053 if (code < 0x10) { 1054 envy24ht_wrmt(sc, ENVY24HT_MT_RATE, code, 1); 1055 if ((((sc->cfg->scfg & ENVY24HT_CCSM_SCFG_XIN2) == 0x00) && (code == ENVY24HT_MT_RATE_192000)) || \ 1056 (code == ENVY24HT_MT_RATE_176400)) { 1057 i2sfmt = envy24ht_rdmt(sc, ENVY24HT_MT_I2S, 1); 1058 i2sfmt |= ENVY24HT_MT_I2S_MLR128; 1059 envy24ht_wrmt(sc, ENVY24HT_MT_I2S, i2sfmt, 1); 1060 } 1061 else { 1062 i2sfmt = envy24ht_rdmt(sc, ENVY24HT_MT_I2S, 1); 1063 i2sfmt &= ~ENVY24HT_MT_I2S_MLR128; 1064 envy24ht_wrmt(sc, ENVY24HT_MT_I2S, i2sfmt, 1); 1065 } 1066 code = envy24ht_rdmt(sc, ENVY24HT_MT_RATE, 1); 1067 code &= ENVY24HT_MT_RATE_MASK; 1068 for (i = 0; envy24ht_speedtab[i].code < 0x10; i++) { 1069 if (envy24ht_speedtab[i].code == code) 1070 break; 1071 } 1072 speed = envy24ht_speedtab[i].speed; 1073 } 1074 else 1075 speed = 0; 1076 1077 #if(0) 1078 device_printf(sc->dev, "envy24ht_setspeed(): return %d\n", speed); 1079 #endif 1080 return speed; 1081 } 1082 1083 static void 1084 envy24ht_setvolume(struct sc_info *sc, unsigned ch) 1085 { 1086 #if(0) 1087 device_printf(sc->dev, "envy24ht_setvolume(sc, %d)\n", ch); 1088 envy24ht_wrmt(sc, ENVY24HT_MT_VOLIDX, ch * 2, 1); 1089 envy24ht_wrmt(sc, ENVY24HT_MT_VOLUME, 0x7f00 | sc->left[ch], 2); 1090 envy24ht_wrmt(sc, ENVY24HT_MT_VOLIDX, ch * 2 + 1, 1); 1091 envy24ht_wrmt(sc, ENVY24HT_MT_VOLUME, (sc->right[ch] << 8) | 0x7f, 2); 1092 #endif 1093 } 1094 1095 static void 1096 envy24ht_mutevolume(struct sc_info *sc, unsigned ch) 1097 { 1098 #if 0 1099 u_int32_t vol; 1100 1101 device_printf(sc->dev, "envy24ht_mutevolume(sc, %d)\n", ch); 1102 vol = ENVY24HT_VOL_MUTE << 8 | ENVY24HT_VOL_MUTE; 1103 envy24ht_wrmt(sc, ENVY24HT_MT_VOLIDX, ch * 2, 1); 1104 envy24ht_wrmt(sc, ENVY24HT_MT_VOLUME, vol, 2); 1105 envy24ht_wrmt(sc, ENVY24HT_MT_VOLIDX, ch * 2 + 1, 1); 1106 envy24ht_wrmt(sc, ENVY24HT_MT_VOLUME, vol, 2); 1107 #endif 1108 } 1109 1110 static u_int32_t 1111 envy24ht_gethwptr(struct sc_info *sc, int dir) 1112 { 1113 int unit, regno; 1114 u_int32_t ptr, rtn; 1115 1116 #if(0) 1117 device_printf(sc->dev, "envy24ht_gethwptr(sc, %d)\n", dir); 1118 #endif 1119 if (dir == PCMDIR_PLAY) { 1120 rtn = sc->psize / 4; 1121 unit = ENVY24HT_PLAY_BUFUNIT / 4; 1122 regno = ENVY24HT_MT_PCNT; 1123 } 1124 else { 1125 rtn = sc->rsize / 4; 1126 unit = ENVY24HT_REC_BUFUNIT / 4; 1127 regno = ENVY24HT_MT_RCNT; 1128 } 1129 1130 ptr = envy24ht_rdmt(sc, regno, 2); 1131 rtn -= (ptr + 1); 1132 rtn /= unit; 1133 1134 #if(0) 1135 device_printf(sc->dev, "envy24ht_gethwptr(): return %d\n", rtn); 1136 #endif 1137 return rtn; 1138 } 1139 1140 static void 1141 envy24ht_updintr(struct sc_info *sc, int dir) 1142 { 1143 int regptr, regintr; 1144 u_int32_t mask, intr; 1145 u_int32_t ptr, size, cnt; 1146 u_int16_t blk; 1147 1148 #if(0) 1149 device_printf(sc->dev, "envy24ht_updintr(sc, %d)\n", dir); 1150 #endif 1151 if (dir == PCMDIR_PLAY) { 1152 blk = sc->blk[0]; 1153 size = sc->psize / 4; 1154 regptr = ENVY24HT_MT_PCNT; 1155 regintr = ENVY24HT_MT_PTERM; 1156 mask = ~ENVY24HT_MT_INT_PMASK; 1157 } 1158 else { 1159 blk = sc->blk[1]; 1160 size = sc->rsize / 4; 1161 regptr = ENVY24HT_MT_RCNT; 1162 regintr = ENVY24HT_MT_RTERM; 1163 mask = ~ENVY24HT_MT_INT_RMASK; 1164 } 1165 1166 ptr = size - envy24ht_rdmt(sc, regptr, 2) - 1; 1167 /* 1168 cnt = blk - ptr % blk - 1; 1169 if (cnt == 0) 1170 cnt = blk - 1; 1171 */ 1172 cnt = blk - 1; 1173 #if(0) 1174 device_printf(sc->dev, "envy24ht_updintr():ptr = %d, blk = %d, cnt = %d\n", ptr, blk, cnt); 1175 #endif 1176 envy24ht_wrmt(sc, regintr, cnt, 2); 1177 intr = envy24ht_rdmt(sc, ENVY24HT_MT_INT_MASK, 1); 1178 #if(0) 1179 device_printf(sc->dev, "envy24ht_updintr():intr = 0x%02x, mask = 0x%02x\n", intr, mask); 1180 #endif 1181 envy24ht_wrmt(sc, ENVY24HT_MT_INT_MASK, intr & mask, 1); 1182 #if(0) 1183 device_printf(sc->dev, "envy24ht_updintr():INT-->0x%02x\n", 1184 envy24ht_rdmt(sc, ENVY24HT_MT_INT_MASK, 1)); 1185 #endif 1186 1187 return; 1188 } 1189 1190 #if 0 1191 static void 1192 envy24ht_maskintr(struct sc_info *sc, int dir) 1193 { 1194 u_int32_t mask, intr; 1195 1196 #if(0) 1197 device_printf(sc->dev, "envy24ht_maskintr(sc, %d)\n", dir); 1198 #endif 1199 if (dir == PCMDIR_PLAY) 1200 mask = ENVY24HT_MT_INT_PMASK; 1201 else 1202 mask = ENVY24HT_MT_INT_RMASK; 1203 intr = envy24ht_rdmt(sc, ENVY24HT_MT_INT, 1); 1204 envy24ht_wrmt(sc, ENVY24HT_MT_INT, intr | mask, 1); 1205 1206 return; 1207 } 1208 #endif 1209 1210 static int 1211 envy24ht_checkintr(struct sc_info *sc, int dir) 1212 { 1213 u_int32_t mask, stat, intr, rtn; 1214 1215 #if(0) 1216 device_printf(sc->dev, "envy24ht_checkintr(sc, %d)\n", dir); 1217 #endif 1218 intr = envy24ht_rdmt(sc, ENVY24HT_MT_INT_STAT, 1); 1219 if (dir == PCMDIR_PLAY) { 1220 if ((rtn = intr & ENVY24HT_MT_INT_PSTAT) != 0) { 1221 mask = ~ENVY24HT_MT_INT_RSTAT; 1222 envy24ht_wrmt(sc, 0x1a, 0x01, 1); 1223 envy24ht_wrmt(sc, ENVY24HT_MT_INT_STAT, (intr & mask) | ENVY24HT_MT_INT_PSTAT | 0x08, 1); 1224 stat = envy24ht_rdmt(sc, ENVY24HT_MT_INT_MASK, 1); 1225 envy24ht_wrmt(sc, ENVY24HT_MT_INT_MASK, stat | ENVY24HT_MT_INT_PMASK, 1); 1226 } 1227 } 1228 else { 1229 if ((rtn = intr & ENVY24HT_MT_INT_RSTAT) != 0) { 1230 mask = ~ENVY24HT_MT_INT_PSTAT; 1231 #if 0 1232 stat = ENVY24HT_MT_INT_RSTAT | ENVY24HT_MT_INT_RMASK; 1233 #endif 1234 envy24ht_wrmt(sc, ENVY24HT_MT_INT_STAT, (intr & mask) | ENVY24HT_MT_INT_RSTAT, 1); 1235 stat = envy24ht_rdmt(sc, ENVY24HT_MT_INT_MASK, 1); 1236 envy24ht_wrmt(sc, ENVY24HT_MT_INT_MASK, stat | ENVY24HT_MT_INT_RMASK, 1); 1237 } 1238 } 1239 1240 return rtn; 1241 } 1242 1243 static void 1244 envy24ht_start(struct sc_info *sc, int dir) 1245 { 1246 u_int32_t stat, sw; 1247 1248 #if(0) 1249 device_printf(sc->dev, "envy24ht_start(sc, %d)\n", dir); 1250 #endif 1251 if (dir == PCMDIR_PLAY) 1252 sw = ENVY24HT_MT_PCTL_PSTART; 1253 else 1254 sw = ENVY24HT_MT_PCTL_RSTART; 1255 1256 stat = envy24ht_rdmt(sc, ENVY24HT_MT_PCTL, 1); 1257 envy24ht_wrmt(sc, ENVY24HT_MT_PCTL, stat | sw, 1); 1258 #if(0) 1259 DELAY(100); 1260 device_printf(sc->dev, "PADDR:0x%08x\n", envy24ht_rdmt(sc, ENVY24HT_MT_PADDR, 4)); 1261 device_printf(sc->dev, "PCNT:%ld\n", envy24ht_rdmt(sc, ENVY24HT_MT_PCNT, 2)); 1262 #endif 1263 1264 return; 1265 } 1266 1267 static void 1268 envy24ht_stop(struct sc_info *sc, int dir) 1269 { 1270 u_int32_t stat, sw; 1271 1272 #if(0) 1273 device_printf(sc->dev, "envy24ht_stop(sc, %d)\n", dir); 1274 #endif 1275 if (dir == PCMDIR_PLAY) 1276 sw = ~ENVY24HT_MT_PCTL_PSTART; 1277 else 1278 sw = ~ENVY24HT_MT_PCTL_RSTART; 1279 1280 stat = envy24ht_rdmt(sc, ENVY24HT_MT_PCTL, 1); 1281 envy24ht_wrmt(sc, ENVY24HT_MT_PCTL, stat & sw, 1); 1282 1283 return; 1284 } 1285 1286 #if 0 1287 static int 1288 envy24ht_route(struct sc_info *sc, int dac, int class, int adc, int rev) 1289 { 1290 return 0; 1291 } 1292 #endif 1293 1294 /* -------------------------------------------------------------------- */ 1295 1296 /* buffer copy routines */ 1297 static void 1298 envy24ht_p32sl(struct sc_chinfo *ch) 1299 { 1300 int length; 1301 sample32_t *dmabuf; 1302 u_int32_t *data; 1303 int src, dst, ssize, dsize, slot; 1304 int i; 1305 1306 length = sndbuf_getready(ch->buffer) / 8; 1307 dmabuf = ch->parent->pbuf; 1308 data = (u_int32_t *)ch->data; 1309 src = sndbuf_getreadyptr(ch->buffer) / 4; 1310 dst = src / 2 + ch->offset; 1311 ssize = ch->size / 4; 1312 dsize = ch->size / 8; 1313 slot = ch->num * 2; 1314 1315 for (i = 0; i < length; i++) { 1316 dmabuf[dst * ENVY24HT_PLAY_CHNUM + slot].buffer = data[src]; 1317 dmabuf[dst * ENVY24HT_PLAY_CHNUM + slot + 1].buffer = data[src + 1]; 1318 dst++; 1319 dst %= dsize; 1320 src += 2; 1321 src %= ssize; 1322 } 1323 1324 return; 1325 } 1326 1327 static void 1328 envy24ht_p16sl(struct sc_chinfo *ch) 1329 { 1330 int length; 1331 sample32_t *dmabuf; 1332 u_int16_t *data; 1333 int src, dst, ssize, dsize, slot; 1334 int i; 1335 1336 #if(0) 1337 device_printf(ch->parent->dev, "envy24ht_p16sl()\n"); 1338 #endif 1339 length = sndbuf_getready(ch->buffer) / 4; 1340 dmabuf = ch->parent->pbuf; 1341 data = (u_int16_t *)ch->data; 1342 src = sndbuf_getreadyptr(ch->buffer) / 2; 1343 dst = src / 2 + ch->offset; 1344 ssize = ch->size / 2; 1345 dsize = ch->size / 4; 1346 slot = ch->num * 2; 1347 #if(0) 1348 device_printf(ch->parent->dev, "envy24ht_p16sl():%lu-->%lu(%lu)\n", src, dst, length); 1349 #endif 1350 1351 for (i = 0; i < length; i++) { 1352 dmabuf[dst * ENVY24HT_PLAY_CHNUM + slot].buffer = (u_int32_t)data[src] << 16; 1353 dmabuf[dst * ENVY24HT_PLAY_CHNUM + slot + 1].buffer = (u_int32_t)data[src + 1] << 16; 1354 #if(0) 1355 if (i < 16) { 1356 printf("%08x", dmabuf[dst * ENVY24HT_PLAY_CHNUM + slot]); 1357 printf("%08x", dmabuf[dst * ENVY24HT_PLAY_CHNUM + slot + 1]); 1358 } 1359 #endif 1360 dst++; 1361 dst %= dsize; 1362 src += 2; 1363 src %= ssize; 1364 } 1365 #if(0) 1366 printf("\n"); 1367 #endif 1368 1369 return; 1370 } 1371 1372 static void 1373 envy24ht_p8u(struct sc_chinfo *ch) 1374 { 1375 int length; 1376 sample32_t *dmabuf; 1377 u_int8_t *data; 1378 int src, dst, ssize, dsize, slot; 1379 int i; 1380 1381 length = sndbuf_getready(ch->buffer) / 2; 1382 dmabuf = ch->parent->pbuf; 1383 data = (u_int8_t *)ch->data; 1384 src = sndbuf_getreadyptr(ch->buffer); 1385 dst = src / 2 + ch->offset; 1386 ssize = ch->size; 1387 dsize = ch->size / 4; 1388 slot = ch->num * 2; 1389 1390 for (i = 0; i < length; i++) { 1391 dmabuf[dst * ENVY24HT_PLAY_CHNUM + slot].buffer = ((u_int32_t)data[src] ^ 0x80) << 24; 1392 dmabuf[dst * ENVY24HT_PLAY_CHNUM + slot + 1].buffer = ((u_int32_t)data[src + 1] ^ 0x80) << 24; 1393 dst++; 1394 dst %= dsize; 1395 src += 2; 1396 src %= ssize; 1397 } 1398 1399 return; 1400 } 1401 1402 static void 1403 envy24ht_r32sl(struct sc_chinfo *ch) 1404 { 1405 int length; 1406 sample32_t *dmabuf; 1407 u_int32_t *data; 1408 int src, dst, ssize, dsize, slot; 1409 int i; 1410 1411 length = sndbuf_getfree(ch->buffer) / 8; 1412 dmabuf = ch->parent->rbuf; 1413 data = (u_int32_t *)ch->data; 1414 dst = sndbuf_getfreeptr(ch->buffer) / 4; 1415 src = dst / 2 + ch->offset; 1416 dsize = ch->size / 4; 1417 ssize = ch->size / 8; 1418 slot = (ch->num - ENVY24HT_CHAN_REC_ADC1) * 2; 1419 1420 for (i = 0; i < length; i++) { 1421 data[dst] = dmabuf[src * ENVY24HT_REC_CHNUM + slot].buffer; 1422 data[dst + 1] = dmabuf[src * ENVY24HT_REC_CHNUM + slot + 1].buffer; 1423 dst += 2; 1424 dst %= dsize; 1425 src++; 1426 src %= ssize; 1427 } 1428 1429 return; 1430 } 1431 1432 static void 1433 envy24ht_r16sl(struct sc_chinfo *ch) 1434 { 1435 int length; 1436 sample32_t *dmabuf; 1437 u_int16_t *data; 1438 int src, dst, ssize, dsize, slot; 1439 int i; 1440 1441 length = sndbuf_getfree(ch->buffer) / 4; 1442 dmabuf = ch->parent->rbuf; 1443 data = (u_int16_t *)ch->data; 1444 dst = sndbuf_getfreeptr(ch->buffer) / 2; 1445 src = dst / 2 + ch->offset; 1446 dsize = ch->size / 2; 1447 ssize = ch->size / 8; 1448 slot = (ch->num - ENVY24HT_CHAN_REC_ADC1) * 2; 1449 1450 for (i = 0; i < length; i++) { 1451 data[dst] = dmabuf[src * ENVY24HT_REC_CHNUM + slot].buffer; 1452 data[dst + 1] = dmabuf[src * ENVY24HT_REC_CHNUM + slot + 1].buffer; 1453 dst += 2; 1454 dst %= dsize; 1455 src++; 1456 src %= ssize; 1457 } 1458 1459 return; 1460 } 1461 1462 /* -------------------------------------------------------------------- */ 1463 1464 /* channel interface */ 1465 static void * 1466 envy24htchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) 1467 { 1468 struct sc_info *sc = (struct sc_info *)devinfo; 1469 struct sc_chinfo *ch; 1470 unsigned num; 1471 1472 #if(0) 1473 device_printf(sc->dev, "envy24htchan_init(obj, devinfo, b, c, %d)\n", dir); 1474 #endif 1475 snd_mtxlock(sc->lock); 1476 #if 0 1477 if ((sc->chnum > ENVY24HT_CHAN_PLAY_SPDIF && dir != PCMDIR_REC) || 1478 (sc->chnum < ENVY24HT_CHAN_REC_ADC1 && dir != PCMDIR_PLAY)) { 1479 snd_mtxunlock(sc->lock); 1480 return NULL; 1481 } 1482 #endif 1483 num = sc->chnum; 1484 1485 ch = &sc->chan[num]; 1486 ch->size = 8 * ENVY24HT_SAMPLE_NUM; 1487 ch->data = malloc(ch->size, M_ENVY24HT, M_NOWAIT); 1488 if (ch->data == NULL) { 1489 ch->size = 0; 1490 ch = NULL; 1491 } 1492 else { 1493 ch->buffer = b; 1494 ch->channel = c; 1495 ch->parent = sc; 1496 ch->dir = dir; 1497 /* set channel map */ 1498 ch->num = envy24ht_chanmap[num]; 1499 snd_mtxunlock(sc->lock); 1500 sndbuf_setup(ch->buffer, ch->data, ch->size); 1501 snd_mtxlock(sc->lock); 1502 /* these 2 values are dummy */ 1503 ch->unit = 4; 1504 ch->blk = 10240; 1505 } 1506 snd_mtxunlock(sc->lock); 1507 1508 return ch; 1509 } 1510 1511 static int 1512 envy24htchan_free(kobj_t obj, void *data) 1513 { 1514 struct sc_chinfo *ch = data; 1515 struct sc_info *sc = ch->parent; 1516 1517 #if(0) 1518 device_printf(sc->dev, "envy24htchan_free()\n"); 1519 #endif 1520 snd_mtxlock(sc->lock); 1521 if (ch->data != NULL) { 1522 free(ch->data, M_ENVY24HT); 1523 ch->data = NULL; 1524 } 1525 snd_mtxunlock(sc->lock); 1526 1527 return 0; 1528 } 1529 1530 static int 1531 envy24htchan_setformat(kobj_t obj, void *data, u_int32_t format) 1532 { 1533 struct sc_chinfo *ch = data; 1534 struct sc_info *sc = ch->parent; 1535 struct envy24ht_emldma *emltab; 1536 /* unsigned int bcnt, bsize; */ 1537 int i; 1538 1539 #if(0) 1540 device_printf(sc->dev, "envy24htchan_setformat(obj, data, 0x%08x)\n", format); 1541 #endif 1542 snd_mtxlock(sc->lock); 1543 /* check and get format related information */ 1544 if (ch->dir == PCMDIR_PLAY) 1545 emltab = envy24ht_pemltab; 1546 else 1547 emltab = envy24ht_remltab; 1548 if (emltab == NULL) { 1549 snd_mtxunlock(sc->lock); 1550 return -1; 1551 } 1552 for (i = 0; emltab[i].format != 0; i++) 1553 if (emltab[i].format == format) 1554 break; 1555 if (emltab[i].format == 0) { 1556 snd_mtxunlock(sc->lock); 1557 return -1; 1558 } 1559 1560 /* set format information */ 1561 ch->format = format; 1562 ch->emldma = emltab[i].emldma; 1563 if (ch->unit > emltab[i].unit) 1564 ch->blk *= ch->unit / emltab[i].unit; 1565 else 1566 ch->blk /= emltab[i].unit / ch->unit; 1567 ch->unit = emltab[i].unit; 1568 1569 /* set channel buffer information */ 1570 ch->size = ch->unit * ENVY24HT_SAMPLE_NUM; 1571 #if 0 1572 if (ch->dir == PCMDIR_PLAY) 1573 bsize = ch->blk * 4 / ENVY24HT_PLAY_BUFUNIT; 1574 else 1575 bsize = ch->blk * 4 / ENVY24HT_REC_BUFUNIT; 1576 bsize *= ch->unit; 1577 bcnt = ch->size / bsize; 1578 sndbuf_resize(ch->buffer, bcnt, bsize); 1579 #endif 1580 snd_mtxunlock(sc->lock); 1581 1582 #if(0) 1583 device_printf(sc->dev, "envy24htchan_setformat(): return 0x%08x\n", 0); 1584 #endif 1585 return 0; 1586 } 1587 1588 /* 1589 IMPLEMENT NOTICE: In this driver, setspeed function only do setting 1590 of speed information value. And real hardware speed setting is done 1591 at start triggered(see envy24htchan_trigger()). So, at this function 1592 is called, any value that ENVY24 can use is able to set. But, at 1593 start triggerd, some other channel is running, and that channel's 1594 speed isn't same with, then trigger function will fail. 1595 */ 1596 static int 1597 envy24htchan_setspeed(kobj_t obj, void *data, u_int32_t speed) 1598 { 1599 struct sc_chinfo *ch = data; 1600 u_int32_t val, prev; 1601 int i; 1602 1603 #if(0) 1604 device_printf(ch->parent->dev, "envy24htchan_setspeed(obj, data, %d)\n", speed); 1605 #endif 1606 prev = 0x7fffffff; 1607 for (i = 0; (val = envy24ht_speed[i]) != 0; i++) { 1608 if (abs(val - speed) < abs(prev - speed)) 1609 prev = val; 1610 else 1611 break; 1612 } 1613 ch->speed = prev; 1614 1615 #if(0) 1616 device_printf(ch->parent->dev, "envy24htchan_setspeed(): return %d\n", ch->speed); 1617 #endif 1618 return ch->speed; 1619 } 1620 1621 static int 1622 envy24htchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) 1623 { 1624 struct sc_chinfo *ch = data; 1625 /* struct sc_info *sc = ch->parent; */ 1626 u_int32_t size, prev; 1627 unsigned int bcnt, bsize; 1628 1629 #if(0) 1630 device_printf(sc->dev, "envy24htchan_setblocksize(obj, data, %d)\n", blocksize); 1631 #endif 1632 prev = 0x7fffffff; 1633 /* snd_mtxlock(sc->lock); */ 1634 for (size = ch->size / 2; size > 0; size /= 2) { 1635 if (abs(size - blocksize) < abs(prev - blocksize)) 1636 prev = size; 1637 else 1638 break; 1639 } 1640 1641 ch->blk = prev / ch->unit; 1642 if (ch->dir == PCMDIR_PLAY) 1643 ch->blk *= ENVY24HT_PLAY_BUFUNIT / 4; 1644 else 1645 ch->blk *= ENVY24HT_REC_BUFUNIT / 4; 1646 /* set channel buffer information */ 1647 /* ch->size = ch->unit * ENVY24HT_SAMPLE_NUM; */ 1648 if (ch->dir == PCMDIR_PLAY) 1649 bsize = ch->blk * 4 / ENVY24HT_PLAY_BUFUNIT; 1650 else 1651 bsize = ch->blk * 4 / ENVY24HT_REC_BUFUNIT; 1652 bsize *= ch->unit; 1653 bcnt = ch->size / bsize; 1654 sndbuf_resize(ch->buffer, bcnt, bsize); 1655 /* snd_mtxunlock(sc->lock); */ 1656 1657 #if(0) 1658 device_printf(sc->dev, "envy24htchan_setblocksize(): return %d\n", prev); 1659 #endif 1660 return prev; 1661 } 1662 1663 /* semantic note: must start at beginning of buffer */ 1664 static int 1665 envy24htchan_trigger(kobj_t obj, void *data, int go) 1666 { 1667 struct sc_chinfo *ch = data; 1668 struct sc_info *sc = ch->parent; 1669 u_int32_t ptr; 1670 int slot; 1671 #if 0 1672 int i; 1673 1674 device_printf(sc->dev, "envy24htchan_trigger(obj, data, %d)\n", go); 1675 #endif 1676 snd_mtxlock(sc->lock); 1677 if (ch->dir == PCMDIR_PLAY) 1678 slot = 0; 1679 else 1680 slot = 1; 1681 switch (go) { 1682 case PCMTRIG_START: 1683 #if(0) 1684 device_printf(sc->dev, "envy24htchan_trigger(): start\n"); 1685 #endif 1686 /* check or set channel speed */ 1687 if (sc->run[0] == 0 && sc->run[1] == 0) { 1688 sc->speed = envy24ht_setspeed(sc, ch->speed); 1689 sc->caps[0].minspeed = sc->caps[0].maxspeed = sc->speed; 1690 sc->caps[1].minspeed = sc->caps[1].maxspeed = sc->speed; 1691 } 1692 else if (ch->speed != 0 && ch->speed != sc->speed) 1693 return -1; 1694 if (ch->speed == 0) 1695 ch->channel->speed = sc->speed; 1696 /* start or enable channel */ 1697 sc->run[slot]++; 1698 if (sc->run[slot] == 1) { 1699 /* first channel */ 1700 ch->offset = 0; 1701 sc->blk[slot] = ch->blk; 1702 } 1703 else { 1704 ptr = envy24ht_gethwptr(sc, ch->dir); 1705 ch->offset = ((ptr / ch->blk + 1) * ch->blk % 1706 (ch->size / 4)) * 4 / ch->unit; 1707 if (ch->blk < sc->blk[slot]) 1708 sc->blk[slot] = ch->blk; 1709 } 1710 if (ch->dir == PCMDIR_PLAY) { 1711 ch->emldma(ch); 1712 envy24ht_setvolume(sc, ch->num); 1713 } 1714 envy24ht_updintr(sc, ch->dir); 1715 if (sc->run[slot] == 1) 1716 envy24ht_start(sc, ch->dir); 1717 ch->run = 1; 1718 break; 1719 case PCMTRIG_EMLDMAWR: 1720 #if(0) 1721 device_printf(sc->dev, "envy24htchan_trigger(): emldmawr\n"); 1722 #endif 1723 if (ch->run != 1) 1724 return -1; 1725 ch->emldma(ch); 1726 break; 1727 case PCMTRIG_EMLDMARD: 1728 #if(0) 1729 device_printf(sc->dev, "envy24htchan_trigger(): emldmard\n"); 1730 #endif 1731 if (ch->run != 1) 1732 return -1; 1733 ch->emldma(ch); 1734 break; 1735 case PCMTRIG_ABORT: 1736 if (ch->run) { 1737 #if(0) 1738 device_printf(sc->dev, "envy24htchan_trigger(): abort\n"); 1739 #endif 1740 ch->run = 0; 1741 sc->run[slot]--; 1742 if (ch->dir == PCMDIR_PLAY) 1743 envy24ht_mutevolume(sc, ch->num); 1744 if (sc->run[slot] == 0) { 1745 envy24ht_stop(sc, ch->dir); 1746 sc->intr[slot] = 0; 1747 } 1748 /* else if (ch->blk == sc->blk[slot]) { 1749 sc->blk[slot] = ENVY24HT_SAMPLE_NUM / 2; 1750 for (i = 0; i < ENVY24HT_CHAN_NUM; i++) { 1751 if (sc->chan[i].dir == ch->dir && 1752 sc->chan[i].run == 1 && 1753 sc->chan[i].blk < sc->blk[slot]) 1754 sc->blk[slot] = sc->chan[i].blk; 1755 } 1756 if (ch->blk != sc->blk[slot]) 1757 envy24ht_updintr(sc, ch->dir); 1758 }*/ 1759 } 1760 break; 1761 } 1762 snd_mtxunlock(sc->lock); 1763 1764 return 0; 1765 } 1766 1767 static int 1768 envy24htchan_getptr(kobj_t obj, void *data) 1769 { 1770 struct sc_chinfo *ch = data; 1771 struct sc_info *sc = ch->parent; 1772 u_int32_t ptr; 1773 int rtn; 1774 1775 #if(0) 1776 device_printf(sc->dev, "envy24htchan_getptr()\n"); 1777 #endif 1778 snd_mtxlock(sc->lock); 1779 ptr = envy24ht_gethwptr(sc, ch->dir); 1780 rtn = ptr * ch->unit; 1781 snd_mtxunlock(sc->lock); 1782 1783 #if(0) 1784 device_printf(sc->dev, "envy24htchan_getptr(): return %d\n", 1785 rtn); 1786 #endif 1787 return rtn; 1788 } 1789 1790 static struct pcmchan_caps * 1791 envy24htchan_getcaps(kobj_t obj, void *data) 1792 { 1793 struct sc_chinfo *ch = data; 1794 struct sc_info *sc = ch->parent; 1795 struct pcmchan_caps *rtn; 1796 1797 #if(0) 1798 device_printf(sc->dev, "envy24htchan_getcaps()\n"); 1799 #endif 1800 snd_mtxlock(sc->lock); 1801 if (ch->dir == PCMDIR_PLAY) { 1802 if (sc->run[0] == 0) 1803 rtn = &envy24ht_playcaps; 1804 else 1805 rtn = &sc->caps[0]; 1806 } 1807 else { 1808 if (sc->run[1] == 0) 1809 rtn = &envy24ht_reccaps; 1810 else 1811 rtn = &sc->caps[1]; 1812 } 1813 snd_mtxunlock(sc->lock); 1814 1815 return rtn; 1816 } 1817 1818 static kobj_method_t envy24htchan_methods[] = { 1819 KOBJMETHOD(channel_init, envy24htchan_init), 1820 KOBJMETHOD(channel_free, envy24htchan_free), 1821 KOBJMETHOD(channel_setformat, envy24htchan_setformat), 1822 KOBJMETHOD(channel_setspeed, envy24htchan_setspeed), 1823 KOBJMETHOD(channel_setblocksize, envy24htchan_setblocksize), 1824 KOBJMETHOD(channel_trigger, envy24htchan_trigger), 1825 KOBJMETHOD(channel_getptr, envy24htchan_getptr), 1826 KOBJMETHOD(channel_getcaps, envy24htchan_getcaps), 1827 { 0, 0 } 1828 }; 1829 CHANNEL_DECLARE(envy24htchan); 1830 1831 /* -------------------------------------------------------------------- */ 1832 1833 /* mixer interface */ 1834 1835 static int 1836 envy24htmixer_init(struct snd_mixer *m) 1837 { 1838 struct sc_info *sc = mix_getdevinfo(m); 1839 1840 #if(0) 1841 device_printf(sc->dev, "envy24htmixer_init()\n"); 1842 #endif 1843 if (sc == NULL) 1844 return -1; 1845 1846 /* set volume control rate */ 1847 snd_mtxlock(sc->lock); 1848 #if 0 1849 envy24ht_wrmt(sc, ENVY24HT_MT_VOLRATE, 0x30, 1); /* 0x30 is default value */ 1850 #endif 1851 1852 pcm_setflags(sc->dev, pcm_getflags(sc->dev) | SD_F_SOFTPCMVOL); 1853 1854 mix_setdevs(m, ENVY24HT_MIX_MASK); 1855 mix_setrecdevs(m, ENVY24HT_MIX_REC_MASK); 1856 1857 snd_mtxunlock(sc->lock); 1858 1859 return 0; 1860 } 1861 1862 static int 1863 envy24htmixer_reinit(struct snd_mixer *m) 1864 { 1865 struct sc_info *sc = mix_getdevinfo(m); 1866 1867 if (sc == NULL) 1868 return -1; 1869 #if(0) 1870 device_printf(sc->dev, "envy24htmixer_reinit()\n"); 1871 #endif 1872 1873 return 0; 1874 } 1875 1876 static int 1877 envy24htmixer_uninit(struct snd_mixer *m) 1878 { 1879 struct sc_info *sc = mix_getdevinfo(m); 1880 1881 if (sc == NULL) 1882 return -1; 1883 #if(0) 1884 device_printf(sc->dev, "envy24htmixer_uninit()\n"); 1885 #endif 1886 1887 return 0; 1888 } 1889 1890 static int 1891 envy24htmixer_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) 1892 { 1893 struct sc_info *sc = mix_getdevinfo(m); 1894 int ch = envy24ht_mixmap[dev]; 1895 int hwch; 1896 int i; 1897 1898 if (sc == NULL) 1899 return -1; 1900 if (dev == 0 && sc->cfg->codec->setvolume == NULL) 1901 return -1; 1902 if (dev != 0 && ch == -1) 1903 return -1; 1904 hwch = envy24ht_chanmap[ch]; 1905 #if(0) 1906 device_printf(sc->dev, "envy24htmixer_set(m, %d, %d, %d)\n", 1907 dev, left, right); 1908 #endif 1909 1910 snd_mtxlock(sc->lock); 1911 if (dev == 0) { 1912 for (i = 0; i < sc->dacn; i++) { 1913 sc->cfg->codec->setvolume(sc->dac[i], PCMDIR_PLAY, left, right); 1914 } 1915 } 1916 else { 1917 /* set volume value for hardware */ 1918 if ((sc->left[hwch] = 100 - left) > ENVY24HT_VOL_MIN) 1919 sc->left[hwch] = ENVY24HT_VOL_MUTE; 1920 if ((sc->right[hwch] = 100 - right) > ENVY24HT_VOL_MIN) 1921 sc->right[hwch] = ENVY24HT_VOL_MUTE; 1922 1923 /* set volume for record channel and running play channel */ 1924 if (hwch > ENVY24HT_CHAN_PLAY_SPDIF || sc->chan[ch].run) 1925 envy24ht_setvolume(sc, hwch); 1926 } 1927 snd_mtxunlock(sc->lock); 1928 1929 return right << 8 | left; 1930 } 1931 1932 static u_int32_t 1933 envy24htmixer_setrecsrc(struct snd_mixer *m, u_int32_t src) 1934 { 1935 struct sc_info *sc = mix_getdevinfo(m); 1936 int ch = envy24ht_mixmap[src]; 1937 #if(0) 1938 device_printf(sc->dev, "envy24htmixer_setrecsrc(m, %d)\n", src); 1939 #endif 1940 1941 if (ch > ENVY24HT_CHAN_PLAY_SPDIF) 1942 sc->src = ch; 1943 return src; 1944 } 1945 1946 static kobj_method_t envy24htmixer_methods[] = { 1947 KOBJMETHOD(mixer_init, envy24htmixer_init), 1948 KOBJMETHOD(mixer_reinit, envy24htmixer_reinit), 1949 KOBJMETHOD(mixer_uninit, envy24htmixer_uninit), 1950 KOBJMETHOD(mixer_set, envy24htmixer_set), 1951 KOBJMETHOD(mixer_setrecsrc, envy24htmixer_setrecsrc), 1952 { 0, 0 } 1953 }; 1954 MIXER_DECLARE(envy24htmixer); 1955 1956 /* -------------------------------------------------------------------- */ 1957 1958 /* The interrupt handler */ 1959 static void 1960 envy24ht_intr(void *p) 1961 { 1962 struct sc_info *sc = (struct sc_info *)p; 1963 struct sc_chinfo *ch; 1964 u_int32_t ptr, dsize, feed; 1965 int i; 1966 1967 #if(0) 1968 device_printf(sc->dev, "envy24ht_intr()\n"); 1969 #endif 1970 snd_mtxlock(sc->lock); 1971 if (envy24ht_checkintr(sc, PCMDIR_PLAY)) { 1972 #if(0) 1973 device_printf(sc->dev, "envy24ht_intr(): play\n"); 1974 #endif 1975 dsize = sc->psize / 4; 1976 ptr = dsize - envy24ht_rdmt(sc, ENVY24HT_MT_PCNT, 2) - 1; 1977 #if(0) 1978 device_printf(sc->dev, "envy24ht_intr(): ptr = %d-->", ptr); 1979 #endif 1980 ptr -= ptr % sc->blk[0]; 1981 feed = (ptr + dsize - sc->intr[0]) % dsize; 1982 #if(0) 1983 printf("%d intr = %d feed = %d\n", ptr, sc->intr[0], feed); 1984 #endif 1985 for (i = ENVY24HT_CHAN_PLAY_DAC1; i <= ENVY24HT_CHAN_PLAY_SPDIF; i++) { 1986 ch = &sc->chan[i]; 1987 #if(0) 1988 if (ch->run) 1989 device_printf(sc->dev, "envy24ht_intr(): chan[%d].blk = %d\n", i, ch->blk); 1990 #endif 1991 if (ch->run && ch->blk <= feed) { 1992 snd_mtxunlock(sc->lock); 1993 chn_intr(ch->channel); 1994 snd_mtxlock(sc->lock); 1995 } 1996 } 1997 sc->intr[0] = ptr; 1998 envy24ht_updintr(sc, PCMDIR_PLAY); 1999 } 2000 if (envy24ht_checkintr(sc, PCMDIR_REC)) { 2001 #if(0) 2002 device_printf(sc->dev, "envy24ht_intr(): rec\n"); 2003 #endif 2004 dsize = sc->rsize / 4; 2005 ptr = dsize - envy24ht_rdmt(sc, ENVY24HT_MT_RCNT, 2) - 1; 2006 ptr -= ptr % sc->blk[1]; 2007 feed = (ptr + dsize - sc->intr[1]) % dsize; 2008 for (i = ENVY24HT_CHAN_REC_ADC1; i <= ENVY24HT_CHAN_REC_SPDIF; i++) { 2009 ch = &sc->chan[i]; 2010 if (ch->run && ch->blk <= feed) { 2011 snd_mtxunlock(sc->lock); 2012 chn_intr(ch->channel); 2013 snd_mtxlock(sc->lock); 2014 } 2015 } 2016 sc->intr[1] = ptr; 2017 envy24ht_updintr(sc, PCMDIR_REC); 2018 } 2019 snd_mtxunlock(sc->lock); 2020 2021 return; 2022 } 2023 2024 /* 2025 * Probe and attach the card 2026 */ 2027 2028 static int 2029 envy24ht_pci_probe(device_t dev) 2030 { 2031 u_int16_t sv, sd; 2032 int i; 2033 2034 #if(0) 2035 printf("envy24ht_pci_probe()\n"); 2036 #endif 2037 if (pci_get_device(dev) == PCID_ENVY24HT && 2038 pci_get_vendor(dev) == PCIV_ENVY24) { 2039 sv = pci_get_subvendor(dev); 2040 sd = pci_get_subdevice(dev); 2041 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++) { 2042 if (cfg_table[i].subvendor == sv && 2043 cfg_table[i].subdevice == sd) { 2044 break; 2045 } 2046 } 2047 device_set_desc(dev, cfg_table[i].name); 2048 #if(0) 2049 printf("envy24ht_pci_probe(): return 0\n"); 2050 #endif 2051 return 0; 2052 } 2053 else { 2054 #if(0) 2055 printf("envy24ht_pci_probe(): return ENXIO\n"); 2056 #endif 2057 return ENXIO; 2058 } 2059 } 2060 2061 static void 2062 envy24ht_dmapsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error) 2063 { 2064 /* struct sc_info *sc = (struct sc_info *)arg; */ 2065 2066 #if(0) 2067 device_printf(sc->dev, "envy24ht_dmapsetmap()\n"); 2068 if (bootverbose) { 2069 printf("envy24ht(play): setmap %lx, %lx; ", 2070 (unsigned long)segs->ds_addr, 2071 (unsigned long)segs->ds_len); 2072 printf("%p -> %lx\n", sc->pmap, (unsigned long)vtophys(sc->pmap)); 2073 } 2074 #endif 2075 } 2076 2077 static void 2078 envy24ht_dmarsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error) 2079 { 2080 /* struct sc_info *sc = (struct sc_info *)arg; */ 2081 2082 #if(0) 2083 device_printf(sc->dev, "envy24ht_dmarsetmap()\n"); 2084 if (bootverbose) { 2085 printf("envy24ht(record): setmap %lx, %lx; ", 2086 (unsigned long)segs->ds_addr, 2087 (unsigned long)segs->ds_len); 2088 printf("%p -> %lx\n", sc->rmap, (unsigned long)vtophys(sc->pmap)); 2089 } 2090 #endif 2091 } 2092 2093 static void 2094 envy24ht_dmafree(struct sc_info *sc) 2095 { 2096 #if(0) 2097 device_printf(sc->dev, "envy24ht_dmafree():"); 2098 if (sc->rmap) printf(" sc->rmap(0x%08x)", (u_int32_t)sc->rmap); 2099 else printf(" sc->rmap(null)"); 2100 if (sc->pmap) printf(" sc->pmap(0x%08x)", (u_int32_t)sc->pmap); 2101 else printf(" sc->pmap(null)"); 2102 if (sc->rbuf) printf(" sc->rbuf(0x%08x)", (u_int32_t)sc->rbuf); 2103 else printf(" sc->rbuf(null)"); 2104 if (sc->pbuf) printf(" sc->pbuf(0x%08x)\n", (u_int32_t)sc->pbuf); 2105 else printf(" sc->pbuf(null)\n"); 2106 #endif 2107 #if(0) 2108 if (sc->rmap) 2109 bus_dmamap_unload(sc->dmat, sc->rmap); 2110 if (sc->pmap) 2111 bus_dmamap_unload(sc->dmat, sc->pmap); 2112 if (sc->rbuf) 2113 bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap); 2114 if (sc->pbuf) 2115 bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap); 2116 #else 2117 bus_dmamap_unload(sc->dmat, sc->rmap); 2118 bus_dmamap_unload(sc->dmat, sc->pmap); 2119 bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap); 2120 bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap); 2121 #endif 2122 2123 sc->rmap = sc->pmap = NULL; 2124 sc->pbuf = NULL; 2125 sc->rbuf = NULL; 2126 2127 return; 2128 } 2129 2130 static int 2131 envy24ht_dmainit(struct sc_info *sc) 2132 { 2133 u_int32_t addr; 2134 2135 #if(0) 2136 device_printf(sc->dev, "envy24ht_dmainit()\n"); 2137 #endif 2138 /* init values */ 2139 sc->psize = ENVY24HT_PLAY_BUFUNIT * ENVY24HT_SAMPLE_NUM; 2140 sc->rsize = ENVY24HT_REC_BUFUNIT * ENVY24HT_SAMPLE_NUM; 2141 sc->pbuf = NULL; 2142 sc->rbuf = NULL; 2143 sc->pmap = sc->rmap = NULL; 2144 sc->blk[0] = sc->blk[1] = 0; 2145 2146 /* allocate DMA buffer */ 2147 #if(0) 2148 device_printf(sc->dev, "envy24ht_dmainit(): bus_dmamem_alloc(): sc->pbuf\n"); 2149 #endif 2150 if (bus_dmamem_alloc(sc->dmat, (void **)&sc->pbuf, BUS_DMA_NOWAIT, &sc->pmap)) 2151 goto bad; 2152 #if(0) 2153 device_printf(sc->dev, "envy24ht_dmainit(): bus_dmamem_alloc(): sc->rbuf\n"); 2154 #endif 2155 if (bus_dmamem_alloc(sc->dmat, (void **)&sc->rbuf, BUS_DMA_NOWAIT, &sc->rmap)) 2156 goto bad; 2157 #if(0) 2158 device_printf(sc->dev, "envy24ht_dmainit(): bus_dmamem_load(): sc->pmap\n"); 2159 #endif 2160 if (bus_dmamap_load(sc->dmat, sc->pmap, sc->pbuf, sc->psize, envy24ht_dmapsetmap, sc, 0)) 2161 goto bad; 2162 #if(0) 2163 device_printf(sc->dev, "envy24ht_dmainit(): bus_dmamem_load(): sc->rmap\n"); 2164 #endif 2165 if (bus_dmamap_load(sc->dmat, sc->rmap, sc->rbuf, sc->rsize, envy24ht_dmarsetmap, sc, 0)) 2166 goto bad; 2167 bzero(sc->pbuf, sc->psize); 2168 bzero(sc->rbuf, sc->rsize); 2169 2170 /* set values to register */ 2171 addr = vtophys(sc->pbuf); 2172 #if(0) 2173 device_printf(sc->dev, "pbuf(0x%08x)\n", addr); 2174 #endif 2175 envy24ht_wrmt(sc, ENVY24HT_MT_PADDR, addr, 4); 2176 #if(0) 2177 device_printf(sc->dev, "PADDR-->(0x%08x)\n", envy24ht_rdmt(sc, ENVY24HT_MT_PADDR, 4)); 2178 device_printf(sc->dev, "psize(%ld)\n", sc->psize / 4 - 1); 2179 #endif 2180 envy24ht_wrmt(sc, ENVY24HT_MT_PCNT, sc->psize / 4 - 1, 2); 2181 #if(0) 2182 device_printf(sc->dev, "PCNT-->(%ld)\n", envy24ht_rdmt(sc, ENVY24HT_MT_PCNT, 2)); 2183 #endif 2184 addr = vtophys(sc->rbuf); 2185 envy24ht_wrmt(sc, ENVY24HT_MT_RADDR, addr, 4); 2186 envy24ht_wrmt(sc, ENVY24HT_MT_RCNT, sc->rsize / 4 - 1, 2); 2187 2188 return 0; 2189 bad: 2190 envy24ht_dmafree(sc); 2191 return ENOSPC; 2192 } 2193 2194 static void 2195 envy24ht_putcfg(struct sc_info *sc) 2196 { 2197 device_printf(sc->dev, "system configuration\n"); 2198 printf(" SubVendorID: 0x%04x, SubDeviceID: 0x%04x\n", 2199 sc->cfg->subvendor, sc->cfg->subdevice); 2200 printf(" XIN2 Clock Source: "); 2201 switch (sc->cfg->scfg & ENVY24HT_CCSM_SCFG_XIN2) { 2202 case 0x00: 2203 printf("24.576MHz(96kHz*256)\n"); 2204 break; 2205 case 0x40: 2206 printf("49.152MHz(192kHz*256)\n"); 2207 break; 2208 case 0x80: 2209 printf("reserved\n"); 2210 break; 2211 default: 2212 printf("illeagal system setting\n"); 2213 } 2214 printf(" MPU-401 UART(s) #: "); 2215 if (sc->cfg->scfg & ENVY24HT_CCSM_SCFG_MPU) 2216 printf("1\n"); 2217 else 2218 printf("not implemented\n"); 2219 switch (sc->adcn) { 2220 case 0x01 || 0x02: 2221 printf(" ADC #: "); 2222 printf("%d\n", sc->adcn); 2223 break; 2224 case 0x03: 2225 printf(" ADC #: "); 2226 printf("%d", 1); 2227 printf(" and SPDIF receiver connected\n"); 2228 break; 2229 default: 2230 printf(" no physical inputs\n"); 2231 } 2232 printf(" DAC #: "); 2233 printf("%d\n", sc->dacn); 2234 printf(" Multi-track converter type: "); 2235 if ((sc->cfg->acl & ENVY24HT_CCSM_ACL_MTC) == 0) { 2236 printf("AC'97(SDATA_OUT:"); 2237 if (sc->cfg->acl & ENVY24HT_CCSM_ACL_OMODE) 2238 printf("packed"); 2239 else 2240 printf("split"); 2241 printf(")\n"); 2242 } 2243 else { 2244 printf("I2S("); 2245 if (sc->cfg->i2s & ENVY24HT_CCSM_I2S_VOL) 2246 printf("with volume, "); 2247 if (sc->cfg->i2s & ENVY24HT_CCSM_I2S_192KHZ) 2248 printf("192KHz support, "); 2249 else 2250 if (sc->cfg->i2s & ENVY24HT_CCSM_I2S_96KHZ) 2251 printf("192KHz support, "); 2252 else 2253 printf("48KHz support, "); 2254 switch (sc->cfg->i2s & ENVY24HT_CCSM_I2S_RES) { 2255 case ENVY24HT_CCSM_I2S_16BIT: 2256 printf("16bit resolution, "); 2257 break; 2258 case ENVY24HT_CCSM_I2S_18BIT: 2259 printf("18bit resolution, "); 2260 break; 2261 case ENVY24HT_CCSM_I2S_20BIT: 2262 printf("20bit resolution, "); 2263 break; 2264 case ENVY24HT_CCSM_I2S_24BIT: 2265 printf("24bit resolution, "); 2266 break; 2267 } 2268 printf("ID#0x%x)\n", sc->cfg->i2s & ENVY24HT_CCSM_I2S_ID); 2269 } 2270 printf(" S/PDIF(IN/OUT): "); 2271 if (sc->cfg->spdif & ENVY24HT_CCSM_SPDIF_IN) 2272 printf("1/"); 2273 else 2274 printf("0/"); 2275 if (sc->cfg->spdif & ENVY24HT_CCSM_SPDIF_OUT) 2276 printf("1 "); 2277 else 2278 printf("0 "); 2279 if (sc->cfg->spdif & (ENVY24HT_CCSM_SPDIF_IN | ENVY24HT_CCSM_SPDIF_OUT)) 2280 printf("ID# 0x%02x\n", (sc->cfg->spdif & ENVY24HT_CCSM_SPDIF_ID) >> 2); 2281 printf(" GPIO(mask/dir/state): 0x%02x/0x%02x/0x%02x\n", 2282 sc->cfg->gpiomask, sc->cfg->gpiodir, sc->cfg->gpiostate); 2283 } 2284 2285 static int 2286 envy24ht_init(struct sc_info *sc) 2287 { 2288 u_int32_t data; 2289 #if(0) 2290 int rtn; 2291 #endif 2292 int i; 2293 u_int32_t sv, sd; 2294 2295 2296 #if(0) 2297 device_printf(sc->dev, "envy24ht_init()\n"); 2298 #endif 2299 2300 /* reset chip */ 2301 #if 0 2302 envy24ht_wrcs(sc, ENVY24HT_CCS_CTL, ENVY24HT_CCS_CTL_RESET, 1); 2303 DELAY(200); 2304 envy24ht_wrcs(sc, ENVY24HT_CCS_CTL, ENVY24HT_CCS_CTL_NATIVE, 1); 2305 DELAY(200); 2306 2307 /* legacy hardware disable */ 2308 data = pci_read_config(sc->dev, PCIR_LAC, 2); 2309 data |= PCIM_LAC_DISABLE; 2310 pci_write_config(sc->dev, PCIR_LAC, data, 2); 2311 #endif 2312 2313 /* check system configuration */ 2314 sc->cfg = NULL; 2315 for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++) { 2316 /* 1st: search configuration from table */ 2317 sv = pci_get_subvendor(sc->dev); 2318 sd = pci_get_subdevice(sc->dev); 2319 if (sv == cfg_table[i].subvendor && sd == cfg_table[i].subdevice) { 2320 #if(0) 2321 device_printf(sc->dev, "Set configuration from table\n"); 2322 #endif 2323 sc->cfg = &cfg_table[i]; 2324 break; 2325 } 2326 } 2327 if (sc->cfg == NULL) { 2328 /* 2nd: read configuration from table */ 2329 sc->cfg = envy24ht_rom2cfg(sc); 2330 } 2331 sc->adcn = ((sc->cfg->scfg & ENVY24HT_CCSM_SCFG_ADC) >> 2) + 1; /* need to be fixed */ 2332 sc->dacn = (sc->cfg->scfg & ENVY24HT_CCSM_SCFG_DAC) + 1; 2333 2334 if (1 /* bootverbose */) { 2335 envy24ht_putcfg(sc); 2336 } 2337 2338 /* set system configuration */ 2339 envy24ht_wrcs(sc, ENVY24HT_CCS_SCFG, sc->cfg->scfg, 1); 2340 envy24ht_wrcs(sc, ENVY24HT_CCS_ACL, sc->cfg->acl, 1); 2341 envy24ht_wrcs(sc, ENVY24HT_CCS_I2S, sc->cfg->i2s, 1); 2342 envy24ht_wrcs(sc, ENVY24HT_CCS_SPDIF, sc->cfg->spdif, 1); 2343 envy24ht_gpiosetmask(sc, sc->cfg->gpiomask); 2344 envy24ht_gpiosetdir(sc, sc->cfg->gpiodir); 2345 envy24ht_gpiowr(sc, sc->cfg->gpiostate); 2346 2347 if ((sc->cfg->subvendor == 0x3031) && (sc->cfg->subdevice == 0x4553)) { 2348 envy24ht_wri2c(sc, 0x22, 0x00, 0x07); 2349 envy24ht_wri2c(sc, 0x22, 0x04, 0x5f | 0x80); 2350 envy24ht_wri2c(sc, 0x22, 0x05, 0x5f | 0x80); 2351 } 2352 2353 for (i = 0; i < sc->adcn; i++) { 2354 sc->adc[i] = sc->cfg->codec->create(sc->dev, sc, PCMDIR_REC, i); 2355 sc->cfg->codec->init(sc->adc[i]); 2356 } 2357 for (i = 0; i < sc->dacn; i++) { 2358 sc->dac[i] = sc->cfg->codec->create(sc->dev, sc, PCMDIR_PLAY, i); 2359 sc->cfg->codec->init(sc->dac[i]); 2360 } 2361 2362 /* initialize DMA buffer */ 2363 #if(0) 2364 device_printf(sc->dev, "envy24ht_init(): initialize DMA buffer\n"); 2365 #endif 2366 if (envy24ht_dmainit(sc)) 2367 return ENOSPC; 2368 2369 /* initialize status */ 2370 sc->run[0] = sc->run[1] = 0; 2371 sc->intr[0] = sc->intr[1] = 0; 2372 sc->speed = 0; 2373 sc->caps[0].fmtlist = envy24ht_playfmt; 2374 sc->caps[1].fmtlist = envy24ht_recfmt; 2375 2376 /* set channel router */ 2377 #if 0 2378 envy24ht_route(sc, ENVY24HT_ROUTE_DAC_1, ENVY24HT_ROUTE_CLASS_MIX, 0, 0); 2379 envy24ht_route(sc, ENVY24HT_ROUTE_DAC_SPDIF, ENVY24HT_ROUTE_CLASS_DMA, 0, 0); 2380 envy24ht_route(sc, ENVY24HT_ROUTE_DAC_SPDIF, ENVY24HT_ROUTE_CLASS_MIX, 0, 0); 2381 #endif 2382 2383 /* set macro interrupt mask */ 2384 data = envy24ht_rdcs(sc, ENVY24HT_CCS_IMASK, 1); 2385 envy24ht_wrcs(sc, ENVY24HT_CCS_IMASK, data & ~ENVY24HT_CCS_IMASK_PMT, 1); 2386 data = envy24ht_rdcs(sc, ENVY24HT_CCS_IMASK, 1); 2387 #if(0) 2388 device_printf(sc->dev, "envy24ht_init(): CCS_IMASK-->0x%02x\n", data); 2389 #endif 2390 2391 return 0; 2392 } 2393 2394 static int 2395 envy24ht_alloc_resource(struct sc_info *sc) 2396 { 2397 /* allocate I/O port resource */ 2398 sc->csid = PCIR_CCS; 2399 sc->cs = bus_alloc_resource(sc->dev, SYS_RES_IOPORT, 2400 &sc->csid, 0, ~0, 1, RF_ACTIVE); 2401 sc->mtid = ENVY24HT_PCIR_MT; 2402 sc->mt = bus_alloc_resource(sc->dev, SYS_RES_IOPORT, 2403 &sc->mtid, 0, ~0, 1, RF_ACTIVE); 2404 if (!sc->cs || !sc->mt) { 2405 device_printf(sc->dev, "unable to map IO port space\n"); 2406 return ENXIO; 2407 } 2408 sc->cst = rman_get_bustag(sc->cs); 2409 sc->csh = rman_get_bushandle(sc->cs); 2410 sc->mtt = rman_get_bustag(sc->mt); 2411 sc->mth = rman_get_bushandle(sc->mt); 2412 #if(0) 2413 device_printf(sc->dev, 2414 "IO port register values\nCCS: 0x%lx\nMT: 0x%lx\n", 2415 pci_read_config(sc->dev, PCIR_CCS, 4), 2416 pci_read_config(sc->dev, PCIR_MT, 4)); 2417 #endif 2418 2419 /* allocate interrupt resource */ 2420 sc->irqid = 0; 2421 sc->irq = bus_alloc_resource(sc->dev, SYS_RES_IRQ, &sc->irqid, 2422 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); 2423 if (!sc->irq || 2424 snd_setup_intr(sc->dev, sc->irq, 0, envy24ht_intr, sc, &sc->ih)) { 2425 device_printf(sc->dev, "unable to map interrupt\n"); 2426 return ENXIO; 2427 } 2428 2429 /* allocate DMA resource */ 2430 if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(sc->dev), 2431 /*alignment*/4, 2432 /*boundary*/0, 2433 /*lowaddr*/BUS_SPACE_MAXADDR_ENVY24, 2434 /*highaddr*/BUS_SPACE_MAXADDR_ENVY24, 2435 /*filter*/NULL, /*filterarg*/NULL, 2436 /*maxsize*/BUS_SPACE_MAXSIZE_ENVY24, 2437 /*nsegments*/1, /*maxsegsz*/0x3ffff, 2438 /*flags*/0, /*lockfunc*/busdma_lock_mutex, 2439 /*lockarg*/&Giant, &sc->dmat) != 0) { 2440 device_printf(sc->dev, "unable to create dma tag\n"); 2441 return ENXIO; 2442 } 2443 2444 return 0; 2445 } 2446 2447 static int 2448 envy24ht_pci_attach(device_t dev) 2449 { 2450 u_int32_t data; 2451 struct sc_info *sc; 2452 char status[SND_STATUSLEN]; 2453 int err = 0; 2454 int i; 2455 2456 #if(0) 2457 device_printf(dev, "envy24ht_pci_attach()\n"); 2458 #endif 2459 /* get sc_info data area */ 2460 if ((sc = malloc(sizeof(*sc), M_ENVY24HT, M_NOWAIT)) == NULL) { 2461 device_printf(dev, "cannot allocate softc\n"); 2462 return ENXIO; 2463 } 2464 2465 bzero(sc, sizeof(*sc)); 2466 sc->lock = snd_mtxcreate(device_get_nameunit(dev), 2467 "snd_envy24ht softc"); 2468 sc->dev = dev; 2469 2470 /* initialize PCI interface */ 2471 data = pci_read_config(dev, PCIR_COMMAND, 2); 2472 data |= (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN); 2473 pci_write_config(dev, PCIR_COMMAND, data, 2); 2474 data = pci_read_config(dev, PCIR_COMMAND, 2); 2475 2476 /* allocate resources */ 2477 err = envy24ht_alloc_resource(sc); 2478 if (err) { 2479 device_printf(dev, "unable to allocate system resources\n"); 2480 goto bad; 2481 } 2482 2483 /* initialize card */ 2484 err = envy24ht_init(sc); 2485 if (err) { 2486 device_printf(dev, "unable to initialize the card\n"); 2487 goto bad; 2488 } 2489 2490 /* set multi track mixer */ 2491 mixer_init(dev, &envy24htmixer_class, sc); 2492 2493 /* set channel information */ 2494 /* err = pcm_register(dev, sc, 5, 2 + sc->adcn); */ 2495 err = pcm_register(dev, sc, 1, 2 + sc->adcn); 2496 if (err) 2497 goto bad; 2498 sc->chnum = 0; 2499 /* for (i = 0; i < 5; i++) { */ 2500 pcm_addchan(dev, PCMDIR_PLAY, &envy24htchan_class, sc); 2501 sc->chnum++; 2502 /* } */ 2503 for (i = 0; i < 2 + sc->adcn; i++) { 2504 pcm_addchan(dev, PCMDIR_REC, &envy24htchan_class, sc); 2505 sc->chnum++; 2506 } 2507 2508 /* set status iformation */ 2509 snprintf(status, SND_STATUSLEN, 2510 "at io 0x%lx:%ld,0x%lx:%ld irq %ld", 2511 rman_get_start(sc->cs), 2512 rman_get_end(sc->cs) - rman_get_start(sc->cs) + 1, 2513 rman_get_start(sc->mt), 2514 rman_get_end(sc->mt) - rman_get_start(sc->mt) + 1, 2515 rman_get_start(sc->irq)); 2516 pcm_setstatus(dev, status); 2517 2518 return 0; 2519 2520 bad: 2521 if (sc->ih) 2522 bus_teardown_intr(dev, sc->irq, sc->ih); 2523 if (sc->irq) 2524 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); 2525 envy24ht_dmafree(sc); 2526 if (sc->dmat) 2527 bus_dma_tag_destroy(sc->dmat); 2528 if (sc->cfg->codec->destroy != NULL) { 2529 for (i = 0; i < sc->adcn; i++) 2530 sc->cfg->codec->destroy(sc->adc[i]); 2531 for (i = 0; i < sc->dacn; i++) 2532 sc->cfg->codec->destroy(sc->dac[i]); 2533 } 2534 envy24ht_cfgfree(sc->cfg); 2535 if (sc->cs) 2536 bus_release_resource(dev, SYS_RES_IOPORT, sc->csid, sc->cs); 2537 if (sc->mt) 2538 bus_release_resource(dev, SYS_RES_IOPORT, sc->mtid, sc->mt); 2539 if (sc->lock) 2540 snd_mtxfree(sc->lock); 2541 free(sc, M_ENVY24HT); 2542 return err; 2543 } 2544 2545 static int 2546 envy24ht_pci_detach(device_t dev) 2547 { 2548 struct sc_info *sc; 2549 int r; 2550 int i; 2551 2552 #if(0) 2553 device_printf(dev, "envy24ht_pci_detach()\n"); 2554 #endif 2555 sc = pcm_getdevinfo(dev); 2556 if (sc == NULL) 2557 return 0; 2558 r = pcm_unregister(dev); 2559 if (r) 2560 return r; 2561 2562 envy24ht_dmafree(sc); 2563 if (sc->cfg->codec->destroy != NULL) { 2564 for (i = 0; i < sc->adcn; i++) 2565 sc->cfg->codec->destroy(sc->adc[i]); 2566 for (i = 0; i < sc->dacn; i++) 2567 sc->cfg->codec->destroy(sc->dac[i]); 2568 } 2569 envy24ht_cfgfree(sc->cfg); 2570 bus_dma_tag_destroy(sc->dmat); 2571 bus_teardown_intr(dev, sc->irq, sc->ih); 2572 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); 2573 bus_release_resource(dev, SYS_RES_IOPORT, sc->csid, sc->cs); 2574 bus_release_resource(dev, SYS_RES_IOPORT, sc->mtid, sc->mt); 2575 snd_mtxfree(sc->lock); 2576 free(sc, M_ENVY24HT); 2577 return 0; 2578 } 2579 2580 static device_method_t envy24ht_methods[] = { 2581 /* Device interface */ 2582 DEVMETHOD(device_probe, envy24ht_pci_probe), 2583 DEVMETHOD(device_attach, envy24ht_pci_attach), 2584 DEVMETHOD(device_detach, envy24ht_pci_detach), 2585 { 0, 0 } 2586 }; 2587 2588 static driver_t envy24ht_driver = { 2589 "pcm", 2590 envy24ht_methods, 2591 #if __FreeBSD_version > 500000 2592 PCM_SOFTC_SIZE, 2593 #else 2594 sizeof(struct snddev_info), 2595 #endif 2596 }; 2597 2598 DRIVER_MODULE(snd_envy24ht, pci, envy24ht_driver, pcm_devclass, 0, 0); 2599 MODULE_DEPEND(snd_envy24ht, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 2600 MODULE_DEPEND(snd_envy24ht, snd_spicds, 1, 1, 1); 2601 MODULE_VERSION(snd_envy24ht, 1); 2602