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