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