xref: /netbsd-src/sys/dev/sbus/cs4231_sbus.c (revision 0b988ad4808006a53e444f835873b8cb143b1c54)
1 /*	$NetBSD: cs4231_sbus.c,v 1.53 2022/07/21 14:41:59 andvar Exp $	*/
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: cs4231_sbus.c,v 1.53 2022/07/21 14:41:59 andvar Exp $");
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/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
59 int 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 
71 struct 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 
81 static int	cs4231_sbus_match(device_t, cfdata_t, void *);
82 static void	cs4231_sbus_attach(device_t, device_t, void *);
83 static int	cs4231_sbus_pint(void *);
84 static int	cs4231_sbus_rint(void *);
85 
86 CFATTACH_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 */
90 static int	cs4231_sbus_trigger_output(void *, void *, void *, int,
91 					   void (*)(void *), void *,
92 					   const audio_params_t *);
93 static int	cs4231_sbus_trigger_input(void *, void *, void *, int,
94 					  void (*)(void *), void *,
95 					  const audio_params_t *);
96 static int	cs4231_sbus_halt_output(void *);
97 static int	cs4231_sbus_halt_input(void *);
98 
99 const struct audio_hw_if audiocs_sbus_hw_if = {
100 	.open			= cs4231_open,
101 	.close			= cs4231_close,
102 	.query_format		= ad1848_query_format,
103 	.set_format		= ad1848_set_format,
104 	.commit_settings	= ad1848_commit_settings,
105 	.halt_output		= cs4231_sbus_halt_output,
106 	.halt_input		= cs4231_sbus_halt_input,
107 	.getdev			= cs4231_getdev,
108 	.set_port		= cs4231_set_port,
109 	.get_port		= cs4231_get_port,
110 	.query_devinfo		= cs4231_query_devinfo,
111 	.allocm			= cs4231_malloc,
112 	.freem			= cs4231_free,
113 	.get_props		= cs4231_get_props,
114 	.trigger_output		= cs4231_sbus_trigger_output,
115 	.trigger_input		= cs4231_sbus_trigger_input,
116 	.get_locks		= ad1848_get_locks,
117 };
118 
119 
120 #ifdef AUDIO_DEBUG
121 static void	cs4231_sbus_regdump(const char *, struct cs4231_sbus_softc *);
122 #endif
123 
124 static int	cs4231_sbus_intr(void *);
125 
126 
127 
128 static int
cs4231_sbus_match(device_t parent,cfdata_t cf,void * aux)129 cs4231_sbus_match(device_t parent, cfdata_t cf, void *aux)
130 {
131 	struct sbus_attach_args *sa;
132 
133 	sa = aux;
134 	return strcmp(sa->sa_name, AUDIOCS_PROM_NAME) == 0;
135 }
136 
137 
138 static void
cs4231_sbus_attach(device_t parent,device_t self,void * aux)139 cs4231_sbus_attach(device_t parent, device_t self, void *aux)
140 {
141 	struct cs4231_sbus_softc *sbsc;
142 	struct cs4231_softc *sc;
143 	struct sbus_attach_args *sa;
144 	bus_space_handle_t bh;
145 
146 	sbsc = device_private(self);
147 	sc = &sbsc->sc_cs4231;
148 	sa = aux;
149 	sbsc->sc_bt = sc->sc_bustag = sa->sa_bustag;
150 	sc->sc_dmatag = sa->sa_dmatag;
151 
152 	sbsc->sc_pint = sparc_softintr_establish(IPL_SCHED,
153 	    (void *)cs4231_sbus_pint, sc);
154 	sbsc->sc_rint = sparc_softintr_establish(IPL_SCHED,
155 	    (void *)cs4231_sbus_rint, sc);
156 
157 	/*
158 	 * Map my registers in, if they aren't already in virtual
159 	 * address space.
160 	 */
161 	if (sa->sa_npromvaddrs) {
162 		sbus_promaddr_to_handle(sa->sa_bustag,
163 			sa->sa_promvaddrs[0], &bh);
164 	} else {
165 		if (sbus_bus_map(sa->sa_bustag,	sa->sa_slot,
166 			sa->sa_offset, sa->sa_size, 0, &bh) != 0) {
167 			aprint_error("%s @ sbus: cannot map registers\n",
168 				device_xname(self));
169 			return;
170 		}
171 	}
172 
173 	bus_space_subregion(sa->sa_bustag, bh, CS4231_APCDMA_OFFSET,
174 		APC_DMA_SIZE, &sbsc->sc_bh);
175 
176 	cs4231_common_attach(sc, self, bh);
177 	printf("\n");
178 
179 	ad1848_init_locks(&sc->sc_ad1848, IPL_SCHED);
180 	/* Establish interrupt channel */
181 	if (sa->sa_nintr)
182 		bus_intr_establish(sa->sa_bustag,
183 				   sa->sa_pri, IPL_SCHED,
184 				   cs4231_sbus_intr, sbsc);
185 
186 	audio_attach_mi(&audiocs_sbus_hw_if, sbsc, self);
187 }
188 
189 
190 #ifdef AUDIO_DEBUG
191 static void
cs4231_sbus_regdump(const char * label,struct cs4231_sbus_softc * sc)192 cs4231_sbus_regdump(const char *label, struct cs4231_sbus_softc *sc)
193 {
194 	char bits[128];
195 
196 	printf("cs4231regdump(%s): regs:", label);
197 	printf("dmapva: 0x%x; ",
198 		bus_space_read_4(sc->sc_bt, sc->sc_bh, APC_DMA_PVA));
199 	printf("dmapc: 0x%x; ",
200 		bus_space_read_4(sc->sc_bt, sc->sc_bh, APC_DMA_PC));
201 	printf("dmapnva: 0x%x; ",
202 		bus_space_read_4(sc->sc_bt, sc->sc_bh, APC_DMA_PNVA));
203 	printf("dmapnc: 0x%x\n",
204 		bus_space_read_4(sc->sc_bt, sc->sc_bh, APC_DMA_PNC));
205 	printf("dmacva: 0x%x; ",
206 		bus_space_read_4(sc->sc_bt, sc->sc_bh, APC_DMA_CVA));
207 	printf("dmacc: 0x%x; ",
208 		bus_space_read_4(sc->sc_bt, sc->sc_bh, APC_DMA_CC));
209 	printf("dmacnva: 0x%x; ",
210 		bus_space_read_4(sc->sc_bt, sc->sc_bh, APC_DMA_CNVA));
211 	printf("dmacnc: 0x%x\n",
212 		bus_space_read_4(sc->sc_bt, sc->sc_bh, APC_DMA_CNC));
213 
214 	snprintb(bits, sizeof(bits), APC_BITS,
215 	    bus_space_read_4(sc->sc_bt, sc->sc_bh, APC_DMA_CSR));
216 	printf("apc_dmacsr=%s\n", bits);
217 
218 	ad1848_dump_regs(&sc->sc_cs4231.sc_ad1848);
219 }
220 #endif /* AUDIO_DEBUG */
221 
222 
223 static int
cs4231_sbus_trigger_output(void * addr,void * start,void * end,int blksize,void (* intr)(void *),void * arg,const audio_params_t * param)224 cs4231_sbus_trigger_output(void *addr, void *start, void *end, int blksize,
225 			   void (*intr)(void *), void *arg,
226 			   const audio_params_t *param)
227 {
228 	struct cs4231_sbus_softc *sbsc;
229 	struct cs4231_softc *sc;
230 	struct cs_transfer *t;
231 	uint32_t csr;
232 	bus_addr_t dmaaddr;
233 	bus_size_t dmasize;
234 	int ret;
235 #ifdef AUDIO_DEBUG
236 	char bits[128];
237 #endif
238 
239 	sbsc = addr;
240 	sc = &sbsc->sc_cs4231;
241 	t = &sc->sc_playback;
242 	ret = cs4231_transfer_init(sc, t, &dmaaddr, &dmasize,
243 				   start, end, blksize, intr, arg);
244 	if (ret != 0)
245 		return ret;
246 
247 	DPRINTF(("trigger_output: was: %x %d, %x %d\n",
248 		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PVA),
249 		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PC),
250 		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNVA),
251 		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNC)));
252 
253 	/* load first block */
254 	bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNVA, dmaaddr);
255 	bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNC, dmasize);
256 
257 	DPRINTF(("trigger_output: 1st: %x %d, %x %d\n",
258 		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PVA),
259 		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PC),
260 		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNVA),
261 		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNC)));
262 
263 	csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
264 #ifdef AUDIO_DEBUG
265 	snprintb(bits, sizeof(bits), APC_BITS, csr);
266 #endif
267 	DPRINTF(("trigger_output: csr=%s\n", bits));
268 	if ((csr & PDMA_GO) == 0 || (csr & APC_PPAUSE) != 0) {
269 		int cfg;
270 
271 		csr &= ~(APC_PPAUSE | APC_PMIE | APC_INTR_MASK);
272 		bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR, csr);
273 
274 		csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
275 		csr &= ~APC_INTR_MASK;
276 		csr |= APC_ENABLE | APC_PIE | APC_PMIE | PDMA_GO;
277 		bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR, csr);
278 
279 		ad_write(&sc->sc_ad1848, SP_LOWER_BASE_COUNT, 0xff);
280 		ad_write(&sc->sc_ad1848, SP_UPPER_BASE_COUNT, 0xff);
281 
282 		cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG);
283 		ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG,
284 			 (cfg | PLAYBACK_ENABLE));
285 	} else {
286 #ifdef AUDIO_DEBUG
287 		snprintb(bits, sizeof(bits), APC_BITS, csr);
288 #endif
289 		DPRINTF(("trigger_output: already: csr=%s\n", bits));
290 
291 	}
292 
293 	/* load next block if we can */
294 	csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
295 	if (csr & APC_PD) {
296 		cs4231_transfer_advance(t, &dmaaddr, &dmasize);
297 		bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNVA, dmaaddr);
298 		bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNC, dmasize);
299 
300 		DPRINTF(("trigger_output: 2nd: %x %d, %x %d\n",
301 		    bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PVA),
302 		    bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PC),
303 		    bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNVA),
304 		    bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNC)));
305 	}
306 
307 	return 0;
308 }
309 
310 
311 static int
cs4231_sbus_halt_output(void * addr)312 cs4231_sbus_halt_output(void *addr)
313 {
314 	struct cs4231_sbus_softc *sbsc;
315 	struct cs4231_softc *sc;
316 	uint32_t csr;
317 	int cfg;
318 #ifdef AUDIO_DEBUG
319 	char bits[128];
320 #endif
321 
322 	sbsc = addr;
323 	sc = &sbsc->sc_cs4231;
324 	sc->sc_playback.t_active = 0;
325 
326 	csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
327 #ifdef AUDIO_DEBUG
328 	snprintb(bits, sizeof(bits), APC_BITS, csr);
329 #endif
330 	DPRINTF(("halt_output: csr=%s\n", bits));
331 
332 	csr &= ~APC_INTR_MASK;	/* do not clear interrupts accidentally */
333 	csr |= APC_PPAUSE;	/* pause playback (let current complete) */
334 	bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR, csr);
335 
336 	/* let the curernt transfer complete */
337 	if (csr & PDMA_GO)
338 		do {
339 			csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh,
340 				APC_DMA_CSR);
341 #ifdef AUDIO_DEBUG
342 			snprintb(bits, sizeof(bits), APC_BITS, csr);
343 #endif
344 			DPRINTF(("halt_output: csr=%s\n", bits));
345 		} while ((csr & APC_PM) == 0);
346 
347 	cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG);
348 	ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG,(cfg & ~PLAYBACK_ENABLE));
349 
350 	return 0;
351 }
352 
353 
354 /* NB: we don't enable APC_CMIE and won't use APC_CM */
355 static int
cs4231_sbus_trigger_input(void * addr,void * start,void * end,int blksize,void (* intr)(void *),void * arg,const audio_params_t * param)356 cs4231_sbus_trigger_input(void *addr, void *start, void *end, int blksize,
357 			  void (*intr)(void *), void *arg,
358 			  const audio_params_t *param)
359 {
360 	struct cs4231_sbus_softc *sbsc;
361 	struct cs4231_softc *sc;
362 	struct cs_transfer *t;
363 	uint32_t csr;
364 	bus_addr_t dmaaddr;
365 	bus_size_t dmasize;
366 	int ret;
367 #ifdef AUDIO_DEBUG
368 	char bits[128];
369 #endif
370 
371 	sbsc = addr;
372 	sc = &sbsc->sc_cs4231;
373 	t = &sc->sc_capture;
374 	ret = cs4231_transfer_init(sc, t, &dmaaddr, &dmasize,
375 				   start, end, blksize, intr, arg);
376 	if (ret != 0)
377 		return ret;
378 
379 	csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
380 #ifdef AUDIO_DEBUG
381 	snprintb(bits, sizeof(bits), APC_BITS, csr);
382 #endif
383 	DPRINTF(("trigger_input: csr=%s\n", bits));
384 	DPRINTF(("trigger_input: was: %x %d, %x %d\n",
385 		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CVA),
386 		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CC),
387 		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNVA),
388 		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNC)));
389 
390 	/* supply first block */
391 	bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNVA, dmaaddr);
392 	bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNC, dmasize);
393 
394 	DPRINTF(("trigger_input: 1st: %x %d, %x %d\n",
395 		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CVA),
396 		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CC),
397 		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNVA),
398 		bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNC)));
399 
400 	csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
401 	if ((csr & CDMA_GO) == 0 || (csr & APC_CPAUSE) != 0) {
402 		int cfg;
403 
404 		csr &= ~(APC_CPAUSE | APC_CMIE | APC_INTR_MASK);
405 		bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR, csr);
406 
407 		csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
408 		csr &= ~APC_INTR_MASK;
409 		csr |= APC_ENABLE | APC_CIE | CDMA_GO;
410 		bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR, csr);
411 
412 		ad_write(&sc->sc_ad1848, CS_LOWER_REC_CNT, 0xff);
413 		ad_write(&sc->sc_ad1848, CS_UPPER_REC_CNT, 0xff);
414 
415 		cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG);
416 		ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG,
417 			 (cfg | CAPTURE_ENABLE));
418 	} else {
419 #ifdef AUDIO_DEBUG
420 		snprintb(bits, sizeof(bits), APC_BITS, csr);
421 #endif
422 		DPRINTF(("trigger_input: already: csr=%s\n", bits));
423 	}
424 
425 	/* supply next block if we can */
426 	csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
427 	if (csr & APC_CD) {
428 		cs4231_transfer_advance(t, &dmaaddr, &dmasize);
429 		bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNVA, dmaaddr);
430 		bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNC, dmasize);
431 		DPRINTF(("trigger_input: 2nd: %x %d, %x %d\n",
432 		    bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CVA),
433 		    bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CC),
434 		    bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNVA),
435 		    bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNC)));
436 	}
437 
438 	return 0;
439 }
440 
441 
442 static int
cs4231_sbus_halt_input(void * addr)443 cs4231_sbus_halt_input(void *addr)
444 {
445 	struct cs4231_sbus_softc *sbsc;
446 	struct cs4231_softc *sc;
447 	uint32_t csr;
448 	int cfg;
449 #ifdef AUDIO_DEBUG
450 	char bits[128];
451 #endif
452 
453 	sbsc = addr;
454 	sc = &sbsc->sc_cs4231;
455 	sc->sc_capture.t_active = 0;
456 
457 	csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
458 #ifdef AUDIO_DEBUG
459 	snprintb(bits, sizeof(bits), APC_BITS, csr);
460 #endif
461 	DPRINTF(("halt_input: csr=%s\n", bits));
462 
463 
464 	csr &= ~APC_INTR_MASK;	/* do not clear interrupts accidentally */
465 	csr |= APC_CPAUSE;
466 	bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR, csr);
467 
468 	/* let the curernt transfer complete */
469 	if (csr & CDMA_GO)
470 		do {
471 			csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh,
472 				APC_DMA_CSR);
473 #ifdef AUDIO_DEBUG
474 			snprintb(bits, sizeof(bits), APC_BITS, csr);
475 #endif
476 			DPRINTF(("halt_input: csr=%s\n", bits));
477 
478 
479 		} while ((csr & APC_CM) == 0);
480 
481 	cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG);
482 	ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, (cfg & ~CAPTURE_ENABLE));
483 
484 	return 0;
485 }
486 
487 
488 static int
cs4231_sbus_intr(void * arg)489 cs4231_sbus_intr(void *arg)
490 {
491 	struct cs4231_sbus_softc *sbsc;
492 	struct cs4231_softc *sc;
493 	uint32_t csr;
494 	int status;
495 	bus_addr_t dmaaddr;
496 	bus_size_t dmasize;
497 	int served;
498 #if defined(AUDIO_DEBUG) || defined(DIAGNOSTIC)
499 	char bits[128];
500 #endif
501 
502 	sbsc = arg;
503 	sc = &sbsc->sc_cs4231;
504 	csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR);
505 	if ((csr & APC_INTR_MASK) == 0)	/* any interrupt pending? */
506 		return 0;
507 
508 	mutex_spin_enter(&sc->sc_ad1848.sc_intr_lock);
509 
510 	/* write back DMA status to clear interrupt */
511 	bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR, csr);
512 	++sc->sc_intrcnt.ev_count;
513 	served = 0;
514 
515 #ifdef AUDIO_DEBUG
516 	if (cs4231_sbus_debug > 1)
517 		cs4231_sbus_regdump("audiointr", sbsc);
518 #endif
519 
520 	status = ADREAD(&sc->sc_ad1848, AD1848_STATUS);
521 #ifdef AUDIO_DEBUG
522 	snprintb(bits, sizeof(bits), AD_R2_BITS, status);
523 #endif
524 	DPRINTF(("%s: status: %s\n", device_xname(sc->sc_ad1848.sc_dev),
525 	    bits));
526 	if (status & INTERRUPT_STATUS) {
527 #ifdef AUDIO_DEBUG
528 		int reason;
529 
530 		reason = ad_read(&sc->sc_ad1848, CS_IRQ_STATUS);
531 		snprintb(bits, sizeof(bits), CS_I24_BITS, reason);
532 		DPRINTF(("%s: i24: %s\n", device_xname(sc->sc_ad1848.sc_dev),
533 		    bits));
534 #endif
535 		/* clear ad1848 interrupt */
536 		ADWRITE(&sc->sc_ad1848, AD1848_STATUS, 0);
537 	}
538 
539 	if (csr & APC_CI) {
540 		if (csr & APC_CD) { /* can supply new block */
541 			struct cs_transfer *t = &sc->sc_capture;
542 
543 			cs4231_transfer_advance(t, &dmaaddr, &dmasize);
544 			bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh,
545 				APC_DMA_CNVA, dmaaddr);
546 			bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh,
547 				APC_DMA_CNC, dmasize);
548 
549 			if (t->t_intr != NULL)
550 				sparc_softintr_schedule(sbsc->sc_rint);
551 			++t->t_intrcnt.ev_count;
552 			served = 1;
553 		}
554 	}
555 
556 	if (csr & APC_PMI) {
557 		if (!sc->sc_playback.t_active)
558 			served = 1; /* draining in halt_output() */
559 	}
560 
561 	if (csr & APC_PI) {
562 		if (csr & APC_PD) { /* can load new block */
563 			struct cs_transfer *t = &sc->sc_playback;
564 
565 			if (t->t_active) {
566 				cs4231_transfer_advance(t, &dmaaddr, &dmasize);
567 				bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh,
568 					APC_DMA_PNVA, dmaaddr);
569 				bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh,
570 					APC_DMA_PNC, dmasize);
571 			}
572 
573 			if (t->t_intr != NULL)
574 				sparc_softintr_schedule(sbsc->sc_pint);
575 			++t->t_intrcnt.ev_count;
576 			served = 1;
577 		}
578 	}
579 
580 	/* got an interrupt we don't know how to handle */
581 	if (!served) {
582 #ifdef DIAGNOSTIC
583 	        snprintb(bits, sizeof(bits), APC_BITS, csr);
584 		printf("%s: unhandled csr=%s\n",
585 		    device_xname(sc->sc_ad1848.sc_dev), bits);
586 #endif
587 		/* evcnt? */
588 	}
589 
590 	mutex_spin_exit(&sc->sc_ad1848.sc_intr_lock);
591 
592 	return 1;
593 }
594 
595 static int
cs4231_sbus_pint(void * cookie)596 cs4231_sbus_pint(void *cookie)
597 {
598 	struct cs4231_softc *sc = cookie;
599 	struct cs_transfer *t;
600 
601 	mutex_spin_enter(&sc->sc_ad1848.sc_intr_lock);
602 	t = &sc->sc_playback;
603 	if (t->t_intr != NULL)
604 		(*t->t_intr)(t->t_arg);
605 	mutex_spin_exit(&sc->sc_ad1848.sc_intr_lock);
606 	return 0;
607 }
608 
609 static int
cs4231_sbus_rint(void * cookie)610 cs4231_sbus_rint(void *cookie)
611 {
612 	struct cs4231_softc *sc = cookie;
613 	struct cs_transfer *t;
614 
615 	mutex_spin_enter(&sc->sc_ad1848.sc_intr_lock);
616 	t = &sc->sc_capture;
617 	if (t->t_intr != NULL)
618 		(*t->t_intr)(t->t_arg);
619 	mutex_spin_exit(&sc->sc_ad1848.sc_intr_lock);
620 	return 0;
621 }
622 
623 #endif /* NAUDIO > 0 */
624