1 /* 2 * Copyright (c) 1999 Cameron Grant <cg@freebsd.org> 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 /* 27 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 31 /* 32 * Copyright (C) 4Front Technologies 1996-2008. 33 */ 34 35 #include <sys/audio/audio_driver.h> 36 #include <sys/note.h> 37 #include <sys/pci.h> 38 #include <sys/stdbool.h> 39 40 41 /* 42 * NB: The Solo-1 is a bit schizophrenic compared to most devices. 43 * It has two separate DMA engines for PCM data. The first can do 44 * either capture or playback, and supports various Sound Blaster 45 * compatibility features. The second is dedicated to playback. The 46 * two engines have very little in common when it comes to programming 47 * them. 48 * 49 * We configure engine 1 for record, and engine 2 for playback. Both 50 * are configured for 48 kHz stereo 16-bit signed PCM. 51 */ 52 53 /* 54 * ESS Solo-1 only implements the low 24-bits on Audio1, and requires 55 * 64KB alignment. For Audio2, it implements the full 32-bit address 56 * space, but requires a 1MB address boundary. Audio1 is used for 57 * recording, and Audio2 is used for playback. 58 */ 59 static struct ddi_dma_attr dma_attr_audio1 = { 60 DMA_ATTR_VERSION, /* dma_attr_version */ 61 0x0, /* dma_attr_addr_lo */ 62 0x00ffffffU, /* dma_attr_addr_hi */ 63 0xffff, /* dma_attr_count_max */ 64 0x10000, /* dma_attr_align */ 65 0x7f, /* dma_attr_burstsizes */ 66 0x4, /* dma_attr_minxfer */ 67 0xffff, /* dma_attr_maxxfer */ 68 0xffff, /* dma_attr_seg */ 69 0x1, /* dma_attr_sgllen */ 70 0x1, /* dma_attr_granular */ 71 0 /* dma_attr_flags */ 72 }; 73 74 static struct ddi_dma_attr dma_attr_audio2 = { 75 DMA_ATTR_VERSION, /* dma_attr_version */ 76 0x0, /* dma_attr_addr_lo */ 77 0xffffffffU, /* dma_attr_addr_hi */ 78 0xfff0, /* dma_attr_count_max */ 79 0x100000, /* dma_attr_align */ 80 0x7f, /* dma_attr_burstsizes */ 81 0x4, /* dma_attr_minxfer */ 82 0xfff0, /* dma_attr_maxxfer */ 83 0xffff, /* dma_attr_seg */ 84 0x1, /* dma_attr_sgllen */ 85 0x1, /* dma_attr_granular */ 86 0 /* dma_attr_flags */ 87 }; 88 89 static ddi_device_acc_attr_t acc_attr = { 90 DDI_DEVICE_ATTR_V0, 91 DDI_STRUCTURE_LE_ACC, 92 DDI_STRICTORDER_ACC 93 }; 94 95 static ddi_device_acc_attr_t buf_attr = { 96 DDI_DEVICE_ATTR_V0, 97 DDI_NEVERSWAP_ACC, 98 DDI_STRICTORDER_ACC 99 }; 100 101 102 /* 103 * For the sake of simplicity, this driver fixes a few parameters with 104 * constants. 105 */ 106 #define SOLO_RATE 48000 107 #define SOLO_FRAGFR 1024 108 #define SOLO_NFRAGS 2 109 #define SOLO_NCHAN 2 110 #define SOLO_SAMPSZ 2 111 #define SOLO_FRAGSZ (SOLO_FRAGFR * (SOLO_NCHAN * SOLO_SAMPSZ)) 112 #define SOLO_BUFFR (SOLO_NFRAGS * SOLO_FRAGFR) 113 #define SOLO_BUFSZ (SOLO_NFRAGS * SOLO_FRAGSZ) 114 115 #define INPUT_MIC 0 116 #define INPUT_LINE 1 117 #define INPUT_CD 2 118 #define INPUT_AUX 3 119 #define INPUT_MONO 4 120 #define INSRCS 0x1f /* bits 0-4 */ 121 122 #define DRVNAME "audiosolo" 123 124 static const char *solo_insrcs[] = { 125 AUDIO_PORT_MIC, 126 AUDIO_PORT_LINEIN, 127 AUDIO_PORT_CD, 128 AUDIO_PORT_AUX1IN, 129 AUDIO_PORT_AUX2IN, /* this is really mono-in */ 130 NULL 131 }; 132 133 typedef struct solo_regs { 134 ddi_acc_handle_t acch; 135 caddr_t base; 136 } solo_regs_t; 137 138 typedef struct solo_engine { 139 struct solo_dev *dev; 140 audio_engine_t *engine; 141 ddi_dma_handle_t dmah; 142 ddi_acc_handle_t acch; 143 caddr_t kaddr; 144 uint32_t paddr; 145 146 bool started; 147 bool trigger; 148 uint64_t count; 149 uint16_t offset; 150 int syncdir; 151 int format; 152 bool swapped; 153 154 void (*start)(struct solo_engine *); 155 void (*stop)(struct solo_engine *); 156 void (*update)(struct solo_engine *); 157 } solo_engine_t; 158 159 typedef enum { 160 CTL_FRONT = 0, 161 CTL_VOLUME, 162 CTL_MIC, 163 CTL_LINE, 164 CTL_CD, 165 CTL_AUX, 166 CTL_MONO, 167 CTL_MICBOOST, 168 CTL_RECGAIN, 169 CTL_RECSRC, 170 CTL_MONSRC, 171 CTL_SPEAKER, 172 CTL_LOOPBACK, 173 CTL_NUM, /* must be last */ 174 } solo_ctrl_num_t; 175 176 typedef struct solo_ctrl { 177 struct solo_dev *dev; 178 audio_ctrl_t *ctrl; 179 solo_ctrl_num_t num; 180 uint64_t val; 181 } solo_ctrl_t; 182 183 typedef struct solo_dev { 184 dev_info_t *dip; 185 audio_dev_t *adev; 186 kmutex_t mutex; 187 ddi_intr_handle_t ihandle; 188 189 bool suspended; 190 191 /* 192 * Audio engines 193 */ 194 solo_engine_t rec; 195 solo_engine_t play; 196 uint32_t last_capture; 197 198 /* 199 * Controls. 200 */ 201 solo_ctrl_t ctrls[CTL_NUM]; 202 203 /* 204 * Mapped registers 205 */ 206 ddi_acc_handle_t pcih; 207 solo_regs_t io; 208 solo_regs_t sb; 209 solo_regs_t vc; 210 211 } solo_dev_t; 212 213 /* 214 * Common code for the pcm function 215 * 216 * solo_cmd write a single byte to the CMD port. 217 * solo_cmd1 write a CMD + 1 byte arg 218 * ess_get_byte returns a single byte from the DSP data port 219 * 220 * solo_write is actually solo_cmd1 221 * solo_read access ext. regs via solo_cmd(0xc0, reg) followed by solo_get_byte 222 */ 223 224 #define PORT_RD8(port, regno) \ 225 ddi_get8(port.acch, (void *)(port.base + (regno))) 226 #define PORT_RD16(port, regno) \ 227 ddi_get16(port.acch, (void *)(port.base + (regno))) 228 #define PORT_RD32(port, regno) \ 229 ddi_get32(port.acch, (void *)(port.base + (regno))) 230 #define PORT_WR8(port, regno, data) \ 231 ddi_put8(port.acch, (void *)(port.base + (regno)), data) 232 #define PORT_WR16(port, regno, data) \ 233 ddi_put16(port.acch, (void *)(port.base + (regno)), data) 234 #define PORT_WR32(port, regno, data) \ 235 ddi_put32(port.acch, (void *)(port.base + (regno)), data) 236 237 static bool 238 solo_dspready(solo_dev_t *dev) 239 { 240 return ((PORT_RD8(dev->sb, 0xc) & 0x80) == 0 ? true : false); 241 } 242 243 static bool 244 solo_dspwr(solo_dev_t *dev, uint8_t val) 245 { 246 int i; 247 248 for (i = 0; i < 1000; i++) { 249 if (solo_dspready(dev)) { 250 PORT_WR8(dev->sb, 0xc, val); 251 return (true); 252 } 253 if (i > 10) 254 drv_usecwait((i > 100)? 1000 : 10); 255 } 256 audio_dev_warn(dev->adev, "solo_dspwr(0x%02x) timed out", val); 257 return (false); 258 } 259 260 static bool 261 solo_cmd(solo_dev_t *dev, uint8_t val) 262 { 263 return (solo_dspwr(dev, val)); 264 } 265 266 static void 267 solo_cmd1(solo_dev_t *dev, uint8_t cmd, uint8_t val) 268 { 269 if (solo_dspwr(dev, cmd)) { 270 (void) solo_dspwr(dev, val); 271 } 272 } 273 274 static void 275 solo_setmixer(solo_dev_t *dev, uint8_t port, uint8_t value) 276 { 277 PORT_WR8(dev->sb, 0x4, port); /* Select register */ 278 drv_usecwait(10); 279 PORT_WR8(dev->sb, 0x5, value); 280 drv_usecwait(10); 281 } 282 283 static uint8_t 284 solo_getmixer(solo_dev_t *dev, uint8_t port) 285 { 286 uint8_t val; 287 288 PORT_WR8(dev->sb, 0x4, port); /* Select register */ 289 drv_usecwait(10); 290 val = PORT_RD8(dev->sb, 0x5); 291 drv_usecwait(10); 292 293 return (val); 294 } 295 296 static uint8_t 297 solo_get_byte(solo_dev_t *dev) 298 { 299 for (int i = 1000; i > 0; i--) { 300 if (PORT_RD8(dev->sb, 0xc) & 0x40) 301 return (PORT_RD8(dev->sb, 0xa)); 302 else 303 drv_usecwait(20); 304 } 305 audio_dev_warn(dev->adev, "timeout waiting to read DSP port"); 306 return (0xff); 307 } 308 309 static void 310 solo_write(solo_dev_t *dev, uint8_t reg, uint8_t val) 311 { 312 solo_cmd1(dev, reg, val); 313 } 314 315 static uint8_t 316 solo_read(solo_dev_t *dev, uint8_t reg) 317 { 318 if (solo_cmd(dev, 0xc0) && solo_cmd(dev, reg)) { 319 return (solo_get_byte(dev)); 320 } 321 return (0xff); 322 } 323 324 static bool 325 solo_reset_dsp(solo_dev_t *dev) 326 { 327 PORT_WR8(dev->sb, 0x6, 3); 328 drv_usecwait(100); 329 PORT_WR8(dev->sb, 0x6, 0); 330 if (solo_get_byte(dev) != 0xAA) { 331 audio_dev_warn(dev->adev, "solo_reset_dsp failed"); 332 return (false); /* Sorry */ 333 } 334 return (true); 335 } 336 337 static uint_t 338 solo_intr(caddr_t arg1, caddr_t arg2) 339 { 340 solo_dev_t *dev = (void *)arg1; 341 uint8_t status; 342 uint_t rv = DDI_INTR_UNCLAIMED; 343 344 _NOTE(ARGUNUSED(arg2)); 345 346 mutex_enter(&dev->mutex); 347 348 if (dev->suspended) { 349 mutex_exit(&dev->mutex); 350 return (rv); 351 } 352 353 status = PORT_RD8(dev->io, 0x7); 354 if (status & 0x20) { 355 rv = DDI_INTR_CLAIMED; 356 /* ack the interrupt */ 357 solo_setmixer(dev, 0x7a, solo_getmixer(dev, 0x7a) & ~0x80); 358 } 359 360 if (status & 0x10) { 361 rv = DDI_INTR_CLAIMED; 362 /* ack the interrupt */ 363 (void) PORT_RD8(dev->sb, 0xe); 364 } 365 mutex_exit(&dev->mutex); 366 367 return (rv); 368 } 369 370 static uint8_t 371 solo_mixer_scale(solo_dev_t *dev, solo_ctrl_num_t num) 372 { 373 uint32_t l, r; 374 uint64_t value = dev->ctrls[num].val; 375 376 l = (value >> 8) & 0xff; 377 r = value & 0xff; 378 379 l = (l * 15) / 100; 380 r = (r * 15) / 100; 381 return ((uint8_t)((l << 4) | (r))); 382 } 383 384 static void 385 solo_configure_mixer(solo_dev_t *dev) 386 { 387 uint32_t v; 388 uint32_t mon, rec; 389 390 /* 391 * We disable hardware volume control (i.e. async updates to volume). 392 * We could in theory support this, but making it work right can be 393 * tricky, and we doubt it is widely used. 394 */ 395 solo_setmixer(dev, 0x64, solo_getmixer(dev, 0x64) | 0xc); 396 solo_setmixer(dev, 0x66, 0); 397 398 /* master volume has 6 bits per channel, bit 6 indicates mute */ 399 /* left */ 400 v = (dev->ctrls[CTL_FRONT].val >> 8) & 0xff; 401 v = v ? (v * 63) / 100 : 64; 402 solo_setmixer(dev, 0x60, v & 0xff); 403 404 /* right */ 405 v = dev->ctrls[CTL_FRONT].val & 0xff; 406 v = v ? (v * 63) / 100 : 64; 407 solo_setmixer(dev, 0x62, v & 0xff); 408 409 v = solo_mixer_scale(dev, CTL_VOLUME); 410 v = v | (v << 4); 411 solo_setmixer(dev, 0x7c, v & 0xff); 412 solo_setmixer(dev, 0x14, v & 0xff); 413 414 mon = dev->ctrls[CTL_MONSRC].val; 415 rec = dev->ctrls[CTL_RECSRC].val; 416 417 /* 418 * The Solo-1 has dual stereo mixers (one for input and one for output), 419 * with separate volume controls for each. 420 */ 421 v = solo_mixer_scale(dev, CTL_MIC); 422 solo_setmixer(dev, 0x68, rec & (1 << INPUT_MIC) ? v : 0); 423 solo_setmixer(dev, 0x1a, mon & (1 << INPUT_MIC) ? v : 0); 424 425 v = solo_mixer_scale(dev, CTL_LINE); 426 solo_setmixer(dev, 0x6e, rec & (1 << INPUT_LINE) ? v : 0); 427 solo_setmixer(dev, 0x3e, mon & (1 << INPUT_LINE) ? v : 0); 428 429 v = solo_mixer_scale(dev, CTL_CD); 430 solo_setmixer(dev, 0x6a, rec & (1 << INPUT_CD) ? v : 0); 431 solo_setmixer(dev, 0x38, mon & (1 << INPUT_CD) ? v : 0); 432 433 v = solo_mixer_scale(dev, CTL_AUX); 434 solo_setmixer(dev, 0x6c, rec & (1 << INPUT_AUX) ? v : 0); 435 solo_setmixer(dev, 0x3a, mon & (1 << INPUT_AUX) ? v : 0); 436 437 v = solo_mixer_scale(dev, CTL_MONO); 438 v = v | (v << 4); 439 solo_setmixer(dev, 0x6f, rec & (1 << INPUT_MONO) ? v : 0); 440 solo_setmixer(dev, 0x6d, mon & (1 << INPUT_MONO) ? v : 0); 441 442 if (dev->ctrls[CTL_MICBOOST].val) { 443 solo_setmixer(dev, 0x7d, solo_getmixer(dev, 0x7d) | 0x8); 444 } else { 445 solo_setmixer(dev, 0x7d, solo_getmixer(dev, 0x7d) & ~(0x8)); 446 } 447 448 v = solo_mixer_scale(dev, CTL_RECGAIN); 449 v = v | (v << 4); 450 solo_write(dev, 0xb4, v & 0xff); 451 452 v = dev->ctrls[CTL_SPEAKER].val & 0xff; 453 v = (v * 7) / 100; 454 solo_setmixer(dev, 0x3c, v & 0xff); 455 456 if (dev->ctrls[CTL_LOOPBACK].val) { 457 /* record-what-you-hear mode */ 458 solo_setmixer(dev, 0x1c, 0x3); 459 } else { 460 /* use record mixer */ 461 solo_setmixer(dev, 0x1c, 0x5); 462 } 463 464 } 465 466 static int 467 solo_set_mixsrc(void *arg, uint64_t val) 468 { 469 solo_ctrl_t *pc = arg; 470 solo_dev_t *dev = pc->dev; 471 472 if ((val & ~INSRCS) != 0) 473 return (EINVAL); 474 475 mutex_enter(&dev->mutex); 476 pc->val = val; 477 solo_configure_mixer(dev); 478 mutex_exit(&dev->mutex); 479 return (0); 480 } 481 482 static int 483 solo_set_mono(void *arg, uint64_t val) 484 { 485 solo_ctrl_t *pc = arg; 486 solo_dev_t *dev = pc->dev; 487 488 val &= 0xff; 489 if (val > 100) 490 return (EINVAL); 491 492 val = (val & 0xff) | ((val & 0xff) << 8); 493 494 mutex_enter(&dev->mutex); 495 pc->val = val; 496 solo_configure_mixer(dev); 497 mutex_exit(&dev->mutex); 498 return (0); 499 } 500 501 static int 502 solo_set_stereo(void *arg, uint64_t val) 503 { 504 solo_ctrl_t *pc = arg; 505 solo_dev_t *dev = pc->dev; 506 uint8_t l; 507 uint8_t r; 508 509 l = (val & 0xff00) >> 8; 510 r = val & 0xff; 511 512 if ((l > 100) || (r > 100)) 513 return (EINVAL); 514 515 mutex_enter(&dev->mutex); 516 pc->val = val; 517 solo_configure_mixer(dev); 518 mutex_exit(&dev->mutex); 519 return (0); 520 } 521 522 static int 523 solo_set_bool(void *arg, uint64_t val) 524 { 525 solo_ctrl_t *pc = arg; 526 solo_dev_t *dev = pc->dev; 527 528 mutex_enter(&dev->mutex); 529 pc->val = val; 530 solo_configure_mixer(dev); 531 mutex_exit(&dev->mutex); 532 return (0); 533 } 534 535 static int 536 solo_get_value(void *arg, uint64_t *val) 537 { 538 solo_ctrl_t *pc = arg; 539 solo_dev_t *dev = pc->dev; 540 541 mutex_enter(&dev->mutex); 542 *val = pc->val; 543 mutex_exit(&dev->mutex); 544 return (0); 545 } 546 547 #define PLAYCTL (AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_PLAY) 548 #define RECCTL (AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_REC) 549 #define MONCTL (AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_MONITOR) 550 #define PCMVOL (PLAYCTL | AUDIO_CTRL_FLAG_PCMVOL) 551 #define MAINVOL (PLAYCTL | AUDIO_CTRL_FLAG_MAINVOL) 552 #define RECVOL (RECCTL | AUDIO_CTRL_FLAG_RECVOL) 553 554 static void 555 solo_alloc_ctrl(solo_dev_t *dev, uint32_t num, uint64_t val) 556 { 557 audio_ctrl_desc_t desc; 558 audio_ctrl_wr_t fn; 559 solo_ctrl_t *pc; 560 561 bzero(&desc, sizeof (desc)); 562 563 pc = &dev->ctrls[num]; 564 pc->num = num; 565 pc->dev = dev; 566 567 switch (num) { 568 case CTL_VOLUME: 569 desc.acd_name = AUDIO_CTRL_ID_VOLUME; 570 desc.acd_type = AUDIO_CTRL_TYPE_MONO; 571 desc.acd_minvalue = 0; 572 desc.acd_maxvalue = 100; 573 desc.acd_flags = PCMVOL; 574 fn = solo_set_mono; 575 break; 576 577 case CTL_FRONT: 578 desc.acd_name = AUDIO_CTRL_ID_LINEOUT; 579 desc.acd_type = AUDIO_CTRL_TYPE_STEREO; 580 desc.acd_minvalue = 0; 581 desc.acd_maxvalue = 100; 582 desc.acd_flags = MAINVOL; 583 fn = solo_set_stereo; 584 break; 585 586 case CTL_SPEAKER: 587 desc.acd_name = AUDIO_CTRL_ID_SPEAKER; 588 desc.acd_type = AUDIO_CTRL_TYPE_MONO; 589 desc.acd_minvalue = 0; 590 desc.acd_maxvalue = 100; 591 desc.acd_flags = MAINVOL; 592 fn = solo_set_mono; 593 break; 594 595 case CTL_MIC: 596 desc.acd_name = AUDIO_CTRL_ID_MIC; 597 desc.acd_type = AUDIO_CTRL_TYPE_STEREO; 598 desc.acd_minvalue = 0; 599 desc.acd_maxvalue = 100; 600 desc.acd_flags = RECVOL; 601 fn = solo_set_stereo; 602 break; 603 604 case CTL_LINE: 605 desc.acd_name = AUDIO_CTRL_ID_LINEIN; 606 desc.acd_type = AUDIO_CTRL_TYPE_STEREO; 607 desc.acd_minvalue = 0; 608 desc.acd_maxvalue = 100; 609 desc.acd_flags = RECVOL; 610 fn = solo_set_stereo; 611 break; 612 613 case CTL_CD: 614 desc.acd_name = AUDIO_CTRL_ID_CD; 615 desc.acd_type = AUDIO_CTRL_TYPE_STEREO; 616 desc.acd_minvalue = 0; 617 desc.acd_maxvalue = 100; 618 desc.acd_flags = RECVOL; 619 fn = solo_set_stereo; 620 break; 621 622 case CTL_AUX: 623 desc.acd_name = AUDIO_CTRL_ID_AUX1IN; 624 desc.acd_type = AUDIO_CTRL_TYPE_STEREO; 625 desc.acd_minvalue = 0; 626 desc.acd_maxvalue = 100; 627 desc.acd_flags = RECVOL; 628 fn = solo_set_stereo; 629 break; 630 631 case CTL_MONO: 632 desc.acd_name = AUDIO_CTRL_ID_AUX2IN; 633 desc.acd_type = AUDIO_CTRL_TYPE_MONO; 634 desc.acd_minvalue = 0; 635 desc.acd_maxvalue = 100; 636 desc.acd_flags = RECVOL; 637 fn = solo_set_mono; 638 break; 639 640 case CTL_RECSRC: 641 desc.acd_name = AUDIO_CTRL_ID_RECSRC; 642 desc.acd_type = AUDIO_CTRL_TYPE_ENUM; 643 desc.acd_minvalue = INSRCS; 644 desc.acd_maxvalue = INSRCS; 645 desc.acd_flags = RECCTL | AUDIO_CTRL_FLAG_MULTI; 646 for (int i = 0; solo_insrcs[i]; i++) { 647 desc.acd_enum[i] = solo_insrcs[i]; 648 } 649 fn = solo_set_mixsrc; 650 break; 651 652 case CTL_MONSRC: 653 desc.acd_name = AUDIO_CTRL_ID_MONSRC; 654 desc.acd_type = AUDIO_CTRL_TYPE_ENUM; 655 desc.acd_minvalue = INSRCS; 656 desc.acd_maxvalue = INSRCS; 657 desc.acd_flags = MONCTL | AUDIO_CTRL_FLAG_MULTI; 658 for (int i = 0; solo_insrcs[i]; i++) { 659 desc.acd_enum[i] = solo_insrcs[i]; 660 } 661 fn = solo_set_mixsrc; 662 break; 663 664 case CTL_MICBOOST: 665 desc.acd_name = AUDIO_CTRL_ID_MICBOOST; 666 desc.acd_type = AUDIO_CTRL_TYPE_BOOLEAN; 667 desc.acd_minvalue = 0; 668 desc.acd_maxvalue = 1; 669 desc.acd_flags = RECCTL; 670 fn = solo_set_bool; 671 break; 672 673 case CTL_LOOPBACK: 674 desc.acd_name = AUDIO_CTRL_ID_LOOPBACK; 675 desc.acd_type = AUDIO_CTRL_TYPE_BOOLEAN; 676 desc.acd_minvalue = 0; 677 desc.acd_maxvalue = 1; 678 desc.acd_flags = RECCTL; 679 fn = solo_set_bool; 680 break; 681 682 case CTL_RECGAIN: 683 desc.acd_name = AUDIO_CTRL_ID_RECGAIN; 684 desc.acd_type = AUDIO_CTRL_TYPE_STEREO; 685 desc.acd_minvalue = 0; 686 desc.acd_maxvalue = 100; 687 desc.acd_flags = RECCTL; 688 fn = solo_set_stereo; 689 break; 690 } 691 692 pc->val = val; 693 pc->ctrl = audio_dev_add_control(dev->adev, &desc, 694 solo_get_value, fn, pc); 695 } 696 697 static bool 698 solo_add_controls(solo_dev_t *dev) 699 { 700 solo_alloc_ctrl(dev, CTL_VOLUME, 0x4b); 701 solo_alloc_ctrl(dev, CTL_FRONT, 0x5a5a); 702 solo_alloc_ctrl(dev, CTL_SPEAKER, 0x4b); 703 solo_alloc_ctrl(dev, CTL_MIC, 0x3232); 704 solo_alloc_ctrl(dev, CTL_LINE, 0x4b4b); 705 solo_alloc_ctrl(dev, CTL_CD, 0x4b4b); 706 solo_alloc_ctrl(dev, CTL_AUX, 0); 707 solo_alloc_ctrl(dev, CTL_MONO, 0); 708 solo_alloc_ctrl(dev, CTL_RECSRC, (1U << INPUT_MIC)); 709 solo_alloc_ctrl(dev, CTL_MONSRC, 0); 710 solo_alloc_ctrl(dev, CTL_RECGAIN, 0x4b4b); 711 solo_alloc_ctrl(dev, CTL_MICBOOST, 1); 712 solo_alloc_ctrl(dev, CTL_LOOPBACK, 0); 713 714 return (true); 715 } 716 717 718 /* utility functions for ESS */ 719 static uint8_t 720 solo_calcfilter(int spd) 721 { 722 int cutoff; 723 724 cutoff = (spd * 9 * 82) / 20; 725 return (256 - (7160000 / cutoff)); 726 } 727 728 static void 729 solo_aud1_update(solo_engine_t *e) 730 { 731 solo_dev_t *dev = e->dev; 732 uint16_t offset, n; 733 uint32_t ptr; 734 uint32_t count; 735 uint32_t diff; 736 int tries; 737 738 ASSERT(mutex_owned(&dev->mutex)); 739 740 /* 741 * During recording, this register is known to give back 742 * garbage if it's not quiescent while being read. This hack 743 * attempts to work around it. We also suspend the DMA 744 * while we do this, to minimize record distortion. 745 */ 746 if (e->trigger) { 747 drv_usecwait(20); 748 } 749 for (tries = 10; tries; tries--) { 750 drv_usecwait(10); 751 ptr = PORT_RD32(dev->vc, 0); 752 count = PORT_RD16(dev->vc, 4); 753 diff = e->paddr + SOLO_BUFSZ - ptr - count; 754 if ((diff > 3) || (ptr < e->paddr) || 755 (ptr >= (e->paddr + SOLO_BUFSZ))) { 756 ptr = dev->last_capture; 757 } else { 758 break; 759 } 760 } 761 if (e->trigger) { 762 PORT_WR8(dev->vc, 0xf, 0); /* restart DMA */ 763 } 764 if (!tries) { 765 /* 766 * Note, this is a pretty bad situation, because we'll 767 * not have an accurate idea of our position. But its 768 * better than making a bad alteration. If we had FMA 769 * for audio devices, this would be a good point to 770 * raise a fault. 771 */ 772 return; 773 } 774 dev->last_capture = ptr; 775 offset = ptr - e->paddr; 776 offset /= (SOLO_NCHAN * SOLO_SAMPSZ); 777 778 n = offset >= e->offset ? 779 offset - e->offset : 780 offset + SOLO_BUFSZ - e->offset; 781 782 e->offset = offset; 783 e->count += n / (SOLO_NCHAN * SOLO_SAMPSZ); 784 } 785 786 static void 787 solo_aud1_start(solo_engine_t *e) 788 { 789 solo_dev_t *dev = e->dev; 790 int len; 791 uint32_t v; 792 793 ASSERT(mutex_owned(&dev->mutex)); 794 795 e->offset = 0; 796 len = SOLO_FRAGSZ / 2; 797 len = -len; 798 799 /* sample rate - 48 kHz */ 800 solo_write(dev, 0xa1, 0xf0); 801 /* filter cutoff */ 802 solo_write(dev, 0xa2, solo_calcfilter(SOLO_RATE)); 803 804 805 /* mono/stereo - bit 0 set, bit 1 clear */ 806 solo_write(dev, 0xa8, (solo_read(dev, 0xa8) & ~0x03) | 1); 807 808 (void) solo_cmd(dev, 0xd3); /* turn off DAC1 output */ 809 810 /* setup fifo for signed 16-bit stereo */ 811 solo_write(dev, 0xb7, 0x71); 812 solo_write(dev, 0xb7, 0xbc); 813 814 v = solo_mixer_scale(dev, CTL_RECGAIN); 815 v = v | (v << 4); 816 solo_write(dev, 0xb4, v & 0xff); 817 818 PORT_WR8(dev->vc, 0x8, 0xc4); /* command */ 819 PORT_WR8(dev->vc, 0xd, 0xff); /* clear DMA */ 820 PORT_WR8(dev->vc, 0xf, 0x01); /* stop DMA */ 821 822 PORT_WR8(dev->vc, 0xd, 0xff); /* reset */ 823 PORT_WR8(dev->vc, 0xf, 0x01); /* mask */ 824 PORT_WR8(dev->vc, 0xb, 0x14); /* mode */ 825 826 PORT_WR32(dev->vc, 0x0, e->paddr); 827 PORT_WR16(dev->vc, 0x4, SOLO_BUFSZ - 1); 828 829 /* transfer length low, high */ 830 solo_write(dev, 0xa4, len & 0x00ff); 831 solo_write(dev, 0xa5, (len & 0xff00) >> 8); 832 833 /* autoinit, dma dir, go for it */ 834 solo_write(dev, 0xb8, 0x0f); 835 PORT_WR8(dev->vc, 0xf, 0); /* start DMA */ 836 837 dev->last_capture = e->paddr; 838 e->trigger = true; 839 } 840 841 static void 842 solo_aud1_stop(solo_engine_t *e) 843 { 844 solo_dev_t *dev = e->dev; 845 846 /* NB: We might be in quiesce, without a lock held */ 847 solo_write(dev, 0xb8, solo_read(dev, 0xb8) & ~0x01); 848 e->trigger = false; 849 } 850 851 static void 852 solo_aud2_update(solo_engine_t *e) 853 { 854 solo_dev_t *dev = e->dev; 855 uint16_t offset = 0, n; 856 857 ASSERT(mutex_owned(&dev->mutex)); 858 859 offset = SOLO_BUFSZ - PORT_RD16(dev->io, 0x4); 860 offset /= (SOLO_NCHAN * SOLO_SAMPSZ); 861 862 n = offset >= e->offset ? 863 offset - e->offset : 864 offset + SOLO_BUFFR - e->offset; 865 866 e->offset = offset; 867 e->count += n; 868 } 869 870 static void 871 solo_aud2_start(solo_engine_t *e) 872 { 873 solo_dev_t *dev = e->dev; 874 int len; 875 uint32_t v; 876 877 ASSERT(mutex_owned(&dev->mutex)); 878 879 e->offset = 0; 880 len = SOLO_FRAGSZ / 2; 881 len = -len; 882 883 /* program transfer type */ 884 solo_setmixer(dev, 0x78, 0x10); 885 /* sample rate - 48 kHz */ 886 solo_setmixer(dev, 0x70, 0xf0); 887 solo_setmixer(dev, 0x72, solo_calcfilter(SOLO_RATE)); 888 /* transfer length low & high */ 889 solo_setmixer(dev, 0x74, len & 0x00ff); 890 solo_setmixer(dev, 0x76, (len & 0xff00) >> 8); 891 /* enable irq, set signed 16-bit stereo format */ 892 solo_setmixer(dev, 0x7a, 0x47); 893 894 PORT_WR8(dev->io, 0x6, 0); 895 PORT_WR32(dev->io, 0x0, e->paddr); 896 PORT_WR16(dev->io, 0x4, SOLO_BUFSZ); 897 898 /* this crazy initialization appears to help with fifo weirdness */ 899 /* start the engine running */ 900 solo_setmixer(dev, 0x78, 0x92); 901 drv_usecwait(10); 902 solo_setmixer(dev, 0x78, 0x93); 903 904 PORT_WR8(dev->io, 0x6, 0x0a); /* autoinit, enable */ 905 906 v = solo_mixer_scale(dev, CTL_VOLUME); 907 v = v | (v << 4); 908 solo_setmixer(dev, 0x7c, v & 0xff); 909 910 e->trigger = true; 911 } 912 913 static void 914 solo_aud2_stop(solo_engine_t *e) 915 { 916 solo_dev_t *dev = e->dev; 917 918 /* NB: We might be in quiesce, without a lock held */ 919 PORT_WR8(dev->io, 0x6, 0); 920 solo_setmixer(dev, 0x78, solo_getmixer(dev, 0x78) & ~0x03); 921 922 e->trigger = false; 923 } 924 925 /* 926 * Audio entry points. 927 */ 928 static int 929 solo_format(void *arg) 930 { 931 solo_engine_t *e = arg; 932 return (e->format); 933 } 934 935 static int 936 solo_channels(void *arg) 937 { 938 _NOTE(ARGUNUSED(arg)); 939 return (SOLO_NCHAN); 940 } 941 942 static int 943 solo_rate(void *arg) 944 { 945 _NOTE(ARGUNUSED(arg)); 946 return (SOLO_RATE); 947 } 948 949 static void 950 solo_chinfo(void *arg, int chan, unsigned *offset, unsigned *incr) 951 { 952 solo_engine_t *e = arg; 953 954 if (e->swapped) { 955 *offset = !chan; 956 } else { 957 *offset = chan; 958 } 959 *incr = 2; 960 } 961 962 static void 963 solo_sync(void *arg, unsigned nframes) 964 { 965 solo_engine_t *e = arg; 966 967 _NOTE(ARGUNUSED(nframes)); 968 969 (void) ddi_dma_sync(e->dmah, 0, 0, e->syncdir); 970 } 971 972 973 static uint64_t 974 solo_count(void *arg) 975 { 976 solo_engine_t *e = arg; 977 solo_dev_t *dev = e->dev; 978 uint64_t count; 979 980 mutex_enter(&dev->mutex); 981 e->update(e); 982 count = e->count; 983 mutex_exit(&dev->mutex); 984 985 return (count); 986 } 987 988 static int 989 solo_open(void *arg, int f, unsigned *nframes, caddr_t *buf) 990 { 991 solo_engine_t *e = arg; 992 solo_dev_t *dev = e->dev; 993 994 _NOTE(ARGUNUSED(f)); 995 996 *nframes = SOLO_NFRAGS * SOLO_FRAGFR; 997 *buf = e->kaddr; 998 999 mutex_enter(&dev->mutex); 1000 e->started = false; 1001 e->count = 0; 1002 mutex_exit(&dev->mutex); 1003 1004 return (0); 1005 } 1006 1007 void 1008 solo_close(void *arg) 1009 { 1010 solo_engine_t *e = arg; 1011 solo_dev_t *dev = e->dev; 1012 1013 mutex_enter(&dev->mutex); 1014 e->stop(e); 1015 e->started = false; 1016 mutex_exit(&dev->mutex); 1017 } 1018 1019 1020 static int 1021 solo_start(void *arg) 1022 { 1023 solo_engine_t *e = arg; 1024 solo_dev_t *dev = e->dev; 1025 1026 mutex_enter(&dev->mutex); 1027 if (!e->started) { 1028 e->start(e); 1029 e->started = true; 1030 } 1031 mutex_exit(&dev->mutex); 1032 1033 return (0); 1034 } 1035 1036 static void 1037 solo_stop(void *arg) 1038 { 1039 solo_engine_t *e = arg; 1040 solo_dev_t *dev = e->dev; 1041 1042 mutex_enter(&dev->mutex); 1043 if (e->started) { 1044 e->stop(e); 1045 e->started = false; 1046 } 1047 mutex_exit(&dev->mutex); 1048 1049 } 1050 1051 static audio_engine_ops_t solo_engine_ops = { 1052 AUDIO_ENGINE_VERSION, 1053 solo_open, 1054 solo_close, 1055 solo_start, 1056 solo_stop, 1057 solo_count, 1058 solo_format, 1059 solo_channels, 1060 solo_rate, 1061 solo_sync, 1062 NULL, 1063 solo_chinfo, 1064 NULL, 1065 }; 1066 1067 static void 1068 solo_release_resources(solo_dev_t *dev) 1069 { 1070 if (dev->ihandle != NULL) { 1071 (void) ddi_intr_disable(dev->ihandle); 1072 (void) ddi_intr_remove_handler(dev->ihandle); 1073 (void) ddi_intr_free(dev->ihandle); 1074 mutex_destroy(&dev->mutex); 1075 } 1076 1077 if (dev->io.acch != NULL) { 1078 ddi_regs_map_free(&dev->io.acch); 1079 } 1080 1081 if (dev->sb.acch != NULL) { 1082 ddi_regs_map_free(&dev->sb.acch); 1083 } 1084 1085 if (dev->vc.acch != NULL) { 1086 ddi_regs_map_free(&dev->vc.acch); 1087 } 1088 1089 if (dev->pcih != NULL) { 1090 pci_config_teardown(&dev->pcih); 1091 } 1092 1093 /* release play resources */ 1094 if (dev->play.paddr != 0) 1095 (void) ddi_dma_unbind_handle(dev->play.dmah); 1096 if (dev->play.acch != NULL) 1097 ddi_dma_mem_free(&dev->play.acch); 1098 if (dev->play.dmah != NULL) 1099 ddi_dma_free_handle(&dev->play.dmah); 1100 1101 if (dev->play.engine != NULL) { 1102 audio_dev_remove_engine(dev->adev, dev->play.engine); 1103 audio_engine_free(dev->play.engine); 1104 } 1105 1106 /* release record resources */ 1107 if (dev->rec.paddr != 0) 1108 (void) ddi_dma_unbind_handle(dev->rec.dmah); 1109 if (dev->rec.acch != NULL) 1110 ddi_dma_mem_free(&dev->rec.acch); 1111 if (dev->rec.dmah != NULL) 1112 ddi_dma_free_handle(&dev->rec.dmah); 1113 1114 if (dev->rec.engine != NULL) { 1115 audio_dev_remove_engine(dev->adev, dev->rec.engine); 1116 audio_engine_free(dev->rec.engine); 1117 } 1118 1119 for (int i = 0; i < CTL_NUM; i++) { 1120 if (dev->ctrls[i].ctrl != NULL) { 1121 audio_dev_del_control(dev->ctrls[i].ctrl); 1122 } 1123 } 1124 1125 if (dev->adev != NULL) { 1126 audio_dev_free(dev->adev); 1127 } 1128 1129 kmem_free(dev, sizeof (*dev)); 1130 } 1131 1132 static bool 1133 solo_setup_interrupts(solo_dev_t *dev) 1134 { 1135 int actual; 1136 uint_t ipri; 1137 1138 if ((ddi_intr_alloc(dev->dip, &dev->ihandle, DDI_INTR_TYPE_FIXED, 1139 0, 1, &actual, DDI_INTR_ALLOC_NORMAL) != DDI_SUCCESS) || 1140 (actual != 1)) { 1141 audio_dev_warn(dev->adev, "can't alloc intr handle"); 1142 return (false); 1143 } 1144 1145 if (ddi_intr_get_pri(dev->ihandle, &ipri) != DDI_SUCCESS) { 1146 audio_dev_warn(dev->adev, "can't determine intr priority"); 1147 (void) ddi_intr_free(dev->ihandle); 1148 dev->ihandle = NULL; 1149 return (false); 1150 } 1151 1152 if (ddi_intr_add_handler(dev->ihandle, solo_intr, dev, 1153 NULL) != DDI_SUCCESS) { 1154 audio_dev_warn(dev->adev, "can't add intr handler"); 1155 (void) ddi_intr_free(dev->ihandle); 1156 dev->ihandle = NULL; 1157 return (false); 1158 } 1159 1160 mutex_init(&dev->mutex, NULL, MUTEX_DRIVER, DDI_INTR_PRI(ipri)); 1161 1162 return (true); 1163 } 1164 1165 static bool 1166 solo_map_registers(solo_dev_t *dev) 1167 { 1168 dev_info_t *dip = dev->dip; 1169 1170 /* map registers */ 1171 if (ddi_regs_map_setup(dip, 1, &dev->io.base, 0, 0, &acc_attr, 1172 &dev->io.acch) != DDI_SUCCESS) { 1173 audio_dev_warn(dev->adev, "can't map IO registers"); 1174 return (false); 1175 } 1176 if (ddi_regs_map_setup(dip, 2, &dev->sb.base, 0, 0, &acc_attr, 1177 &dev->sb.acch) != DDI_SUCCESS) { 1178 audio_dev_warn(dev->adev, "can't map SB registers"); 1179 return (false); 1180 } 1181 if (ddi_regs_map_setup(dip, 3, &dev->vc.base, 0, 0, &acc_attr, 1182 &dev->vc.acch) != DDI_SUCCESS) { 1183 audio_dev_warn(dev->adev, "can't map VC registers"); 1184 return (false); 1185 } 1186 1187 return (true); 1188 } 1189 1190 #define ESS_PCI_LEGACYCONTROL 0x40 1191 #define ESS_PCI_CONFIG 0x50 1192 #define ESS_PCI_DDMACONTROL 0x60 1193 1194 static bool 1195 solo_init_hw(solo_dev_t *dev) 1196 { 1197 uint32_t data; 1198 1199 /* 1200 * Legacy audio register -- disable legacy audio. We also 1201 * arrange for 16-bit I/O address decoding. 1202 */ 1203 /* this version disables the MPU, FM synthesis (Adlib), and Game Port */ 1204 pci_config_put16(dev->pcih, ESS_PCI_LEGACYCONTROL, 0x8041); 1205 1206 /* 1207 * Note that Solo-1 uses I/O space for all BARs, and hardwires 1208 * the upper 32-bits to zero. 1209 */ 1210 data = pci_config_get32(dev->pcih, PCI_CONF_BASE2); 1211 data |= 1; 1212 pci_config_put16(dev->pcih, ESS_PCI_DDMACONTROL, data & 0xffff); 1213 1214 /* 1215 * Make sure that legacy IRQ and DRQ are disbled. We disable most 1216 * other legacy features too. 1217 */ 1218 pci_config_put16(dev->pcih, ESS_PCI_CONFIG, 0); 1219 1220 if (!solo_reset_dsp(dev)) 1221 return (false); 1222 1223 /* enable extended mode */ 1224 (void) solo_cmd(dev, 0xc6); 1225 1226 1227 PORT_WR8(dev->io, 0x7, 0x30); /* enable audio irqs */ 1228 1229 /* demand mode, 4 bytes/xfer */ 1230 solo_write(dev, 0xb9, 0x01); 1231 1232 /* 1233 * This sets Audio 2 (playback) to use its own independent 1234 * rate control, and gives us 48 kHz compatible divisors. It 1235 * also bypasses the switched capacitor filter. 1236 */ 1237 solo_setmixer(dev, 0x71, 0x2a); 1238 1239 /* irq control */ 1240 solo_write(dev, 0xb1, (solo_read(dev, 0xb1) & 0x0f) | 0x50); 1241 /* drq control */ 1242 solo_write(dev, 0xb2, (solo_read(dev, 0xb2) & 0x0f) | 0x50); 1243 1244 solo_setmixer(dev, 0, 0); /* reset mixer settings */ 1245 1246 solo_configure_mixer(dev); 1247 return (true); 1248 } 1249 1250 static bool 1251 solo_alloc_engine(solo_dev_t *dev, int engno) 1252 { 1253 size_t rlen; 1254 ddi_dma_attr_t *dattr; 1255 ddi_dma_cookie_t c; 1256 unsigned ccnt; 1257 unsigned caps; 1258 unsigned dflags; 1259 const char *desc; 1260 solo_engine_t *e; 1261 1262 ASSERT((engno == 1) || (engno = 2)); 1263 1264 switch (engno) { 1265 case 1: /* record */ 1266 e = &dev->rec; 1267 desc = "record"; 1268 dattr = &dma_attr_audio1; 1269 caps = ENGINE_INPUT_CAP; 1270 dflags = DDI_DMA_READ | DDI_DMA_CONSISTENT; 1271 e->syncdir = DDI_DMA_SYNC_FORKERNEL; 1272 e->update = solo_aud1_update; 1273 e->start = solo_aud1_start; 1274 e->stop = solo_aud1_stop; 1275 e->format = AUDIO_FORMAT_S16_BE; 1276 e->swapped = true; 1277 break; 1278 1279 case 2: /* playback */ 1280 e = &dev->play; 1281 desc = "playback"; 1282 dattr = &dma_attr_audio2; 1283 caps = ENGINE_OUTPUT_CAP; 1284 dflags = DDI_DMA_WRITE | DDI_DMA_CONSISTENT; 1285 e->syncdir = DDI_DMA_SYNC_FORDEV; 1286 e->update = solo_aud2_update; 1287 e->start = solo_aud2_start; 1288 e->stop = solo_aud2_stop; 1289 e->format = AUDIO_FORMAT_S16_LE; 1290 e->swapped = false; 1291 break; 1292 1293 default: 1294 audio_dev_warn(dev->adev, "bad engine number!"); 1295 return (false); 1296 } 1297 1298 e->dev = dev; 1299 1300 if (ddi_dma_alloc_handle(dev->dip, dattr, DDI_DMA_SLEEP, NULL, 1301 &e->dmah) != DDI_SUCCESS) { 1302 audio_dev_warn(dev->adev, "%s dma handle alloc failed", desc); 1303 return (false); 1304 } 1305 if (ddi_dma_mem_alloc(e->dmah, SOLO_BUFSZ, &buf_attr, 1306 DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &e->kaddr, 1307 &rlen, &e->acch) != DDI_SUCCESS) { 1308 audio_dev_warn(dev->adev, "%s dma memory alloc failed", desc); 1309 return (false); 1310 } 1311 /* ensure that the buffer is zeroed out properly */ 1312 bzero(e->kaddr, rlen); 1313 if (ddi_dma_addr_bind_handle(e->dmah, NULL, e->kaddr, SOLO_BUFSZ, 1314 dflags, DDI_DMA_SLEEP, NULL, &c, &ccnt) != DDI_DMA_MAPPED) { 1315 audio_dev_warn(dev->adev, "%s dma binding failed", desc); 1316 return (false); 1317 } 1318 e->paddr = c.dmac_address; 1319 1320 /* 1321 * Allocate and configure audio engine. 1322 */ 1323 e->engine = audio_engine_alloc(&solo_engine_ops, caps); 1324 if (e->engine == NULL) { 1325 audio_dev_warn(dev->adev, "record audio_engine_alloc failed"); 1326 return (false); 1327 } 1328 1329 audio_engine_set_private(e->engine, e); 1330 audio_dev_add_engine(dev->adev, e->engine); 1331 1332 return (true); 1333 } 1334 1335 1336 static int 1337 solo_suspend(solo_dev_t *dev) 1338 { 1339 audio_dev_suspend(dev->adev); 1340 1341 mutex_enter(&dev->mutex); 1342 dev->suspended = true; 1343 mutex_exit(&dev->mutex); 1344 1345 return (DDI_SUCCESS); 1346 } 1347 1348 static int 1349 solo_resume(solo_dev_t *dev) 1350 { 1351 mutex_enter(&dev->mutex); 1352 if (!solo_init_hw(dev)) { 1353 /* yikes! */ 1354 audio_dev_warn(dev->adev, "unable to resume audio!"); 1355 audio_dev_warn(dev->adev, "reboot or reload driver to reset"); 1356 } 1357 dev->suspended = false; 1358 mutex_exit(&dev->mutex); 1359 1360 audio_dev_resume(dev->adev); 1361 1362 return (DDI_SUCCESS); 1363 } 1364 1365 static int 1366 solo_attach(dev_info_t *dip) 1367 { 1368 solo_dev_t *dev; 1369 uint32_t data; 1370 1371 dev = kmem_zalloc(sizeof (*dev), KM_SLEEP); 1372 dev->dip = dip; 1373 ddi_set_driver_private(dip, dev); 1374 1375 dev->adev = audio_dev_alloc(dip, 0); 1376 if (dev->adev == NULL) 1377 goto no; 1378 1379 audio_dev_set_description(dev->adev, "ESS Solo-1 PCI AudioDrive"); 1380 audio_dev_set_version(dev->adev, "ES1938"); 1381 1382 if (pci_config_setup(dip, &dev->pcih) != DDI_SUCCESS) { 1383 audio_dev_warn(NULL, "pci_config_setup failed"); 1384 goto no; 1385 } 1386 1387 data = pci_config_get16(dev->pcih, PCI_CONF_COMM); 1388 data |= PCI_COMM_ME | PCI_COMM_IO; 1389 pci_config_put16(dev->pcih, PCI_CONF_COMM, data); 1390 1391 if ((!solo_map_registers(dev)) || 1392 (!solo_setup_interrupts(dev)) || 1393 (!solo_alloc_engine(dev, 1)) || 1394 (!solo_alloc_engine(dev, 2)) || 1395 (!solo_add_controls(dev)) || 1396 (!solo_init_hw(dev))) { 1397 goto no; 1398 } 1399 1400 if (audio_dev_register(dev->adev) != DDI_SUCCESS) { 1401 audio_dev_warn(dev->adev, 1402 "unable to register with audio framework"); 1403 goto no; 1404 } 1405 1406 (void) ddi_intr_enable(dev->ihandle); 1407 ddi_report_dev(dip); 1408 1409 return (DDI_SUCCESS); 1410 1411 no: 1412 solo_release_resources(dev); 1413 return (DDI_FAILURE); 1414 } 1415 1416 static int 1417 solo_detach(solo_dev_t *dev) 1418 { 1419 if (audio_dev_unregister(dev->adev) != DDI_SUCCESS) { 1420 return (DDI_FAILURE); 1421 } 1422 1423 solo_release_resources(dev); 1424 return (DDI_SUCCESS); 1425 } 1426 1427 static int 1428 solo_ddi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 1429 { 1430 solo_dev_t *dev; 1431 1432 switch (cmd) { 1433 case DDI_ATTACH: 1434 return (solo_attach(dip)); 1435 1436 case DDI_RESUME: 1437 if ((dev = ddi_get_driver_private(dip)) == NULL) { 1438 return (DDI_FAILURE); 1439 } 1440 return (solo_resume(dev)); 1441 1442 default: 1443 return (DDI_FAILURE); 1444 } 1445 } 1446 1447 static int 1448 solo_ddi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 1449 { 1450 solo_dev_t *dev; 1451 1452 if ((dev = ddi_get_driver_private(dip)) == NULL) { 1453 return (DDI_FAILURE); 1454 } 1455 1456 switch (cmd) { 1457 case DDI_DETACH: 1458 return (solo_detach(dev)); 1459 1460 case DDI_SUSPEND: 1461 return (solo_suspend(dev)); 1462 default: 1463 return (DDI_FAILURE); 1464 } 1465 } 1466 1467 static int 1468 solo_quiesce(dev_info_t *dip) 1469 { 1470 solo_dev_t *dev; 1471 1472 dev = ddi_get_driver_private(dip); 1473 1474 solo_aud1_stop(&dev->rec); 1475 solo_aud2_stop(&dev->play); 1476 1477 solo_setmixer(dev, 0, 0); 1478 PORT_WR8(dev->io, 0x7, 0); /* disable all irqs */ 1479 return (0); 1480 } 1481 1482 struct dev_ops solo_dev_ops = { 1483 DEVO_REV, /* rev */ 1484 0, /* refcnt */ 1485 NULL, /* getinfo */ 1486 nulldev, /* identify */ 1487 nulldev, /* probe */ 1488 solo_ddi_attach, /* attach */ 1489 solo_ddi_detach, /* detach */ 1490 nodev, /* reset */ 1491 NULL, /* cb_ops */ 1492 NULL, /* bus_ops */ 1493 NULL, /* power */ 1494 solo_quiesce, /* quiesce */ 1495 }; 1496 1497 static struct modldrv solo_modldrv = { 1498 &mod_driverops, /* drv_modops */ 1499 "ESS Solo-1 Audio", /* linkinfo */ 1500 &solo_dev_ops, /* dev_ops */ 1501 }; 1502 1503 static struct modlinkage modlinkage = { 1504 MODREV_1, 1505 { &solo_modldrv, NULL } 1506 }; 1507 1508 int 1509 _init(void) 1510 { 1511 int rv; 1512 1513 audio_init_ops(&solo_dev_ops, DRVNAME); 1514 if ((rv = mod_install(&modlinkage)) != 0) { 1515 audio_fini_ops(&solo_dev_ops); 1516 } 1517 return (rv); 1518 } 1519 1520 int 1521 _fini(void) 1522 { 1523 int rv; 1524 1525 if ((rv = mod_remove(&modlinkage)) == 0) { 1526 audio_fini_ops(&solo_dev_ops); 1527 } 1528 return (rv); 1529 } 1530 1531 int 1532 _info(struct modinfo *modinfop) 1533 { 1534 return (mod_info(&modlinkage, modinfop)); 1535 } 1536