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