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