1/*	$NetBSD$	*/
2
3/*-
4 * Copyright (c) 1998, 1999, 2002, 2007 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Paul Kranenburg.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <sys/cdefs.h>
33__KERNEL_RCSID(0, "$NetBSD$");
34
35#include "audio.h"
36#if NAUDIO > 0
37
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/errno.h>
41#include <sys/device.h>
42#include <sys/malloc.h>
43#include <sys/bus.h>
44#include <sys/intr.h>
45
46#include <dev/sbus/sbusvar.h>
47
48#include <sys/audioio.h>
49#include <dev/audio_if.h>
50
51#include <dev/ic/ad1848reg.h>
52#include <dev/ic/cs4231reg.h>
53#include <dev/ic/ad1848var.h>
54#include <dev/ic/cs4231var.h>
55
56#include <dev/ic/apcdmareg.h>
57
58#ifdef AUDIO_DEBUG
59int cs4231_sbus_debug = 0;
60#define DPRINTF(x)      if (cs4231_sbus_debug) printf x
61#else
62#define DPRINTF(x)
63#endif
64
65/* where APC DMA registers are located */
66#define CS4231_APCDMA_OFFSET	16
67
68/* interrupt enable bits except those specific for playback/capture */
69#define APC_ENABLE		(APC_EI | APC_IE | APC_EIE)
70
71struct cs4231_sbus_softc {
72	struct cs4231_softc sc_cs4231;
73
74	void *sc_pint;
75	void *sc_rint;
76	bus_space_tag_t sc_bt;			/* DMA controller tag */
77	bus_space_handle_t sc_bh;		/* DMA controller registers */
78};
79
80
81static int	cs4231_sbus_match(device_t, cfdata_t, void *);
82static void	cs4231_sbus_attach(device_t, device_t, void *);
83static int	cs4231_sbus_pint(void *);
84static int	cs4231_sbus_rint(void *);
85
86CFATTACH_DECL_NEW(audiocs_sbus, sizeof(struct cs4231_sbus_softc),
87    cs4231_sbus_match, cs4231_sbus_attach, NULL, NULL);
88
89/* audio_hw_if methods specific to apc DMA */
90static int	cs4231_sbus_trigger_output(void *, void *, void *, int,
91					   void (*)(void *), void *,
92					   const audio_params_t *);
93static int	cs4231_sbus_trigger_input(void *, void *, void *, int,
94					  void (*)(void *), void *,
95					  const audio_params_t *);
96static int	cs4231_sbus_halt_output(void *);
97static int	cs4231_sbus_halt_input(void *);
98
99const struct audio_hw_if audiocs_sbus_hw_if = {
100	cs4231_open,
101	cs4231_close,
102	NULL,			/* drain */
103	ad1848_query_encoding,
104	ad1848_set_params,
105	NULL,			/* round_blocksize */
106	ad1848_commit_settings,
107	NULL,			/* init_output */
108	NULL,			/* init_input */
109	NULL,			/* start_output */
110	NULL,			/* start_input */
111	cs4231_sbus_halt_output,
112	cs4231_sbus_halt_input,
113	NULL,			/* speaker_ctl */
114	cs4231_getdev,
115	NULL,			/* setfd */
116	cs4231_set_port,
117	cs4231_get_port,
118	cs4231_query_devinfo,
119	cs4231_malloc,
120	cs4231_free,
121	NULL,			/* round_buffersize */
122	NULL,			/* mappage */
123	cs4231_get_props,
124	cs4231_sbus_trigger_output,
125	cs4231_sbus_trigger_input,
126	NULL,			/* dev_ioctl */
127	ad1848_get_locks,
128};
129
130
131#ifdef AUDIO_DEBUG
132static void	cs4231_sbus_regdump(char *, struct cs4231_sbus_softc *);
133#endif
134
135static int	cs4231_sbus_intr(void *);
136
137
138
139static int
140cs4231_sbus_match(device_t parent, cfdata_t cf, void *aux)
141{
142	struct sbus_attach_args *sa;
143
144	sa = aux;
145	return strcmp(sa->sa_name, AUDIOCS_PROM_NAME) == 0;
146}
147
148
149static void
150cs4231_sbus_attach(device_t parent, device_t self, void *aux)
151{
152	struct cs4231_sbus_softc *sbsc;
153	struct cs4231_softc *sc;
154	struct sbus_attach_args *sa;
155	bus_space_handle_t bh;
156
157	sbsc = device_private(self);
158	sc = &sbsc->sc_cs4231;
159	sa = aux;
160	sbsc->sc_bt = sc->sc_bustag = sa->sa_bustag;
161	sc->sc_dmatag = sa->sa_dmatag;
162
163	sbsc->sc_pint = sparc_softintr_establish(IPL_SCHED,
164	    (void *)cs4231_sbus_pint, sc);
165	sbsc->sc_rint = sparc_softintr_establish(IPL_SCHED,
166	    (void *)cs4231_sbus_rint, sc);
167
168	/*
169	 * Map my registers in, if they aren't already in virtual
170	 * address space.
171	 */
172	if (sa->sa_npromvaddrs) {
173		sbus_promaddr_to_handle(sa->sa_bustag,
174			sa->sa_promvaddrs[0], &bh);
175	} else {
176		if (sbus_bus_map(sa->sa_bustag,	sa->sa_slot,
177			sa->sa_offset, sa->sa_size, 0, &bh) != 0) {
178			aprint_error("%s @ sbus: cannot map registers\n",
179				device_xname(self));
180			return;
181		}
182	}
183
184	bus_space_subregion(sa->sa_bustag, bh, CS4231_APCDMA_OFFSET,
185		APC_DMA_SIZE, &sbsc->sc_bh);
186
187	cs4231_common_attach(sc, self, bh);
188	printf("\n");
189
190	ad1848_init_locks(&sc->sc_ad1848, IPL_SCHED);
191	/* Establish interrupt channel */
192	if (sa->sa_nintr)
193		bus_intr_establish(sa->sa_bustag,
194				   sa->sa_pri, IPL_SCHED,
195				   cs4231_sbus_intr, sbsc);
196
197	audio_attach_mi(&audiocs_sbus_hw_if, sbsc, self);
198}
199
200
201#ifdef AUDIO_DEBUG
202static void
203cs4231_sbus_regdump(char *label, struct cs4231_sbus_softc *sc)
204{
205	char bits[128];
206
207	printf("cs4231regdump(%s): regs:", label);
208	printf("dmapva: 0x%x; ",
209		bus_space_read_4(sc->sc_bh, sc->sc_bh, APC_DMA_PVA));
210	printf("dmapc: 0x%x; ",
211		bus_space_read_4(sc->sc_bh, sc->sc_bh, APC_DMA_PC));
212	printf("dmapnva: 0x%x; ",
213		bus_space_read_4(sc->sc_bh, sc->sc_bh, APC_DMA_PNVA));
214	printf("dmapnc: 0x%x\n",
215		bus_space_read_4(sc->sc_bh, sc->sc_bh, APC_DMA_PNC));
216	printf("dmacva: 0x%x; ",
217		bus_space_read_4(sc->sc_bh, sc->sc_bh, APC_DMA_CVA));
218	printf("dmacc: 0x%x; ",
219		bus_space_read_4(sc->sc_bh, sc->sc_bh, APC_DMA_CC));
220	printf("dmacnva: 0x%x; ",
221		bus_space_read_4(sc->sc_bh, sc->sc_bh, APC_DMA_CNVA));
222	printf("dmacnc: 0x%x\n",
223		bus_space_read_4(sc->sc_bh, sc->sc_bh, APC_DMA_CNC));
224
225	snprintb(bits, sizeof(bits), APC_BITS,
226	    bus_space_read_4(sc->sc_bh, sc->sc_bh, APC_DMA_CSR));
227	printf("apc_dmacsr=%s\n", bits);
228
229	ad1848_dump_regs(&sc->sc_cs4231.sc_ad1848);
230}
231#endif /* AUDIO_DEBUG */
232
233
234static int
235cs4231_sbus_trigger_output(void *addr, void *start, void *end, int blksize,
236			   void (*intr)(void *), void *arg,
237			   const audio_params_t *param)
238{
239	struct cs4231_sbus_softc *sbsc;
240	struct cs4231_softc *sc;
241	struct cs_transfer *t;
242	uint32_t csr;
243	bus_addr_t dmaaddr;
244	bus_size_t dmasize;
245	int ret;
246#ifdef AUDIO_DEBUG
247	char bits[128];
248#endif
249
250	sbsc = addr;
251	sc = &sbsc->sc_cs4231;
252	t = &sc->sc_playback;
253	ret = cs4231_transfer_init(sc, t, &dmaaddr, &dmasize,
254				   start, end, blksize, intr, arg);
255	if (ret != 0)
256		return ret;
257
258	DPRINTF(("trigger_output: was: %x %d, %x %d\n",
259		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PVA),
260		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PC),
261		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNVA),
262		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNC)));
263
264	/* load first block */
265	bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNVA, dmaaddr);
266	bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNC, dmasize);
267
268	DPRINTF(("trigger_output: 1st: %x %d, %x %d\n",
269		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PVA),
270		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PC),
271		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNVA),
272		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNC)));
273
274	csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
275#ifdef AUDIO_DEBUG
276	snprintb(bits, sizeof(bits), APC_BITS, csr);
277#endif
278	DPRINTF(("trigger_output: csr=%s\n", bits));
279	if ((csr & PDMA_GO) == 0 || (csr & APC_PPAUSE) != 0) {
280		int cfg;
281
282		csr &= ~(APC_PPAUSE | APC_PMIE | APC_INTR_MASK);
283		bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR, csr);
284
285		csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
286		csr &= ~APC_INTR_MASK;
287		csr |= APC_ENABLE | APC_PIE | APC_PMIE | PDMA_GO;
288		bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR, csr);
289
290		ad_write(&sc->sc_ad1848, SP_LOWER_BASE_COUNT, 0xff);
291		ad_write(&sc->sc_ad1848, SP_UPPER_BASE_COUNT, 0xff);
292
293		cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG);
294		ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG,
295			 (cfg | PLAYBACK_ENABLE));
296	} else {
297#ifdef AUDIO_DEBUG
298		snprintb(bits, sizeof(bits), APC_BITS, csr);
299#endif
300		DPRINTF(("trigger_output: already: csr=%s\n", bits));
301
302	}
303
304	/* load next block if we can */
305	csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
306	if (csr & APC_PD) {
307		cs4231_transfer_advance(t, &dmaaddr, &dmasize);
308		bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNVA, dmaaddr);
309		bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNC, dmasize);
310
311		DPRINTF(("trigger_output: 2nd: %x %d, %x %d\n",
312		    bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PVA),
313		    bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PC),
314		    bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNVA),
315		    bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNC)));
316	}
317
318	return 0;
319}
320
321
322static int
323cs4231_sbus_halt_output(void *addr)
324{
325	struct cs4231_sbus_softc *sbsc;
326	struct cs4231_softc *sc;
327	uint32_t csr;
328	int cfg;
329#ifdef AUDIO_DEBUG
330	char bits[128];
331#endif
332
333	sbsc = addr;
334	sc = &sbsc->sc_cs4231;
335	sc->sc_playback.t_active = 0;
336
337	csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
338#ifdef AUDIO_DEBUG
339	snprintb(bits, sizeof(bits), APC_BITS, csr);
340#endif
341	DPRINTF(("halt_output: csr=%s\n", bits));
342
343	csr &= ~APC_INTR_MASK;	/* do not clear interrupts accidentally */
344	csr |= APC_PPAUSE;	/* pause playback (let current complete) */
345	bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR, csr);
346
347	/* let the curernt transfer complete */
348	if (csr & PDMA_GO)
349		do {
350			csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh,
351				APC_DMA_CSR);
352#ifdef AUDIO_DEBUG
353			snprintb(bits, sizeof(bits), APC_BITS, csr);
354#endif
355			DPRINTF(("halt_output: csr=%s\n", bits));
356		} while ((csr & APC_PM) == 0);
357
358	cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG);
359	ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG,(cfg & ~PLAYBACK_ENABLE));
360
361	return 0;
362}
363
364
365/* NB: we don't enable APC_CMIE and won't use APC_CM */
366static int
367cs4231_sbus_trigger_input(void *addr, void *start, void *end, int blksize,
368			  void (*intr)(void *), void *arg,
369			  const audio_params_t *param)
370{
371	struct cs4231_sbus_softc *sbsc;
372	struct cs4231_softc *sc;
373	struct cs_transfer *t;
374	uint32_t csr;
375	bus_addr_t dmaaddr;
376	bus_size_t dmasize;
377	int ret;
378#ifdef AUDIO_DEBUG
379	char bits[128];
380#endif
381
382	sbsc = addr;
383	sc = &sbsc->sc_cs4231;
384	t = &sc->sc_capture;
385	ret = cs4231_transfer_init(sc, t, &dmaaddr, &dmasize,
386				   start, end, blksize, intr, arg);
387	if (ret != 0)
388		return ret;
389
390	csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
391#ifdef AUDIO_DEBUG
392	snprintb(bits, sizeof(bits), APC_BITS, csr);
393#endif
394	DPRINTF(("trigger_input: csr=%s\n", bits));
395	DPRINTF(("trigger_input: was: %x %d, %x %d\n",
396		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CVA),
397		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CC),
398		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNVA),
399		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNC)));
400
401	/* supply first block */
402	bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNVA, dmaaddr);
403	bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNC, dmasize);
404
405	DPRINTF(("trigger_input: 1st: %x %d, %x %d\n",
406		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CVA),
407		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CC),
408		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNVA),
409		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNC)));
410
411	csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
412	if ((csr & CDMA_GO) == 0 || (csr & APC_CPAUSE) != 0) {
413		int cfg;
414
415		csr &= ~(APC_CPAUSE | APC_CMIE | APC_INTR_MASK);
416		bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR, csr);
417
418		csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
419		csr &= ~APC_INTR_MASK;
420		csr |= APC_ENABLE | APC_CIE | CDMA_GO;
421		bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR, csr);
422
423		ad_write(&sc->sc_ad1848, CS_LOWER_REC_CNT, 0xff);
424		ad_write(&sc->sc_ad1848, CS_UPPER_REC_CNT, 0xff);
425
426		cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG);
427		ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG,
428			 (cfg | CAPTURE_ENABLE));
429	} else {
430#ifdef AUDIO_DEBUG
431		snprintb(bits, sizeof(bits), APC_BITS, csr);
432#endif
433		DPRINTF(("trigger_input: already: csr=%s\n", bits));
434	}
435
436	/* supply next block if we can */
437	csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
438	if (csr & APC_CD) {
439		cs4231_transfer_advance(t, &dmaaddr, &dmasize);
440		bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNVA, dmaaddr);
441		bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNC, dmasize);
442		DPRINTF(("trigger_input: 2nd: %x %d, %x %d\n",
443		    bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CVA),
444		    bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CC),
445		    bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNVA),
446		    bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNC)));
447	}
448
449	return 0;
450}
451
452
453static int
454cs4231_sbus_halt_input(void *addr)
455{
456	struct cs4231_sbus_softc *sbsc;
457	struct cs4231_softc *sc;
458	uint32_t csr;
459	int cfg;
460#ifdef AUDIO_DEBUG
461	char bits[128];
462#endif
463
464	sbsc = addr;
465	sc = &sbsc->sc_cs4231;
466	sc->sc_capture.t_active = 0;
467
468	csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
469#ifdef AUDIO_DEBUG
470	snprintb(bits, sizeof(bits), APC_BITS, csr);
471#endif
472	DPRINTF(("halt_input: csr=%s\n", bits));
473
474
475	csr &= ~APC_INTR_MASK;	/* do not clear interrupts accidentally */
476	csr |= APC_CPAUSE;
477	bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR, csr);
478
479	/* let the curernt transfer complete */
480	if (csr & CDMA_GO)
481		do {
482			csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh,
483				APC_DMA_CSR);
484#ifdef AUDIO_DEBUG
485			snprintb(bits, sizeof(bits), APC_BITS, csr);
486#endif
487			DPRINTF(("halt_input: csr=%s\n", bits));
488
489
490		} while ((csr & APC_CM) == 0);
491
492	cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG);
493	ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, (cfg & ~CAPTURE_ENABLE));
494
495	return 0;
496}
497
498
499static int
500cs4231_sbus_intr(void *arg)
501{
502	struct cs4231_sbus_softc *sbsc;
503	struct cs4231_softc *sc;
504	uint32_t csr;
505	int status;
506	bus_addr_t dmaaddr;
507	bus_size_t dmasize;
508	int served;
509#if defined(AUDIO_DEBUG) || defined(DIAGNOSTIC)
510	char bits[128];
511#endif
512
513	sbsc = arg;
514	sc = &sbsc->sc_cs4231;
515	csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
516	if ((csr & APC_INTR_MASK) == 0)	/* any interrupt pedning? */
517		return 0;
518
519	mutex_spin_enter(&sc->sc_ad1848.sc_intr_lock);
520
521	/* write back DMA status to clear interrupt */
522	bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR, csr);
523	++sc->sc_intrcnt.ev_count;
524	served = 0;
525
526#ifdef AUDIO_DEBUG
527	if (cs4231_sbus_debug > 1)
528		cs4231_sbus_regdump("audiointr", sbsc);
529#endif
530
531	status = ADREAD(&sc->sc_ad1848, AD1848_STATUS);
532#ifdef AUDIO_DEBUG
533	snprintb(bits, sizeof(bits), AD_R2_BITS, status);
534#endif
535	DPRINTF(("%s: status: %s\n", device_xname(sc->sc_ad1848.sc_dev),
536	    bits));
537	if (status & INTERRUPT_STATUS) {
538#ifdef AUDIO_DEBUG
539		int reason;
540
541		reason = ad_read(&sc->sc_ad1848, CS_IRQ_STATUS);
542		snprintb(bits, sizeof(bits), CS_I24_BITS, reason);
543		DPRINTF(("%s: i24: %s\n", device_xname(sc->sc_ad1848.sc_dev),
544		    bits));
545#endif
546		/* clear ad1848 interrupt */
547		ADWRITE(&sc->sc_ad1848, AD1848_STATUS, 0);
548	}
549
550	if (csr & APC_CI) {
551		if (csr & APC_CD) { /* can supply new block */
552			struct cs_transfer *t = &sc->sc_capture;
553
554			cs4231_transfer_advance(t, &dmaaddr, &dmasize);
555			bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh,
556				APC_DMA_CNVA, dmaaddr);
557			bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh,
558				APC_DMA_CNC, dmasize);
559
560			if (t->t_intr != NULL)
561				sparc_softintr_schedule(sbsc->sc_rint);
562			++t->t_intrcnt.ev_count;
563			served = 1;
564		}
565	}
566
567	if (csr & APC_PMI) {
568		if (!sc->sc_playback.t_active)
569			served = 1; /* draining in halt_output() */
570	}
571
572	if (csr & APC_PI) {
573		if (csr & APC_PD) { /* can load new block */
574			struct cs_transfer *t = &sc->sc_playback;
575
576			if (t->t_active) {
577				cs4231_transfer_advance(t, &dmaaddr, &dmasize);
578				bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh,
579					APC_DMA_PNVA, dmaaddr);
580				bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh,
581					APC_DMA_PNC, dmasize);
582			}
583
584			if (t->t_intr != NULL)
585				sparc_softintr_schedule(sbsc->sc_pint);
586			++t->t_intrcnt.ev_count;
587			served = 1;
588		}
589	}
590
591	/* got an interrupt we don't know how to handle */
592	if (!served) {
593#ifdef DIAGNOSTIC
594	        snprintb(bits, sizeof(bits), APC_BITS, csr);
595		printf("%s: unhandled csr=%s\n",
596		    device_xname(sc->sc_ad1848.sc_dev), bits);
597#endif
598		/* evcnt? */
599	}
600
601	mutex_spin_exit(&sc->sc_ad1848.sc_intr_lock);
602
603	return 1;
604}
605
606static int
607cs4231_sbus_pint(void *cookie)
608{
609	struct cs4231_softc *sc = cookie;
610	struct cs_transfer *t;
611
612	mutex_spin_enter(&sc->sc_ad1848.sc_intr_lock);
613	t = &sc->sc_playback;
614	if (t->t_intr != NULL)
615		(*t->t_intr)(t->t_arg);
616	mutex_spin_exit(&sc->sc_ad1848.sc_intr_lock);
617	return 0;
618}
619
620static int
621cs4231_sbus_rint(void *cookie)
622{
623	struct cs4231_softc *sc = cookie;
624	struct cs_transfer *t;
625
626	mutex_spin_enter(&sc->sc_ad1848.sc_intr_lock);
627	t = &sc->sc_capture;
628	if (t->t_intr != NULL)
629		(*t->t_intr)(t->t_arg);
630	mutex_spin_exit(&sc->sc_ad1848.sc_intr_lock);
631	return 0;
632}
633
634#endif /* NAUDIO > 0 */
635