1 /*- 2 * Copyright (c) 2000 Taku YAMAMOTO <taku@cent.saitama-u.ac.jp> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $Id: maestro.c,v 1.12 2000/09/06 03:32:34 taku Exp $ 27 * $FreeBSD: src/sys/dev/sound/pci/maestro.c,v 1.2.2.5 2002/04/22 15:49:32 cg Exp $ 28 * $DragonFly: src/sys/dev/sound/pci/maestro.c,v 1.5 2005/06/10 23:06:59 dillon Exp $ 29 */ 30 31 /* 32 * Credits: 33 * 34 * Part of this code (especially in many magic numbers) was heavily inspired 35 * by the Linux driver originally written by 36 * Alan Cox <alan.cox@linux.org>, modified heavily by 37 * Zach Brown <zab@zabbo.net>. 38 * 39 * busdma()-ize and buffer size reduction were suggested by 40 * Cameron Grant <gandalf@vilnya.demon.co.uk>. 41 * Also he showed me the way to use busdma() suite. 42 * 43 * Internal speaker problems on NEC VersaPro's and Dell Inspiron 7500 44 * were looked at by 45 * Munehiro Matsuda <haro@tk.kubota.co.jp>, 46 * who brought patches based on the Linux driver with some simplification. 47 */ 48 49 #include <dev/sound/pcm/sound.h> 50 #include <dev/sound/pcm/ac97.h> 51 #include <bus/pci/pcireg.h> 52 #include <bus/pci/pcivar.h> 53 54 #include <dev/sound/pci/maestro_reg.h> 55 56 SND_DECLARE_FILE("$DragonFly: src/sys/dev/sound/pci/maestro.c,v 1.5 2005/06/10 23:06:59 dillon Exp $"); 57 58 #define inline __inline 59 60 /* 61 * PCI IDs of supported chips: 62 * 63 * MAESTRO-1 0x01001285 64 * MAESTRO-2 0x1968125d 65 * MAESTRO-2E 0x1978125d 66 */ 67 68 #define MAESTRO_1_PCI_ID 0x01001285 69 #define MAESTRO_2_PCI_ID 0x1968125d 70 #define MAESTRO_2E_PCI_ID 0x1978125d 71 72 #define NEC_SUBID1 0x80581033 /* Taken from Linux driver */ 73 #define NEC_SUBID2 0x803c1033 /* NEC VersaProNX VA26D */ 74 75 #ifndef AGG_MAXPLAYCH 76 # define AGG_MAXPLAYCH 4 77 #endif 78 79 #define AGG_DEFAULT_BUFSZ 0x4000 /* 0x1000, but gets underflows */ 80 81 82 /* ----------------------------- 83 * Data structures. 84 */ 85 struct agg_chinfo { 86 struct agg_info *parent; 87 struct pcm_channel *channel; 88 struct snd_dbuf *buffer; 89 bus_addr_t offset; 90 u_int32_t blocksize; 91 u_int32_t speed; 92 int dir; 93 u_int num; 94 u_int16_t aputype; 95 u_int16_t wcreg_tpl; 96 }; 97 98 struct agg_info { 99 device_t dev; 100 struct resource *reg; 101 int regid; 102 103 bus_space_tag_t st; 104 bus_space_handle_t sh; 105 bus_dma_tag_t parent_dmat; 106 107 struct resource *irq; 108 int irqid; 109 void *ih; 110 111 u_int8_t *stat; 112 bus_addr_t baseaddr; 113 114 struct ac97_info *codec; 115 void *lock; 116 117 unsigned int bufsz; 118 u_int playchns, active; 119 struct agg_chinfo pch[AGG_MAXPLAYCH]; 120 struct agg_chinfo rch; 121 }; 122 123 static inline void ringbus_setdest(struct agg_info*, int, int); 124 125 static inline u_int16_t wp_rdreg(struct agg_info*, u_int16_t); 126 static inline void wp_wrreg(struct agg_info*, u_int16_t, u_int16_t); 127 static inline u_int16_t wp_rdapu(struct agg_info*, int, u_int16_t); 128 static inline void wp_wrapu(struct agg_info*, int, u_int16_t, u_int16_t); 129 static inline void wp_settimer(struct agg_info*, u_int); 130 static inline void wp_starttimer(struct agg_info*); 131 static inline void wp_stoptimer(struct agg_info*); 132 133 static inline u_int16_t wc_rdreg(struct agg_info*, u_int16_t); 134 static inline void wc_wrreg(struct agg_info*, u_int16_t, u_int16_t); 135 static inline u_int16_t wc_rdchctl(struct agg_info*, int); 136 static inline void wc_wrchctl(struct agg_info*, int, u_int16_t); 137 138 static inline void agg_power(struct agg_info*, int); 139 140 static void agg_init(struct agg_info*); 141 142 static void aggch_start_dac(struct agg_chinfo*); 143 static void aggch_stop_dac(struct agg_chinfo*); 144 145 static inline void suppress_jitter(struct agg_chinfo*); 146 147 static inline u_int calc_timer_freq(struct agg_chinfo*); 148 static void set_timer(struct agg_info*); 149 150 static void agg_intr(void *); 151 static int agg_probe(device_t); 152 static int agg_attach(device_t); 153 static int agg_detach(device_t); 154 static int agg_suspend(device_t); 155 static int agg_resume(device_t); 156 static int agg_shutdown(device_t); 157 158 static void *dma_malloc(struct agg_info*, u_int32_t, bus_addr_t*); 159 static void dma_free(struct agg_info*, void *); 160 161 /* ----------------------------- 162 * Subsystems. 163 */ 164 165 /* Codec/Ringbus */ 166 167 /* -------------------------------------------------------------------- */ 168 169 static u_int32_t 170 agg_ac97_init(kobj_t obj, void *sc) 171 { 172 struct agg_info *ess = sc; 173 174 return (bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) & CODEC_STAT_MASK)? 0 : 1; 175 } 176 177 static int 178 agg_rdcodec(kobj_t obj, void *sc, int regno) 179 { 180 struct agg_info *ess = sc; 181 unsigned t; 182 183 /* We have to wait for a SAFE time to write addr/data */ 184 for (t = 0; t < 20; t++) { 185 if ((bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) 186 & CODEC_STAT_MASK) != CODEC_STAT_PROGLESS) 187 break; 188 DELAY(2); /* 20.8us / 13 */ 189 } 190 if (t == 20) 191 device_printf(ess->dev, "agg_rdcodec() PROGLESS timed out.\n"); 192 193 bus_space_write_1(ess->st, ess->sh, PORT_CODEC_CMD, 194 CODEC_CMD_READ | regno); 195 DELAY(21); /* AC97 cycle = 20.8usec */ 196 197 /* Wait for data retrieve */ 198 for (t = 0; t < 20; t++) { 199 if ((bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) 200 & CODEC_STAT_MASK) == CODEC_STAT_RW_DONE) 201 break; 202 DELAY(2); /* 20.8us / 13 */ 203 } 204 if (t == 20) 205 /* Timed out, but perform dummy read. */ 206 device_printf(ess->dev, "agg_rdcodec() RW_DONE timed out.\n"); 207 208 return bus_space_read_2(ess->st, ess->sh, PORT_CODEC_REG); 209 } 210 211 static int 212 agg_wrcodec(kobj_t obj, void *sc, int regno, u_int32_t data) 213 { 214 unsigned t; 215 struct agg_info *ess = sc; 216 217 /* We have to wait for a SAFE time to write addr/data */ 218 for (t = 0; t < 20; t++) { 219 if ((bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) 220 & CODEC_STAT_MASK) != CODEC_STAT_PROGLESS) 221 break; 222 DELAY(2); /* 20.8us / 13 */ 223 } 224 if (t == 20) { 225 /* Timed out. Abort writing. */ 226 device_printf(ess->dev, "agg_wrcodec() PROGLESS timed out.\n"); 227 return -1; 228 } 229 230 bus_space_write_2(ess->st, ess->sh, PORT_CODEC_REG, data); 231 bus_space_write_1(ess->st, ess->sh, PORT_CODEC_CMD, 232 CODEC_CMD_WRITE | regno); 233 234 return 0; 235 } 236 237 static kobj_method_t agg_ac97_methods[] = { 238 KOBJMETHOD(ac97_init, agg_ac97_init), 239 KOBJMETHOD(ac97_read, agg_rdcodec), 240 KOBJMETHOD(ac97_write, agg_wrcodec), 241 { 0, 0 } 242 }; 243 AC97_DECLARE(agg_ac97); 244 245 /* -------------------------------------------------------------------- */ 246 247 static inline void 248 ringbus_setdest(struct agg_info *ess, int src, int dest) 249 { 250 u_int32_t data; 251 252 data = bus_space_read_4(ess->st, ess->sh, PORT_RINGBUS_CTRL); 253 data &= ~(0xfU << src); 254 data |= (0xfU & dest) << src; 255 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, data); 256 } 257 258 /* Wave Processor */ 259 260 static inline u_int16_t 261 wp_rdreg(struct agg_info *ess, u_int16_t reg) 262 { 263 bus_space_write_2(ess->st, ess->sh, PORT_DSP_INDEX, reg); 264 return bus_space_read_2(ess->st, ess->sh, PORT_DSP_DATA); 265 } 266 267 static inline void 268 wp_wrreg(struct agg_info *ess, u_int16_t reg, u_int16_t data) 269 { 270 bus_space_write_2(ess->st, ess->sh, PORT_DSP_INDEX, reg); 271 bus_space_write_2(ess->st, ess->sh, PORT_DSP_DATA, data); 272 } 273 274 static inline void 275 apu_setindex(struct agg_info *ess, u_int16_t reg) 276 { 277 int t; 278 279 wp_wrreg(ess, WPREG_CRAM_PTR, reg); 280 /* Sometimes WP fails to set apu register index. */ 281 for (t = 0; t < 1000; t++) { 282 if (bus_space_read_2(ess->st, ess->sh, PORT_DSP_DATA) == reg) 283 break; 284 bus_space_write_2(ess->st, ess->sh, PORT_DSP_DATA, reg); 285 } 286 if (t == 1000) 287 device_printf(ess->dev, "apu_setindex() timed out.\n"); 288 } 289 290 static inline u_int16_t 291 wp_rdapu(struct agg_info *ess, int ch, u_int16_t reg) 292 { 293 u_int16_t ret; 294 295 apu_setindex(ess, ((unsigned)ch << 4) + reg); 296 ret = wp_rdreg(ess, WPREG_DATA_PORT); 297 return ret; 298 } 299 300 static inline void 301 wp_wrapu(struct agg_info *ess, int ch, u_int16_t reg, u_int16_t data) 302 { 303 int t; 304 305 apu_setindex(ess, ((unsigned)ch << 4) + reg); 306 wp_wrreg(ess, WPREG_DATA_PORT, data); 307 for (t = 0; t < 1000; t++) { 308 if (bus_space_read_2(ess->st, ess->sh, PORT_DSP_DATA) == data) 309 break; 310 bus_space_write_2(ess->st, ess->sh, PORT_DSP_DATA, data); 311 } 312 if (t == 1000) 313 device_printf(ess->dev, "wp_wrapu() timed out.\n"); 314 } 315 316 static inline void 317 wp_settimer(struct agg_info *ess, u_int freq) 318 { 319 u_int clock = 48000 << 2; 320 u_int prescale = 0, divide = (freq != 0) ? (clock / freq) : ~0; 321 322 RANGE(divide, 4, 32 << 8); 323 324 for (; divide > 32 << 1; divide >>= 1) 325 prescale++; 326 divide = (divide + 1) >> 1; 327 328 for (; prescale < 7 && divide > 2 && !(divide & 1); divide >>= 1) 329 prescale++; 330 331 wp_wrreg(ess, WPREG_TIMER_ENABLE, 0); 332 wp_wrreg(ess, WPREG_TIMER_FREQ, 333 (prescale << WP_TIMER_FREQ_PRESCALE_SHIFT) | (divide - 1)); 334 wp_wrreg(ess, WPREG_TIMER_ENABLE, 1); 335 } 336 337 static inline void 338 wp_starttimer(struct agg_info *ess) 339 { 340 wp_wrreg(ess, WPREG_TIMER_START, 1); 341 } 342 343 static inline void 344 wp_stoptimer(struct agg_info *ess) 345 { 346 wp_wrreg(ess, WPREG_TIMER_START, 0); 347 bus_space_write_2(ess->st, ess->sh, PORT_INT_STAT, 1); 348 } 349 350 /* WaveCache */ 351 352 static inline u_int16_t 353 wc_rdreg(struct agg_info *ess, u_int16_t reg) 354 { 355 bus_space_write_2(ess->st, ess->sh, PORT_WAVCACHE_INDEX, reg); 356 return bus_space_read_2(ess->st, ess->sh, PORT_WAVCACHE_DATA); 357 } 358 359 static inline void 360 wc_wrreg(struct agg_info *ess, u_int16_t reg, u_int16_t data) 361 { 362 bus_space_write_2(ess->st, ess->sh, PORT_WAVCACHE_INDEX, reg); 363 bus_space_write_2(ess->st, ess->sh, PORT_WAVCACHE_DATA, data); 364 } 365 366 static inline u_int16_t 367 wc_rdchctl(struct agg_info *ess, int ch) 368 { 369 return wc_rdreg(ess, ch << 3); 370 } 371 372 static inline void 373 wc_wrchctl(struct agg_info *ess, int ch, u_int16_t data) 374 { 375 wc_wrreg(ess, ch << 3, data); 376 } 377 378 /* Power management */ 379 380 static inline void 381 agg_power(struct agg_info *ess, int status) 382 { 383 u_int8_t data; 384 385 data = pci_read_config(ess->dev, CONF_PM_PTR, 1); 386 if (pci_read_config(ess->dev, data, 1) == PPMI_CID) 387 pci_write_config(ess->dev, data + PM_CTRL, status, 1); 388 } 389 390 391 /* ----------------------------- 392 * Controller. 393 */ 394 395 static inline void 396 agg_initcodec(struct agg_info* ess) 397 { 398 u_int16_t data; 399 400 if (bus_space_read_4(ess->st, ess->sh, PORT_RINGBUS_CTRL) 401 & RINGBUS_CTRL_ACLINK_ENABLED) { 402 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 0); 403 DELAY(104); /* 20.8us * (4 + 1) */ 404 } 405 /* XXX - 2nd codec should be looked at. */ 406 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 407 RINGBUS_CTRL_AC97_SWRESET); 408 DELAY(2); 409 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 410 RINGBUS_CTRL_ACLINK_ENABLED); 411 DELAY(21); 412 413 agg_rdcodec(NULL, ess, 0); 414 if (bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) 415 & CODEC_STAT_MASK) { 416 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 0); 417 DELAY(21); 418 419 /* Try cold reset. */ 420 device_printf(ess->dev, "will perform cold reset.\n"); 421 data = bus_space_read_2(ess->st, ess->sh, PORT_GPIO_DIR); 422 if (pci_read_config(ess->dev, 0x58, 2) & 1) 423 data |= 0x10; 424 data |= 0x009 & 425 ~bus_space_read_2(ess->st, ess->sh, PORT_GPIO_DATA); 426 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_MASK, 0xff6); 427 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DIR, 428 data | 0x009); 429 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 0x000); 430 DELAY(2); 431 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 0x001); 432 DELAY(1); 433 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 0x009); 434 DELAY(500000); 435 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DIR, data); 436 DELAY(84); /* 20.8us * 4 */ 437 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 438 RINGBUS_CTRL_ACLINK_ENABLED); 439 DELAY(21); 440 } 441 } 442 443 static void 444 agg_init(struct agg_info* ess) 445 { 446 u_int32_t data; 447 448 /* Setup PCI config registers. */ 449 450 /* Disable all legacy emulations. */ 451 data = pci_read_config(ess->dev, CONF_LEGACY, 2); 452 data |= LEGACY_DISABLED; 453 pci_write_config(ess->dev, CONF_LEGACY, data, 2); 454 455 /* Disconnect from CHI. (Makes Dell inspiron 7500 work?) 456 * Enable posted write. 457 * Prefer PCI timing rather than that of ISA. 458 * Don't swap L/R. */ 459 data = pci_read_config(ess->dev, CONF_MAESTRO, 4); 460 data |= MAESTRO_CHIBUS | MAESTRO_POSTEDWRITE | MAESTRO_DMA_PCITIMING; 461 data &= ~MAESTRO_SWAP_LR; 462 pci_write_config(ess->dev, CONF_MAESTRO, data, 4); 463 464 /* Reset direct sound. */ 465 bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 466 HOSTINT_CTRL_DSOUND_RESET); 467 DELAY(10000); /* XXX - too long? */ 468 bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 0); 469 DELAY(10000); 470 471 /* Enable direct sound interruption and hardware volume control. */ 472 bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 473 HOSTINT_CTRL_DSOUND_INT_ENABLED | HOSTINT_CTRL_HWVOL_ENABLED); 474 475 /* Setup Wave Processor. */ 476 477 /* Enable WaveCache, set DMA base address. */ 478 wp_wrreg(ess, WPREG_WAVE_ROMRAM, 479 WP_WAVE_VIRTUAL_ENABLED | WP_WAVE_DRAM_ENABLED); 480 bus_space_write_2(ess->st, ess->sh, PORT_WAVCACHE_CTRL, 481 WAVCACHE_ENABLED | WAVCACHE_WTSIZE_4MB); 482 483 for (data = WAVCACHE_PCMBAR; data < WAVCACHE_PCMBAR + 4; data++) 484 wc_wrreg(ess, data, ess->baseaddr >> WAVCACHE_BASEADDR_SHIFT); 485 486 /* Setup Codec/Ringbus. */ 487 agg_initcodec(ess); 488 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 489 RINGBUS_CTRL_RINGBUS_ENABLED | RINGBUS_CTRL_ACLINK_ENABLED); 490 491 wp_wrreg(ess, WPREG_BASE, 0x8500); /* Parallel I/O */ 492 ringbus_setdest(ess, RINGBUS_SRC_ADC, 493 RINGBUS_DEST_STEREO | RINGBUS_DEST_DSOUND_IN); 494 ringbus_setdest(ess, RINGBUS_SRC_DSOUND, 495 RINGBUS_DEST_STEREO | RINGBUS_DEST_DAC); 496 497 /* Setup ASSP. Needed for Dell Inspiron 7500? */ 498 bus_space_write_1(ess->st, ess->sh, PORT_ASSP_CTRL_B, 0x00); 499 bus_space_write_1(ess->st, ess->sh, PORT_ASSP_CTRL_A, 0x03); 500 bus_space_write_1(ess->st, ess->sh, PORT_ASSP_CTRL_C, 0x00); 501 502 /* 503 * Setup GPIO. 504 * There seems to be speciality with NEC systems. 505 */ 506 switch (pci_get_subvendor(ess->dev) 507 | (pci_get_subdevice(ess->dev) << 16)) { 508 case NEC_SUBID1: 509 case NEC_SUBID2: 510 /* Matthew Braithwaite <matt@braithwaite.net> reported that 511 * NEC Versa LX doesn't need GPIO operation. */ 512 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_MASK, 0x9ff); 513 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DIR, 514 bus_space_read_2(ess->st, ess->sh, PORT_GPIO_DIR) | 0x600); 515 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 0x200); 516 break; 517 } 518 } 519 520 /* Channel controller. */ 521 522 static void 523 aggch_start_dac(struct agg_chinfo *ch) 524 { 525 bus_addr_t wpwa = APU_USE_SYSMEM | (ch->offset >> 9); 526 u_int size = ch->parent->bufsz >> 1; 527 u_int speed = ch->speed; 528 bus_addr_t offset = ch->offset >> 1; 529 u_int cp = 0; 530 u_int16_t apuch = ch->num << 1; 531 u_int dv; 532 int pan = 0; 533 534 switch (ch->aputype) { 535 case APUTYPE_16BITSTEREO: 536 wpwa >>= 1; 537 size >>= 1; 538 offset >>= 1; 539 cp >>= 1; 540 /* FALLTHROUGH */ 541 case APUTYPE_8BITSTEREO: 542 pan = 8; 543 apuch++; 544 break; 545 case APUTYPE_8BITLINEAR: 546 speed >>= 1; 547 break; 548 } 549 550 dv = (((speed % 48000) << 16) + 24000) / 48000 551 + ((speed / 48000) << 16); 552 553 do { 554 wp_wrapu(ch->parent, apuch, APUREG_WAVESPACE, wpwa & 0xff00); 555 wp_wrapu(ch->parent, apuch, APUREG_CURPTR, offset + cp); 556 wp_wrapu(ch->parent, apuch, APUREG_ENDPTR, offset + size); 557 wp_wrapu(ch->parent, apuch, APUREG_LOOPLEN, size); 558 wp_wrapu(ch->parent, apuch, APUREG_AMPLITUDE, 0xe800); 559 wp_wrapu(ch->parent, apuch, APUREG_POSITION, 0x8f00 560 | (RADIUS_CENTERCIRCLE << APU_RADIUS_SHIFT) 561 | ((PAN_FRONT + pan) << APU_PAN_SHIFT)); 562 wp_wrapu(ch->parent, apuch, APUREG_FREQ_LOBYTE, APU_plus6dB 563 | ((dv & 0xff) << APU_FREQ_LOBYTE_SHIFT)); 564 wp_wrapu(ch->parent, apuch, APUREG_FREQ_HIWORD, dv >> 8); 565 566 if (ch->aputype == APUTYPE_16BITSTEREO) 567 wpwa |= APU_STEREO >> 1; 568 pan = -pan; 569 } while (pan < 0 && apuch--); 570 571 wc_wrchctl(ch->parent, apuch, ch->wcreg_tpl); 572 wc_wrchctl(ch->parent, apuch + 1, ch->wcreg_tpl); 573 574 wp_wrapu(ch->parent, apuch, APUREG_APUTYPE, 575 (ch->aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf); 576 if (ch->wcreg_tpl & WAVCACHE_CHCTL_STEREO) 577 wp_wrapu(ch->parent, apuch + 1, APUREG_APUTYPE, 578 (ch->aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf); 579 } 580 581 static void 582 aggch_stop_dac(struct agg_chinfo *ch) 583 { 584 wp_wrapu(ch->parent, (ch->num << 1), APUREG_APUTYPE, 585 APUTYPE_INACTIVE << APU_APUTYPE_SHIFT); 586 wp_wrapu(ch->parent, (ch->num << 1) + 1, APUREG_APUTYPE, 587 APUTYPE_INACTIVE << APU_APUTYPE_SHIFT); 588 } 589 590 /* 591 * Stereo jitter suppressor. 592 * Sometimes playback pointers differ in stereo-paired channels. 593 * Calling this routine within intr fixes the problem. 594 */ 595 static inline void 596 suppress_jitter(struct agg_chinfo *ch) 597 { 598 if (ch->wcreg_tpl & WAVCACHE_CHCTL_STEREO) { 599 int cp, diff, halfsize = ch->parent->bufsz >> 2; 600 601 if (ch->aputype == APUTYPE_16BITSTEREO) 602 halfsize >>= 1; 603 cp = wp_rdapu(ch->parent, (ch->num << 1), APUREG_CURPTR); 604 diff = wp_rdapu(ch->parent, (ch->num << 1) + 1, APUREG_CURPTR); 605 diff -= cp; 606 if (diff >> 1 && diff > -halfsize && diff < halfsize) 607 bus_space_write_2(ch->parent->st, ch->parent->sh, 608 PORT_DSP_DATA, cp); 609 } 610 } 611 612 static inline u_int 613 calc_timer_freq(struct agg_chinfo *ch) 614 { 615 u_int ss = 2; 616 617 if (ch->aputype == APUTYPE_16BITSTEREO) 618 ss <<= 1; 619 if (ch->aputype == APUTYPE_8BITLINEAR) 620 ss >>= 1; 621 622 return (ch->speed * ss) / ch->blocksize; 623 } 624 625 static void 626 set_timer(struct agg_info *ess) 627 { 628 int i; 629 u_int freq = 0; 630 631 for (i = 0; i < ess->playchns; i++) 632 if ((ess->active & (1 << i)) && 633 (freq < calc_timer_freq(ess->pch + i))) 634 freq = calc_timer_freq(ess->pch + i); 635 636 wp_settimer(ess, freq); 637 } 638 639 640 /* ----------------------------- 641 * Newpcm glue. 642 */ 643 644 static void * 645 aggch_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) 646 { 647 struct agg_info *ess = devinfo; 648 struct agg_chinfo *ch; 649 bus_addr_t physaddr; 650 void *p; 651 652 ch = (dir == PCMDIR_PLAY)? ess->pch + ess->playchns : &ess->rch; 653 654 ch->parent = ess; 655 ch->channel = c; 656 ch->buffer = b; 657 ch->num = ess->playchns; 658 ch->dir = dir; 659 660 p = dma_malloc(ess, ess->bufsz, &physaddr); 661 if (p == NULL) 662 return NULL; 663 sndbuf_setup(b, p, ess->bufsz); 664 665 ch->offset = physaddr - ess->baseaddr; 666 if (physaddr < ess->baseaddr || ch->offset > WPWA_MAXADDR) { 667 device_printf(ess->dev, 668 "offset %#llx exceeds limit. ", (long long)ch->offset); 669 dma_free(ess, sndbuf_getbuf(b)); 670 return NULL; 671 } 672 673 ch->wcreg_tpl = (physaddr - 16) & WAVCACHE_CHCTL_ADDRTAG_MASK; 674 675 if (dir == PCMDIR_PLAY) { 676 ess->playchns++; 677 if (bootverbose) 678 device_printf(ess->dev, "pch[%d].offset = %#llx\n", ch->num, (long long)ch->offset); 679 } else if (bootverbose) 680 device_printf(ess->dev, "rch.offset = %#llx\n", (long long)ch->offset); 681 682 return ch; 683 } 684 685 static int 686 aggch_free(kobj_t obj, void *data) 687 { 688 struct agg_chinfo *ch = data; 689 struct agg_info *ess = ch->parent; 690 691 /* free up buffer - called after channel stopped */ 692 dma_free(ess, sndbuf_getbuf(ch->buffer)); 693 694 /* return 0 if ok */ 695 return 0; 696 } 697 698 static int 699 aggch_setplayformat(kobj_t obj, void *data, u_int32_t format) 700 { 701 struct agg_chinfo *ch = data; 702 u_int16_t wcreg_tpl; 703 u_int16_t aputype = APUTYPE_16BITLINEAR; 704 705 wcreg_tpl = ch->wcreg_tpl & WAVCACHE_CHCTL_ADDRTAG_MASK; 706 707 if (format & AFMT_STEREO) { 708 wcreg_tpl |= WAVCACHE_CHCTL_STEREO; 709 aputype += 1; 710 } 711 if (format & AFMT_U8 || format & AFMT_S8) { 712 aputype += 2; 713 if (format & AFMT_U8) 714 wcreg_tpl |= WAVCACHE_CHCTL_U8; 715 } 716 if (format & AFMT_BIGENDIAN || format & AFMT_U16_LE) { 717 format &= ~AFMT_BIGENDIAN & ~AFMT_U16_LE; 718 format |= AFMT_S16_LE; 719 } 720 ch->wcreg_tpl = wcreg_tpl; 721 ch->aputype = aputype; 722 return 0; 723 } 724 725 static int 726 aggch_setspeed(kobj_t obj, void *data, u_int32_t speed) 727 { 728 struct agg_chinfo *ch = data; 729 730 ch->speed = speed; 731 return ch->speed; 732 } 733 734 static int 735 aggch_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) 736 { 737 return ((struct agg_chinfo*)data)->blocksize = blocksize; 738 } 739 740 static int 741 aggch_trigger(kobj_t obj, void *data, int go) 742 { 743 struct agg_chinfo *ch = data; 744 745 switch (go) { 746 case PCMTRIG_EMLDMAWR: 747 return 0; 748 case PCMTRIG_START: 749 ch->parent->active |= (1 << ch->num); 750 if (ch->dir == PCMDIR_PLAY) 751 aggch_start_dac(ch); 752 #if 0 /* XXX - RECORDING */ 753 else 754 aggch_start_adc(ch); 755 #endif 756 break; 757 case PCMTRIG_ABORT: 758 case PCMTRIG_STOP: 759 ch->parent->active &= ~(1 << ch->num); 760 if (ch->dir == PCMDIR_PLAY) 761 aggch_stop_dac(ch); 762 #if 0 /* XXX - RECORDING */ 763 else 764 aggch_stop_adc(ch); 765 #endif 766 break; 767 } 768 769 if (ch->parent->active) { 770 set_timer(ch->parent); 771 wp_starttimer(ch->parent); 772 } else 773 wp_stoptimer(ch->parent); 774 775 return 0; 776 } 777 778 static int 779 aggch_getplayptr(kobj_t obj, void *data) 780 { 781 struct agg_chinfo *ch = data; 782 u_int cp; 783 784 cp = wp_rdapu(ch->parent, (ch->num << 1), APUREG_CURPTR); 785 if (ch->aputype == APUTYPE_16BITSTEREO) 786 cp = (0xffff << 2) & ((cp << 2) - ch->offset); 787 else 788 cp = (0xffff << 1) & ((cp << 1) - ch->offset); 789 790 return cp; 791 } 792 793 static struct pcmchan_caps * 794 aggch_getcaps(kobj_t obj, void *data) 795 { 796 static u_int32_t playfmt[] = { 797 AFMT_U8, 798 AFMT_STEREO | AFMT_U8, 799 AFMT_S8, 800 AFMT_STEREO | AFMT_S8, 801 AFMT_S16_LE, 802 AFMT_STEREO | AFMT_S16_LE, 803 0 804 }; 805 static struct pcmchan_caps playcaps = {2000, 96000, playfmt, 0}; 806 807 static u_int32_t recfmt[] = { 808 AFMT_S8, 809 AFMT_STEREO | AFMT_S8, 810 AFMT_S16_LE, 811 AFMT_STEREO | AFMT_S16_LE, 812 0 813 }; 814 static struct pcmchan_caps reccaps = {4000, 48000, recfmt, 0}; 815 816 return (((struct agg_chinfo*)data)->dir == PCMDIR_PLAY)? 817 &playcaps : &reccaps; 818 } 819 820 static kobj_method_t aggch_methods[] = { 821 KOBJMETHOD(channel_init, aggch_init), 822 KOBJMETHOD(channel_free, aggch_free), 823 KOBJMETHOD(channel_setformat, aggch_setplayformat), 824 KOBJMETHOD(channel_setspeed, aggch_setspeed), 825 KOBJMETHOD(channel_setblocksize, aggch_setblocksize), 826 KOBJMETHOD(channel_trigger, aggch_trigger), 827 KOBJMETHOD(channel_getptr, aggch_getplayptr), 828 KOBJMETHOD(channel_getcaps, aggch_getcaps), 829 { 0, 0 } 830 }; 831 CHANNEL_DECLARE(aggch); 832 833 /* ----------------------------- 834 * Bus space. 835 */ 836 837 static void 838 agg_intr(void *sc) 839 { 840 struct agg_info* ess = sc; 841 u_int16_t status; 842 int i; 843 844 status = bus_space_read_1(ess->st, ess->sh, PORT_HOSTINT_STAT); 845 if (!status) 846 return; 847 848 /* Acknowledge all. */ 849 bus_space_write_2(ess->st, ess->sh, PORT_INT_STAT, 1); 850 bus_space_write_1(ess->st, ess->sh, PORT_HOSTINT_STAT, 0xff); 851 852 if (status & HOSTINT_STAT_HWVOL) { 853 u_int event; 854 855 event = bus_space_read_1(ess->st, ess->sh, PORT_HWVOL_MASTER); 856 switch (event) { 857 case HWVOL_MUTE: 858 mixer_hwvol_mute(ess->dev); 859 break; 860 case HWVOL_UP: 861 mixer_hwvol_step(ess->dev, 1, 1); 862 break; 863 case HWVOL_DOWN: 864 mixer_hwvol_step(ess->dev, -1, -1); 865 break; 866 case HWVOL_NOP: 867 break; 868 default: 869 device_printf(ess->dev, "%s: unknown HWVOL event 0x%x\n", 870 device_get_nameunit(ess->dev), event); 871 } 872 bus_space_write_1(ess->st, ess->sh, PORT_HWVOL_MASTER, 873 HWVOL_NOP); 874 } 875 876 for (i = 0; i < ess->playchns; i++) 877 if (ess->active & (1 << i)) { 878 suppress_jitter(ess->pch + i); 879 chn_intr(ess->pch[i].channel); 880 } 881 #if 0 /* XXX - RECORDING */ 882 if (ess->active & (1 << i)) 883 chn_intr(ess->rch.channel); 884 #endif 885 } 886 887 static void 888 setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error) 889 { 890 bus_addr_t *phys = arg; 891 892 *phys = error? 0 : segs->ds_addr; 893 894 if (bootverbose) { 895 printf("setmap (%lx, %lx), nseg=%d, error=%d\n", 896 (unsigned long)segs->ds_addr, (unsigned long)segs->ds_len, 897 nseg, error); 898 } 899 } 900 901 static void * 902 dma_malloc(struct agg_info *sc, u_int32_t sz, bus_addr_t *phys) 903 { 904 void *buf; 905 bus_dmamap_t map; 906 907 if (bus_dmamem_alloc(sc->parent_dmat, &buf, BUS_DMA_NOWAIT, &map)) 908 return NULL; 909 if (bus_dmamap_load(sc->parent_dmat, map, buf, sz, setmap, phys, 0) 910 || !*phys) { 911 bus_dmamem_free(sc->parent_dmat, buf, map); 912 return NULL; 913 } 914 return buf; 915 } 916 917 static void 918 dma_free(struct agg_info *sc, void *buf) 919 { 920 bus_dmamem_free(sc->parent_dmat, buf, NULL); 921 } 922 923 static int 924 agg_probe(device_t dev) 925 { 926 char *s = NULL; 927 928 switch (pci_get_devid(dev)) { 929 case MAESTRO_1_PCI_ID: 930 s = "ESS Technology Maestro-1"; 931 break; 932 933 case MAESTRO_2_PCI_ID: 934 s = "ESS Technology Maestro-2"; 935 break; 936 937 case MAESTRO_2E_PCI_ID: 938 s = "ESS Technology Maestro-2E"; 939 break; 940 } 941 942 if (s != NULL && pci_get_class(dev) == PCIC_MULTIMEDIA) { 943 device_set_desc(dev, s); 944 return 0; 945 } 946 return ENXIO; 947 } 948 949 static int 950 agg_attach(device_t dev) 951 { 952 struct agg_info *ess = NULL; 953 u_int32_t data; 954 int mapped = 0; 955 int regid = PCIR_MAPS; 956 struct resource *reg = NULL; 957 struct ac97_info *codec = NULL; 958 int irqid = 0; 959 struct resource *irq = NULL; 960 void *ih = NULL; 961 char status[SND_STATUSLEN]; 962 963 if ((ess = malloc(sizeof *ess, M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) { 964 device_printf(dev, "cannot allocate softc\n"); 965 return ENXIO; 966 } 967 ess->dev = dev; 968 969 ess->bufsz = pcm_getbuffersize(dev, 4096, AGG_DEFAULT_BUFSZ, 65536); 970 971 if (bus_dma_tag_create(/*parent*/NULL, 972 /*alignment*/1 << WAVCACHE_BASEADDR_SHIFT, 973 /*boundary*/WPWA_MAXADDR + 1, 974 /*lowaddr*/MAESTRO_MAXADDR, /*highaddr*/BUS_SPACE_MAXADDR, 975 /*filter*/NULL, /*filterarg*/NULL, 976 /*maxsize*/ess->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff, 977 /*flags*/0, &ess->parent_dmat) != 0) { 978 device_printf(dev, "unable to create dma tag\n"); 979 goto bad; 980 } 981 982 ess->stat = dma_malloc(ess, ess->bufsz, &ess->baseaddr); 983 if (ess->stat == NULL) { 984 device_printf(dev, "cannot allocate status buffer\n"); 985 goto bad; 986 } 987 if (bootverbose) 988 device_printf(dev, "Maestro DMA base: %#llx\n", 989 (long long)ess->baseaddr); 990 991 agg_power(ess, PPMI_D0); 992 DELAY(100000); 993 994 data = pci_read_config(dev, PCIR_COMMAND, 2); 995 data |= (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN); 996 pci_write_config(dev, PCIR_COMMAND, data, 2); 997 data = pci_read_config(dev, PCIR_COMMAND, 2); 998 999 if (data & PCIM_CMD_PORTEN) { 1000 reg = bus_alloc_resource(dev, SYS_RES_IOPORT, ®id, 1001 0, BUS_SPACE_UNRESTRICTED, 256, RF_ACTIVE); 1002 if (reg != NULL) { 1003 ess->reg = reg; 1004 ess->regid = regid; 1005 ess->st = rman_get_bustag(reg); 1006 ess->sh = rman_get_bushandle(reg); 1007 mapped++; 1008 } 1009 } 1010 if (mapped == 0) { 1011 device_printf(dev, "unable to map register space\n"); 1012 goto bad; 1013 } 1014 1015 agg_init(ess); 1016 if (agg_rdcodec(NULL, ess, 0) == 0x80) { 1017 device_printf(dev, "PT101 codec detected!\n"); 1018 goto bad; 1019 } 1020 codec = AC97_CREATE(dev, ess, agg_ac97); 1021 if (codec == NULL) 1022 goto bad; 1023 if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) 1024 goto bad; 1025 ess->codec = codec; 1026 1027 irq = bus_alloc_resource(dev, SYS_RES_IRQ, &irqid, 1028 0, BUS_SPACE_UNRESTRICTED, 1, RF_ACTIVE | RF_SHAREABLE); 1029 if (irq == NULL || snd_setup_intr(dev, irq, 0, agg_intr, ess, &ih, NULL)) { 1030 device_printf(dev, "unable to map interrupt\n"); 1031 goto bad; 1032 } 1033 ess->irq = irq; 1034 ess->irqid = irqid; 1035 ess->ih = ih; 1036 1037 snprintf(status, SND_STATUSLEN, "at I/O port 0x%lx irq %ld", 1038 rman_get_start(reg), rman_get_start(irq)); 1039 1040 if (pcm_register(dev, ess, AGG_MAXPLAYCH, 1)) 1041 goto bad; 1042 1043 mixer_hwvol_init(dev); 1044 for (data = 0; data < AGG_MAXPLAYCH; data++) 1045 pcm_addchan(dev, PCMDIR_PLAY, &aggch_class, ess); 1046 #if 0 /* XXX - RECORDING */ 1047 pcm_addchan(dev, PCMDIR_REC, &aggrch_class, ess); 1048 #endif 1049 pcm_setstatus(dev, status); 1050 1051 return 0; 1052 1053 bad: 1054 if (codec != NULL) 1055 ac97_destroy(codec); 1056 if (ih != NULL) 1057 bus_teardown_intr(dev, irq, ih); 1058 if (irq != NULL) 1059 bus_release_resource(dev, SYS_RES_IRQ, irqid, irq); 1060 if (reg != NULL) 1061 bus_release_resource(dev, SYS_RES_IOPORT, regid, reg); 1062 if (ess != NULL) { 1063 agg_power(ess, PPMI_D3); 1064 if (ess->stat != NULL) 1065 dma_free(ess, ess->stat); 1066 if (ess->parent_dmat != NULL) 1067 bus_dma_tag_destroy(ess->parent_dmat); 1068 free(ess, M_DEVBUF); 1069 } 1070 1071 return ENXIO; 1072 } 1073 1074 static int 1075 agg_detach(device_t dev) 1076 { 1077 struct agg_info *ess = pcm_getdevinfo(dev); 1078 int r; 1079 1080 r = pcm_unregister(dev); 1081 if (r) 1082 return r; 1083 1084 ess = pcm_getdevinfo(dev); 1085 dma_free(ess, ess->stat); 1086 1087 /* Power down everything except clock and vref. */ 1088 agg_wrcodec(NULL, ess, AC97_REG_POWER, 0xd700); 1089 DELAY(20); 1090 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 0); 1091 agg_power(ess, PPMI_D3); 1092 1093 bus_teardown_intr(dev, ess->irq, ess->ih); 1094 bus_release_resource(dev, SYS_RES_IRQ, ess->irqid, ess->irq); 1095 bus_release_resource(dev, SYS_RES_IOPORT, ess->regid, ess->reg); 1096 bus_dma_tag_destroy(ess->parent_dmat); 1097 free(ess, M_DEVBUF); 1098 return 0; 1099 } 1100 1101 static int 1102 agg_suspend(device_t dev) 1103 { 1104 struct agg_info *ess = pcm_getdevinfo(dev); 1105 int i; 1106 1107 crit_enter(); 1108 wp_stoptimer(ess); 1109 bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 0); 1110 1111 for (i = 0; i < ess->playchns; i++) 1112 aggch_stop_dac(ess->pch + i); 1113 1114 #if 0 /* XXX - RECORDING */ 1115 aggch_stop_adc(&ess->rch); 1116 #endif 1117 crit_exit(); 1118 /* Power down everything except clock. */ 1119 agg_wrcodec(NULL, ess, AC97_REG_POWER, 0xdf00); 1120 DELAY(20); 1121 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 0); 1122 DELAY(1); 1123 agg_power(ess, PPMI_D3); 1124 1125 return 0; 1126 } 1127 1128 static int 1129 agg_resume(device_t dev) 1130 { 1131 int i; 1132 struct agg_info *ess = pcm_getdevinfo(dev); 1133 1134 agg_power(ess, PPMI_D0); 1135 DELAY(100000); 1136 agg_init(ess); 1137 if (mixer_reinit(dev)) { 1138 device_printf(dev, "unable to reinitialize the mixer\n"); 1139 return ENXIO; 1140 } 1141 1142 crit_enter(); 1143 for (i = 0; i < ess->playchns; i++) 1144 if (ess->active & (1 << i)) 1145 aggch_start_dac(ess->pch + i); 1146 #if 0 /* XXX - RECORDING */ 1147 if (ess->active & (1 << i)) 1148 aggch_start_adc(&ess->rch); 1149 #endif 1150 if (ess->active) { 1151 set_timer(ess); 1152 wp_starttimer(ess); 1153 } 1154 crit_exit(); 1155 return 0; 1156 } 1157 1158 static int 1159 agg_shutdown(device_t dev) 1160 { 1161 struct agg_info *ess = pcm_getdevinfo(dev); 1162 int i; 1163 1164 wp_stoptimer(ess); 1165 bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 0); 1166 1167 for (i = 0; i < ess->playchns; i++) 1168 aggch_stop_dac(ess->pch + i); 1169 1170 #if 0 /* XXX - RECORDING */ 1171 aggch_stop_adc(&ess->rch); 1172 #endif 1173 return 0; 1174 } 1175 1176 1177 static device_method_t agg_methods[] = { 1178 DEVMETHOD(device_probe, agg_probe), 1179 DEVMETHOD(device_attach, agg_attach), 1180 DEVMETHOD(device_detach, agg_detach), 1181 DEVMETHOD(device_suspend, agg_suspend), 1182 DEVMETHOD(device_resume, agg_resume), 1183 DEVMETHOD(device_shutdown, agg_shutdown), 1184 1185 { 0, 0 } 1186 }; 1187 1188 static driver_t agg_driver = { 1189 "pcm", 1190 agg_methods, 1191 PCM_SOFTC_SIZE, 1192 }; 1193 1194 DRIVER_MODULE(snd_maestro, pci, agg_driver, pcm_devclass, 0, 0); 1195 MODULE_DEPEND(snd_maestro, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); 1196 MODULE_VERSION(snd_maestro, 1); 1197