maestro.c revision 82180
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 */ 28 29/* 30 * Credits: 31 * 32 * Part of this code (especially in many magic numbers) was heavily inspired 33 * by the Linux driver originally written by 34 * Alan Cox <alan.cox@linux.org>, modified heavily by 35 * Zach Brown <zab@zabbo.net>. 36 * 37 * busdma()-ize and buffer size reduction were suggested by 38 * Cameron Grant <gandalf@vilnya.demon.co.uk>. 39 * Also he showed me the way to use busdma() suite. 40 * 41 * Internal speaker problems on NEC VersaPro's and Dell Inspiron 7500 42 * were looked at by 43 * Munehiro Matsuda <haro@tk.kubota.co.jp>, 44 * who brought patches based on the Linux driver with some simplification. 45 */ 46 47#include <dev/sound/pcm/sound.h> 48#include <dev/sound/pcm/ac97.h> 49#include <pci/pcireg.h> 50#include <pci/pcivar.h> 51 52#include <dev/sound/pci/maestro_reg.h> 53 54SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/maestro.c 82180 2001-08-23 11:30:52Z cg $"); 55 56#define inline __inline 57 58/* 59 * 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_BUFSIZ 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 u_int playchns, active; 116 struct agg_chinfo pch[AGG_MAXPLAYCH]; 117 struct agg_chinfo rch; 118}; 119 120static inline void ringbus_setdest(struct agg_info*, int, int); 121 122static inline u_int16_t wp_rdreg(struct agg_info*, u_int16_t); 123static inline void wp_wrreg(struct agg_info*, u_int16_t, u_int16_t); 124static inline u_int16_t wp_rdapu(struct agg_info*, int, u_int16_t); 125static inline void wp_wrapu(struct agg_info*, int, u_int16_t, u_int16_t); 126static inline void wp_settimer(struct agg_info*, u_int); 127static inline void wp_starttimer(struct agg_info*); 128static inline void wp_stoptimer(struct agg_info*); 129 130static inline u_int16_t wc_rdreg(struct agg_info*, u_int16_t); 131static inline void wc_wrreg(struct agg_info*, u_int16_t, u_int16_t); 132static inline u_int16_t wc_rdchctl(struct agg_info*, int); 133static inline void wc_wrchctl(struct agg_info*, int, u_int16_t); 134 135static inline void agg_power(struct agg_info*, int); 136 137static void agg_init(struct agg_info*); 138 139static void aggch_start_dac(struct agg_chinfo*); 140static void aggch_stop_dac(struct agg_chinfo*); 141 142static inline void suppress_jitter(struct agg_chinfo*); 143 144static inline u_int calc_timer_freq(struct agg_chinfo*); 145static void set_timer(struct agg_info*); 146 147static void agg_intr(void *); 148static int agg_probe(device_t); 149static int agg_attach(device_t); 150static int agg_detach(device_t); 151static int agg_suspend(device_t); 152static int agg_resume(device_t); 153static int agg_shutdown(device_t); 154 155static void *dma_malloc(struct agg_info*, u_int32_t, bus_addr_t*); 156static void dma_free(struct agg_info*, void *); 157 158/* ----------------------------- 159 * Subsystems. 160 */ 161 162/* Codec/Ringbus */ 163 164/* -------------------------------------------------------------------- */ 165 166static u_int32_t 167agg_ac97_init(kobj_t obj, void *sc) 168{ 169 struct agg_info *ess = sc; 170 171 return (bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) & CODEC_STAT_MASK)? 0 : 1; 172} 173 174static int 175agg_rdcodec(kobj_t obj, void *sc, int regno) 176{ 177 struct agg_info *ess = sc; 178 unsigned t; 179 180 /* We have to wait for a SAFE time to write addr/data */ 181 for (t = 0; t < 20; t++) { 182 if ((bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) 183 & CODEC_STAT_MASK) != CODEC_STAT_PROGLESS) 184 break; 185 DELAY(2); /* 20.8us / 13 */ 186 } 187 if (t == 20) 188 device_printf(ess->dev, "agg_rdcodec() PROGLESS timed out.\n"); 189 190 bus_space_write_1(ess->st, ess->sh, PORT_CODEC_CMD, 191 CODEC_CMD_READ | regno); 192 DELAY(21); /* AC97 cycle = 20.8usec */ 193 194 /* Wait for data retrieve */ 195 for (t = 0; t < 20; t++) { 196 if ((bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) 197 & CODEC_STAT_MASK) == CODEC_STAT_RW_DONE) 198 break; 199 DELAY(2); /* 20.8us / 13 */ 200 } 201 if (t == 20) 202 /* Timed out, but perform dummy read. */ 203 device_printf(ess->dev, "agg_rdcodec() RW_DONE timed out.\n"); 204 205 return bus_space_read_2(ess->st, ess->sh, PORT_CODEC_REG); 206} 207 208static int 209agg_wrcodec(kobj_t obj, void *sc, int regno, u_int32_t data) 210{ 211 unsigned t; 212 struct agg_info *ess = sc; 213 214 /* We have to wait for a SAFE time to write addr/data */ 215 for (t = 0; t < 20; t++) { 216 if ((bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) 217 & CODEC_STAT_MASK) != CODEC_STAT_PROGLESS) 218 break; 219 DELAY(2); /* 20.8us / 13 */ 220 } 221 if (t == 20) { 222 /* Timed out. Abort writing. */ 223 device_printf(ess->dev, "agg_wrcodec() PROGLESS timed out.\n"); 224 return -1; 225 } 226 227 bus_space_write_2(ess->st, ess->sh, PORT_CODEC_REG, data); 228 bus_space_write_1(ess->st, ess->sh, PORT_CODEC_CMD, 229 CODEC_CMD_WRITE | regno); 230 231 return 0; 232} 233 234static kobj_method_t agg_ac97_methods[] = { 235 KOBJMETHOD(ac97_init, agg_ac97_init), 236 KOBJMETHOD(ac97_read, agg_rdcodec), 237 KOBJMETHOD(ac97_write, agg_wrcodec), 238 { 0, 0 } 239}; 240AC97_DECLARE(agg_ac97); 241 242/* -------------------------------------------------------------------- */ 243 244static inline void 245ringbus_setdest(struct agg_info *ess, int src, int dest) 246{ 247 u_int32_t data; 248 249 data = bus_space_read_4(ess->st, ess->sh, PORT_RINGBUS_CTRL); 250 data &= ~(0xfU << src); 251 data |= (0xfU & dest) << src; 252 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, data); 253} 254 255/* Wave Processor */ 256 257static inline u_int16_t 258wp_rdreg(struct agg_info *ess, u_int16_t reg) 259{ 260 bus_space_write_2(ess->st, ess->sh, PORT_DSP_INDEX, reg); 261 return bus_space_read_2(ess->st, ess->sh, PORT_DSP_DATA); 262} 263 264static inline void 265wp_wrreg(struct agg_info *ess, u_int16_t reg, u_int16_t data) 266{ 267 bus_space_write_2(ess->st, ess->sh, PORT_DSP_INDEX, reg); 268 bus_space_write_2(ess->st, ess->sh, PORT_DSP_DATA, data); 269} 270 271static inline void 272apu_setindex(struct agg_info *ess, u_int16_t reg) 273{ 274 int t; 275 276 wp_wrreg(ess, WPREG_CRAM_PTR, reg); 277 /* Sometimes WP fails to set apu register index. */ 278 for (t = 0; t < 1000; t++) { 279 if (bus_space_read_2(ess->st, ess->sh, PORT_DSP_DATA) == reg) 280 break; 281 bus_space_write_2(ess->st, ess->sh, PORT_DSP_DATA, reg); 282 } 283 if (t == 1000) 284 device_printf(ess->dev, "apu_setindex() timed out.\n"); 285} 286 287static inline u_int16_t 288wp_rdapu(struct agg_info *ess, int ch, u_int16_t reg) 289{ 290 u_int16_t ret; 291 292 apu_setindex(ess, ((unsigned)ch << 4) + reg); 293 ret = wp_rdreg(ess, WPREG_DATA_PORT); 294 return ret; 295} 296 297static inline void 298wp_wrapu(struct agg_info *ess, int ch, u_int16_t reg, u_int16_t data) 299{ 300 int t; 301 302 apu_setindex(ess, ((unsigned)ch << 4) + reg); 303 wp_wrreg(ess, WPREG_DATA_PORT, data); 304 for (t = 0; t < 1000; t++) { 305 if (bus_space_read_2(ess->st, ess->sh, PORT_DSP_DATA) == data) 306 break; 307 bus_space_write_2(ess->st, ess->sh, PORT_DSP_DATA, data); 308 } 309 if (t == 1000) 310 device_printf(ess->dev, "wp_wrapu() timed out.\n"); 311} 312 313static inline void 314wp_settimer(struct agg_info *ess, u_int freq) 315{ 316 u_int clock = 48000 << 2; 317 u_int prescale = 0, divide = (freq != 0) ? (clock / freq) : ~0; 318 319 RANGE(divide, 4, 32 << 8); 320 321 for (; divide > 32 << 1; divide >>= 1) 322 prescale++; 323 divide = (divide + 1) >> 1; 324 325 for (; prescale < 7 && divide > 2 && !(divide & 1); divide >>= 1) 326 prescale++; 327 328 wp_wrreg(ess, WPREG_TIMER_ENABLE, 0); 329 wp_wrreg(ess, WPREG_TIMER_FREQ, 330 (prescale << WP_TIMER_FREQ_PRESCALE_SHIFT) | (divide - 1)); 331 wp_wrreg(ess, WPREG_TIMER_ENABLE, 1); 332} 333 334static inline void 335wp_starttimer(struct agg_info *ess) 336{ 337 wp_wrreg(ess, WPREG_TIMER_START, 1); 338} 339 340static inline void 341wp_stoptimer(struct agg_info *ess) 342{ 343 wp_wrreg(ess, WPREG_TIMER_START, 0); 344 bus_space_write_2(ess->st, ess->sh, PORT_INT_STAT, 1); 345} 346 347/* WaveCache */ 348 349static inline u_int16_t 350wc_rdreg(struct agg_info *ess, u_int16_t reg) 351{ 352 bus_space_write_2(ess->st, ess->sh, PORT_WAVCACHE_INDEX, reg); 353 return bus_space_read_2(ess->st, ess->sh, PORT_WAVCACHE_DATA); 354} 355 356static inline void 357wc_wrreg(struct agg_info *ess, u_int16_t reg, u_int16_t data) 358{ 359 bus_space_write_2(ess->st, ess->sh, PORT_WAVCACHE_INDEX, reg); 360 bus_space_write_2(ess->st, ess->sh, PORT_WAVCACHE_DATA, data); 361} 362 363static inline u_int16_t 364wc_rdchctl(struct agg_info *ess, int ch) 365{ 366 return wc_rdreg(ess, ch << 3); 367} 368 369static inline void 370wc_wrchctl(struct agg_info *ess, int ch, u_int16_t data) 371{ 372 wc_wrreg(ess, ch << 3, data); 373} 374 375/* Power management */ 376 377static inline void 378agg_power(struct agg_info *ess, int status) 379{ 380 u_int8_t data; 381 382 data = pci_read_config(ess->dev, CONF_PM_PTR, 1); 383 if (pci_read_config(ess->dev, data, 1) == PPMI_CID) 384 pci_write_config(ess->dev, data + PM_CTRL, status, 1); 385} 386 387 388/* ----------------------------- 389 * Controller. 390 */ 391 392static inline void 393agg_initcodec(struct agg_info* ess) 394{ 395 u_int16_t data; 396 397 if (bus_space_read_4(ess->st, ess->sh, PORT_RINGBUS_CTRL) 398 & RINGBUS_CTRL_ACLINK_ENABLED) { 399 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 0); 400 DELAY(104); /* 20.8us * (4 + 1) */ 401 } 402 /* XXX - 2nd codec should be looked at. */ 403 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 404 RINGBUS_CTRL_AC97_SWRESET); 405 DELAY(2); 406 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 407 RINGBUS_CTRL_ACLINK_ENABLED); 408 DELAY(21); 409 410 agg_rdcodec(NULL, ess, 0); 411 if (bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) 412 & CODEC_STAT_MASK) { 413 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 0); 414 DELAY(21); 415 416 /* Try cold reset. */ 417 device_printf(ess->dev, "will perform cold reset.\n"); 418 data = bus_space_read_2(ess->st, ess->sh, PORT_GPIO_DIR); 419 if (pci_read_config(ess->dev, 0x58, 2) & 1) 420 data |= 0x10; 421 data |= 0x009 & 422 ~bus_space_read_2(ess->st, ess->sh, PORT_GPIO_DATA); 423 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_MASK, 0xff6); 424 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DIR, 425 data | 0x009); 426 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 0x000); 427 DELAY(2); 428 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 0x001); 429 DELAY(1); 430 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 0x009); 431 DELAY(500000); 432 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DIR, data); 433 DELAY(84); /* 20.8us * 4 */ 434 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 435 RINGBUS_CTRL_ACLINK_ENABLED); 436 DELAY(21); 437 } 438} 439 440static void 441agg_init(struct agg_info* ess) 442{ 443 u_int32_t data; 444 445 /* Setup PCI config registers. */ 446 447 /* Disable all legacy emulations. */ 448 data = pci_read_config(ess->dev, CONF_LEGACY, 2); 449 data |= LEGACY_DISABLED; 450 pci_write_config(ess->dev, CONF_LEGACY, data, 2); 451 452 /* Disconnect from CHI. (Makes Dell inspiron 7500 work?) 453 * Enable posted write. 454 * Prefer PCI timing rather than that of ISA. 455 * Don't swap L/R. */ 456 data = pci_read_config(ess->dev, CONF_MAESTRO, 4); 457 data |= MAESTRO_CHIBUS | MAESTRO_POSTEDWRITE | MAESTRO_DMA_PCITIMING; 458 data &= ~MAESTRO_SWAP_LR; 459 pci_write_config(ess->dev, CONF_MAESTRO, data, 4); 460 461 /* Reset direct sound. */ 462 bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 463 HOSTINT_CTRL_DSOUND_RESET); 464 DELAY(10000); /* XXX - too long? */ 465 bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 0); 466 DELAY(10000); 467 468 /* Enable direct sound interruption and hardware volume control. */ 469 bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 470 HOSTINT_CTRL_DSOUND_INT_ENABLED | HOSTINT_CTRL_HWVOL_ENABLED); 471 472 /* Setup Wave Processor. */ 473 474 /* Enable WaveCache, set DMA base address. */ 475 wp_wrreg(ess, WPREG_WAVE_ROMRAM, 476 WP_WAVE_VIRTUAL_ENABLED | WP_WAVE_DRAM_ENABLED); 477 bus_space_write_2(ess->st, ess->sh, PORT_WAVCACHE_CTRL, 478 WAVCACHE_ENABLED | WAVCACHE_WTSIZE_4MB); 479 480 for (data = WAVCACHE_PCMBAR; data < WAVCACHE_PCMBAR + 4; data++) 481 wc_wrreg(ess, data, ess->baseaddr >> WAVCACHE_BASEADDR_SHIFT); 482 483 /* Setup Codec/Ringbus. */ 484 agg_initcodec(ess); 485 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 486 RINGBUS_CTRL_RINGBUS_ENABLED | RINGBUS_CTRL_ACLINK_ENABLED); 487 488 wp_wrreg(ess, WPREG_BASE, 0x8500); /* Parallel I/O */ 489 ringbus_setdest(ess, RINGBUS_SRC_ADC, 490 RINGBUS_DEST_STEREO | RINGBUS_DEST_DSOUND_IN); 491 ringbus_setdest(ess, RINGBUS_SRC_DSOUND, 492 RINGBUS_DEST_STEREO | RINGBUS_DEST_DAC); 493 494 /* Setup ASSP. Needed for Dell Inspiron 7500? */ 495 bus_space_write_1(ess->st, ess->sh, PORT_ASSP_CTRL_B, 0x00); 496 bus_space_write_1(ess->st, ess->sh, PORT_ASSP_CTRL_A, 0x03); 497 bus_space_write_1(ess->st, ess->sh, PORT_ASSP_CTRL_C, 0x00); 498 499 /* 500 * Setup GPIO. 501 * There seems to be speciality with NEC systems. 502 */ 503 switch (pci_get_subvendor(ess->dev) 504 | (pci_get_subdevice(ess->dev) << 16)) { 505 case NEC_SUBID1: 506 case NEC_SUBID2: 507 /* Matthew Braithwaite <matt@braithwaite.net> reported that 508 * NEC Versa LX doesn't need GPIO operation. */ 509 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_MASK, 0x9ff); 510 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DIR, 511 bus_space_read_2(ess->st, ess->sh, PORT_GPIO_DIR) | 0x600); 512 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 0x200); 513 break; 514 } 515} 516 517/* Channel controller. */ 518 519static void 520aggch_start_dac(struct agg_chinfo *ch) 521{ 522 u_int wpwa = APU_USE_SYSMEM | (ch->offset >> 9); 523 u_int size = AGG_BUFSIZ >> 1; 524 u_int speed = ch->speed; 525 u_int offset = ch->offset >> 1; 526 u_int cp = 0; 527 u_int16_t apuch = ch->num << 1; 528 u_int dv; 529 int pan = 0; 530 531 switch (ch->aputype) { 532 case APUTYPE_16BITSTEREO: 533 wpwa >>= 1; 534 size >>= 1; 535 offset >>= 1; 536 cp >>= 1; 537 /* FALLTHROUGH */ 538 case APUTYPE_8BITSTEREO: 539 pan = 8; 540 apuch++; 541 break; 542 case APUTYPE_8BITLINEAR: 543 speed >>= 1; 544 break; 545 } 546 547 dv = (((speed % 48000) << 16) + 24000) / 48000 548 + ((speed / 48000) << 16); 549 550 do { 551 wp_wrapu(ch->parent, apuch, APUREG_WAVESPACE, wpwa & 0xff00); 552 wp_wrapu(ch->parent, apuch, APUREG_CURPTR, offset + cp); 553 wp_wrapu(ch->parent, apuch, APUREG_ENDPTR, offset + size); 554 wp_wrapu(ch->parent, apuch, APUREG_LOOPLEN, size); 555 wp_wrapu(ch->parent, apuch, APUREG_AMPLITUDE, 0xe800); 556 wp_wrapu(ch->parent, apuch, APUREG_POSITION, 0x8f00 557 | (RADIUS_CENTERCIRCLE << APU_RADIUS_SHIFT) 558 | ((PAN_FRONT + pan) << APU_PAN_SHIFT)); 559 wp_wrapu(ch->parent, apuch, APUREG_FREQ_LOBYTE, APU_plus6dB 560 | ((dv & 0xff) << APU_FREQ_LOBYTE_SHIFT)); 561 wp_wrapu(ch->parent, apuch, APUREG_FREQ_HIWORD, dv >> 8); 562 563 if (ch->aputype == APUTYPE_16BITSTEREO) 564 wpwa |= APU_STEREO >> 1; 565 pan = -pan; 566 } while (pan < 0 && apuch--); 567 568 wc_wrchctl(ch->parent, apuch, ch->wcreg_tpl); 569 wc_wrchctl(ch->parent, apuch + 1, ch->wcreg_tpl); 570 571 wp_wrapu(ch->parent, apuch, APUREG_APUTYPE, 572 (ch->aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf); 573 if (ch->wcreg_tpl & WAVCACHE_CHCTL_STEREO) 574 wp_wrapu(ch->parent, apuch + 1, APUREG_APUTYPE, 575 (ch->aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf); 576} 577 578static void 579aggch_stop_dac(struct agg_chinfo *ch) 580{ 581 wp_wrapu(ch->parent, (ch->num << 1), APUREG_APUTYPE, 582 APUTYPE_INACTIVE << APU_APUTYPE_SHIFT); 583 wp_wrapu(ch->parent, (ch->num << 1) + 1, APUREG_APUTYPE, 584 APUTYPE_INACTIVE << APU_APUTYPE_SHIFT); 585} 586 587/* 588 * Stereo jitter suppressor. 589 * Sometimes playback pointers differ in stereo-paired channels. 590 * Calling this routine within intr fixes the problem. 591 */ 592static inline void 593suppress_jitter(struct agg_chinfo *ch) 594{ 595 if (ch->wcreg_tpl & WAVCACHE_CHCTL_STEREO) { 596 int cp, diff, halfsize = AGG_BUFSIZ >> 2; 597 598 if (ch->aputype == APUTYPE_16BITSTEREO) 599 halfsize >>= 1; 600 cp = wp_rdapu(ch->parent, (ch->num << 1), APUREG_CURPTR); 601 diff = wp_rdapu(ch->parent, (ch->num << 1) + 1, APUREG_CURPTR); 602 diff -= cp; 603 if (diff >> 1 && diff > -halfsize && diff < halfsize) 604 bus_space_write_2(ch->parent->st, ch->parent->sh, 605 PORT_DSP_DATA, cp); 606 } 607} 608 609static inline u_int 610calc_timer_freq(struct agg_chinfo *ch) 611{ 612 u_int ss = 2; 613 614 if (ch->aputype == APUTYPE_16BITSTEREO) 615 ss <<= 1; 616 if (ch->aputype == APUTYPE_8BITLINEAR) 617 ss >>= 1; 618 619 return (ch->speed * ss) / ch->blocksize; 620} 621 622static void 623set_timer(struct agg_info *ess) 624{ 625 int i; 626 u_int freq = 0; 627 628 for (i = 0; i < ess->playchns; i++) 629 if ((ess->active & (1 << i)) && 630 (freq < calc_timer_freq(ess->pch + i))) 631 freq = calc_timer_freq(ess->pch + i); 632 633 wp_settimer(ess, freq); 634} 635 636 637/* ----------------------------- 638 * Newpcm glue. 639 */ 640 641static void * 642aggch_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) 643{ 644 struct agg_info *ess = devinfo; 645 struct agg_chinfo *ch; 646 bus_addr_t physaddr; 647 void *p; 648 649 ch = (dir == PCMDIR_PLAY)? ess->pch + ess->playchns : &ess->rch; 650 651 ch->parent = ess; 652 ch->channel = c; 653 ch->buffer = b; 654 ch->num = ess->playchns; 655 ch->dir = dir; 656 657 p = dma_malloc(ess, AGG_BUFSIZ, &physaddr); 658 if (p == NULL) 659 return NULL; 660 sndbuf_setup(b, p, AGG_BUFSIZ); 661 662 ch->offset = physaddr - ess->baseaddr; 663 if (physaddr < ess->baseaddr || ch->offset > WPWA_MAXADDR) { 664 device_printf(ess->dev, 665 "offset %#x exceeds limit. ", ch->offset); 666 dma_free(ess, sndbuf_getbuf(b)); 667 return NULL; 668 } 669 670 ch->wcreg_tpl = (physaddr - 16) & WAVCACHE_CHCTL_ADDRTAG_MASK; 671 672 if (dir == PCMDIR_PLAY) { 673 ess->playchns++; 674 if (bootverbose) 675 device_printf(ess->dev, "pch[%d].offset = %#x\n", ch->num, ch->offset); 676 } else if (bootverbose) 677 device_printf(ess->dev, "rch.offset = %#x\n", ch->offset); 678 679 return ch; 680} 681 682static int 683aggch_free(kobj_t obj, void *data) 684{ 685 struct agg_chinfo *ch = data; 686 struct agg_info *ess = ch->parent; 687 688 /* free up buffer - called after channel stopped */ 689 dma_free(ess, sndbuf_getbuf(ch->buffer)); 690 691 /* return 0 if ok */ 692 return 0; 693} 694 695static int 696aggch_setplayformat(kobj_t obj, void *data, u_int32_t format) 697{ 698 struct agg_chinfo *ch = data; 699 u_int16_t wcreg_tpl; 700 u_int16_t aputype = APUTYPE_16BITLINEAR; 701 702 wcreg_tpl = ch->wcreg_tpl & WAVCACHE_CHCTL_ADDRTAG_MASK; 703 704 if (format & AFMT_STEREO) { 705 wcreg_tpl |= WAVCACHE_CHCTL_STEREO; 706 aputype += 1; 707 } 708 if (format & AFMT_U8 || format & AFMT_S8) { 709 aputype += 2; 710 if (format & AFMT_U8) 711 wcreg_tpl |= WAVCACHE_CHCTL_U8; 712 } 713 if (format & AFMT_BIGENDIAN || format & AFMT_U16_LE) { 714 format &= ~AFMT_BIGENDIAN & ~AFMT_U16_LE; 715 format |= AFMT_S16_LE; 716 } 717 ch->wcreg_tpl = wcreg_tpl; 718 ch->aputype = aputype; 719 return format; 720} 721 722static int 723aggch_setspeed(kobj_t obj, void *data, u_int32_t speed) 724{ 725 struct agg_chinfo *ch = data; 726 727 ch->speed = speed; 728 return ch->speed; 729} 730 731static int 732aggch_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) 733{ 734 return ((struct agg_chinfo*)data)->blocksize = blocksize; 735} 736 737static int 738aggch_trigger(kobj_t obj, void *data, int go) 739{ 740 struct agg_chinfo *ch = data; 741 742 switch (go) { 743 case PCMTRIG_EMLDMAWR: 744 return 0; 745 case PCMTRIG_START: 746 ch->parent->active |= (1 << ch->num); 747 if (ch->dir == PCMDIR_PLAY) 748 aggch_start_dac(ch); 749#if 0 /* XXX - RECORDING */ 750 else 751 aggch_start_adc(ch); 752#endif 753 break; 754 case PCMTRIG_ABORT: 755 case PCMTRIG_STOP: 756 ch->parent->active &= ~(1 << ch->num); 757 if (ch->dir == PCMDIR_PLAY) 758 aggch_stop_dac(ch); 759#if 0 /* XXX - RECORDING */ 760 else 761 aggch_stop_adc(ch); 762#endif 763 break; 764 } 765 766 if (ch->parent->active) { 767 set_timer(ch->parent); 768 wp_starttimer(ch->parent); 769 } else 770 wp_stoptimer(ch->parent); 771 772 return 0; 773} 774 775static int 776aggch_getplayptr(kobj_t obj, void *data) 777{ 778 struct agg_chinfo *ch = data; 779 u_int cp; 780 781 cp = wp_rdapu(ch->parent, (ch->num << 1), APUREG_CURPTR); 782 if (ch->aputype == APUTYPE_16BITSTEREO) 783 cp = (0xffff << 2) & ((cp << 2) - ch->offset); 784 else 785 cp = (0xffff << 1) & ((cp << 1) - ch->offset); 786 787 return cp; 788} 789 790static struct pcmchan_caps * 791aggch_getcaps(kobj_t obj, void *data) 792{ 793 static u_int32_t playfmt[] = { 794 AFMT_U8, 795 AFMT_STEREO | AFMT_U8, 796 AFMT_S8, 797 AFMT_STEREO | AFMT_S8, 798 AFMT_S16_LE, 799 AFMT_STEREO | AFMT_S16_LE, 800 0 801 }; 802 static struct pcmchan_caps playcaps = {2000, 96000, playfmt, 0}; 803 804 static u_int32_t recfmt[] = { 805 AFMT_S8, 806 AFMT_STEREO | AFMT_S8, 807 AFMT_S16_LE, 808 AFMT_STEREO | AFMT_S16_LE, 809 0 810 }; 811 static struct pcmchan_caps reccaps = {4000, 48000, recfmt, 0}; 812 813 return (((struct agg_chinfo*)data)->dir == PCMDIR_PLAY)? 814 &playcaps : &reccaps; 815} 816 817static kobj_method_t aggch_methods[] = { 818 KOBJMETHOD(channel_init, aggch_init), 819 KOBJMETHOD(channel_free, aggch_free), 820 KOBJMETHOD(channel_setformat, aggch_setplayformat), 821 KOBJMETHOD(channel_setspeed, aggch_setspeed), 822 KOBJMETHOD(channel_setblocksize, aggch_setblocksize), 823 KOBJMETHOD(channel_trigger, aggch_trigger), 824 KOBJMETHOD(channel_getptr, aggch_getplayptr), 825 KOBJMETHOD(channel_getcaps, aggch_getcaps), 826 { 0, 0 } 827}; 828CHANNEL_DECLARE(aggch); 829 830/* ----------------------------- 831 * Bus space. 832 */ 833 834static void 835agg_intr(void *sc) 836{ 837 struct agg_info* ess = sc; 838 u_int16_t status; 839 int i; 840 841 status = bus_space_read_1(ess->st, ess->sh, PORT_HOSTINT_STAT); 842 if (!status) 843 return; 844 845 /* Acknowledge all. */ 846 bus_space_write_2(ess->st, ess->sh, PORT_INT_STAT, 1); 847 bus_space_write_1(ess->st, ess->sh, PORT_HOSTINT_STAT, 0xff); 848 849 if (status & HOSTINT_STAT_HWVOL) { 850 u_int event; 851 852 event = bus_space_read_1(ess->st, ess->sh, PORT_HWVOL_MASTER); 853 switch (event) { 854 case HWVOL_MUTE: 855 mixer_hwvol_mute(ess->dev); 856 break; 857 case HWVOL_UP: 858 mixer_hwvol_step(ess->dev, 1, 1); 859 break; 860 case HWVOL_DOWN: 861 mixer_hwvol_step(ess->dev, -1, -1); 862 break; 863 case HWVOL_NOP: 864 break; 865 default: 866 device_printf(ess->dev, "%s: unknown HWVOL event 0x%x\n", 867 device_get_nameunit(ess->dev), event); 868 } 869 bus_space_write_1(ess->st, ess->sh, PORT_HWVOL_MASTER, 870 HWVOL_NOP); 871 } 872 873 for (i = 0; i < ess->playchns; i++) 874 if (ess->active & (1 << i)) { 875 suppress_jitter(ess->pch + i); 876 chn_intr(ess->pch[i].channel); 877 } 878#if 0 /* XXX - RECORDING */ 879 if (ess->active & (1 << i)) 880 chn_intr(ess->rch.channel); 881#endif 882} 883 884static void 885setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error) 886{ 887 bus_addr_t *phys = arg; 888 889 *phys = error? 0 : segs->ds_addr; 890 891 if (bootverbose) { 892 printf("setmap (%lx, %lx), nseg=%d, error=%d\n", 893 (unsigned long)segs->ds_addr, (unsigned long)segs->ds_len, 894 nseg, error); 895 } 896} 897 898static void * 899dma_malloc(struct agg_info *sc, u_int32_t sz, bus_addr_t *phys) 900{ 901 void *buf; 902 bus_dmamap_t map; 903 904 if (bus_dmamem_alloc(sc->parent_dmat, &buf, BUS_DMA_NOWAIT, &map)) 905 return NULL; 906 if (bus_dmamap_load(sc->parent_dmat, map, buf, sz, setmap, phys, 0) 907 || !*phys) { 908 bus_dmamem_free(sc->parent_dmat, buf, map); 909 return NULL; 910 } 911 return buf; 912} 913 914static void 915dma_free(struct agg_info *sc, void *buf) 916{ 917 bus_dmamem_free(sc->parent_dmat, buf, NULL); 918} 919 920static int 921agg_probe(device_t dev) 922{ 923 char *s = NULL; 924 925 switch (pci_get_devid(dev)) { 926 case MAESTRO_1_PCI_ID: 927 s = "ESS Technology Maestro-1"; 928 break; 929 930 case MAESTRO_2_PCI_ID: 931 s = "ESS Technology Maestro-2"; 932 break; 933 934 case MAESTRO_2E_PCI_ID: 935 s = "ESS Technology Maestro-2E"; 936 break; 937 } 938 939 if (s != NULL && pci_get_class(dev) == PCIC_MULTIMEDIA) { 940 device_set_desc(dev, s); 941 return 0; 942 } 943 return ENXIO; 944} 945 946static int 947agg_attach(device_t dev) 948{ 949 struct agg_info *ess = NULL; 950 u_int32_t data; 951 int mapped = 0; 952 int regid = PCIR_MAPS; 953 struct resource *reg = NULL; 954 struct ac97_info *codec = NULL; 955 int irqid = 0; 956 struct resource *irq = NULL; 957 void *ih = NULL; 958 char status[SND_STATUSLEN]; 959 960 if ((ess = malloc(sizeof *ess, M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) { 961 device_printf(dev, "cannot allocate softc\n"); 962 return ENXIO; 963 } 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 PCM_SOFTC_SIZE, 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