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
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/audio/drv/audioens/audioens.c
+++ new/usr/src/uts/common/io/audio/drv/audioens/audioens.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
23 + * Copyright 2016 Garrett D'Amore <garrett@damore.org>
23 24 */
24 25 /*
25 26 * Purpose: Creative/Ensoniq AudioPCI97 driver (ES1371/ES1373)
26 27 *
27 28 * This driver is used with the original Ensoniq AudioPCI97 card and many
28 29 * PCI based Sound Blaster cards by Creative Technologies. For example
29 30 * Sound Blaster PCI128 and Creative/Ectiva EV1938.
30 31 */
31 32
32 33 /*
33 34 * This file is part of Open Sound System
34 35 *
35 36 * Copyright (C) 4Front Technologies 1996-2008.
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
36 37 *
37 38 * This software is released under CDDL 1.0 source license.
38 39 * See the COPYING file included in the main directory of this source
39 40 * distribution for the license terms and conditions.
40 41 */
41 42
42 43 #include <sys/audio/audio_driver.h>
43 44 #include <sys/audio/ac97.h>
44 45 #include <sys/note.h>
45 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 +
46 59 #include "audioens.h"
47 60
48 61 /*
49 62 * Set the latency to 32, 64, 96, 128 clocks - some APCI97 devices exhibit
50 63 * garbled audio in some cases and setting the latency to higer values fixes it
51 64 * Values: 32, 64, 96, 128 - Default: 64 (or defined by bios)
52 65 */
53 66 int audioens_latency = 0;
54 67
55 68 /*
56 69 * Enable SPDIF port on SoundBlaster 128D or Sound Blaster Digital-4.1 models
57 70 * Values: 1=Enable 0=Disable Default: 0
58 71 */
59 72 int audioens_spdif = 0;
60 73
61 74 /*
62 75 * Note: Latest devices can support SPDIF with AC3 pass thru.
63 76 * However, in order to do this, one of the two DMA engines must be
64 77 * dedicated to this, which would prevent the card from supporting 4
65 78 * channel audio. For now we don't bother with the AC3 pass through
66 79 * mode, and instead just focus on 4 channel support. In the future,
67 80 * this could be selectable via a property.
68 81 */
69 82
70 83 #define ENSONIQ_VENDOR_ID 0x1274
71 84 #define CREATIVE_VENDOR_ID 0x1102
72 85 #define ECTIVA_VENDOR_ID 0x1102
73 86 #define ENSONIQ_ES1371 0x1371
74 87 #define ENSONIQ_ES5880 0x8001
75 88 #define ENSONIQ_ES5880A 0x8002
76 89 #define ENSONIQ_ES5880B 0x5880
77 90 #define ECTIVA_ES1938 0x8938
78 91
79 92 #define DEFRATE 48000
80 93 #define DRVNAME "audioens"
81 94
82 95 typedef struct audioens_port
83 96 {
84 97 /* Audio parameters */
85 98 int speed;
86 99
87 100 int num;
↓ open down ↓ |
32 lines elided |
↑ open up ↑ |
88 101 #define PORT_DAC 0
89 102 #define PORT_ADC 1
90 103 #define PORT_MAX PORT_ADC
91 104
92 105 caddr_t kaddr;
93 106 uint32_t paddr;
94 107 ddi_acc_handle_t acch;
95 108 ddi_dma_handle_t dmah;
96 109 int nchan;
97 110 unsigned nframes;
111 + unsigned iframes;
98 112 unsigned frameno;
99 113 uint64_t count;
100 114
101 115 struct audioens_dev *dev;
102 - audio_engine_t *engine;
116 + audio_engine_t *engine;
103 117 } audioens_port_t;
104 118
105 119 typedef struct audioens_dev
106 120 {
107 121 audio_dev_t *osdev;
108 122 kmutex_t mutex;
109 123 uint16_t devid;
110 124 uint8_t revision;
111 125 dev_info_t *dip;
112 126
113 127 audioens_port_t port[PORT_MAX + 1];
114 128
115 129 ac97_t *ac97;
116 130
117 131 caddr_t regs;
118 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
119 141 } audioens_dev_t;
120 142
121 143 static ddi_device_acc_attr_t acc_attr = {
122 144 DDI_DEVICE_ATTR_V0,
123 145 DDI_STRUCTURE_LE_ACC,
124 146 DDI_STRICTORDER_ACC
125 147 };
126 148
127 149 static ddi_device_acc_attr_t buf_attr = {
128 150 DDI_DEVICE_ATTR_V0,
129 151 DDI_NEVERSWAP_ACC,
130 152 DDI_STRICTORDER_ACC
131 153 };
132 154
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 155 static ddi_dma_attr_t dma_attr = {
140 156 DMA_ATTR_VERSION, /* dma_attr_version */
141 157 0x0, /* dma_attr_addr_lo */
142 158 0xffffffffU, /* dma_attr_addr_hi */
143 159 0x3ffff, /* dma_attr_count_max */
144 160 0x8, /* dma_attr_align */
145 161 0x7f, /* dma_attr_burstsizes */
146 162 0x1, /* dma_attr_minxfer */
147 163 0x3ffff, /* dma_attr_maxxfer */
148 164 0x3ffff, /* dma_attr_seg */
149 165 0x1, /* dma_attr_sgllen */
150 166 0x1, /* dma_attr_granular */
151 167 0 /* dma_attr_flags */
152 168 };
153 169
154 170 #define GET8(dev, offset) \
155 171 ddi_get8(dev->acch, (uint8_t *)(dev->regs + (offset)))
156 172 #define GET16(dev, offset) \
157 173 ddi_get16(dev->acch, (uint16_t *)(void *)(dev->regs + (offset)))
158 174 #define GET32(dev, offset) \
159 175 ddi_get32(dev->acch, (uint32_t *)(void *)(dev->regs + (offset)))
160 176 #define PUT8(dev, offset, v) \
161 177 ddi_put8(dev->acch, (uint8_t *)(dev->regs + (offset)), v)
162 178 #define PUT16(dev, offset, v) \
163 179 ddi_put16(dev->acch, (uint16_t *)(void *)(dev->regs + (offset)), v)
164 180 #define PUT32(dev, offset, v) \
165 181 ddi_put32(dev->acch, (uint32_t *)(void *)(dev->regs + (offset)), v)
166 182
167 183 #define CLR8(dev, offset, v) PUT8(dev, offset, GET8(dev, offset) & ~(v))
168 184 #define SET8(dev, offset, v) PUT8(dev, offset, GET8(dev, offset) | (v))
169 185 #define CLR32(dev, offset, v) PUT32(dev, offset, GET32(dev, offset) & ~(v))
170 186 #define SET32(dev, offset, v) PUT32(dev, offset, GET32(dev, offset) | (v))
171 187
172 188 static void audioens_init_hw(audioens_dev_t *);
173 189
174 190 static uint16_t
175 191 audioens_rd97(void *dev_, uint8_t wAddr)
176 192 {
177 193 audioens_dev_t *dev = dev_;
178 194 int i, dtemp;
179 195
180 196 mutex_enter(&dev->mutex);
181 197 dtemp = GET32(dev, CONC_dCODECCTL_OFF);
182 198 /* wait for WIP to go away saving the current state for later */
183 199 for (i = 0; i < 0x100UL; ++i) {
184 200 dtemp = GET32(dev, CONC_dCODECCTL_OFF);
185 201 if ((dtemp & (1UL << 30)) == 0)
186 202 break;
187 203 }
188 204
189 205 /* write addr w/data=0 and assert read request ... */
190 206 PUT32(dev, CONC_dCODECCTL_OFF, ((int)wAddr << 16) | (1UL << 23));
191 207
192 208 /* now wait for the data (RDY) */
193 209 for (i = 0; i < 0x100UL; ++i) {
194 210 dtemp = GET32(dev, CONC_dCODECCTL_OFF);
195 211 if (dtemp & (1UL << 31))
196 212 break;
197 213 }
198 214 dtemp = GET32(dev, CONC_dCODECCTL_OFF);
199 215 mutex_exit(&dev->mutex);
200 216
201 217 return (dtemp & 0xffff);
202 218 }
203 219
204 220 static void
205 221 audioens_wr97(void *dev_, uint8_t wAddr, uint16_t wData)
206 222 {
207 223 audioens_dev_t *dev = dev_;
208 224 int i, dtemp;
209 225
210 226 mutex_enter(&dev->mutex);
211 227 /* wait for WIP to go away */
212 228 for (i = 0; i < 0x100UL; ++i) {
213 229 dtemp = GET32(dev, CONC_dCODECCTL_OFF);
214 230 if ((dtemp & (1UL << 30)) == 0)
215 231 break;
216 232 }
217 233
218 234 PUT32(dev, CONC_dCODECCTL_OFF, ((int)wAddr << 16) | wData);
219 235
220 236 mutex_exit(&dev->mutex);
221 237 }
222 238
223 239 static unsigned short
224 240 SRCRegRead(audioens_dev_t *dev, unsigned short reg)
225 241 {
226 242 int i, dtemp;
227 243
228 244 dtemp = GET32(dev, CONC_dSRCIO_OFF);
229 245 /* wait for ready */
230 246 for (i = 0; i < SRC_IOPOLL_COUNT; ++i) {
231 247 dtemp = GET32(dev, CONC_dSRCIO_OFF);
232 248 if ((dtemp & SRC_BUSY) == 0)
233 249 break;
234 250 }
235 251
236 252 /* assert a read request */
237 253 PUT32(dev, CONC_dSRCIO_OFF, (dtemp & SRC_CTLMASK) | ((int)reg << 25));
238 254
239 255 /* now wait for the data */
240 256 for (i = 0; i < SRC_IOPOLL_COUNT; ++i) {
241 257 dtemp = GET32(dev, CONC_dSRCIO_OFF);
242 258 if ((dtemp & SRC_BUSY) == 0)
243 259 break;
244 260 }
245 261
246 262 return ((unsigned short) dtemp);
247 263 }
248 264
249 265 static void
250 266 SRCRegWrite(audioens_dev_t *dev, unsigned short reg, unsigned short val)
251 267 {
252 268 int i, dtemp;
253 269 int writeval;
254 270
255 271 dtemp = GET32(dev, CONC_dSRCIO_OFF);
256 272 /* wait for ready */
257 273 for (i = 0; i < SRC_IOPOLL_COUNT; ++i) {
258 274 dtemp = GET32(dev, CONC_dSRCIO_OFF);
259 275 if ((dtemp & SRC_BUSY) == 0)
260 276 break;
261 277 }
262 278
263 279 /* assert the write request */
264 280 writeval = (dtemp & SRC_CTLMASK) | SRC_WENABLE |
265 281 ((int)reg << 25) | val;
266 282 PUT32(dev, CONC_dSRCIO_OFF, writeval);
267 283 }
268 284
269 285 static void
270 286 SRCSetRate(audioens_dev_t *dev, unsigned char base, unsigned short rate)
271 287 {
272 288 int i, freq, dtemp;
273 289 unsigned short N, truncM, truncStart;
274 290
275 291 if (base != SRC_ADC_BASE) {
276 292 /* freeze the channel */
277 293 dtemp = (base == SRC_DAC1_BASE) ?
278 294 SRC_DAC1FREEZE : SRC_DAC2FREEZE;
279 295 for (i = 0; i < SRC_IOPOLL_COUNT; ++i) {
280 296 if (!(GET32(dev, CONC_dSRCIO_OFF) & SRC_BUSY))
281 297 break;
282 298 }
283 299 PUT32(dev, CONC_dSRCIO_OFF,
284 300 (GET32(dev, CONC_dSRCIO_OFF) & SRC_CTLMASK) | dtemp);
285 301
286 302 /* calculate new frequency and write it - preserve accum */
287 303 freq = ((int)rate << 16) / 3000U;
288 304 SRCRegWrite(dev, (unsigned short) base + SRC_INT_REGS_OFF,
289 305 (SRCRegRead(dev, (unsigned short) base + SRC_INT_REGS_OFF)
290 306 & 0x00ffU) | ((unsigned short) (freq >> 6) & 0xfc00));
291 307 SRCRegWrite(dev, (unsigned short) base + SRC_VFREQ_FRAC_OFF,
292 308 (unsigned short) freq >> 1);
293 309
294 310 /* un-freeze the channel */
295 311 for (i = 0; i < SRC_IOPOLL_COUNT; ++i)
296 312 if (!(GET32(dev, CONC_dSRCIO_OFF) & SRC_BUSY))
297 313 break;
298 314 PUT32(dev, CONC_dSRCIO_OFF,
299 315 (GET32(dev, CONC_dSRCIO_OFF) & SRC_CTLMASK) & ~dtemp);
300 316 } else {
301 317 /* derive oversample ratio */
302 318 N = rate / 3000U;
303 319 if (N == 15 || N == 13 || N == 11 || N == 9)
304 320 --N;
305 321
306 322 /* truncate the filter and write n/trunc_start */
307 323 truncM = (21 * N - 1) | 1;
308 324 if (rate >= 24000U) {
309 325 if (truncM > 239)
310 326 truncM = 239;
311 327 truncStart = (239 - truncM) >> 1;
312 328
313 329 SRCRegWrite(dev, base + SRC_TRUNC_N_OFF,
314 330 (truncStart << 9) | (N << 4));
315 331 } else {
316 332 if (truncM > 119)
317 333 truncM = 119;
318 334 truncStart = (119 - truncM) >> 1;
319 335
320 336 SRCRegWrite(dev, base + SRC_TRUNC_N_OFF,
321 337 0x8000U | (truncStart << 9) | (N << 4));
322 338 }
323 339
324 340 /* calculate new frequency and write it - preserve accum */
325 341 freq = ((48000UL << 16) / rate) * N;
326 342 SRCRegWrite(dev, base + SRC_INT_REGS_OFF,
327 343 (SRCRegRead(dev, (unsigned short) base + SRC_INT_REGS_OFF)
328 344 & 0x00ff) | ((unsigned short) (freq >> 6) & 0xfc00));
329 345 SRCRegWrite(dev, base + SRC_VFREQ_FRAC_OFF,
330 346 (unsigned short) freq >> 1);
331 347
332 348 SRCRegWrite(dev, SRC_ADC_VOL_L, N << 8);
333 349 SRCRegWrite(dev, SRC_ADC_VOL_R, N << 8);
334 350 }
335 351 }
336 352
337 353 static void
338 354 SRCInit(audioens_dev_t *dev)
339 355 {
340 356 int i;
341 357
342 358 /* Clear all SRC RAM then init - keep SRC disabled until done */
343 359 for (i = 0; i < SRC_IOPOLL_COUNT; ++i) {
344 360 if (!(GET32(dev, CONC_dSRCIO_OFF) & SRC_BUSY))
345 361 break;
346 362 }
347 363 PUT32(dev, CONC_dSRCIO_OFF, SRC_DISABLE);
348 364
349 365 for (i = 0; i < 0x80; ++i)
350 366 SRCRegWrite(dev, (unsigned short) i, 0U);
351 367
352 368 SRCRegWrite(dev, SRC_DAC1_BASE + SRC_TRUNC_N_OFF, 16 << 4);
353 369 SRCRegWrite(dev, SRC_DAC1_BASE + SRC_INT_REGS_OFF, 16 << 10);
354 370 SRCRegWrite(dev, SRC_DAC2_BASE + SRC_TRUNC_N_OFF, 16 << 4);
355 371 SRCRegWrite(dev, SRC_DAC2_BASE + SRC_INT_REGS_OFF, 16 << 10);
356 372 SRCRegWrite(dev, SRC_DAC1_VOL_L, 1 << 12);
357 373 SRCRegWrite(dev, SRC_DAC1_VOL_R, 1 << 12);
358 374 SRCRegWrite(dev, SRC_DAC2_VOL_L, 1 << 12);
359 375 SRCRegWrite(dev, SRC_DAC2_VOL_R, 1 << 12);
360 376 SRCRegWrite(dev, SRC_ADC_VOL_L, 1 << 12);
361 377 SRCRegWrite(dev, SRC_ADC_VOL_R, 1 << 12);
362 378
363 379 /* default some rates */
364 380 SRCSetRate(dev, SRC_DAC1_BASE, 48000);
365 381 SRCSetRate(dev, SRC_DAC2_BASE, 48000);
366 382 SRCSetRate(dev, SRC_ADC_BASE, 48000);
367 383
368 384 /* now enable the whole deal */
369 385 for (i = 0; i < SRC_IOPOLL_COUNT; ++i) {
370 386 if (!(GET32(dev, CONC_dSRCIO_OFF) & SRC_BUSY))
371 387 break;
372 388 }
373 389 PUT32(dev, CONC_dSRCIO_OFF, 0);
374 390 }
375 391
376 392 static void
377 393 audioens_writemem(audioens_dev_t *dev, uint32_t page, uint32_t offs,
378 394 uint32_t data)
379 395 {
380 396 /* Select memory page */
381 397 PUT32(dev, CONC_bMEMPAGE_OFF, page);
↓ open down ↓ |
233 lines elided |
↑ open up ↑ |
382 398 PUT32(dev, offs, data);
383 399 }
384 400
385 401 static uint32_t
386 402 audioens_readmem(audioens_dev_t *dev, uint32_t page, uint32_t offs)
387 403 {
388 404 PUT32(dev, CONC_bMEMPAGE_OFF, page); /* Select memory page */
389 405 return (GET32(dev, offs));
390 406 }
391 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 +
392 513 /*
393 514 * Audio routines
394 515 */
395 516 static int
396 517 audioens_format(void *arg)
397 518 {
398 519 _NOTE(ARGUNUSED(arg));
399 520
400 521 /* hardware can also do AUDIO_FORMAT_U8, but no need for it */
401 522 return (AUDIO_FORMAT_S16_LE);
402 523 }
403 524
404 525 static int
405 526 audioens_channels(void *arg)
406 527 {
407 528 audioens_port_t *port = arg;
408 529
409 530 return (port->nchan);
410 531 }
411 532
412 533 static int
413 534 audioens_rate(void *arg)
414 535 {
415 536 audioens_port_t *port = arg;
416 537
417 538 return (port->speed);
418 539 }
419 540
↓ open down ↓ |
18 lines elided |
↑ open up ↑ |
420 541 static int
421 542 audioens_open(void *arg, int flag, unsigned *nframes, caddr_t *bufp)
422 543 {
423 544 audioens_port_t *port = arg;
424 545 audioens_dev_t *dev = port->dev;
425 546
426 547 _NOTE(ARGUNUSED(flag));
427 548
428 549 mutex_enter(&dev->mutex);
429 550
430 - port->nframes = AUDIOENS_BUF_LEN / (port->nchan * sizeof (int16_t));
431 551 port->count = 0;
432 552
433 553 *nframes = port->nframes;
434 554 *bufp = port->kaddr;
435 555 mutex_exit(&dev->mutex);
436 556
437 557 return (0);
438 558 }
439 559
440 560 static int
441 561 audioens_start(void *arg)
442 562 {
443 563 audioens_port_t *port = arg;
444 564 audioens_dev_t *dev = port->dev;
445 565 uint32_t tmp;
446 566
447 567 mutex_enter(&dev->mutex);
448 568
449 569 switch (port->num) {
450 570 case PORT_DAC:
451 571 /* Set physical address of the DMA buffer */
452 572 audioens_writemem(dev, CONC_DAC1CTL_PAGE, CONC_dDAC1PADDR_OFF,
453 573 port->paddr);
454 574 audioens_writemem(dev, CONC_DAC2CTL_PAGE, CONC_dDAC2PADDR_OFF,
455 575 port->paddr + (port->nframes * sizeof (int16_t) * 2));
456 576
457 577 /* Set DAC rate */
458 578 SRCSetRate(dev, SRC_DAC1_BASE, port->speed);
459 579 SRCSetRate(dev, SRC_DAC2_BASE, port->speed);
460 580
461 581 /* Configure the channel setup - SPDIF only uses front */
462 582 tmp = GET32(dev, CONC_dSTATUS_OFF);
463 583 tmp &= ~(CONC_STATUS_SPKR_MASK | CONC_STATUS_SPDIF_MASK);
464 584 tmp |= CONC_STATUS_SPKR_4CH | CONC_STATUS_SPDIF_P1;
465 585 PUT32(dev, CONC_dSTATUS_OFF, tmp);
466 586
467 587 /* Set format */
468 588 PUT8(dev, CONC_bSKIPC_OFF, 0x10);
↓ open down ↓ |
28 lines elided |
↑ open up ↑ |
469 589 SET8(dev, CONC_bSERFMT_OFF,
470 590 CONC_PCM_DAC1_16BIT | CONC_PCM_DAC2_16BIT |
471 591 CONC_PCM_DAC1_STEREO | CONC_PCM_DAC2_STEREO);
472 592
473 593 /* Set the frame count */
474 594 audioens_writemem(dev, CONC_DAC1CTL_PAGE, CONC_wDAC1FC_OFF,
475 595 port->nframes - 1);
476 596 audioens_writemem(dev, CONC_DAC2CTL_PAGE, CONC_wDAC2FC_OFF,
477 597 port->nframes - 1);
478 598
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 -
599 + PUT16(dev, CONC_wDAC1IC_OFF, port->iframes - 1);
600 + PUT16(dev, CONC_wDAC2IC_OFF, port->iframes - 1);
483 601 SET8(dev, CONC_bDEVCTL_OFF,
484 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
485 608
486 609 break;
487 610
488 611 case PORT_ADC:
489 612 /* Set physical address of the DMA buffer */
490 613 audioens_writemem(dev, CONC_ADCCTL_PAGE, CONC_dADCPADDR_OFF,
491 614 port->paddr);
492 615
493 616 /* Set ADC rate */
494 617 SRCSetRate(dev, SRC_ADC_BASE, port->speed);
495 618
496 619 /* Set format - for input we only support 16 bit input */
497 620 tmp = GET8(dev, CONC_bSERFMT_OFF);
498 621 tmp |= CONC_PCM_ADC_16BIT;
499 622 tmp |= CONC_PCM_ADC_STEREO;
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
500 623
501 624 PUT8(dev, CONC_bSKIPC_OFF, 0x10);
502 625
503 626 PUT8(dev, CONC_bSERFMT_OFF, tmp);
504 627
505 628 /* Set the frame count */
506 629 audioens_writemem(dev, CONC_ADCCTL_PAGE, CONC_wADCFC_OFF,
507 630 port->nframes - 1);
508 631
509 632 /* Set # of frames between interrupts */
510 - PUT16(dev, CONC_wADCIC_OFF, port->nframes - 1);
633 + PUT16(dev, CONC_wADCIC_OFF, port->iframes - 1);
511 634
512 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
513 641 break;
514 642 }
515 643
516 644 port->frameno = 0;
517 645 mutex_exit(&dev->mutex);
518 646
519 647 return (0);
520 648 }
521 649
522 650 static void
523 651 audioens_stop(void *arg)
524 652 {
525 653 audioens_port_t *port = arg;
526 654 audioens_dev_t *dev = port->dev;
527 655
528 656 mutex_enter(&dev->mutex);
529 657 switch (port->num) {
530 658 case PORT_DAC:
531 659 CLR8(dev, CONC_bDEVCTL_OFF,
532 660 CONC_DEVCTL_DAC2_EN | CONC_DEVCTL_DAC1_EN);
533 661 break;
534 662 case PORT_ADC:
535 663 CLR8(dev, CONC_bDEVCTL_OFF, CONC_DEVCTL_ADC_EN);
536 664 break;
537 665 }
538 666 mutex_exit(&dev->mutex);
539 667 }
540 668
541 669 static uint64_t
542 670 audioens_count(void *arg)
543 671 {
544 672 audioens_port_t *port = arg;
545 673 audioens_dev_t *dev = port->dev;
546 674 uint64_t val;
547 675 uint32_t page, offs;
548 676 int frameno, n;
549 677
550 678 switch (port->num) {
551 679 case PORT_DAC:
552 680 page = CONC_DAC1CTL_PAGE;
↓ open down ↓ |
30 lines elided |
↑ open up ↑ |
553 681 offs = CONC_wDAC1FC_OFF;
554 682 break;
555 683
556 684 case PORT_ADC:
557 685 page = CONC_ADCCTL_PAGE;
558 686 offs = CONC_wADCFC_OFF;
559 687 break;
560 688 }
561 689
562 690 mutex_enter(&dev->mutex);
691 +#ifdef __x86
692 + if (!dev->useintr) {
693 +#endif
694 +
563 695 /*
564 696 * Note that the current frame counter is in the high nybble.
565 697 */
566 698 frameno = audioens_readmem(port->dev, page, offs) >> 16;
567 699 n = frameno >= port->frameno ?
568 700 frameno - port->frameno :
569 701 frameno + port->nframes - port->frameno;
570 702 port->frameno = frameno;
571 703 port->count += n;
572 704
705 +#ifdef __x86
706 + }
707 +#endif
708 +
573 709 val = port->count;
574 710 mutex_exit(&dev->mutex);
575 711
576 712 return (val);
577 713 }
578 714
579 715 static void
580 716 audioens_close(void *arg)
581 717 {
582 718 _NOTE(ARGUNUSED(arg));
583 719 }
584 720
585 721 static void
586 722 audioens_sync(void *arg, unsigned nframes)
587 723 {
588 724 audioens_port_t *port = arg;
589 725
590 726 _NOTE(ARGUNUSED(nframes));
591 727
592 728 if (port->num == PORT_ADC) {
593 729 (void) ddi_dma_sync(port->dmah, 0, 0, DDI_DMA_SYNC_FORKERNEL);
594 730 } else {
595 731 (void) ddi_dma_sync(port->dmah, 0, 0, DDI_DMA_SYNC_FORDEV);
596 732 }
597 733 }
598 734
599 735 static void
600 736 audioens_chinfo(void *arg, int chan, unsigned *offset, unsigned *incr)
601 737 {
602 738 audioens_port_t *port = arg;
603 739
604 740 if ((port->num == PORT_DAC) && (chan >= 2)) {
605 741 *offset = (port->nframes * 2) + (chan % 2);
606 742 *incr = 2;
607 743 } else {
608 744 *offset = chan;
609 745 *incr = 2;
610 746 }
611 747 }
612 748
613 749 audio_engine_ops_t audioens_engine_ops = {
614 750 AUDIO_ENGINE_VERSION, /* version number */
615 751 audioens_open,
616 752 audioens_close,
617 753 audioens_start,
618 754 audioens_stop,
619 755 audioens_count,
620 756 audioens_format,
621 757 audioens_channels,
622 758 audioens_rate,
623 759 audioens_sync,
624 760 NULL,
625 761 audioens_chinfo,
626 762 NULL,
627 763 };
628 764
629 765 void
630 766 audioens_init_hw(audioens_dev_t *dev)
631 767 {
632 768 int tmp;
633 769
634 770 if ((dev->devid == ENSONIQ_ES5880) ||
635 771 (dev->devid == ENSONIQ_ES5880A) ||
636 772 (dev->devid == ENSONIQ_ES5880B) ||
637 773 (dev->devid == 0x1371 && dev->revision == 7) ||
638 774 (dev->devid == 0x1371 && dev->revision >= 9)) {
639 775
640 776 /* Have a ES5880 so enable the codec manually */
641 777 tmp = GET8(dev, CONC_bINTSUMM_OFF) & 0xff;
642 778 tmp |= 0x20;
643 779 PUT8(dev, CONC_bINTSUMM_OFF, tmp);
644 780 for (int i = 0; i < 2000; i++)
645 781 drv_usecwait(10);
646 782 }
647 783
648 784 SRCInit(dev);
649 785
650 786 /*
651 787 * Turn on CODEC (UART and joystick left disabled)
652 788 */
653 789 tmp = GET32(dev, CONC_bDEVCTL_OFF) & 0xff;
654 790 tmp &= ~(CONC_DEVCTL_PCICLK_DS | CONC_DEVCTL_XTALCLK_DS);
655 791 PUT8(dev, CONC_bDEVCTL_OFF, tmp);
656 792 PUT8(dev, CONC_bUARTCSTAT_OFF, 0x00);
657 793
658 794 /* Perform AC97 codec warm reset */
659 795 tmp = GET8(dev, CONC_bMISCCTL_OFF) & 0xff;
660 796 PUT8(dev, CONC_bMISCCTL_OFF, tmp | CONC_MISCCTL_SYNC_RES);
661 797 drv_usecwait(200);
662 798 PUT8(dev, CONC_bMISCCTL_OFF, tmp);
663 799 drv_usecwait(200);
664 800
665 801 if (dev->revision >= 4) {
666 802 /* XXX: enable SPDIF - PCM only for now */
667 803 if (audioens_spdif) {
668 804 /* enable SPDIF */
669 805 PUT32(dev, 0x04, GET32(dev, 0x04) | (1 << 18));
670 806 /* SPDIF out = data from DAC */
671 807 PUT32(dev, 0x00, GET32(dev, 0x00) | (1 << 26));
672 808 CLR32(dev, CONC_dSPDIF_OFF, CONC_SPDIF_AC3);
673 809
674 810 } else {
675 811 /* disable spdif out */
676 812 PUT32(dev, 0x04, GET32(dev, 0x04) & ~(1 << 18));
677 813 PUT32(dev, 0x00, GET32(dev, 0x00) & ~(1 << 26));
678 814 }
679 815
680 816 /* we want to run each channel independently */
681 817 CLR32(dev, CONC_dSTATUS_OFF, CONC_STATUS_ECHO);
682 818 }
683 819 }
684 820
685 821 static int
686 822 audioens_init(audioens_dev_t *dev)
687 823 {
688 824
689 825 audioens_init_hw(dev);
690 826
691 827 /*
692 828 * On this hardware, we want to disable the internal speaker by
693 829 * default, if it exists. (We don't have a speakerphone on any
694 830 * of these cards, and no SPARC hardware uses it either!)
695 831 */
696 832 (void) ddi_prop_update_int(DDI_DEV_T_NONE, dev->dip, AC97_PROP_SPEAKER,
697 833 0);
698 834
699 835 /*
700 836 * Init mixer
701 837 */
702 838
703 839 dev->ac97 = ac97_alloc(dev->dip, audioens_rd97, audioens_wr97, dev);
704 840 if (dev->ac97 == NULL)
705 841 return (DDI_FAILURE);
706 842
707 843 if (ac97_init(dev->ac97, dev->osdev) != 0) {
↓ open down ↓ |
125 lines elided |
↑ open up ↑ |
708 844 return (DDI_FAILURE);
709 845 }
710 846
711 847 for (int i = 0; i <= PORT_MAX; i++) {
712 848 audioens_port_t *port;
713 849 unsigned caps;
714 850 unsigned dmaflags;
715 851 size_t rlen;
716 852 ddi_dma_cookie_t c;
717 853 unsigned ccnt;
854 + size_t bufsz;
718 855
719 856 port = &dev->port[i];
720 857 port->dev = dev;
721 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 +
722 866 switch (i) {
723 867 case PORT_DAC:
724 868 port->nchan = 4;
725 869 port->speed = 48000;
870 + port->iframes = 128;
871 + port->nframes = 2048;
726 872 caps = ENGINE_OUTPUT_CAP;
727 873 dmaflags = DDI_DMA_WRITE | DDI_DMA_CONSISTENT;
728 874 break;
729 875
730 876 case PORT_ADC:
731 877 port->nchan = 2;
732 878 port->speed = 48000;
879 + port->iframes = 128;
880 + port->nframes = 2048;
733 881 caps = ENGINE_INPUT_CAP;
734 882 dmaflags = DDI_DMA_READ | DDI_DMA_CONSISTENT;
735 883 break;
736 884 }
737 885
738 886 port->num = i;
887 + bufsz = port->nframes * port->nchan * sizeof (uint16_t);
739 888
740 889 /*
741 890 * Allocate DMA resources.
742 891 */
743 892
744 893 if (ddi_dma_alloc_handle(dev->dip, &dma_attr, DDI_DMA_SLEEP,
745 894 NULL, &port->dmah) != DDI_SUCCESS) {
746 895 audio_dev_warn(dev->osdev,
747 896 "port %d: dma handle allocation failed", i);
748 897 return (DDI_FAILURE);
749 898 }
750 - if (ddi_dma_mem_alloc(port->dmah, AUDIOENS_BUF_LEN, &buf_attr,
899 + if (ddi_dma_mem_alloc(port->dmah, bufsz, &buf_attr,
751 900 DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &port->kaddr,
752 901 &rlen, &port->acch) != DDI_SUCCESS) {
753 902 audio_dev_warn(dev->osdev,
754 903 "port %d: dma memory allocation failed", i);
755 904 return (DDI_FAILURE);
756 905 }
757 906 /* ensure that the buffer is zeroed out properly */
758 907 bzero(port->kaddr, rlen);
759 908 if (ddi_dma_addr_bind_handle(port->dmah, NULL, port->kaddr,
760 - AUDIOENS_BUF_LEN, dmaflags, DDI_DMA_SLEEP, NULL,
909 + bufsz, dmaflags, DDI_DMA_SLEEP, NULL,
761 910 &c, &ccnt) != DDI_DMA_MAPPED) {
762 911 audio_dev_warn(dev->osdev,
763 912 "port %d: dma binding failed", i);
764 913 return (DDI_FAILURE);
765 914 }
766 915 port->paddr = c.dmac_address;
767 916
768 917 /*
769 918 * Allocate and configure audio engine.
770 919 */
771 920 port->engine = audio_engine_alloc(&audioens_engine_ops, caps);
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
772 921 if (port->engine == NULL) {
773 922 audio_dev_warn(dev->osdev,
774 923 "port %d: audio_engine_alloc failed", i);
775 924 return (DDI_FAILURE);
776 925 }
777 926
778 927 audio_engine_set_private(port->engine, port);
779 928 audio_dev_add_engine(dev->osdev, port->engine);
780 929 }
781 930
782 - /*
783 - * Set up kstats for interrupt reporting.
784 - */
785 931 if (audio_dev_register(dev->osdev) != DDI_SUCCESS) {
786 932 audio_dev_warn(dev->osdev,
787 933 "unable to register with audio framework");
788 934 return (DDI_FAILURE);
789 935 }
790 936
791 937 return (DDI_SUCCESS);
792 938 }
793 939
794 940 void
795 941 audioens_destroy(audioens_dev_t *dev)
796 942 {
797 943 int i;
798 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 +
799 954 mutex_destroy(&dev->mutex);
800 955
801 956 /* free up ports, including DMA resources for ports */
802 957 for (i = 0; i <= PORT_MAX; i++) {
803 958 audioens_port_t *port = &dev->port[i];
804 959
805 960 if (port->paddr != 0)
806 961 (void) ddi_dma_unbind_handle(port->dmah);
807 962 if (port->acch != NULL)
808 963 ddi_dma_mem_free(&port->acch);
809 964 if (port->dmah != NULL)
810 965 ddi_dma_free_handle(&port->dmah);
811 966
812 967 if (port->engine != NULL) {
813 968 audio_dev_remove_engine(dev->osdev, port->engine);
814 969 audio_engine_free(port->engine);
815 970 }
816 971 }
817 972
818 973 if (dev->acch != NULL) {
819 974 ddi_regs_map_free(&dev->acch);
820 975 }
821 976
822 977 if (dev->ac97) {
823 978 ac97_free(dev->ac97);
824 979 }
825 980
826 981 if (dev->osdev != NULL) {
827 982 audio_dev_free(dev->osdev);
828 983 }
829 984
830 985 kmem_free(dev, sizeof (*dev));
831 986 }
832 987
833 988 int
834 989 audioens_attach(dev_info_t *dip)
835 990 {
836 991 uint16_t pci_command, vendor, device;
837 992 uint8_t revision;
838 993 audioens_dev_t *dev;
839 994 ddi_acc_handle_t pcih;
↓ open down ↓ |
31 lines elided |
↑ open up ↑ |
840 995 const char *chip_name;
841 996 const char *chip_vers;
842 997
843 998 dev = kmem_zalloc(sizeof (*dev), KM_SLEEP);
844 999 dev->dip = dip;
845 1000 ddi_set_driver_private(dip, dev);
846 1001 mutex_init(&dev->mutex, NULL, MUTEX_DRIVER, NULL);
847 1002
848 1003 if (pci_config_setup(dip, &pcih) != DDI_SUCCESS) {
849 1004 audio_dev_warn(dev->osdev, "pci_config_setup failed");
850 - mutex_destroy(&dev->mutex);
851 - kmem_free(dev, sizeof (*dev));
852 - return (DDI_FAILURE);
1005 + goto err_exit;
853 1006 }
854 1007
855 1008 vendor = pci_config_get16(pcih, PCI_CONF_VENID);
856 1009 device = pci_config_get16(pcih, PCI_CONF_DEVID);
857 1010 revision = pci_config_get8(pcih, PCI_CONF_REVID);
858 1011
859 1012 if ((vendor != ENSONIQ_VENDOR_ID && vendor != CREATIVE_VENDOR_ID) ||
860 1013 (device != ENSONIQ_ES1371 && device != ENSONIQ_ES5880 &&
861 1014 device != ENSONIQ_ES5880A && device != ECTIVA_ES1938 &&
862 - device != ENSONIQ_ES5880B))
1015 + device != ENSONIQ_ES5880B)) {
1016 + audio_dev_warn(dev->osdev, "unrecognized device");
863 1017 goto err_exit;
1018 + }
864 1019
865 1020 chip_name = "AudioPCI97";
866 1021 chip_vers = "unknown";
867 1022
868 1023 switch (device) {
869 1024 case ENSONIQ_ES1371:
870 1025 chip_name = "AudioPCI97";
871 1026 switch (revision) {
872 1027 case 0x02:
873 1028 case 0x09:
874 1029 default:
875 1030 chip_vers = "ES1371";
876 1031 break;
877 1032 case 0x04:
878 1033 case 0x06:
879 1034 case 0x08:
880 1035 chip_vers = "ES1373";
881 1036 break;
882 1037 case 0x07:
883 1038 chip_vers = "ES5880";
884 1039 break;
885 1040 }
886 1041 break;
887 1042
888 1043 case ENSONIQ_ES5880:
889 1044 chip_name = "SB PCI128";
890 1045 chip_vers = "ES5880";
891 1046 break;
892 1047 case ENSONIQ_ES5880A:
893 1048 chip_name = "SB PCI128";
894 1049 chip_vers = "ES5880A";
895 1050 break;
896 1051 case ENSONIQ_ES5880B:
897 1052 chip_name = "SB PCI128";
898 1053 chip_vers = "ES5880B";
899 1054 break;
900 1055
901 1056 case ECTIVA_ES1938:
902 1057 chip_name = "AudioPCI";
903 1058 chip_vers = "ES1938";
904 1059 break;
905 1060 }
906 1061
907 1062 dev->revision = revision;
908 1063 dev->devid = device;
909 1064
910 1065 dev->osdev = audio_dev_alloc(dip, 0);
911 1066 if (dev->osdev == NULL) {
912 1067 goto err_exit;
913 1068 }
914 1069
915 1070 audio_dev_set_description(dev->osdev, chip_name);
916 1071 audio_dev_set_version(dev->osdev, chip_vers);
917 1072
918 1073 /* set the PCI latency */
919 1074 if ((audioens_latency == 32) || (audioens_latency == 64) ||
920 1075 (audioens_latency == 96))
921 1076 pci_config_put8(pcih, PCI_CONF_LATENCY_TIMER,
922 1077 audioens_latency);
923 1078
924 1079 /* activate the device */
925 1080 pci_command = pci_config_get16(pcih, PCI_CONF_COMM);
↓ open down ↓ |
52 lines elided |
↑ open up ↑ |
926 1081 pci_command |= PCI_COMM_ME | PCI_COMM_IO;
927 1082 pci_config_put16(pcih, PCI_CONF_COMM, pci_command);
928 1083
929 1084 /* map registers */
930 1085 if (ddi_regs_map_setup(dip, 1, &dev->regs, 0, 0, &acc_attr,
931 1086 &dev->acch) != DDI_SUCCESS) {
932 1087 audio_dev_warn(dev->osdev, "can't map registers");
933 1088 goto err_exit;
934 1089 }
935 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 +
936 1110 /* This allocates and configures the engines */
937 1111 if (audioens_init(dev) != DDI_SUCCESS) {
938 1112 audio_dev_warn(dev->osdev, "can't init device");
939 1113 goto err_exit;
940 1114 }
941 1115
1116 +#ifdef __x86
1117 + if (dev->useintr) {
1118 + (void) ddi_intr_enable(dev->intrh);
1119 + }
1120 +#endif
942 1121 pci_config_teardown(&pcih);
943 1122
944 1123 ddi_report_dev(dip);
945 1124
946 1125 return (DDI_SUCCESS);
947 1126
948 1127 err_exit:
949 1128 pci_config_teardown(&pcih);
950 1129
951 1130 audioens_destroy(dev);
952 1131
953 1132 return (DDI_FAILURE);
954 1133 }
955 1134
956 1135 int
957 1136 audioens_detach(audioens_dev_t *dev)
958 1137 {
959 1138 int tmp;
960 1139
961 1140 /* first unregister us from the DDI framework, might be busy */
962 1141 if (audio_dev_unregister(dev->osdev) != DDI_SUCCESS)
963 1142 return (DDI_FAILURE);
964 1143
965 1144 mutex_enter(&dev->mutex);
966 1145
967 1146 tmp = GET8(dev, CONC_bSERCTL_OFF) &
968 1147 ~(CONC_SERCTL_DAC2IE | CONC_SERCTL_DAC1IE | CONC_SERCTL_ADCIE);
969 1148 PUT8(dev, CONC_bSERCTL_OFF, tmp);
970 1149 PUT8(dev, CONC_bSERCTL_OFF, tmp);
971 1150 PUT8(dev, CONC_bSERCTL_OFF, tmp);
972 1151 PUT8(dev, CONC_bSERCTL_OFF, tmp);
973 1152
974 1153 tmp = GET8(dev, CONC_bDEVCTL_OFF) &
975 1154 ~(CONC_DEVCTL_DAC2_EN | CONC_DEVCTL_ADC_EN | CONC_DEVCTL_DAC1_EN);
976 1155 PUT8(dev, CONC_bDEVCTL_OFF, tmp);
977 1156 PUT8(dev, CONC_bDEVCTL_OFF, tmp);
978 1157 PUT8(dev, CONC_bDEVCTL_OFF, tmp);
979 1158 PUT8(dev, CONC_bDEVCTL_OFF, tmp);
980 1159
↓ open down ↓ |
29 lines elided |
↑ open up ↑ |
981 1160 mutex_exit(&dev->mutex);
982 1161
983 1162 audioens_destroy(dev);
984 1163
985 1164 return (DDI_SUCCESS);
986 1165 }
987 1166
988 1167 static int
989 1168 audioens_resume(audioens_dev_t *dev)
990 1169 {
1170 + mutex_enter(&dev->mutex);
1171 + dev->suspended = B_FALSE;
1172 + mutex_exit(&dev->mutex);
1173 +
991 1174 /* reinitialize hardware */
992 1175 audioens_init_hw(dev);
993 1176
994 1177 /* restore AC97 state */
995 1178 ac97_reset(dev->ac97);
996 1179
997 1180 audio_dev_resume(dev->osdev);
998 1181
999 1182 return (DDI_SUCCESS);
1000 1183 }
1001 1184
1002 1185 static int
1003 1186 audioens_suspend(audioens_dev_t *dev)
1004 1187 {
1005 1188 audio_dev_suspend(dev->osdev);
1006 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 +
1007 1196 return (DDI_SUCCESS);
1008 1197 }
1009 1198
1010 1199 static int
1011 1200 audioens_quiesce(dev_info_t *dip)
1012 1201 {
1013 1202 audioens_dev_t *dev;
1014 1203 uint8_t tmp;
1015 1204
1016 1205 if ((dev = ddi_get_driver_private(dip)) == NULL) {
1017 1206 return (DDI_FAILURE);
1018 1207 }
1019 1208
1020 1209 /* This disables all DMA engines and interrupts */
1021 1210 tmp = GET8(dev, CONC_bSERCTL_OFF) &
1022 1211 ~(CONC_SERCTL_DAC2IE | CONC_SERCTL_DAC1IE | CONC_SERCTL_ADCIE);
1023 1212 PUT8(dev, CONC_bSERCTL_OFF, tmp);
1024 1213 PUT8(dev, CONC_bSERCTL_OFF, tmp);
1025 1214 PUT8(dev, CONC_bSERCTL_OFF, tmp);
1026 1215 PUT8(dev, CONC_bSERCTL_OFF, tmp);
1027 1216
1028 1217 tmp = GET8(dev, CONC_bDEVCTL_OFF) &
1029 1218 ~(CONC_DEVCTL_DAC2_EN | CONC_DEVCTL_ADC_EN | CONC_DEVCTL_DAC1_EN);
1030 1219 PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1031 1220 PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1032 1221 PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1033 1222 PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1034 1223
1035 1224 return (DDI_SUCCESS);
1036 1225 }
1037 1226
1038 1227
1039 1228 static int
1040 1229 audioens_ddi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1041 1230 {
1042 1231 audioens_dev_t *dev;
1043 1232
1044 1233 switch (cmd) {
1045 1234 case DDI_ATTACH:
1046 1235 return (audioens_attach(dip));
1047 1236
1048 1237 case DDI_RESUME:
1049 1238 if ((dev = ddi_get_driver_private(dip)) == NULL) {
1050 1239 return (DDI_FAILURE);
1051 1240 }
1052 1241 return (audioens_resume(dev));
1053 1242
1054 1243 default:
1055 1244 return (DDI_FAILURE);
1056 1245 }
1057 1246 }
1058 1247
1059 1248 static int
1060 1249 audioens_ddi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1061 1250 {
1062 1251 audioens_dev_t *dev;
1063 1252
1064 1253 if ((dev = ddi_get_driver_private(dip)) == NULL) {
1065 1254 return (DDI_FAILURE);
1066 1255 }
1067 1256
1068 1257 switch (cmd) {
1069 1258 case DDI_DETACH:
1070 1259 return (audioens_detach(dev));
1071 1260
1072 1261 case DDI_SUSPEND:
1073 1262 return (audioens_suspend(dev));
1074 1263 default:
1075 1264 return (DDI_FAILURE);
1076 1265 }
1077 1266 }
1078 1267
1079 1268 static int audioens_ddi_attach(dev_info_t *, ddi_attach_cmd_t);
1080 1269 static int audioens_ddi_detach(dev_info_t *, ddi_detach_cmd_t);
1081 1270
1082 1271 static struct dev_ops audioens_dev_ops = {
1083 1272 DEVO_REV, /* rev */
1084 1273 0, /* refcnt */
1085 1274 NULL, /* getinfo */
1086 1275 nulldev, /* identify */
1087 1276 nulldev, /* probe */
1088 1277 audioens_ddi_attach, /* attach */
1089 1278 audioens_ddi_detach, /* detach */
1090 1279 nodev, /* reset */
1091 1280 NULL, /* cb_ops */
1092 1281 NULL, /* bus_ops */
1093 1282 NULL, /* power */
1094 1283 audioens_quiesce, /* quiesce */
1095 1284 };
1096 1285
1097 1286 static struct modldrv audioens_modldrv = {
1098 1287 &mod_driverops, /* drv_modops */
1099 1288 "Ensoniq 1371/1373 Audio", /* linkinfo */
1100 1289 &audioens_dev_ops, /* dev_ops */
1101 1290 };
1102 1291
1103 1292 static struct modlinkage modlinkage = {
1104 1293 MODREV_1,
1105 1294 { &audioens_modldrv, NULL }
1106 1295 };
1107 1296
1108 1297 int
1109 1298 _init(void)
1110 1299 {
1111 1300 int rv;
1112 1301
1113 1302 audio_init_ops(&audioens_dev_ops, DRVNAME);
1114 1303 if ((rv = mod_install(&modlinkage)) != 0) {
1115 1304 audio_fini_ops(&audioens_dev_ops);
1116 1305 }
1117 1306 return (rv);
1118 1307 }
1119 1308
1120 1309 int
1121 1310 _fini(void)
1122 1311 {
1123 1312 int rv;
1124 1313
1125 1314 if ((rv = mod_remove(&modlinkage)) == 0) {
1126 1315 audio_fini_ops(&audioens_dev_ops);
1127 1316 }
1128 1317 return (rv);
1129 1318 }
1130 1319
1131 1320 int
1132 1321 _info(struct modinfo *modinfop)
1133 1322 {
1134 1323 return (mod_info(&modlinkage, modinfop));
1135 1324 }
↓ open down ↓ |
119 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX