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);
|