cs4231_sbus.c revision 1.1 1 /* $NetBSD: cs4231_sbus.c,v 1.1 1998/08/27 20:51:17 pk Exp $ */
2
3 #include "audio.h"
4 #if NAUDIO > 0
5
6 #include <sys/param.h>
7 #include <sys/systm.h>
8 #include <sys/errno.h>
9 #include <sys/ioctl.h>
10 #include <sys/device.h>
11 #include <sys/malloc.h>
12 #include <sys/proc.h>
13
14 #include <machine/autoconf.h>
15 #include <machine/cpu.h>
16
17 #include <sys/audioio.h>
18 #include <dev/audio_if.h>
19
20 #include <dev/ic/ad1848reg.h>
21 #include <dev/ic/cs4231reg.h>
22 #include <dev/ic/ad1848var.h>
23
24 #if 0
25 /* XXX- put these elsewhere */
26 #define SUNAUDIO_MIC_PORT 0
27 #define SUNAUDIO_SPEAKER 1
28 #define SUNAUDIO_HEADPHONES 2
29 #define SUNAUDIO_MONITOR 3
30 #define SUNAUDIO_SOURCE 4
31 #define SUNAUDIO_OUTPUT 5
32 #define SUNAUDIO_INPUT_CLASS 6
33 #define SUNAUDIO_OUTPUT_CLASS 7
34 #define SUNAUDIO_RECORD_CLASS 8
35 #define SUNAUDIO_MONITOR_CLASS 9
36 #endif
37
38 /*---*/
39 #define CSAUDIO_DAC_LVL 0
40 #define CSAUDIO_LINE_IN_LVL 1
41 #define CSAUDIO_MONO_LVL 2
42 #define CSAUDIO_CD_LVL 3
43 #define CSAUDIO_MONITOR_LVL 4
44 #define CSAUDIO_OUT_LVL 5
45 #define CSAUDIO_LINE_IN_MUTE 6
46 #define CSAUDIO_DAC_MUTE 7
47 #define CSAUDIO_CD_MUTE 8
48 #define CSAUDIO_MONO_MUTE 9
49 #define CSAUDIO_MONITOR_MUTE 10
50 #define CSAUDIO_REC_LVL 11
51 #define CSAUDIO_RECORD_SOURCE 12
52
53 #define CSAUDIO_INPUT_CLASS 13
54 #define CSAUDIO_OUTPUT_CLASS 14
55 #define CSAUDIO_RECORD_CLASS 15
56 #define CSAUDIO_MONITOR_CLASS 16
57
58 #define AUDIO_ROM_NAME "SUNW,CS4231"
59
60 #define Dprintf printf
61 #ifdef AUDIO_DEBUG
62 extern void Dprintf __P((const char *, ...));
63
64 int cs4231debug = 0;
65 #define DPRINTF(x) if (cs4231debug) Dprintf x
66 #else
67 #define DPRINTF(x)
68 #endif
69
70 /*
71 * Layout of 4231 registers.
72 *
73 struct cs4231_reg {
74 volatile u_int8_t iar; // Index Address Register
75 volatile u_int8_t pad0[3];
76 volatile u_int8_t idr; // Data Register
77 volatile u_int8_t pad1[3];
78 volatile u_int8_t status; // Status Register
79 volatile u_int8_t pad2[3];
80 volatile u_int8_t piodr; // PIO Data Register I/O
81 volatile u_int8_t pad3[3];
82 };
83 */
84 #define CS4231_REG_SIZE 16
85
86
87 /*
88 * APC DMA hardware; from SunOS header
89 * Thanks to Derrick J. Brashear for additional info on the
90 * meaning of some of these bits.
91 */
92 struct apc_dma {
93 volatile u_long dmacsr; /* APC CSR */
94 volatile u_long lpad[3]; /* */
95 volatile u_long dmacva; /* Capture Virtual Address */
96 volatile u_long dmacc; /* Capture Count */
97 volatile u_long dmacnva; /* Capture Next Virtual Address */
98 volatile u_long dmacnc; /* Capture next count */
99 volatile u_long dmapva; /* Playback Virtual Address */
100 volatile u_long dmapc; /* Playback Count */
101 volatile u_long dmapnva; /* Playback Next VAddress */
102 volatile u_long dmapnc; /* Playback Next Count */
103 };
104
105 /*
106 * APC CSR Register bit definitions
107 */
108 #define APC_IP 0x00800000 /* Interrupt Pending */
109 #define APC_PI 0x00400000 /* Playback interrupt */
110 #define APC_CI 0x00200000 /* Capture interrupt */
111 #define APC_EI 0x00100000 /* General interrupt */
112 #define APC_IE 0x00080000 /* General ext int. enable */
113 #define APC_PIE 0x00040000 /* Playback ext intr */
114 #define APC_CIE 0x00020000 /* Capture ext intr */
115 #define APC_EIE 0x00010000 /* Error ext intr */
116 #define APC_PMI 0x00008000 /* Pipe empty interrupt */
117 #define APC_PM 0x00004000 /* Play pipe empty */
118 #define APC_PD 0x00002000 /* Playback NVA dirty */
119 #define APC_PMIE 0x00001000 /* play pipe empty Int enable */
120 #define APC_CM 0x00000800 /* Cap data dropped on floor */
121 #define APC_CD 0x00000400 /* Capture NVA dirty */
122 #define APC_CMI 0x00000200 /* Capture pipe empty interrupt */
123 #define APC_CMIE 0x00000100 /* Cap. pipe empty int enable */
124 #define APC_PPAUSE 0x00000080 /* Pause the play DMA */
125 #define APC_CPAUSE 0x00000040 /* Pause the capture DMA */
126 #define APC_CODEC_PDN 0x00000020 /* CODEC RESET */
127 #define PDMA_GO 0x00000008
128 #define CDMA_GO 0x00000004 /* bit 2 of the csr */
129 #define APC_RESET 0x00000001 /* Reset the chip */
130
131 #define APC_BITS \
132 "\20\30IP\27PI\26CI\25EI\24IE" \
133 "\23PIE\22CIE\21EIE\20PMI\17PM\16PD\15PMIE" \
134 "\14CM\13CD\12CMI\11CMIE\10PPAUSE\7CPAUSE\6PDN\4PGO\3CGO"
135
136 /*
137 * To start DMA, you write to dma[cp]nva and dma[cp]nc and set [CP]DMA_GO
138 * in dmacsr. dma[cp]va and dma[cp]c, when read, appear to be the live
139 * counter as the DMA operation progresses.
140 * Supposedly, you get an interrupt with the "dirty" bits (APC_PD,APC_CD)
141 * set, when the next DMA buffer can be programmed, while the current one
142 * is still in progress. We don't currently use this feature, since I
143 * haven't been able to make it work.. instead the next buffer goes in
144 * as soon as we see a "pipe empty" (APC_PM) interrupt.
145 */
146
147 /* It's not clear if there's a maximum DMA size.. */
148 #define APC_MAX (sc->sc_blksz)/*(16*1024)*/
149
150 /*
151 * List of device memory allocations (see cs4231_malloc/cs4231_free).
152 */
153 struct cs_dma {
154 struct cs_dma *next;
155 caddr_t addr;
156 bus_dma_segment_t segs[1];
157 int nsegs;
158 size_t size;
159 };
160
161
162 /*
163 * Software state, per CS4231 audio chip.
164 */
165 struct cs4231_softc {
166 struct ad1848_softc sc_ad1848; /* base device */
167 struct sbusdev sc_sd; /* sbus device */
168 bus_space_tag_t sc_bustag;
169 bus_dma_tag_t sc_dmatag;
170 struct evcnt sc_intrcnt; /* statistics */
171
172 struct cs_dma *sc_dmas;
173 struct cs_dma *sc_nowplaying; /*XXX*/
174 u_long sc_playsegsz; /*XXX*/
175 u_long sc_playcnt;
176 u_long sc_blksz;
177
178 int sc_open; /* single use device */
179 int sc_locked; /* true when transfering data */
180 struct apc_dma *sc_dmareg; /* DMA registers */
181
182 /* interfacing with the interrupt handlers */
183 void (*sc_rintr)(void*); /* input completion intr handler */
184 void *sc_rarg; /* arg for sc_rintr() */
185 void (*sc_pintr)(void*); /* output completion intr handler */
186 void *sc_parg; /* arg for sc_pintr() */
187 };
188
189 /* autoconfiguration driver */
190 void cs4231attach __P((struct device *, struct device *, void *));
191 int cs4231match __P((struct device *, struct cfdata *, void *));
192
193 struct cfattach audiocs_ca = {
194 sizeof(struct cs4231_softc), cs4231match, cs4231attach
195 };
196
197 struct audio_device cs4231_device = {
198 "cs4231",
199 "x",
200 "audio"
201 };
202
203
204 /*
205 * Define our interface to the higher level audio driver.
206 */
207 int cs4231_open __P((void *, int));
208 void cs4231_close __P((void *));
209 u_long cs4231_round_buffersize __P((void *, u_long));
210 int cs4231_round_blocksize __P((void *, int));
211 int cs4231_halt_output __P((void *));
212 int cs4231_halt_input __P((void *));
213 int cs4231_getdev __P((void *, struct audio_device *));
214 int cs4231_set_port __P((void *, mixer_ctrl_t *));
215 int cs4231_get_port __P((void *, mixer_ctrl_t *));
216 int cs4231_query_devinfo __P((void *, mixer_devinfo_t *));
217 int cs4231_get_props __P((void *));
218
219 void *cs4231_malloc __P((void *, u_long, int, int));
220 void cs4231_free __P((void *, void *, int));
221 int cs4231_trigger_output __P((void *, void *, void *, int,
222 void (*)(void *), void *,
223 struct audio_params *));
224 int cs4231_trigger_input __P((void *, void *, void *, int,
225 void (*)(void *), void *,
226 struct audio_params *));
227
228 int cs4231_intr __P((void *));
229 void cs4231_init __P((struct cs4231_softc *));
230
231
232 static void cs4231_regdump __P((char *, struct cs4231_softc *));
233 static int cs_read __P((struct ad1848_softc *, int));
234 static void cs_write __P((struct ad1848_softc *, int, int));
235
236 static int
237 cs_read(sc, index)
238 struct ad1848_softc *sc;
239 int index;
240 {
241 u_int8_t *p = (u_int8_t *)sc->sc_ioh + (index << 2);
242 int v;
243
244 v = *p;
245 return (v);
246 }
247
248 static void
249 cs_write(sc, index, value)
250 struct ad1848_softc *sc;
251 int index, value;
252 {
253 u_int8_t *p = (u_int8_t *)sc->sc_ioh + (index << 2);
254
255 *p = value;
256 }
257
258 static struct audio_hw_if hw_if = {
259 cs4231_open,
260 cs4231_close,
261 0,
262 ad1848_query_encoding,
263 ad1848_set_params,
264 cs4231_round_blocksize,
265 ad1848_commit_settings,
266 0,
267 0,
268 NULL,
269 NULL,
270 cs4231_halt_output,
271 cs4231_halt_input,
272 0,
273 cs4231_getdev,
274 0,
275 cs4231_set_port,
276 cs4231_get_port,
277 cs4231_query_devinfo,
278 cs4231_malloc,
279 cs4231_free,
280 cs4231_round_buffersize,
281 0,
282 cs4231_get_props,
283 cs4231_trigger_output,
284 cs4231_trigger_input
285 };
286
287 /* autoconfig routines */
288
289 int
290 cs4231match(parent, cf, aux)
291 struct device *parent;
292 struct cfdata *cf;
293 void *aux;
294 {
295 struct sbus_attach_args *sa = aux;
296
297 return (strcmp(AUDIO_ROM_NAME, sa->sa_name) == 0);
298 }
299
300 /*
301 * Audio chip found.
302 */
303 void
304 cs4231attach(parent, self, aux)
305 struct device *parent, *self;
306 void *aux;
307 {
308 struct cs4231_softc *sc = (struct cs4231_softc *)self;
309 struct sbus_attach_args *sa = aux;
310 bus_space_handle_t bh;
311
312 sc->sc_bustag = sa->sa_bustag;
313 sc->sc_dmatag = sa->sa_dmatag;
314
315 sc->sc_ad1848.parent = sc;
316 sc->sc_ad1848.sc_readreg = cs_read;
317 sc->sc_ad1848.sc_writereg = cs_write;
318
319 /*
320 * Map my registers in, if they aren't already in virtual
321 * address space.
322 */
323 if (sa->sa_npromvaddrs) {
324 bh = (bus_space_handle_t)sa->sa_promvaddrs[0];
325 } else {
326 if (sbus_bus_map(sa->sa_bustag, sa->sa_slot,
327 sa->sa_offset,
328 sa->sa_size,
329 BUS_SPACE_MAP_LINEAR,
330 0, &bh) != 0) {
331 printf("%s @ sbus: cannot map registers\n",
332 self->dv_xname);
333 return;
334 }
335 }
336
337 sc->sc_ad1848.sc_ioh = bh;
338 sc->sc_dmareg = (struct apc_dma *)((int)bh + CS4231_REG_SIZE);
339
340 cs4231_init(sc);
341
342 /* Put ad1848 driver in `MODE 2' mode */
343 sc->sc_ad1848.mode = 2;
344 ad1848_attach(&sc->sc_ad1848);
345
346 printf("\n");
347
348 sbus_establish(&sc->sc_sd, &sc->sc_ad1848.sc_dev);
349
350 /* Establish interrupt channel */
351 bus_intr_establish(sa->sa_bustag,
352 sa->sa_pri, 0,
353 cs4231_intr, sc);
354
355 evcnt_attach(&sc->sc_ad1848.sc_dev, "intr", &sc->sc_intrcnt);
356 audio_attach_mi(&hw_if, sc, &sc->sc_ad1848.sc_dev);
357 }
358
359
360 static void
361 cs4231_regdump(label, sc)
362 char *label;
363 struct cs4231_softc *sc;
364 {
365 char bits[128];
366 volatile struct apc_dma *dma = sc->sc_dmareg;
367
368 printf("cs4231regdump(%s): regs:", label);
369 printf("dmapva: 0x%lx; ", dma->dmapva);
370 printf("dmapc: 0x%lx; ", dma->dmapc);
371 printf("dmapnva: 0x%lx; ", dma->dmapnva);
372 printf("dmapnc: 0x%lx\n", dma->dmapnc);
373 printf("dmacva: 0x%lx; ", dma->dmacva);
374 printf("dmacc: 0x%lx; ", dma->dmacc);
375 printf("dmacnva: 0x%lx; ", dma->dmacnva);
376 printf("dmacnc: 0x%lx\n", dma->dmacnc);
377
378 printf("apc_dmacsr=%s\n",
379 bitmask_snprintf(dma->dmacsr, APC_BITS, bits, sizeof(bits)) );
380
381 ad1848_dump_regs(&sc->sc_ad1848);
382 }
383
384 void
385 cs4231_init(sc)
386 register struct cs4231_softc *sc;
387 {
388 char *buf;
389 #if 0
390 volatile struct apc_dma *dma = sc->sc_dmareg;
391 #endif
392 int reg;
393
394 #if 0
395 dma->dmacsr = APC_CODEC_PDN;
396 delay(20);
397 dma->dmacsr &= ~APC_CODEC_PDN;
398 #endif
399 /* First, put chip in native mode */
400 reg = ad_read(&sc->sc_ad1848, SP_MISC_INFO);
401 ad_write(&sc->sc_ad1848, SP_MISC_INFO, reg | MODE2);
402
403 /* Read version numbers from I25 */
404 reg = ad_read(&sc->sc_ad1848, CS_VERSION_ID);
405 switch (reg & (CS_VERSION_NUMBER | CS_VERSION_CHIPID)) {
406 case 0xa0:
407 sc->sc_ad1848.chip_name = "CS4231A";
408 break;
409 case 0x80:
410 sc->sc_ad1848.chip_name = "CS4231";
411 break;
412 case 0x82:
413 sc->sc_ad1848.chip_name = "CS4232";
414 break;
415 default:
416 if ((buf = malloc(32, M_TEMP, M_NOWAIT)) != NULL) {
417 sprintf(buf, "unknown rev: %x/%x", reg&0xe, reg&7);
418 sc->sc_ad1848.chip_name = buf;
419 }
420 }
421 }
422
423 void *
424 cs4231_malloc(addr, size, pool, flags)
425 void *addr;
426 u_long size;
427 int pool;
428 int flags;
429 {
430 struct cs4231_softc *sc = addr;
431 struct cs_dma *p;
432 int error;
433
434 p = malloc(sizeof(*p), pool, flags);
435 if (p == NULL)
436 return (NULL);
437
438 p->size = size;
439 error = bus_dmamem_alloc(sc->sc_dmatag, size, 64*1024, 0,
440 p->segs, sizeof(p->segs)/sizeof(p->segs[0]),
441 &p->nsegs, BUS_DMA_NOWAIT);
442 if (error) {
443 free(p, pool);
444 return (NULL);
445 }
446
447 error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size,
448 &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
449 if (error) {
450 bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
451 free(p, pool);
452 return (NULL);
453 }
454
455 p->next = sc->sc_dmas;
456 sc->sc_dmas = p;
457 return (p->addr);
458 }
459
460 void
461 cs4231_free(addr, ptr, pool)
462 void *addr;
463 void *ptr;
464 int pool;
465 {
466 struct cs4231_softc *sc = addr;
467 struct cs_dma *p, **pp;
468
469 for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &(*pp)->next) {
470 if (p->addr != ptr)
471 continue;
472 bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
473 bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
474 *pp = p->next;
475 free(p, pool);
476 return;
477 }
478 printf("cs4231_free: rogue pointer\n");
479 }
480
481 int
482 cs4231_open(addr, flags)
483 void *addr;
484 int flags;
485 {
486 struct cs4231_softc *sc = addr;
487 #if 0
488 struct apc_dma *dma = sc->sc_dmareg;
489 #endif
490
491 DPRINTF(("sa_open: unit %p\n", sc));
492
493 if (sc->sc_open)
494 return (EBUSY);
495 sc->sc_open = 1;
496 sc->sc_locked = 0;
497 sc->sc_rintr = 0;
498 sc->sc_rarg = 0;
499 sc->sc_pintr = 0;
500 sc->sc_parg = 0;
501 #if 1
502 /*No interrupts from ad1848 */
503 ad_write(&sc->sc_ad1848, SP_PIN_CONTROL, 0);
504 #endif
505 #if 0
506 dma->dmacsr = APC_RESET;
507 delay(10);
508 dma->dmacsr = 0;
509 delay(10);
510 ad1848_reset(&sc->sc_ad1848);
511 #endif
512
513 DPRINTF(("saopen: ok -> sc=%p\n", sc));
514 return (0);
515 }
516
517 void
518 cs4231_close(addr)
519 void *addr;
520 {
521 register struct cs4231_softc *sc = addr;
522
523 DPRINTF(("sa_close: sc=%p\n", sc));
524 /*
525 * halt i/o, clear open flag, and done.
526 */
527 cs4231_halt_input(sc);
528 cs4231_halt_output(sc);
529 sc->sc_open = 0;
530
531 DPRINTF(("sa_close: closed.\n"));
532 }
533
534 u_long
535 cs4231_round_buffersize(addr, size)
536 void *addr;
537 u_long size;
538 {
539 #if 0
540 if (size > APC_MAX)
541 size = APC_MAX;
542 #endif
543 return (size);
544 }
545
546 int
547 cs4231_round_blocksize(addr, blk)
548 void *addr;
549 int blk;
550 {
551 return (blk & -4);
552 }
553
554 int
555 cs4231_getdev(addr, retp)
556 void *addr;
557 struct audio_device *retp;
558 {
559 *retp = cs4231_device;
560 return (0);
561 }
562
563 static ad1848_devmap_t csmapping[] = {
564 { CSAUDIO_DAC_LVL, AD1848_KIND_LVL, AD1848_AUX1_CHANNEL },
565 { CSAUDIO_LINE_IN_LVL, AD1848_KIND_LVL, AD1848_LINE_CHANNEL },
566 { CSAUDIO_MONO_LVL, AD1848_KIND_LVL, AD1848_MONO_CHANNEL },
567 { CSAUDIO_CD_LVL, AD1848_KIND_LVL, AD1848_AUX2_CHANNEL },
568 { CSAUDIO_MONITOR_LVL, AD1848_KIND_LVL, AD1848_MONITOR_CHANNEL },
569 { CSAUDIO_OUT_LVL, AD1848_KIND_LVL, AD1848_DAC_CHANNEL },
570 { CSAUDIO_DAC_MUTE, AD1848_KIND_MUTE, AD1848_AUX1_CHANNEL },
571 { CSAUDIO_LINE_IN_MUTE, AD1848_KIND_MUTE, AD1848_LINE_CHANNEL },
572 { CSAUDIO_MONO_MUTE, AD1848_KIND_MUTE, AD1848_MONO_CHANNEL },
573 { CSAUDIO_CD_MUTE, AD1848_KIND_MUTE, AD1848_AUX2_CHANNEL },
574 { CSAUDIO_MONITOR_MUTE, AD1848_KIND_MUTE, AD1848_MONITOR_CHANNEL },
575 { CSAUDIO_REC_LVL, AD1848_KIND_RECORDGAIN, -1 },
576 { CSAUDIO_RECORD_SOURCE, AD1848_KIND_RECORDSOURCE, -1 }
577 };
578
579 static int nummap = sizeof(csmapping) / sizeof(csmapping[0]);
580
581
582 int
583 cs4231_set_port(addr, cp)
584 void *addr;
585 mixer_ctrl_t *cp;
586 {
587 struct ad1848_softc *ac = addr;
588
589 DPRINTF(("cs4231_set_port: port=%d", cp->dev));
590 return (ad1848_mixer_get_port(ac, csmapping, nummap, cp));
591 }
592
593 int
594 cs4231_get_port(addr, cp)
595 void *addr;
596 mixer_ctrl_t *cp;
597 {
598 struct ad1848_softc *ac = addr;
599
600 DPRINTF(("cs4231_get_port: port=%d", cp->dev));
601 return (ad1848_mixer_get_port(ac, csmapping, nummap, cp));
602 }
603
604 int
605 cs4231_get_props(addr)
606 void *addr;
607 {
608 return (AUDIO_PROP_FULLDUPLEX);
609 }
610
611 int
612 cs4231_query_devinfo(addr, dip)
613 void *addr;
614 register mixer_devinfo_t *dip;
615 {
616
617 switch(dip->index) {
618 #if 0
619 case CSAUDIO_MIC_IN_LVL: /* Microphone */
620 dip->type = AUDIO_MIXER_VALUE;
621 dip->mixer_class = CSAUDIO_INPUT_CLASS;
622 dip->prev = AUDIO_MIXER_LAST;
623 dip->next = CSAUDIO_MIC_IN_MUTE;
624 strcpy(dip->label.name, AudioNmicrophone);
625 dip->un.v.num_channels = 2;
626 strcpy(dip->un.v.units.name, AudioNvolume);
627 break;
628 #endif
629
630 case CSAUDIO_MONO_LVL: /* mono/microphone mixer */
631 dip->type = AUDIO_MIXER_VALUE;
632 dip->mixer_class = CSAUDIO_INPUT_CLASS;
633 dip->prev = AUDIO_MIXER_LAST;
634 dip->next = CSAUDIO_MONO_MUTE;
635 strcpy(dip->label.name, AudioNmicrophone);
636 dip->un.v.num_channels = 1;
637 strcpy(dip->un.v.units.name, AudioNvolume);
638 break;
639
640 case CSAUDIO_DAC_LVL: /* dacout */
641 dip->type = AUDIO_MIXER_VALUE;
642 dip->mixer_class = CSAUDIO_INPUT_CLASS;
643 dip->prev = AUDIO_MIXER_LAST;
644 dip->next = CSAUDIO_DAC_MUTE;
645 strcpy(dip->label.name, AudioNdac);
646 dip->un.v.num_channels = 2;
647 strcpy(dip->un.v.units.name, AudioNvolume);
648 break;
649
650 case CSAUDIO_LINE_IN_LVL: /* line */
651 dip->type = AUDIO_MIXER_VALUE;
652 dip->mixer_class = CSAUDIO_INPUT_CLASS;
653 dip->prev = AUDIO_MIXER_LAST;
654 dip->next = CSAUDIO_LINE_IN_MUTE;
655 strcpy(dip->label.name, AudioNline);
656 dip->un.v.num_channels = 2;
657 strcpy(dip->un.v.units.name, AudioNvolume);
658 break;
659
660 case CSAUDIO_CD_LVL: /* cd */
661 dip->type = AUDIO_MIXER_VALUE;
662 dip->mixer_class = CSAUDIO_INPUT_CLASS;
663 dip->prev = AUDIO_MIXER_LAST;
664 dip->next = CSAUDIO_CD_MUTE;
665 strcpy(dip->label.name, AudioNcd);
666 dip->un.v.num_channels = 2;
667 strcpy(dip->un.v.units.name, AudioNvolume);
668 break;
669
670
671 case CSAUDIO_MONITOR_LVL: /* monitor level */
672 dip->type = AUDIO_MIXER_VALUE;
673 dip->mixer_class = CSAUDIO_MONITOR_CLASS;
674 dip->next = CSAUDIO_MONITOR_MUTE;
675 dip->prev = AUDIO_MIXER_LAST;
676 strcpy(dip->label.name, AudioNmonitor);
677 dip->un.v.num_channels = 1;
678 strcpy(dip->un.v.units.name, AudioNvolume);
679 break;
680
681 case CSAUDIO_OUT_LVL: /* cs4231 output volume: not useful? */
682 dip->type = AUDIO_MIXER_VALUE;
683 dip->mixer_class = CSAUDIO_MONITOR_CLASS;
684 dip->prev = dip->next = AUDIO_MIXER_LAST;
685 strcpy(dip->label.name, AudioNoutput);
686 dip->un.v.num_channels = 2;
687 strcpy(dip->un.v.units.name, AudioNvolume);
688 break;
689
690 case CSAUDIO_LINE_IN_MUTE:
691 dip->mixer_class = CSAUDIO_INPUT_CLASS;
692 dip->type = AUDIO_MIXER_ENUM;
693 dip->prev = CSAUDIO_LINE_IN_LVL;
694 dip->next = AUDIO_MIXER_LAST;
695 goto mute;
696
697 case CSAUDIO_DAC_MUTE:
698 dip->mixer_class = CSAUDIO_INPUT_CLASS;
699 dip->type = AUDIO_MIXER_ENUM;
700 dip->prev = CSAUDIO_DAC_LVL;
701 dip->next = AUDIO_MIXER_LAST;
702 goto mute;
703
704 case CSAUDIO_CD_MUTE:
705 dip->mixer_class = CSAUDIO_INPUT_CLASS;
706 dip->type = AUDIO_MIXER_ENUM;
707 dip->prev = CSAUDIO_CD_LVL;
708 dip->next = AUDIO_MIXER_LAST;
709 goto mute;
710
711 case CSAUDIO_MONO_MUTE:
712 dip->mixer_class = CSAUDIO_INPUT_CLASS;
713 dip->type = AUDIO_MIXER_ENUM;
714 dip->prev = CSAUDIO_MONO_LVL;
715 dip->next = AUDIO_MIXER_LAST;
716 goto mute;
717
718 case CSAUDIO_MONITOR_MUTE:
719 dip->mixer_class = CSAUDIO_OUTPUT_CLASS;
720 dip->type = AUDIO_MIXER_ENUM;
721 dip->prev = CSAUDIO_MONITOR_LVL;
722 dip->next = AUDIO_MIXER_LAST;
723 mute:
724 strcpy(dip->label.name, AudioNmute);
725 dip->un.e.num_mem = 2;
726 strcpy(dip->un.e.member[0].label.name, AudioNoff);
727 dip->un.e.member[0].ord = 0;
728 strcpy(dip->un.e.member[1].label.name, AudioNon);
729 dip->un.e.member[1].ord = 1;
730 break;
731
732 case CSAUDIO_REC_LVL: /* record level */
733 dip->type = AUDIO_MIXER_VALUE;
734 dip->mixer_class = CSAUDIO_RECORD_CLASS;
735 dip->prev = AUDIO_MIXER_LAST;
736 dip->next = CSAUDIO_RECORD_SOURCE;
737 strcpy(dip->label.name, AudioNrecord);
738 dip->un.v.num_channels = 2;
739 strcpy(dip->un.v.units.name, AudioNvolume);
740 break;
741
742 case CSAUDIO_RECORD_SOURCE:
743 dip->mixer_class = CSAUDIO_RECORD_CLASS;
744 dip->type = AUDIO_MIXER_ENUM;
745 dip->prev = CSAUDIO_REC_LVL;
746 dip->next = AUDIO_MIXER_LAST;
747 strcpy(dip->label.name, AudioNsource);
748 dip->un.e.num_mem = 4;
749 strcpy(dip->un.e.member[0].label.name, AudioNoutput);
750 dip->un.e.member[0].ord = DAC_IN_PORT;
751 strcpy(dip->un.e.member[1].label.name, AudioNmicrophone);
752 dip->un.e.member[1].ord = MIC_IN_PORT;
753 strcpy(dip->un.e.member[2].label.name, AudioNdac);
754 dip->un.e.member[2].ord = AUX1_IN_PORT;
755 strcpy(dip->un.e.member[3].label.name, AudioNline);
756 dip->un.e.member[3].ord = LINE_IN_PORT;
757 break;
758
759 case CSAUDIO_INPUT_CLASS: /* input class descriptor */
760 dip->type = AUDIO_MIXER_CLASS;
761 dip->mixer_class = CSAUDIO_INPUT_CLASS;
762 dip->next = dip->prev = AUDIO_MIXER_LAST;
763 strcpy(dip->label.name, AudioCinputs);
764 break;
765
766 case CSAUDIO_OUTPUT_CLASS: /* output class descriptor */
767 dip->type = AUDIO_MIXER_CLASS;
768 dip->mixer_class = CSAUDIO_OUTPUT_CLASS;
769 dip->next = dip->prev = AUDIO_MIXER_LAST;
770 strcpy(dip->label.name, AudioCoutputs);
771 break;
772
773 case CSAUDIO_MONITOR_CLASS: /* monitor class descriptor */
774 dip->type = AUDIO_MIXER_CLASS;
775 dip->mixer_class = CSAUDIO_MONITOR_CLASS;
776 dip->next = dip->prev = AUDIO_MIXER_LAST;
777 strcpy(dip->label.name, AudioCmonitor);
778 break;
779
780 case CSAUDIO_RECORD_CLASS: /* record source class */
781 dip->type = AUDIO_MIXER_CLASS;
782 dip->mixer_class = CSAUDIO_RECORD_CLASS;
783 dip->next = dip->prev = AUDIO_MIXER_LAST;
784 strcpy(dip->label.name, AudioCrecord);
785 break;
786
787 default:
788 return ENXIO;
789 /*NOTREACHED*/
790 }
791 DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
792
793 return (0);
794 }
795
796
797 int
798 cs4231_trigger_output(addr, start, end, blksize, intr, arg, param)
799 void *addr;
800 void *start, *end;
801 int blksize;
802 void (*intr) __P((void *));
803 void *arg;
804 struct audio_params *param;
805 {
806 struct cs4231_softc *sc = addr;
807 struct cs_dma *p;
808 volatile struct apc_dma *dma = sc->sc_dmareg;
809 int csr;
810 u_long n;
811
812 if (sc->sc_locked != 0) {
813 printf("cs4231_trigger_output: already running\n");
814 return (EINVAL);
815 }
816
817 sc->sc_locked = 1;
818 sc->sc_pintr = intr;
819 sc->sc_parg = arg;
820
821 for (p = sc->sc_dmas; p != NULL && p->addr != start; p = p->next)
822 /*void*/;
823 if (p == NULL) {
824 printf("cs4231_trigger_output: bad addr %p\n", start);
825 return (EINVAL);
826 }
827
828 n = end - start;
829
830 /* XXX
831 * Do only `blksize' at a time, so audio_pint() is kept
832 * synchronous with us...
833 */
834 /*XXX*/sc->sc_blksz = blksize;
835 /*XXX*/sc->sc_nowplaying = p;
836 /*XXX*/sc->sc_playsegsz = n;
837
838 if (n > APC_MAX)
839 n = APC_MAX;
840
841 sc->sc_playcnt = n;
842
843 DPRINTF(("trigger_out: start %p, end %p, size %lu; "
844 "dmaaddr 0x%lx, dmacnt %lu, segsize %lu\n",
845 start, end, sc->sc_playsegsz, p->segs[0].ds_addr,
846 n, (u_long)p->size));
847
848 csr = dma->dmacsr;
849 dma->dmapnva = (u_long)p->segs[0].ds_addr;
850 dma->dmapnc = n;
851 if ((csr & PDMA_GO) == 0 || (csr & APC_PPAUSE) != 0) {
852 int reg;
853
854 dma->dmacsr &= ~(APC_PIE|APC_PPAUSE);
855 dma->dmacsr |= APC_EI|APC_IE|APC_PIE|APC_EIE|APC_PMIE|PDMA_GO;
856
857 /* Start chip */
858
859 /* Probably should just ignore this.. */
860 ad_write(&sc->sc_ad1848, SP_LOWER_BASE_COUNT, 0xff);
861 ad_write(&sc->sc_ad1848, SP_UPPER_BASE_COUNT, 0xff);
862
863 reg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG);
864 ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG,
865 (PLAYBACK_ENABLE|reg));
866 }
867
868 return (0);
869 }
870
871 int
872 cs4231_trigger_input(addr, start, end, blksize, intr, arg, param)
873 void *addr;
874 void *start, *end;
875 int blksize;
876 void (*intr) __P((void *));
877 void *arg;
878 struct audio_params *param;
879 {
880 return (ENXIO);
881 }
882
883 int
884 cs4231_halt_output(addr)
885 void *addr;
886 {
887 struct cs4231_softc *sc = addr;
888 volatile struct apc_dma *dma = sc->sc_dmareg;
889 int reg;
890
891 dma->dmacsr &= ~(APC_EI | APC_IE | APC_PIE | APC_EIE | PDMA_GO | APC_PMIE);
892 reg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG);
893 ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, (reg & ~PLAYBACK_ENABLE));
894 sc->sc_locked = 0;
895
896 return (0);
897 }
898
899 int
900 cs4231_halt_input(addr)
901 void *addr;
902 {
903 struct cs4231_softc *sc = addr;
904 int reg;
905
906 reg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG);
907 ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, (reg & ~CAPTURE_ENABLE));
908 sc->sc_locked = 0;
909
910 return (0);
911 }
912
913
914 int
915 cs4231_intr(arg)
916 void *arg;
917 {
918 struct cs4231_softc *sc = arg;
919 volatile struct apc_dma *dma = sc->sc_dmareg;
920 struct cs_dma *p;
921 int ret = 0;
922 int csr;
923 int reg, status;
924 char bits[128];
925
926 #ifdef AUDIO_DEBUG
927 if (cs4231debug > 1)
928 cs4231_regdump("audiointr", sc);
929 #endif
930
931 /* Read DMA status */
932 csr = dma->dmacsr;
933 DPRINTF((
934 "intr: csr=%s; dmapva=0x%lx,dmapc=%lu;dmapnva=0x%lx,dmapnc=%lu\n",
935 bitmask_snprintf(csr, APC_BITS, bits, sizeof(bits)),
936 dma->dmapva, dma->dmapc, dma->dmapnva, dma->dmapnc));
937
938 status = ADREAD(&sc->sc_ad1848, AD1848_STATUS);
939 DPRINTF(("%s: status: %s\n", sc->sc_ad1848.sc_dev.dv_xname,
940 bitmask_snprintf(status, AD_R2_BITS, bits, sizeof(bits))));
941 if (status & (INTERRUPT_STATUS | SAMPLE_ERROR)) {
942 reg = ad_read(&sc->sc_ad1848, CS_IRQ_STATUS);
943 DPRINTF(("%s: i24: %s\n", sc->sc_ad1848.sc_dev.dv_xname,
944 bitmask_snprintf(reg, CS_I24_BITS, bits, sizeof(bits))));
945
946 if (reg & CS_IRQ_PI) {
947 ad_write(&sc->sc_ad1848, SP_LOWER_BASE_COUNT, 0xff);
948 ad_write(&sc->sc_ad1848, SP_UPPER_BASE_COUNT, 0xff);
949 }
950 /* Clear interrupt bit */
951 ADWRITE(&sc->sc_ad1848, AD1848_STATUS, 0);
952 }
953
954 /* Write back DMA status (clears interrupt) */
955 dma->dmacsr = csr;
956
957 /*
958 * Simplistic.. if "play emtpy" is set advance to next chunk.
959 */
960 #if 1
961 /* Ack all play interrupts*/
962 if ((csr & (APC_PI|APC_PD|APC_PIE|APC_PMI)) != 0)
963 ret = 1;
964 #endif
965 if (csr & APC_PM) {
966 u_long nextaddr, togo;
967
968 p = sc->sc_nowplaying;
969
970 togo = sc->sc_playsegsz - sc->sc_playcnt;
971 if (togo == 0) {
972 /* Roll over */
973 nextaddr = (u_long)p->segs[0].ds_addr;
974 sc->sc_playcnt = togo = APC_MAX;
975 } else {
976 nextaddr = dma->dmapnva + APC_MAX;
977 if (togo > APC_MAX)
978 togo = APC_MAX;
979 sc->sc_playcnt += togo;
980 }
981
982 dma->dmapnva = nextaddr;
983 dma->dmapnc = togo;
984
985 if (sc->sc_pintr != NULL)
986 (*sc->sc_pintr)(sc->sc_parg);
987
988 ret = 1;
989 }
990
991 if (csr & APC_CI) {
992 if (sc->sc_rintr != NULL) {
993 ret = 1;
994 (*sc->sc_rintr)(sc->sc_rarg);
995 }
996 }
997
998 #ifdef DEBUG
999 if (ret == 0) {
1000 printf(
1001 "oops: csr=%s; dmapva=0x%lx,dmapc=%lu;dmapnva=0x%lx,dmapnc=%lu\n",
1002 bitmask_snprintf(csr, APC_BITS, bits, sizeof(bits)),
1003 dma->dmapva, dma->dmapc, dma->dmapnva, dma->dmapnc);
1004 ret = 1;
1005 }
1006 #endif
1007
1008 return (ret);
1009 }
1010 #endif /* NAUDIO > 0 */
1011