maestro.c revision 70619
150477Speter/*- 249016Swpaul * Copyright (c) 2000 Taku YAMAMOTO <taku@cent.saitama-u.ac.jp> 3158061Syongari * All rights reserved. 449016Swpaul * 570711Sobrien * Redistribution and use in source and binary forms, with or without 6150636Smlaier * modification, are permitted provided that the following conditions 770711Sobrien * are met: 870711Sobrien * 1. Redistributions of source code must retain the above copyright 960966Speter * 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 70619 2001-01-03 01:32:57Z jhb $ 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 pcm_channel *channel; 85 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 113 u_int playchns, active; 114 struct agg_chinfo pch[AGG_MAXPLAYCH]; 115 struct agg_chinfo rch; 116}; 117 118static inline void ringbus_setdest(struct agg_info*, int, int); 119 120static inline u_int16_t wp_rdreg(struct agg_info*, u_int16_t); 121static inline void wp_wrreg(struct agg_info*, u_int16_t, u_int16_t); 122static inline u_int16_t wp_rdapu(struct agg_info*, int, u_int16_t); 123static inline void wp_wrapu(struct agg_info*, int, u_int16_t, u_int16_t); 124static inline void wp_settimer(struct agg_info*, u_int); 125static inline void wp_starttimer(struct agg_info*); 126static inline void wp_stoptimer(struct agg_info*); 127 128static inline u_int16_t wc_rdreg(struct agg_info*, u_int16_t); 129static inline void wc_wrreg(struct agg_info*, u_int16_t, u_int16_t); 130static inline u_int16_t wc_rdchctl(struct agg_info*, int); 131static inline void wc_wrchctl(struct agg_info*, int, u_int16_t); 132 133static inline void agg_power(struct agg_info*, int); 134 135static void agg_init(struct agg_info*); 136 137static void aggch_start_dac(struct agg_chinfo*); 138static void aggch_stop_dac(struct agg_chinfo*); 139 140static inline void suppress_jitter(struct agg_chinfo*); 141 142static inline u_int calc_timer_freq(struct agg_chinfo*); 143static void set_timer(struct agg_info*); 144 145static void agg_intr(void *); 146static int agg_probe(device_t); 147static int agg_attach(device_t); 148static int agg_detach(device_t); 149static int agg_suspend(device_t); 150static int agg_resume(device_t); 151static int agg_shutdown(device_t); 152 153static void *dma_malloc(struct agg_info*, u_int32_t, bus_addr_t*); 154static void dma_free(struct agg_info*, void *); 155 156/* ----------------------------- 157 * Subsystems. 158 */ 159 160/* Codec/Ringbus */ 161 162/* -------------------------------------------------------------------- */ 163 164static u_int32_t 165agg_ac97_init(kobj_t obj, void *sc) 166{ 167 struct agg_info *ess = sc; 168 169 return (bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) & CODEC_STAT_MASK)? 0 : 1; 170} 171 172static int 173agg_rdcodec(kobj_t obj, void *sc, int regno) 174{ 175 struct agg_info *ess = sc; 176 unsigned t; 177 178 /* We have to wait for a SAFE time to write addr/data */ 179 for (t = 0; t < 20; t++) { 180 if ((bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) 181 & CODEC_STAT_MASK) != CODEC_STAT_PROGLESS) 182 break; 183 DELAY(2); /* 20.8us / 13 */ 184 } 185 if (t == 20) 186 device_printf(ess->dev, "agg_rdcodec() PROGLESS timed out.\n"); 187 188 bus_space_write_1(ess->st, ess->sh, PORT_CODEC_CMD, 189 CODEC_CMD_READ | regno); 190 DELAY(21); /* AC97 cycle = 20.8usec */ 191 192 /* Wait for data retrieve */ 193 for (t = 0; t < 20; t++) { 194 if ((bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) 195 & CODEC_STAT_MASK) == CODEC_STAT_RW_DONE) 196 break; 197 DELAY(2); /* 20.8us / 13 */ 198 } 199 if (t == 20) 200 /* Timed out, but perform dummy read. */ 201 device_printf(ess->dev, "agg_rdcodec() RW_DONE timed out.\n"); 202 203 return bus_space_read_2(ess->st, ess->sh, PORT_CODEC_REG); 204} 205 206static int 207agg_wrcodec(kobj_t obj, void *sc, int regno, u_int32_t data) 208{ 209 unsigned t; 210 struct agg_info *ess = sc; 211 212 /* We have to wait for a SAFE time to write addr/data */ 213 for (t = 0; t < 20; t++) { 214 if ((bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) 215 & CODEC_STAT_MASK) != CODEC_STAT_PROGLESS) 216 break; 217 DELAY(2); /* 20.8us / 13 */ 218 } 219 if (t == 20) { 220 /* Timed out. Abort writing. */ 221 device_printf(ess->dev, "agg_wrcodec() PROGLESS timed out.\n"); 222 return -1; 223 } 224 225 bus_space_write_2(ess->st, ess->sh, PORT_CODEC_REG, data); 226 bus_space_write_1(ess->st, ess->sh, PORT_CODEC_CMD, 227 CODEC_CMD_WRITE | regno); 228 229 return 0; 230} 231 232static kobj_method_t agg_ac97_methods[] = { 233 KOBJMETHOD(ac97_init, agg_ac97_init), 234 KOBJMETHOD(ac97_read, agg_rdcodec), 235 KOBJMETHOD(ac97_write, agg_wrcodec), 236 { 0, 0 } 237}; 238AC97_DECLARE(agg_ac97); 239 240/* -------------------------------------------------------------------- */ 241 242static inline void 243ringbus_setdest(struct agg_info *ess, int src, int dest) 244{ 245 u_int32_t data; 246 247 data = bus_space_read_4(ess->st, ess->sh, PORT_RINGBUS_CTRL); 248 data &= ~(0xfU << src); 249 data |= (0xfU & dest) << src; 250 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, data); 251} 252 253/* Wave Processor */ 254 255static inline u_int16_t 256wp_rdreg(struct agg_info *ess, u_int16_t reg) 257{ 258 bus_space_write_2(ess->st, ess->sh, PORT_DSP_INDEX, reg); 259 return bus_space_read_2(ess->st, ess->sh, PORT_DSP_DATA); 260} 261 262static inline void 263wp_wrreg(struct agg_info *ess, u_int16_t reg, u_int16_t data) 264{ 265 bus_space_write_2(ess->st, ess->sh, PORT_DSP_INDEX, reg); 266 bus_space_write_2(ess->st, ess->sh, PORT_DSP_DATA, data); 267} 268 269static inline void 270apu_setindex(struct agg_info *ess, u_int16_t reg) 271{ 272 int t; 273 274 wp_wrreg(ess, WPREG_CRAM_PTR, reg); 275 /* Sometimes WP fails to set apu register index. */ 276 for (t = 0; t < 1000; t++) { 277 if (bus_space_read_2(ess->st, ess->sh, PORT_DSP_DATA) == reg) 278 break; 279 bus_space_write_2(ess->st, ess->sh, PORT_DSP_DATA, reg); 280 } 281 if (t == 1000) 282 device_printf(ess->dev, "apu_setindex() timed out.\n"); 283} 284 285static inline u_int16_t 286wp_rdapu(struct agg_info *ess, int ch, u_int16_t reg) 287{ 288 u_int16_t ret; 289 290 apu_setindex(ess, ((unsigned)ch << 4) + reg); 291 ret = wp_rdreg(ess, WPREG_DATA_PORT); 292 return ret; 293} 294 295static inline void 296wp_wrapu(struct agg_info *ess, int ch, u_int16_t reg, u_int16_t data) 297{ 298 int t; 299 300 apu_setindex(ess, ((unsigned)ch << 4) + reg); 301 wp_wrreg(ess, WPREG_DATA_PORT, data); 302 for (t = 0; t < 1000; t++) { 303 if (bus_space_read_2(ess->st, ess->sh, PORT_DSP_DATA) == data) 304 break; 305 bus_space_write_2(ess->st, ess->sh, PORT_DSP_DATA, data); 306 } 307 if (t == 1000) 308 device_printf(ess->dev, "wp_wrapu() timed out.\n"); 309} 310 311static inline void 312wp_settimer(struct agg_info *ess, u_int freq) 313{ 314 u_int clock = 48000 << 2; 315 u_int prescale = 0, divide = (freq != 0) ? (clock / freq) : ~0; 316 317 RANGE(divide, 4, 32 << 8); 318 319 for (; divide > 32 << 1; divide >>= 1) 320 prescale++; 321 divide = (divide + 1) >> 1; 322 323 for (; prescale < 7 && divide > 2 && !(divide & 1); divide >>= 1) 324 prescale++; 325 326 wp_wrreg(ess, WPREG_TIMER_ENABLE, 0); 327 wp_wrreg(ess, WPREG_TIMER_FREQ, 328 (prescale << WP_TIMER_FREQ_PRESCALE_SHIFT) | (divide - 1)); 329 wp_wrreg(ess, WPREG_TIMER_ENABLE, 1); 330} 331 332static inline void 333wp_starttimer(struct agg_info *ess) 334{ 335 wp_wrreg(ess, WPREG_TIMER_START, 1); 336} 337 338static inline void 339wp_stoptimer(struct agg_info *ess) 340{ 341 wp_wrreg(ess, WPREG_TIMER_START, 0); 342 bus_space_write_2(ess->st, ess->sh, PORT_INT_STAT, 1); 343} 344 345/* WaveCache */ 346 347static inline u_int16_t 348wc_rdreg(struct agg_info *ess, u_int16_t reg) 349{ 350 bus_space_write_2(ess->st, ess->sh, PORT_WAVCACHE_INDEX, reg); 351 return bus_space_read_2(ess->st, ess->sh, PORT_WAVCACHE_DATA); 352} 353 354static inline void 355wc_wrreg(struct agg_info *ess, u_int16_t reg, u_int16_t data) 356{ 357 bus_space_write_2(ess->st, ess->sh, PORT_WAVCACHE_INDEX, reg); 358 bus_space_write_2(ess->st, ess->sh, PORT_WAVCACHE_DATA, data); 359} 360 361static inline u_int16_t 362wc_rdchctl(struct agg_info *ess, int ch) 363{ 364 return wc_rdreg(ess, ch << 3); 365} 366 367static inline void 368wc_wrchctl(struct agg_info *ess, int ch, u_int16_t data) 369{ 370 wc_wrreg(ess, ch << 3, data); 371} 372 373/* Power management */ 374 375static inline void 376agg_power(struct agg_info *ess, int status) 377{ 378 u_int8_t data; 379 380 data = pci_read_config(ess->dev, CONF_PM_PTR, 1); 381 if (pci_read_config(ess->dev, data, 1) == PPMI_CID) 382 pci_write_config(ess->dev, data + PM_CTRL, status, 1); 383} 384 385 386/* ----------------------------- 387 * Controller. 388 */ 389 390static inline void 391agg_initcodec(struct agg_info* ess) 392{ 393 u_int16_t data; 394 395 if (bus_space_read_4(ess->st, ess->sh, PORT_RINGBUS_CTRL) 396 & RINGBUS_CTRL_ACLINK_ENABLED) { 397 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 0); 398 DELAY(104); /* 20.8us * (4 + 1) */ 399 } 400 /* XXX - 2nd codec should be looked at. */ 401 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 402 RINGBUS_CTRL_AC97_SWRESET); 403 DELAY(2); 404 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 405 RINGBUS_CTRL_ACLINK_ENABLED); 406 DELAY(21); 407 408 agg_rdcodec(NULL, ess, 0); 409 if (bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) 410 & CODEC_STAT_MASK) { 411 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 0); 412 DELAY(21); 413 414 /* Try cold reset. */ 415 device_printf(ess->dev, "will perform cold reset.\n"); 416 data = bus_space_read_2(ess->st, ess->sh, PORT_GPIO_DIR); 417 if (pci_read_config(ess->dev, 0x58, 2) & 1) 418 data |= 0x10; 419 data |= 0x009 & 420 ~bus_space_read_2(ess->st, ess->sh, PORT_GPIO_DATA); 421 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_MASK, 0xff6); 422 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DIR, 423 data | 0x009); 424 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 0x000); 425 DELAY(2); 426 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 0x001); 427 DELAY(1); 428 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 0x009); 429 DELAY(500000); 430 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DIR, data); 431 DELAY(84); /* 20.8us * 4 */ 432 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 433 RINGBUS_CTRL_ACLINK_ENABLED); 434 DELAY(21); 435 } 436} 437 438static void 439agg_init(struct agg_info* ess) 440{ 441 u_int32_t data; 442 443 /* Setup PCI config registers. */ 444 445 /* Disable all legacy emulations. */ 446 data = pci_read_config(ess->dev, CONF_LEGACY, 2); 447 data |= LEGACY_DISABLED; 448 pci_write_config(ess->dev, CONF_LEGACY, data, 2); 449 450 /* Disconnect from CHI. (Makes Dell inspiron 7500 work?) 451 * Enable posted write. 452 * Prefer PCI timing rather than that of ISA. 453 * Don't swap L/R. */ 454 data = pci_read_config(ess->dev, CONF_MAESTRO, 4); 455 data |= MAESTRO_CHIBUS | MAESTRO_POSTEDWRITE | MAESTRO_DMA_PCITIMING; 456 data &= ~MAESTRO_SWAP_LR; 457 pci_write_config(ess->dev, CONF_MAESTRO, data, 4); 458 459 /* Reset direct sound. */ 460 bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 461 HOSTINT_CTRL_DSOUND_RESET); 462 DELAY(10000); /* XXX - too long? */ 463 bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 0); 464 DELAY(10000); 465 466 /* Enable direct sound interruption and hardware volume control. */ 467 bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 468 HOSTINT_CTRL_DSOUND_INT_ENABLED | HOSTINT_CTRL_HWVOL_ENABLED); 469 470 /* Setup Wave Processor. */ 471 472 /* Enable WaveCache, set DMA base address. */ 473 wp_wrreg(ess, WPREG_WAVE_ROMRAM, 474 WP_WAVE_VIRTUAL_ENABLED | WP_WAVE_DRAM_ENABLED); 475 bus_space_write_2(ess->st, ess->sh, PORT_WAVCACHE_CTRL, 476 WAVCACHE_ENABLED | WAVCACHE_WTSIZE_4MB); 477 478 for (data = WAVCACHE_PCMBAR; data < WAVCACHE_PCMBAR + 4; data++) 479 wc_wrreg(ess, data, ess->baseaddr >> WAVCACHE_BASEADDR_SHIFT); 480 481 /* Setup Codec/Ringbus. */ 482 agg_initcodec(ess); 483 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 484 RINGBUS_CTRL_RINGBUS_ENABLED | RINGBUS_CTRL_ACLINK_ENABLED); 485 486 wp_wrreg(ess, WPREG_BASE, 0x8500); /* Parallel I/O */ 487 ringbus_setdest(ess, RINGBUS_SRC_ADC, 488 RINGBUS_DEST_STEREO | RINGBUS_DEST_DSOUND_IN); 489 ringbus_setdest(ess, RINGBUS_SRC_DSOUND, 490 RINGBUS_DEST_STEREO | RINGBUS_DEST_DAC); 491 492 /* Setup ASSP. Needed for Dell Inspiron 7500? */ 493 bus_space_write_1(ess->st, ess->sh, PORT_ASSP_CTRL_B, 0x00); 494 bus_space_write_1(ess->st, ess->sh, PORT_ASSP_CTRL_A, 0x03); 495 bus_space_write_1(ess->st, ess->sh, PORT_ASSP_CTRL_C, 0x00); 496 497 /* 498 * Setup GPIO. 499 * There seems to be speciality with NEC systems. 500 */ 501 switch (pci_get_subvendor(ess->dev) 502 | (pci_get_subdevice(ess->dev) << 16)) { 503 case NEC_SUBID1: 504 case NEC_SUBID2: 505 /* Matthew Braithwaite <matt@braithwaite.net> reported that 506 * NEC Versa LX doesn't need GPIO operation. */ 507 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_MASK, 0x9ff); 508 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DIR, 509 bus_space_read_2(ess->st, ess->sh, PORT_GPIO_DIR) | 0x600); 510 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 0x200); 511 break; 512 } 513} 514 515/* Channel controller. */ 516 517static void 518aggch_start_dac(struct agg_chinfo *ch) 519{ 520 u_int wpwa = APU_USE_SYSMEM | (ch->offset >> 9); 521 u_int size = AGG_BUFSIZ >> 1; 522 u_int speed = ch->speed; 523 u_int offset = ch->offset >> 1; 524 u_int cp = 0; 525 u_int16_t apuch = ch->num << 1; 526 u_int dv; 527 int pan = 0; 528 529 switch (ch->aputype) { 530 case APUTYPE_16BITSTEREO: 531 wpwa >>= 1; 532 size >>= 1; 533 offset >>= 1; 534 cp >>= 1; 535 /* FALLTHROUGH */ 536 case APUTYPE_8BITSTEREO: 537 pan = 8; 538 apuch++; 539 break; 540 case APUTYPE_8BITLINEAR: 541 speed >>= 1; 542 break; 543 } 544 545 dv = (((speed % 48000) << 16) + 24000) / 48000 546 + ((speed / 48000) << 16); 547 548 do { 549 wp_wrapu(ch->parent, apuch, APUREG_WAVESPACE, wpwa & 0xff00); 550 wp_wrapu(ch->parent, apuch, APUREG_CURPTR, offset + cp); 551 wp_wrapu(ch->parent, apuch, APUREG_ENDPTR, offset + size); 552 wp_wrapu(ch->parent, apuch, APUREG_LOOPLEN, size); 553 wp_wrapu(ch->parent, apuch, APUREG_AMPLITUDE, 0xe800); 554 wp_wrapu(ch->parent, apuch, APUREG_POSITION, 0x8f00 555 | (RADIUS_CENTERCIRCLE << APU_RADIUS_SHIFT) 556 | ((PAN_FRONT + pan) << APU_PAN_SHIFT)); 557 wp_wrapu(ch->parent, apuch, APUREG_FREQ_LOBYTE, APU_plus6dB 558 | ((dv & 0xff) << APU_FREQ_LOBYTE_SHIFT)); 559 wp_wrapu(ch->parent, apuch, APUREG_FREQ_HIWORD, dv >> 8); 560 561 if (ch->aputype == APUTYPE_16BITSTEREO) 562 wpwa |= APU_STEREO >> 1; 563 pan = -pan; 564 } while (pan < 0 && apuch--); 565 566 wc_wrchctl(ch->parent, apuch, ch->wcreg_tpl); 567 wc_wrchctl(ch->parent, apuch + 1, ch->wcreg_tpl); 568 569 wp_wrapu(ch->parent, apuch, APUREG_APUTYPE, 570 (ch->aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf); 571 if (ch->wcreg_tpl & WAVCACHE_CHCTL_STEREO) 572 wp_wrapu(ch->parent, apuch + 1, APUREG_APUTYPE, 573 (ch->aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf); 574} 575 576static void 577aggch_stop_dac(struct agg_chinfo *ch) 578{ 579 wp_wrapu(ch->parent, (ch->num << 1), APUREG_APUTYPE, 580 APUTYPE_INACTIVE << APU_APUTYPE_SHIFT); 581 wp_wrapu(ch->parent, (ch->num << 1) + 1, APUREG_APUTYPE, 582 APUTYPE_INACTIVE << APU_APUTYPE_SHIFT); 583} 584 585/* 586 * Stereo jitter suppressor. 587 * Sometimes playback pointers differ in stereo-paired channels. 588 * Calling this routine within intr fixes the problem. 589 */ 590static inline void 591suppress_jitter(struct agg_chinfo *ch) 592{ 593 if (ch->wcreg_tpl & WAVCACHE_CHCTL_STEREO) { 594 int cp, diff, halfsize = AGG_BUFSIZ >> 2; 595 596 if (ch->aputype == APUTYPE_16BITSTEREO) 597 halfsize >>= 1; 598 cp = wp_rdapu(ch->parent, (ch->num << 1), APUREG_CURPTR); 599 diff = wp_rdapu(ch->parent, (ch->num << 1) + 1, APUREG_CURPTR); 600 diff -= cp; 601 if (diff >> 1 && diff > -halfsize && diff < halfsize) 602 bus_space_write_2(ch->parent->st, ch->parent->sh, 603 PORT_DSP_DATA, cp); 604 } 605} 606 607static inline u_int 608calc_timer_freq(struct agg_chinfo *ch) 609{ 610 u_int ss = 2; 611 612 if (ch->aputype == APUTYPE_16BITSTEREO) 613 ss <<= 1; 614 if (ch->aputype == APUTYPE_8BITLINEAR) 615 ss >>= 1; 616 617 return (ch->speed * ss) / ch->blocksize; 618} 619 620static void 621set_timer(struct agg_info *ess) 622{ 623 int i; 624 u_int freq = 0; 625 626 for (i = 0; i < ess->playchns; i++) 627 if ((ess->active & (1 << i)) && 628 (freq < calc_timer_freq(ess->pch + i))) 629 freq = calc_timer_freq(ess->pch + i); 630 631 wp_settimer(ess, freq); 632} 633 634 635/* ----------------------------- 636 * Newpcm glue. 637 */ 638 639static void * 640aggch_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) 641{ 642 struct agg_info *ess = devinfo; 643 struct agg_chinfo *ch; 644 bus_addr_t physaddr; 645 void *p; 646 647 ch = (dir == PCMDIR_PLAY)? ess->pch + ess->playchns : &ess->rch; 648 649 ch->parent = ess; 650 ch->channel = c; 651 ch->buffer = b; 652 ch->num = ess->playchns; 653 ch->dir = dir; 654 655 p = dma_malloc(ess, AGG_BUFSIZ, &physaddr); 656 if (p == NULL) 657 return NULL; 658 sndbuf_setup(b, p, AGG_BUFSIZ); 659 660 ch->offset = physaddr - ess->baseaddr; 661 if (physaddr < ess->baseaddr || ch->offset > WPWA_MAXADDR) { 662 device_printf(ess->dev, 663 "offset %#x exceeds limit. ", ch->offset); 664 dma_free(ess, b->buf); 665 b->buf = NULL; 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 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 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 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_hwmute(ess->dev); 855 break; 856 case HWVOL_UP: 857 mixer_hwstep(ess->dev, 1, 1); 858 break; 859 case HWVOL_DOWN: 860 mixer_hwstep(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 1024 || bus_setup_intr(dev, irq, INTR_TYPE_TTY, agg_intr, ess, &ih)) { 1025 device_printf(dev, "unable to map interrupt\n"); 1026 goto bad; 1027 } 1028 ess->irq = irq; 1029 ess->irqid = irqid; 1030 ess->ih = ih; 1031 1032 snprintf(status, SND_STATUSLEN, "at I/O port 0x%lx irq %ld", 1033 rman_get_start(reg), rman_get_start(irq)); 1034 1035 if (pcm_register(dev, ess, AGG_MAXPLAYCH, 1)) 1036 goto bad; 1037 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(snddev_info), 1186}; 1187 1188static devclass_t pcm_devclass; 1189 1190DRIVER_MODULE(snd_maestro, pci, agg_driver, pcm_devclass, 0, 0); 1191MODULE_DEPEND(snd_maestro, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); 1192MODULE_VERSION(snd_maestro, 1); 1193