Print this page
6973 audioens driver does not work on VMWare
Reviewed by: Toomas Soome <tsoome@me.com>
Reviewed by: Igor Kozhukhov <ikozhukhov@gmail.com>
Approved by: TBD


   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.

  23  */
  24 /*
  25  * Purpose: Creative/Ensoniq AudioPCI97  driver (ES1371/ES1373)
  26  *
  27  * This driver is used with the original Ensoniq AudioPCI97 card and many
  28  * PCI based Sound Blaster cards by Creative Technologies. For example
  29  * Sound Blaster PCI128 and Creative/Ectiva EV1938.
  30  */
  31 
  32 /*
  33  * This file is part of Open Sound System
  34  *
  35  * Copyright (C) 4Front Technologies 1996-2008.
  36  *
  37  * This software is released under CDDL 1.0 source license.
  38  * See the COPYING file included in the main directory of this source
  39  * distribution for the license terms and conditions.
  40  */
  41 
  42 #include <sys/audio/audio_driver.h>
  43 #include <sys/audio/ac97.h>
  44 #include <sys/note.h>
  45 #include <sys/pci.h>












  46 #include "audioens.h"
  47 
  48 /*
  49  * Set the latency to 32, 64, 96, 128 clocks - some APCI97 devices exhibit
  50  * garbled audio in some cases and setting the latency to higer values fixes it
  51  * Values: 32, 64, 96, 128 - Default: 64 (or defined by bios)
  52  */
  53 int audioens_latency = 0;
  54 
  55 /*
  56  * Enable SPDIF port on SoundBlaster 128D or Sound Blaster Digital-4.1 models
  57  * Values: 1=Enable 0=Disable Default: 0
  58  */
  59 int audioens_spdif = 0;
  60 
  61 /*
  62  * Note: Latest devices can support SPDIF with AC3 pass thru.
  63  * However, in order to do this, one of the two DMA engines must be
  64  * dedicated to this, which would prevent the card from supporting 4
  65  * channel audio.  For now we don't bother with the AC3 pass through


  78 
  79 #define DEFRATE                 48000
  80 #define DRVNAME                 "audioens"
  81 
  82 typedef struct audioens_port
  83 {
  84         /* Audio parameters */
  85         int                     speed;
  86 
  87         int                     num;
  88 #define PORT_DAC                0
  89 #define PORT_ADC                1
  90 #define PORT_MAX                PORT_ADC
  91 
  92         caddr_t                 kaddr;
  93         uint32_t                paddr;
  94         ddi_acc_handle_t        acch;
  95         ddi_dma_handle_t        dmah;
  96         int                     nchan;
  97         unsigned                nframes;

  98         unsigned                frameno;
  99         uint64_t                count;
 100 
 101         struct audioens_dev     *dev;
 102         audio_engine_t  *engine;
 103 } audioens_port_t;
 104 
 105 typedef struct audioens_dev
 106 {
 107         audio_dev_t             *osdev;
 108         kmutex_t                mutex;
 109         uint16_t                devid;
 110         uint8_t                 revision;
 111         dev_info_t              *dip;
 112 
 113         audioens_port_t         port[PORT_MAX + 1];
 114 
 115         ac97_t                  *ac97;
 116 
 117         caddr_t                 regs;
 118         ddi_acc_handle_t        acch;








 119 } audioens_dev_t;
 120 
 121 static ddi_device_acc_attr_t acc_attr = {
 122         DDI_DEVICE_ATTR_V0,
 123         DDI_STRUCTURE_LE_ACC,
 124         DDI_STRICTORDER_ACC
 125 };
 126 
 127 static ddi_device_acc_attr_t buf_attr = {
 128         DDI_DEVICE_ATTR_V0,
 129         DDI_NEVERSWAP_ACC,
 130         DDI_STRICTORDER_ACC
 131 };
 132 
 133 /*
 134  * The hardware appears to be able to address up to 16-bits worth of longwords,
 135  * giving a total address space of 256K.  But we need substantially less.
 136  */
 137 #define AUDIOENS_BUF_LEN        (16384)
 138 
 139 static ddi_dma_attr_t dma_attr = {
 140         DMA_ATTR_VERSION,       /* dma_attr_version */
 141         0x0,                    /* dma_attr_addr_lo */
 142         0xffffffffU,            /* dma_attr_addr_hi */
 143         0x3ffff,                /* dma_attr_count_max */
 144         0x8,                    /* dma_attr_align */
 145         0x7f,                   /* dma_attr_burstsizes */
 146         0x1,                    /* dma_attr_minxfer */
 147         0x3ffff,                /* dma_attr_maxxfer */
 148         0x3ffff,                /* dma_attr_seg */
 149         0x1,                    /* dma_attr_sgllen */
 150         0x1,                    /* dma_attr_granular */
 151         0                       /* dma_attr_flags */
 152 };
 153 
 154 #define GET8(dev, offset)       \
 155         ddi_get8(dev->acch, (uint8_t *)(dev->regs + (offset)))
 156 #define GET16(dev, offset)      \
 157         ddi_get16(dev->acch, (uint16_t *)(void *)(dev->regs + (offset)))
 158 #define GET32(dev, offset)      \


 372         }
 373         PUT32(dev, CONC_dSRCIO_OFF, 0);
 374 }
 375 
 376 static void
 377 audioens_writemem(audioens_dev_t *dev, uint32_t page, uint32_t offs,
 378     uint32_t data)
 379 {
 380         /* Select memory page */
 381         PUT32(dev, CONC_bMEMPAGE_OFF, page);
 382         PUT32(dev, offs, data);
 383 }
 384 
 385 static uint32_t
 386 audioens_readmem(audioens_dev_t *dev, uint32_t page, uint32_t offs)
 387 {
 388         PUT32(dev, CONC_bMEMPAGE_OFF, page);    /* Select memory page */
 389         return (GET32(dev, offs));
 390 }
 391 









































































































 392 /*
 393  * Audio routines
 394  */
 395 static int
 396 audioens_format(void *arg)
 397 {
 398         _NOTE(ARGUNUSED(arg));
 399 
 400         /* hardware can also do AUDIO_FORMAT_U8, but no need for it */
 401         return (AUDIO_FORMAT_S16_LE);
 402 }
 403 
 404 static int
 405 audioens_channels(void *arg)
 406 {
 407         audioens_port_t *port = arg;
 408 
 409         return (port->nchan);
 410 }
 411 
 412 static int
 413 audioens_rate(void *arg)
 414 {
 415         audioens_port_t *port = arg;
 416 
 417         return (port->speed);
 418 }
 419 
 420 static int
 421 audioens_open(void *arg, int flag, unsigned *nframes, caddr_t *bufp)
 422 {
 423         audioens_port_t *port = arg;
 424         audioens_dev_t  *dev = port->dev;
 425 
 426         _NOTE(ARGUNUSED(flag));
 427 
 428         mutex_enter(&dev->mutex);
 429 
 430         port->nframes = AUDIOENS_BUF_LEN / (port->nchan * sizeof (int16_t));
 431         port->count = 0;
 432 
 433         *nframes = port->nframes;
 434         *bufp = port->kaddr;
 435         mutex_exit(&dev->mutex);
 436 
 437         return (0);
 438 }
 439 
 440 static int
 441 audioens_start(void *arg)
 442 {
 443         audioens_port_t *port = arg;
 444         audioens_dev_t *dev = port->dev;
 445         uint32_t tmp;
 446 
 447         mutex_enter(&dev->mutex);
 448 
 449         switch (port->num) {
 450         case PORT_DAC:


 459                 SRCSetRate(dev, SRC_DAC2_BASE, port->speed);
 460 
 461                 /* Configure the channel setup - SPDIF only uses front */
 462                 tmp = GET32(dev, CONC_dSTATUS_OFF);
 463                 tmp &= ~(CONC_STATUS_SPKR_MASK | CONC_STATUS_SPDIF_MASK);
 464                 tmp |= CONC_STATUS_SPKR_4CH | CONC_STATUS_SPDIF_P1;
 465                 PUT32(dev, CONC_dSTATUS_OFF, tmp);
 466 
 467                 /* Set format */
 468                 PUT8(dev, CONC_bSKIPC_OFF, 0x10);
 469                 SET8(dev, CONC_bSERFMT_OFF,
 470                     CONC_PCM_DAC1_16BIT | CONC_PCM_DAC2_16BIT |
 471                     CONC_PCM_DAC1_STEREO | CONC_PCM_DAC2_STEREO);
 472 
 473                 /* Set the frame count */
 474                 audioens_writemem(dev, CONC_DAC1CTL_PAGE, CONC_wDAC1FC_OFF,
 475                     port->nframes - 1);
 476                 audioens_writemem(dev, CONC_DAC2CTL_PAGE, CONC_wDAC2FC_OFF,
 477                     port->nframes - 1);
 478 
 479                 /* Set # of frames between interrupts */
 480                 PUT16(dev, CONC_wDAC1IC_OFF, port->nframes - 1);
 481                 PUT16(dev, CONC_wDAC2IC_OFF, port->nframes - 1);
 482 
 483                 SET8(dev, CONC_bDEVCTL_OFF,
 484                     CONC_DEVCTL_DAC2_EN | CONC_DEVCTL_DAC1_EN);





 485 
 486                 break;
 487 
 488         case PORT_ADC:
 489                 /* Set physical address of the DMA buffer */
 490                 audioens_writemem(dev, CONC_ADCCTL_PAGE, CONC_dADCPADDR_OFF,
 491                     port->paddr);
 492 
 493                 /* Set ADC rate */
 494                 SRCSetRate(dev, SRC_ADC_BASE, port->speed);
 495 
 496                 /* Set format - for input we only support 16 bit input */
 497                 tmp = GET8(dev, CONC_bSERFMT_OFF);
 498                 tmp |= CONC_PCM_ADC_16BIT;
 499                 tmp |= CONC_PCM_ADC_STEREO;
 500 
 501                 PUT8(dev, CONC_bSKIPC_OFF, 0x10);
 502 
 503                 PUT8(dev, CONC_bSERFMT_OFF, tmp);
 504 
 505                 /* Set the frame count */
 506                 audioens_writemem(dev, CONC_ADCCTL_PAGE, CONC_wADCFC_OFF,
 507                     port->nframes - 1);
 508 
 509                 /* Set # of frames between interrupts */
 510                 PUT16(dev, CONC_wADCIC_OFF, port->nframes - 1);
 511 
 512                 SET8(dev, CONC_bDEVCTL_OFF, CONC_DEVCTL_ADC_EN);





 513                 break;
 514         }
 515 
 516         port->frameno = 0;
 517         mutex_exit(&dev->mutex);
 518 
 519         return (0);
 520 }
 521 
 522 static void
 523 audioens_stop(void *arg)
 524 {
 525         audioens_port_t *port = arg;
 526         audioens_dev_t *dev = port->dev;
 527 
 528         mutex_enter(&dev->mutex);
 529         switch (port->num) {
 530         case PORT_DAC:
 531                 CLR8(dev, CONC_bDEVCTL_OFF,
 532                     CONC_DEVCTL_DAC2_EN | CONC_DEVCTL_DAC1_EN);


 543 {
 544         audioens_port_t *port = arg;
 545         audioens_dev_t *dev = port->dev;
 546         uint64_t val;
 547         uint32_t page, offs;
 548         int frameno, n;
 549 
 550         switch (port->num) {
 551         case PORT_DAC:
 552                 page = CONC_DAC1CTL_PAGE;
 553                 offs = CONC_wDAC1FC_OFF;
 554                 break;
 555 
 556         case PORT_ADC:
 557                 page = CONC_ADCCTL_PAGE;
 558                 offs = CONC_wADCFC_OFF;
 559                 break;
 560         }
 561 
 562         mutex_enter(&dev->mutex);




 563         /*
 564          * Note that the current frame counter is in the high nybble.
 565          */
 566         frameno = audioens_readmem(port->dev, page, offs) >> 16;
 567         n = frameno >= port->frameno ?
 568             frameno - port->frameno :
 569             frameno + port->nframes - port->frameno;
 570         port->frameno = frameno;
 571         port->count += n;
 572 




 573         val = port->count;
 574         mutex_exit(&dev->mutex);
 575 
 576         return (val);
 577 }
 578 
 579 static void
 580 audioens_close(void *arg)
 581 {
 582         _NOTE(ARGUNUSED(arg));
 583 }
 584 
 585 static void
 586 audioens_sync(void *arg, unsigned nframes)
 587 {
 588         audioens_port_t *port = arg;
 589 
 590         _NOTE(ARGUNUSED(nframes));
 591 
 592         if (port->num == PORT_ADC) {


 698 
 699         /*
 700          * Init mixer
 701          */
 702 
 703         dev->ac97 = ac97_alloc(dev->dip, audioens_rd97, audioens_wr97, dev);
 704         if (dev->ac97 == NULL)
 705                 return (DDI_FAILURE);
 706 
 707         if (ac97_init(dev->ac97, dev->osdev) != 0) {
 708                 return (DDI_FAILURE);
 709         }
 710 
 711         for (int i = 0; i <= PORT_MAX; i++) {
 712                 audioens_port_t *port;
 713                 unsigned caps;
 714                 unsigned dmaflags;
 715                 size_t rlen;
 716                 ddi_dma_cookie_t c;
 717                 unsigned ccnt;

 718 
 719                 port = &dev->port[i];
 720                 port->dev = dev;
 721 







 722                 switch (i) {
 723                 case PORT_DAC:
 724                         port->nchan = 4;
 725                         port->speed = 48000;


 726                         caps = ENGINE_OUTPUT_CAP;
 727                         dmaflags = DDI_DMA_WRITE | DDI_DMA_CONSISTENT;
 728                         break;
 729 
 730                 case PORT_ADC:
 731                         port->nchan = 2;
 732                         port->speed = 48000;


 733                         caps = ENGINE_INPUT_CAP;
 734                         dmaflags = DDI_DMA_READ | DDI_DMA_CONSISTENT;
 735                         break;
 736                 }
 737 
 738                 port->num = i;

 739 
 740                 /*
 741                  * Allocate DMA resources.
 742                  */
 743 
 744                 if (ddi_dma_alloc_handle(dev->dip, &dma_attr, DDI_DMA_SLEEP,
 745                     NULL, &port->dmah) != DDI_SUCCESS) {
 746                         audio_dev_warn(dev->osdev,
 747                             "port %d: dma handle allocation failed", i);
 748                         return (DDI_FAILURE);
 749                 }
 750                 if (ddi_dma_mem_alloc(port->dmah, AUDIOENS_BUF_LEN, &buf_attr,
 751                     DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &port->kaddr,
 752                     &rlen, &port->acch) != DDI_SUCCESS) {
 753                         audio_dev_warn(dev->osdev,
 754                             "port %d: dma memory allocation failed", i);
 755                         return (DDI_FAILURE);
 756                 }
 757                 /* ensure that the buffer is zeroed out properly */
 758                 bzero(port->kaddr, rlen);
 759                 if (ddi_dma_addr_bind_handle(port->dmah, NULL, port->kaddr,
 760                     AUDIOENS_BUF_LEN, dmaflags, DDI_DMA_SLEEP, NULL,
 761                     &c, &ccnt) != DDI_DMA_MAPPED) {
 762                         audio_dev_warn(dev->osdev,
 763                             "port %d: dma binding failed", i);
 764                         return (DDI_FAILURE);
 765                 }
 766                 port->paddr = c.dmac_address;
 767 
 768                 /*
 769                  * Allocate and configure audio engine.
 770                  */
 771                 port->engine = audio_engine_alloc(&audioens_engine_ops, caps);
 772                 if (port->engine == NULL) {
 773                         audio_dev_warn(dev->osdev,
 774                             "port %d: audio_engine_alloc failed", i);
 775                         return (DDI_FAILURE);
 776                 }
 777 
 778                 audio_engine_set_private(port->engine, port);
 779                 audio_dev_add_engine(dev->osdev, port->engine);
 780         }
 781 
 782         /*
 783          * Set up kstats for interrupt reporting.
 784          */
 785         if (audio_dev_register(dev->osdev) != DDI_SUCCESS) {
 786                 audio_dev_warn(dev->osdev,
 787                     "unable to register with audio framework");
 788                 return (DDI_FAILURE);
 789         }
 790 
 791         return (DDI_SUCCESS);
 792 }
 793 
 794 void
 795 audioens_destroy(audioens_dev_t *dev)
 796 {
 797         int     i;
 798 









 799         mutex_destroy(&dev->mutex);
 800 
 801         /* free up ports, including DMA resources for ports */
 802         for (i = 0; i <= PORT_MAX; i++) {
 803                 audioens_port_t *port = &dev->port[i];
 804 
 805                 if (port->paddr != 0)
 806                         (void) ddi_dma_unbind_handle(port->dmah);
 807                 if (port->acch != NULL)
 808                         ddi_dma_mem_free(&port->acch);
 809                 if (port->dmah != NULL)
 810                         ddi_dma_free_handle(&port->dmah);
 811 
 812                 if (port->engine != NULL) {
 813                         audio_dev_remove_engine(dev->osdev, port->engine);
 814                         audio_engine_free(port->engine);
 815                 }
 816         }
 817 
 818         if (dev->acch != NULL) {


 830         kmem_free(dev, sizeof (*dev));
 831 }
 832 
 833 int
 834 audioens_attach(dev_info_t *dip)
 835 {
 836         uint16_t pci_command, vendor, device;
 837         uint8_t revision;
 838         audioens_dev_t *dev;
 839         ddi_acc_handle_t pcih;
 840         const char *chip_name;
 841         const char *chip_vers;
 842 
 843         dev = kmem_zalloc(sizeof (*dev), KM_SLEEP);
 844         dev->dip = dip;
 845         ddi_set_driver_private(dip, dev);
 846         mutex_init(&dev->mutex, NULL, MUTEX_DRIVER, NULL);
 847 
 848         if (pci_config_setup(dip, &pcih) != DDI_SUCCESS) {
 849                 audio_dev_warn(dev->osdev, "pci_config_setup failed");
 850                 mutex_destroy(&dev->mutex);
 851                 kmem_free(dev, sizeof (*dev));
 852                 return (DDI_FAILURE);
 853         }
 854 
 855         vendor = pci_config_get16(pcih, PCI_CONF_VENID);
 856         device = pci_config_get16(pcih, PCI_CONF_DEVID);
 857         revision = pci_config_get8(pcih, PCI_CONF_REVID);
 858 
 859         if ((vendor != ENSONIQ_VENDOR_ID && vendor != CREATIVE_VENDOR_ID) ||
 860             (device != ENSONIQ_ES1371 && device != ENSONIQ_ES5880 &&
 861             device != ENSONIQ_ES5880A && device != ECTIVA_ES1938 &&
 862             device != ENSONIQ_ES5880B))

 863                 goto err_exit;

 864 
 865         chip_name = "AudioPCI97";
 866         chip_vers = "unknown";
 867 
 868         switch (device) {
 869         case ENSONIQ_ES1371:
 870                 chip_name = "AudioPCI97";
 871                 switch (revision) {
 872                 case 0x02:
 873                 case 0x09:
 874                 default:
 875                         chip_vers = "ES1371";
 876                         break;
 877                 case 0x04:
 878                 case 0x06:
 879                 case 0x08:
 880                         chip_vers = "ES1373";
 881                         break;
 882                 case 0x07:
 883                         chip_vers = "ES5880";


 916         audio_dev_set_version(dev->osdev, chip_vers);
 917 
 918         /* set the PCI latency */
 919         if ((audioens_latency == 32) || (audioens_latency == 64) ||
 920             (audioens_latency == 96))
 921                 pci_config_put8(pcih, PCI_CONF_LATENCY_TIMER,
 922                     audioens_latency);
 923 
 924         /* activate the device */
 925         pci_command = pci_config_get16(pcih, PCI_CONF_COMM);
 926         pci_command |= PCI_COMM_ME | PCI_COMM_IO;
 927         pci_config_put16(pcih, PCI_CONF_COMM, pci_command);
 928 
 929         /* map registers */
 930         if (ddi_regs_map_setup(dip, 1, &dev->regs, 0, 0, &acc_attr,
 931             &dev->acch) != DDI_SUCCESS) {
 932                 audio_dev_warn(dev->osdev, "can't map registers");
 933                 goto err_exit;
 934         }
 935 



















 936         /* This allocates and configures the engines */
 937         if (audioens_init(dev) != DDI_SUCCESS) {
 938                 audio_dev_warn(dev->osdev, "can't init device");
 939                 goto err_exit;
 940         }
 941 





 942         pci_config_teardown(&pcih);
 943 
 944         ddi_report_dev(dip);
 945 
 946         return (DDI_SUCCESS);
 947 
 948 err_exit:
 949         pci_config_teardown(&pcih);
 950 
 951         audioens_destroy(dev);
 952 
 953         return (DDI_FAILURE);
 954 }
 955 
 956 int
 957 audioens_detach(audioens_dev_t *dev)
 958 {
 959         int tmp;
 960 
 961         /* first unregister us from the DDI framework, might be busy */


 971         PUT8(dev, CONC_bSERCTL_OFF, tmp);
 972         PUT8(dev, CONC_bSERCTL_OFF, tmp);
 973 
 974         tmp = GET8(dev, CONC_bDEVCTL_OFF) &
 975             ~(CONC_DEVCTL_DAC2_EN | CONC_DEVCTL_ADC_EN | CONC_DEVCTL_DAC1_EN);
 976         PUT8(dev, CONC_bDEVCTL_OFF, tmp);
 977         PUT8(dev, CONC_bDEVCTL_OFF, tmp);
 978         PUT8(dev, CONC_bDEVCTL_OFF, tmp);
 979         PUT8(dev, CONC_bDEVCTL_OFF, tmp);
 980 
 981         mutex_exit(&dev->mutex);
 982 
 983         audioens_destroy(dev);
 984 
 985         return (DDI_SUCCESS);
 986 }
 987 
 988 static int
 989 audioens_resume(audioens_dev_t *dev)
 990 {




 991         /* reinitialize hardware */
 992         audioens_init_hw(dev);
 993 
 994         /* restore AC97 state */
 995         ac97_reset(dev->ac97);
 996 
 997         audio_dev_resume(dev->osdev);
 998 
 999         return (DDI_SUCCESS);
1000 }
1001 
1002 static int
1003 audioens_suspend(audioens_dev_t *dev)
1004 {
1005         audio_dev_suspend(dev->osdev);
1006 






1007         return (DDI_SUCCESS);
1008 }
1009 
1010 static int
1011 audioens_quiesce(dev_info_t *dip)
1012 {
1013         audioens_dev_t  *dev;
1014         uint8_t         tmp;
1015 
1016         if ((dev = ddi_get_driver_private(dip)) == NULL) {
1017                 return (DDI_FAILURE);
1018         }
1019 
1020         /* This disables all DMA engines and interrupts */
1021         tmp = GET8(dev, CONC_bSERCTL_OFF) &
1022             ~(CONC_SERCTL_DAC2IE | CONC_SERCTL_DAC1IE | CONC_SERCTL_ADCIE);
1023         PUT8(dev, CONC_bSERCTL_OFF, tmp);
1024         PUT8(dev, CONC_bSERCTL_OFF, tmp);
1025         PUT8(dev, CONC_bSERCTL_OFF, tmp);
1026         PUT8(dev, CONC_bSERCTL_OFF, tmp);




   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2016 Garrett D'Amore <garrett@damore.org>
  24  */
  25 /*
  26  * Purpose: Creative/Ensoniq AudioPCI97  driver (ES1371/ES1373)
  27  *
  28  * This driver is used with the original Ensoniq AudioPCI97 card and many
  29  * PCI based Sound Blaster cards by Creative Technologies. For example
  30  * Sound Blaster PCI128 and Creative/Ectiva EV1938.
  31  */
  32 
  33 /*
  34  * This file is part of Open Sound System
  35  *
  36  * Copyright (C) 4Front Technologies 1996-2008.
  37  *
  38  * This software is released under CDDL 1.0 source license.
  39  * See the COPYING file included in the main directory of this source
  40  * distribution for the license terms and conditions.
  41  */
  42 
  43 #include <sys/audio/audio_driver.h>
  44 #include <sys/audio/ac97.h>
  45 #include <sys/note.h>
  46 #include <sys/pci.h>
  47 
  48 /*
  49  * For VMWare platforms, we have to utilize the (emulated) hardware interrupts
  50  * of the device.  This is necessary for audio playback to function, as
  51  * the toggling of the interrupt bits apparently triggers logic inside the
  52  * emulated device.  So we need to detect this platform, and conditionally
  53  * wire up the interrupt handler.
  54  */
  55 #ifdef __x86
  56 #include <sys/x86_archext.h>
  57 #endif
  58 
  59 #include "audioens.h"
  60 
  61 /*
  62  * Set the latency to 32, 64, 96, 128 clocks - some APCI97 devices exhibit
  63  * garbled audio in some cases and setting the latency to higer values fixes it
  64  * Values: 32, 64, 96, 128 - Default: 64 (or defined by bios)
  65  */
  66 int audioens_latency = 0;
  67 
  68 /*
  69  * Enable SPDIF port on SoundBlaster 128D or Sound Blaster Digital-4.1 models
  70  * Values: 1=Enable 0=Disable Default: 0
  71  */
  72 int audioens_spdif = 0;
  73 
  74 /*
  75  * Note: Latest devices can support SPDIF with AC3 pass thru.
  76  * However, in order to do this, one of the two DMA engines must be
  77  * dedicated to this, which would prevent the card from supporting 4
  78  * channel audio.  For now we don't bother with the AC3 pass through


  91 
  92 #define DEFRATE                 48000
  93 #define DRVNAME                 "audioens"
  94 
  95 typedef struct audioens_port
  96 {
  97         /* Audio parameters */
  98         int                     speed;
  99 
 100         int                     num;
 101 #define PORT_DAC                0
 102 #define PORT_ADC                1
 103 #define PORT_MAX                PORT_ADC
 104 
 105         caddr_t                 kaddr;
 106         uint32_t                paddr;
 107         ddi_acc_handle_t        acch;
 108         ddi_dma_handle_t        dmah;
 109         int                     nchan;
 110         unsigned                nframes;
 111         unsigned                iframes;
 112         unsigned                frameno;
 113         uint64_t                count;
 114 
 115         struct audioens_dev     *dev;
 116         audio_engine_t          *engine;
 117 } audioens_port_t;
 118 
 119 typedef struct audioens_dev
 120 {
 121         audio_dev_t             *osdev;
 122         kmutex_t                mutex;
 123         uint16_t                devid;
 124         uint8_t                 revision;
 125         dev_info_t              *dip;
 126 
 127         audioens_port_t         port[PORT_MAX + 1];
 128 
 129         ac97_t                  *ac97;
 130 
 131         caddr_t                 regs;
 132         ddi_acc_handle_t        acch;
 133 
 134         boolean_t               suspended;
 135 
 136 #ifdef __x86
 137         boolean_t               useintr;
 138         ddi_intr_handle_t       intrh;
 139         uint_t                  intrpri;
 140 #endif
 141 } audioens_dev_t;
 142 
 143 static ddi_device_acc_attr_t acc_attr = {
 144         DDI_DEVICE_ATTR_V0,
 145         DDI_STRUCTURE_LE_ACC,
 146         DDI_STRICTORDER_ACC
 147 };
 148 
 149 static ddi_device_acc_attr_t buf_attr = {
 150         DDI_DEVICE_ATTR_V0,
 151         DDI_NEVERSWAP_ACC,
 152         DDI_STRICTORDER_ACC
 153 };
 154 






 155 static ddi_dma_attr_t dma_attr = {
 156         DMA_ATTR_VERSION,       /* dma_attr_version */
 157         0x0,                    /* dma_attr_addr_lo */
 158         0xffffffffU,            /* dma_attr_addr_hi */
 159         0x3ffff,                /* dma_attr_count_max */
 160         0x8,                    /* dma_attr_align */
 161         0x7f,                   /* dma_attr_burstsizes */
 162         0x1,                    /* dma_attr_minxfer */
 163         0x3ffff,                /* dma_attr_maxxfer */
 164         0x3ffff,                /* dma_attr_seg */
 165         0x1,                    /* dma_attr_sgllen */
 166         0x1,                    /* dma_attr_granular */
 167         0                       /* dma_attr_flags */
 168 };
 169 
 170 #define GET8(dev, offset)       \
 171         ddi_get8(dev->acch, (uint8_t *)(dev->regs + (offset)))
 172 #define GET16(dev, offset)      \
 173         ddi_get16(dev->acch, (uint16_t *)(void *)(dev->regs + (offset)))
 174 #define GET32(dev, offset)      \


 388         }
 389         PUT32(dev, CONC_dSRCIO_OFF, 0);
 390 }
 391 
 392 static void
 393 audioens_writemem(audioens_dev_t *dev, uint32_t page, uint32_t offs,
 394     uint32_t data)
 395 {
 396         /* Select memory page */
 397         PUT32(dev, CONC_bMEMPAGE_OFF, page);
 398         PUT32(dev, offs, data);
 399 }
 400 
 401 static uint32_t
 402 audioens_readmem(audioens_dev_t *dev, uint32_t page, uint32_t offs)
 403 {
 404         PUT32(dev, CONC_bMEMPAGE_OFF, page);    /* Select memory page */
 405         return (GET32(dev, offs));
 406 }
 407 
 408 #ifdef __x86
 409 static unsigned
 410 audioens_intr(caddr_t arg1, caddr_t arg2)
 411 {
 412         audioens_dev_t *dev = (void *)arg1;
 413         uint32_t status;
 414         uint32_t frameno;
 415         uint32_t n;
 416         audioens_port_t *port;
 417 
 418         _NOTE(ARGUNUSED(arg2));
 419 
 420         mutex_enter(&dev->mutex);
 421         if (dev->suspended || !dev->useintr) {
 422                 mutex_exit(&dev->mutex);
 423                 return (DDI_INTR_UNCLAIMED);
 424         }
 425 
 426         status = GET32(dev, CONC_dSTATUS_OFF);
 427         if ((status & CONC_STATUS_PENDING) == 0) {
 428                 mutex_exit(&dev->mutex);
 429                 return (DDI_INTR_UNCLAIMED);
 430         }
 431 
 432         /* Three interrupts, DAC1, DAC2, and ADC.  The UART we just toss. */
 433 
 434         if (status & CONC_STATUS_DAC1INT) {
 435                 port = &dev->port[PORT_DAC];
 436 
 437                 /* current frame counter is in high nybble */
 438                 frameno = audioens_readmem(dev,
 439                     CONC_DAC1CTL_PAGE, CONC_wDAC1FC_OFF) >> 16;
 440                 n = frameno >= port->frameno ?
 441                     frameno - port->frameno :
 442                     frameno + port->nframes - port->frameno;
 443                 port->frameno = frameno;
 444                 port->count += n;
 445                 CLR8(dev, CONC_bSERCTL_OFF, CONC_SERCTL_DAC1IE);
 446                 SET8(dev, CONC_bSERCTL_OFF, CONC_SERCTL_DAC1IE);
 447         }
 448         if (status & CONC_STATUS_ADCINT) {
 449                 port = &dev->port[PORT_ADC];
 450 
 451                 /* current frame counter is in high nybble */
 452                 frameno = audioens_readmem(dev,
 453                     CONC_ADCCTL_PAGE, CONC_wADCFC_OFF) >> 16;
 454                 n = frameno >= port->frameno ?
 455                     frameno - port->frameno :
 456                     frameno + port->nframes - port->frameno;
 457                 port->frameno = frameno;
 458                 port->count += n;
 459                 CLR8(dev, CONC_bSERCTL_OFF, CONC_SERCTL_ADCIE);
 460                 SET8(dev, CONC_bSERCTL_OFF, CONC_SERCTL_ADCIE);
 461         }
 462         if (status & CONC_STATUS_DAC2INT) {
 463                 CLR8(dev, CONC_bSERCTL_OFF, CONC_SERCTL_DAC2IE);
 464                 SET8(dev, CONC_bSERCTL_OFF, CONC_SERCTL_DAC2IE);
 465         }
 466         if (status & CONC_STATUS_UARTINT) {
 467                 /*
 468                  * Consume data in the UART RX FIFO.  We don't support
 469                  * the UART for now, so just eat it.
 470                  */
 471                 while (GET8(dev, CONC_bUARTCSTAT_OFF) & CONC_UART_RXRDY)
 472                         continue;
 473         }
 474         mutex_exit(&dev->mutex);
 475 
 476         return (DDI_INTR_CLAIMED);
 477 }
 478 
 479 static int
 480 audioens_setup_intr(audioens_dev_t *dev)
 481 {
 482         int     act;
 483         uint_t  ipri;
 484 
 485         if ((ddi_intr_alloc(dev->dip, &dev->intrh, DDI_INTR_TYPE_FIXED, 0, 1,
 486             &act, DDI_INTR_ALLOC_NORMAL) != DDI_SUCCESS) || (act != 1)) {
 487                 audio_dev_warn(dev->osdev, "can't alloc intr handle");
 488                 goto fail;
 489         }
 490 
 491         if (ddi_intr_get_pri(dev->intrh, &ipri) != DDI_SUCCESS) {
 492                 audio_dev_warn(dev->osdev, "can't get interrupt priority");
 493                 goto fail;
 494         }
 495         if (ddi_intr_add_handler(dev->intrh, audioens_intr, dev, NULL) !=
 496             DDI_SUCCESS) {
 497                 audio_dev_warn(dev->osdev, "cannot add interrupt handler");
 498                 goto fail;
 499         }
 500         dev->intrpri = ipri;
 501         return (DDI_SUCCESS);
 502 
 503 fail:
 504         if (dev->intrh != NULL) {
 505                 (void) ddi_intr_free(dev->intrh);
 506                 dev->intrh = NULL;
 507         }
 508         return (DDI_FAILURE);
 509 }
 510 
 511 #endif  /* __x86 */
 512 
 513 /*
 514  * Audio routines
 515  */
 516 static int
 517 audioens_format(void *arg)
 518 {
 519         _NOTE(ARGUNUSED(arg));
 520 
 521         /* hardware can also do AUDIO_FORMAT_U8, but no need for it */
 522         return (AUDIO_FORMAT_S16_LE);
 523 }
 524 
 525 static int
 526 audioens_channels(void *arg)
 527 {
 528         audioens_port_t *port = arg;
 529 
 530         return (port->nchan);
 531 }
 532 
 533 static int
 534 audioens_rate(void *arg)
 535 {
 536         audioens_port_t *port = arg;
 537 
 538         return (port->speed);
 539 }
 540 
 541 static int
 542 audioens_open(void *arg, int flag, unsigned *nframes, caddr_t *bufp)
 543 {
 544         audioens_port_t *port = arg;
 545         audioens_dev_t  *dev = port->dev;
 546 
 547         _NOTE(ARGUNUSED(flag));
 548 
 549         mutex_enter(&dev->mutex);
 550 

 551         port->count = 0;
 552 
 553         *nframes = port->nframes;
 554         *bufp = port->kaddr;
 555         mutex_exit(&dev->mutex);
 556 
 557         return (0);
 558 }
 559 
 560 static int
 561 audioens_start(void *arg)
 562 {
 563         audioens_port_t *port = arg;
 564         audioens_dev_t *dev = port->dev;
 565         uint32_t tmp;
 566 
 567         mutex_enter(&dev->mutex);
 568 
 569         switch (port->num) {
 570         case PORT_DAC:


 579                 SRCSetRate(dev, SRC_DAC2_BASE, port->speed);
 580 
 581                 /* Configure the channel setup - SPDIF only uses front */
 582                 tmp = GET32(dev, CONC_dSTATUS_OFF);
 583                 tmp &= ~(CONC_STATUS_SPKR_MASK | CONC_STATUS_SPDIF_MASK);
 584                 tmp |= CONC_STATUS_SPKR_4CH | CONC_STATUS_SPDIF_P1;
 585                 PUT32(dev, CONC_dSTATUS_OFF, tmp);
 586 
 587                 /* Set format */
 588                 PUT8(dev, CONC_bSKIPC_OFF, 0x10);
 589                 SET8(dev, CONC_bSERFMT_OFF,
 590                     CONC_PCM_DAC1_16BIT | CONC_PCM_DAC2_16BIT |
 591                     CONC_PCM_DAC1_STEREO | CONC_PCM_DAC2_STEREO);
 592 
 593                 /* Set the frame count */
 594                 audioens_writemem(dev, CONC_DAC1CTL_PAGE, CONC_wDAC1FC_OFF,
 595                     port->nframes - 1);
 596                 audioens_writemem(dev, CONC_DAC2CTL_PAGE, CONC_wDAC2FC_OFF,
 597                     port->nframes - 1);
 598 
 599                 PUT16(dev, CONC_wDAC1IC_OFF, port->iframes - 1);
 600                 PUT16(dev, CONC_wDAC2IC_OFF, port->iframes - 1);


 601                 SET8(dev, CONC_bDEVCTL_OFF,
 602                     CONC_DEVCTL_DAC2_EN | CONC_DEVCTL_DAC1_EN);
 603 #ifdef __x86
 604                 if (dev->useintr) {
 605                         SET8(dev, CONC_bSERCTL_OFF, CONC_SERCTL_DAC1IE);
 606                 }
 607 #endif
 608 
 609                 break;
 610 
 611         case PORT_ADC:
 612                 /* Set physical address of the DMA buffer */
 613                 audioens_writemem(dev, CONC_ADCCTL_PAGE, CONC_dADCPADDR_OFF,
 614                     port->paddr);
 615 
 616                 /* Set ADC rate */
 617                 SRCSetRate(dev, SRC_ADC_BASE, port->speed);
 618 
 619                 /* Set format - for input we only support 16 bit input */
 620                 tmp = GET8(dev, CONC_bSERFMT_OFF);
 621                 tmp |= CONC_PCM_ADC_16BIT;
 622                 tmp |= CONC_PCM_ADC_STEREO;
 623 
 624                 PUT8(dev, CONC_bSKIPC_OFF, 0x10);
 625 
 626                 PUT8(dev, CONC_bSERFMT_OFF, tmp);
 627 
 628                 /* Set the frame count */
 629                 audioens_writemem(dev, CONC_ADCCTL_PAGE, CONC_wADCFC_OFF,
 630                     port->nframes - 1);
 631 
 632                 /* Set # of frames between interrupts */
 633                 PUT16(dev, CONC_wADCIC_OFF, port->iframes - 1);
 634 
 635                 SET8(dev, CONC_bDEVCTL_OFF, CONC_DEVCTL_ADC_EN);
 636 #ifdef __x86
 637                 if (dev->useintr) {
 638                         SET8(dev, CONC_bSERCTL_OFF, CONC_SERCTL_ADCIE);
 639                 }
 640 #endif
 641                 break;
 642         }
 643 
 644         port->frameno = 0;
 645         mutex_exit(&dev->mutex);
 646 
 647         return (0);
 648 }
 649 
 650 static void
 651 audioens_stop(void *arg)
 652 {
 653         audioens_port_t *port = arg;
 654         audioens_dev_t *dev = port->dev;
 655 
 656         mutex_enter(&dev->mutex);
 657         switch (port->num) {
 658         case PORT_DAC:
 659                 CLR8(dev, CONC_bDEVCTL_OFF,
 660                     CONC_DEVCTL_DAC2_EN | CONC_DEVCTL_DAC1_EN);


 671 {
 672         audioens_port_t *port = arg;
 673         audioens_dev_t *dev = port->dev;
 674         uint64_t val;
 675         uint32_t page, offs;
 676         int frameno, n;
 677 
 678         switch (port->num) {
 679         case PORT_DAC:
 680                 page = CONC_DAC1CTL_PAGE;
 681                 offs = CONC_wDAC1FC_OFF;
 682                 break;
 683 
 684         case PORT_ADC:
 685                 page = CONC_ADCCTL_PAGE;
 686                 offs = CONC_wADCFC_OFF;
 687                 break;
 688         }
 689 
 690         mutex_enter(&dev->mutex);
 691 #ifdef __x86
 692         if (!dev->useintr) {
 693 #endif
 694 
 695         /*
 696          * Note that the current frame counter is in the high nybble.
 697          */
 698         frameno = audioens_readmem(port->dev, page, offs) >> 16;
 699         n = frameno >= port->frameno ?
 700             frameno - port->frameno :
 701             frameno + port->nframes - port->frameno;
 702         port->frameno = frameno;
 703         port->count += n;
 704 
 705 #ifdef __x86
 706         }
 707 #endif
 708 
 709         val = port->count;
 710         mutex_exit(&dev->mutex);
 711 
 712         return (val);
 713 }
 714 
 715 static void
 716 audioens_close(void *arg)
 717 {
 718         _NOTE(ARGUNUSED(arg));
 719 }
 720 
 721 static void
 722 audioens_sync(void *arg, unsigned nframes)
 723 {
 724         audioens_port_t *port = arg;
 725 
 726         _NOTE(ARGUNUSED(nframes));
 727 
 728         if (port->num == PORT_ADC) {


 834 
 835         /*
 836          * Init mixer
 837          */
 838 
 839         dev->ac97 = ac97_alloc(dev->dip, audioens_rd97, audioens_wr97, dev);
 840         if (dev->ac97 == NULL)
 841                 return (DDI_FAILURE);
 842 
 843         if (ac97_init(dev->ac97, dev->osdev) != 0) {
 844                 return (DDI_FAILURE);
 845         }
 846 
 847         for (int i = 0; i <= PORT_MAX; i++) {
 848                 audioens_port_t *port;
 849                 unsigned caps;
 850                 unsigned dmaflags;
 851                 size_t rlen;
 852                 ddi_dma_cookie_t c;
 853                 unsigned ccnt;
 854                 size_t bufsz;
 855 
 856                 port = &dev->port[i];
 857                 port->dev = dev;
 858 
 859                 /*
 860                  * We have 48000Hz.  At that rate, 128 frames will give
 861                  * us an interrupt rate of 375Hz.  2048 frames buys about
 862                  * 42ms of buffer.  Note that interrupts are only enabled
 863                  * for platforms which need them (i.e. VMWare).
 864                  */
 865 
 866                 switch (i) {
 867                 case PORT_DAC:
 868                         port->nchan = 4;
 869                         port->speed = 48000;
 870                         port->iframes = 128;
 871                         port->nframes = 2048;
 872                         caps = ENGINE_OUTPUT_CAP;
 873                         dmaflags = DDI_DMA_WRITE | DDI_DMA_CONSISTENT;
 874                         break;
 875 
 876                 case PORT_ADC:
 877                         port->nchan = 2;
 878                         port->speed = 48000;
 879                         port->iframes = 128;
 880                         port->nframes = 2048;
 881                         caps = ENGINE_INPUT_CAP;
 882                         dmaflags = DDI_DMA_READ | DDI_DMA_CONSISTENT;
 883                         break;
 884                 }
 885 
 886                 port->num = i;
 887                 bufsz = port->nframes * port->nchan * sizeof (uint16_t);
 888 
 889                 /*
 890                  * Allocate DMA resources.
 891                  */
 892 
 893                 if (ddi_dma_alloc_handle(dev->dip, &dma_attr, DDI_DMA_SLEEP,
 894                     NULL, &port->dmah) != DDI_SUCCESS) {
 895                         audio_dev_warn(dev->osdev,
 896                             "port %d: dma handle allocation failed", i);
 897                         return (DDI_FAILURE);
 898                 }
 899                 if (ddi_dma_mem_alloc(port->dmah, bufsz, &buf_attr,
 900                     DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &port->kaddr,
 901                     &rlen, &port->acch) != DDI_SUCCESS) {
 902                         audio_dev_warn(dev->osdev,
 903                             "port %d: dma memory allocation failed", i);
 904                         return (DDI_FAILURE);
 905                 }
 906                 /* ensure that the buffer is zeroed out properly */
 907                 bzero(port->kaddr, rlen);
 908                 if (ddi_dma_addr_bind_handle(port->dmah, NULL, port->kaddr,
 909                     bufsz, dmaflags, DDI_DMA_SLEEP, NULL,
 910                     &c, &ccnt) != DDI_DMA_MAPPED) {
 911                         audio_dev_warn(dev->osdev,
 912                             "port %d: dma binding failed", i);
 913                         return (DDI_FAILURE);
 914                 }
 915                 port->paddr = c.dmac_address;
 916 
 917                 /*
 918                  * Allocate and configure audio engine.
 919                  */
 920                 port->engine = audio_engine_alloc(&audioens_engine_ops, caps);
 921                 if (port->engine == NULL) {
 922                         audio_dev_warn(dev->osdev,
 923                             "port %d: audio_engine_alloc failed", i);
 924                         return (DDI_FAILURE);
 925                 }
 926 
 927                 audio_engine_set_private(port->engine, port);
 928                 audio_dev_add_engine(dev->osdev, port->engine);
 929         }
 930 



 931         if (audio_dev_register(dev->osdev) != DDI_SUCCESS) {
 932                 audio_dev_warn(dev->osdev,
 933                     "unable to register with audio framework");
 934                 return (DDI_FAILURE);
 935         }
 936 
 937         return (DDI_SUCCESS);
 938 }
 939 
 940 void
 941 audioens_destroy(audioens_dev_t *dev)
 942 {
 943         int     i;
 944 
 945 #ifdef __x86
 946         if (dev->useintr && dev->intrh != NULL) {
 947                 (void) ddi_intr_disable(dev->intrh);
 948                 (void) ddi_intr_remove_handler(dev->intrh);
 949                 (void) ddi_intr_free(dev->intrh);
 950                 dev->intrh = NULL;
 951         }
 952 #endif
 953 
 954         mutex_destroy(&dev->mutex);
 955 
 956         /* free up ports, including DMA resources for ports */
 957         for (i = 0; i <= PORT_MAX; i++) {
 958                 audioens_port_t *port = &dev->port[i];
 959 
 960                 if (port->paddr != 0)
 961                         (void) ddi_dma_unbind_handle(port->dmah);
 962                 if (port->acch != NULL)
 963                         ddi_dma_mem_free(&port->acch);
 964                 if (port->dmah != NULL)
 965                         ddi_dma_free_handle(&port->dmah);
 966 
 967                 if (port->engine != NULL) {
 968                         audio_dev_remove_engine(dev->osdev, port->engine);
 969                         audio_engine_free(port->engine);
 970                 }
 971         }
 972 
 973         if (dev->acch != NULL) {


 985         kmem_free(dev, sizeof (*dev));
 986 }
 987 
 988 int
 989 audioens_attach(dev_info_t *dip)
 990 {
 991         uint16_t pci_command, vendor, device;
 992         uint8_t revision;
 993         audioens_dev_t *dev;
 994         ddi_acc_handle_t pcih;
 995         const char *chip_name;
 996         const char *chip_vers;
 997 
 998         dev = kmem_zalloc(sizeof (*dev), KM_SLEEP);
 999         dev->dip = dip;
1000         ddi_set_driver_private(dip, dev);
1001         mutex_init(&dev->mutex, NULL, MUTEX_DRIVER, NULL);
1002 
1003         if (pci_config_setup(dip, &pcih) != DDI_SUCCESS) {
1004                 audio_dev_warn(dev->osdev, "pci_config_setup failed");
1005                 goto err_exit;


1006         }
1007 
1008         vendor = pci_config_get16(pcih, PCI_CONF_VENID);
1009         device = pci_config_get16(pcih, PCI_CONF_DEVID);
1010         revision = pci_config_get8(pcih, PCI_CONF_REVID);
1011 
1012         if ((vendor != ENSONIQ_VENDOR_ID && vendor != CREATIVE_VENDOR_ID) ||
1013             (device != ENSONIQ_ES1371 && device != ENSONIQ_ES5880 &&
1014             device != ENSONIQ_ES5880A && device != ECTIVA_ES1938 &&
1015             device != ENSONIQ_ES5880B)) {
1016                 audio_dev_warn(dev->osdev, "unrecognized device");
1017                 goto err_exit;
1018         }
1019 
1020         chip_name = "AudioPCI97";
1021         chip_vers = "unknown";
1022 
1023         switch (device) {
1024         case ENSONIQ_ES1371:
1025                 chip_name = "AudioPCI97";
1026                 switch (revision) {
1027                 case 0x02:
1028                 case 0x09:
1029                 default:
1030                         chip_vers = "ES1371";
1031                         break;
1032                 case 0x04:
1033                 case 0x06:
1034                 case 0x08:
1035                         chip_vers = "ES1373";
1036                         break;
1037                 case 0x07:
1038                         chip_vers = "ES5880";


1071         audio_dev_set_version(dev->osdev, chip_vers);
1072 
1073         /* set the PCI latency */
1074         if ((audioens_latency == 32) || (audioens_latency == 64) ||
1075             (audioens_latency == 96))
1076                 pci_config_put8(pcih, PCI_CONF_LATENCY_TIMER,
1077                     audioens_latency);
1078 
1079         /* activate the device */
1080         pci_command = pci_config_get16(pcih, PCI_CONF_COMM);
1081         pci_command |= PCI_COMM_ME | PCI_COMM_IO;
1082         pci_config_put16(pcih, PCI_CONF_COMM, pci_command);
1083 
1084         /* map registers */
1085         if (ddi_regs_map_setup(dip, 1, &dev->regs, 0, 0, &acc_attr,
1086             &dev->acch) != DDI_SUCCESS) {
1087                 audio_dev_warn(dev->osdev, "can't map registers");
1088                 goto err_exit;
1089         }
1090 
1091 #ifdef __x86
1092         /*
1093          * Virtual platforms (mostly VMWare!) seem to need us to pulse
1094          * the interrupt enables to make progress.  So enable (emulated)
1095          * hardware interrupts.
1096          */
1097         dev->useintr = B_FALSE;
1098         if (get_hwenv() & HW_VIRTUAL) {
1099                 dev->useintr = B_TRUE;
1100                 if (audioens_setup_intr(dev) != DDI_SUCCESS) {
1101                         goto err_exit;
1102                 }
1103                 /* Reinitialize the mutex with interrupt priority. */
1104                 mutex_destroy(&dev->mutex);
1105                 mutex_init(&dev->mutex, NULL, MUTEX_DRIVER,
1106                     DDI_INTR_PRI(dev->intrpri));
1107         }
1108 #endif
1109 
1110         /* This allocates and configures the engines */
1111         if (audioens_init(dev) != DDI_SUCCESS) {
1112                 audio_dev_warn(dev->osdev, "can't init device");
1113                 goto err_exit;
1114         }
1115 
1116 #ifdef __x86
1117         if (dev->useintr) {
1118                 (void) ddi_intr_enable(dev->intrh);
1119         }
1120 #endif
1121         pci_config_teardown(&pcih);
1122 
1123         ddi_report_dev(dip);
1124 
1125         return (DDI_SUCCESS);
1126 
1127 err_exit:
1128         pci_config_teardown(&pcih);
1129 
1130         audioens_destroy(dev);
1131 
1132         return (DDI_FAILURE);
1133 }
1134 
1135 int
1136 audioens_detach(audioens_dev_t *dev)
1137 {
1138         int tmp;
1139 
1140         /* first unregister us from the DDI framework, might be busy */


1150         PUT8(dev, CONC_bSERCTL_OFF, tmp);
1151         PUT8(dev, CONC_bSERCTL_OFF, tmp);
1152 
1153         tmp = GET8(dev, CONC_bDEVCTL_OFF) &
1154             ~(CONC_DEVCTL_DAC2_EN | CONC_DEVCTL_ADC_EN | CONC_DEVCTL_DAC1_EN);
1155         PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1156         PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1157         PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1158         PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1159 
1160         mutex_exit(&dev->mutex);
1161 
1162         audioens_destroy(dev);
1163 
1164         return (DDI_SUCCESS);
1165 }
1166 
1167 static int
1168 audioens_resume(audioens_dev_t *dev)
1169 {
1170         mutex_enter(&dev->mutex);
1171         dev->suspended = B_FALSE;
1172         mutex_exit(&dev->mutex);
1173 
1174         /* reinitialize hardware */
1175         audioens_init_hw(dev);
1176 
1177         /* restore AC97 state */
1178         ac97_reset(dev->ac97);
1179 
1180         audio_dev_resume(dev->osdev);
1181 
1182         return (DDI_SUCCESS);
1183 }
1184 
1185 static int
1186 audioens_suspend(audioens_dev_t *dev)
1187 {
1188         audio_dev_suspend(dev->osdev);
1189 
1190         mutex_enter(&dev->mutex);
1191         CLR8(dev, CONC_bDEVCTL_OFF,
1192             CONC_DEVCTL_DAC2_EN | CONC_DEVCTL_DAC1_EN | CONC_DEVCTL_ADC_EN);
1193         dev->suspended = B_TRUE;
1194         mutex_exit(&dev->mutex);
1195 
1196         return (DDI_SUCCESS);
1197 }
1198 
1199 static int
1200 audioens_quiesce(dev_info_t *dip)
1201 {
1202         audioens_dev_t  *dev;
1203         uint8_t         tmp;
1204 
1205         if ((dev = ddi_get_driver_private(dip)) == NULL) {
1206                 return (DDI_FAILURE);
1207         }
1208 
1209         /* This disables all DMA engines and interrupts */
1210         tmp = GET8(dev, CONC_bSERCTL_OFF) &
1211             ~(CONC_SERCTL_DAC2IE | CONC_SERCTL_DAC1IE | CONC_SERCTL_ADCIE);
1212         PUT8(dev, CONC_bSERCTL_OFF, tmp);
1213         PUT8(dev, CONC_bSERCTL_OFF, tmp);
1214         PUT8(dev, CONC_bSERCTL_OFF, tmp);
1215         PUT8(dev, CONC_bSERCTL_OFF, tmp);