1 /* $NetBSD: cs4231_ebus.c,v 1.32 2009/05/12 12:12:38 cegger Exp $ */
4 * Copyright (c) 2002 Valeriy E. Ushakov
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: cs4231_ebus.c,v 1.32 2009/05/12 12:12:38 cegger Exp $");
34 #include "opt_sparc_arch.h"
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/errno.h>
40 #include <sys/device.h>
41 #include <sys/malloc.h>
44 #include <machine/autoconf.h>
46 #include <dev/ebus/ebusreg.h>
47 #include <dev/ebus/ebusvar.h>
49 #include <sys/audioio.h>
50 #include <dev/audio_if.h>
52 #include <dev/ic/ad1848reg.h>
53 #include <dev/ic/cs4231reg.h>
54 #include <dev/ic/ad1848var.h>
55 #include <dev/ic/cs4231var.h>
58 int cs4231_ebus_debug
= 0;
59 #define DPRINTF(x) if (cs4231_ebus_debug) printf x
65 struct cs4231_ebus_softc
{
66 struct cs4231_softc sc_cs4231
;
70 bus_space_tag_t sc_bt
;
71 bus_space_handle_t sc_pdmareg
; /* playback DMA */
72 bus_space_handle_t sc_cdmareg
; /* record DMA */
76 void cs4231_ebus_attach(device_t
, device_t
, void *);
77 int cs4231_ebus_match(device_t
, cfdata_t
, void *);
79 static int cs4231_ebus_pint(void *);
80 static int cs4231_ebus_rint(void *);
82 CFATTACH_DECL(audiocs_ebus
, sizeof(struct cs4231_ebus_softc
),
83 cs4231_ebus_match
, cs4231_ebus_attach
, NULL
, NULL
);
85 /* audio_hw_if methods specific to ebus DMA */
86 static int cs4231_ebus_round_blocksize(void *, int, int,
87 const audio_params_t
*);
88 static int cs4231_ebus_trigger_output(void *, void *, void *, int,
89 void (*)(void *), void *,
90 const audio_params_t
*);
91 static int cs4231_ebus_trigger_input(void *, void *, void *, int,
92 void (*)(void *), void *,
93 const audio_params_t
*);
94 static int cs4231_ebus_halt_output(void *);
95 static int cs4231_ebus_halt_input(void *);
97 const struct audio_hw_if audiocs_ebus_hw_if
= {
101 ad1848_query_encoding
,
103 cs4231_ebus_round_blocksize
,
104 ad1848_commit_settings
,
105 NULL
, /* init_output */
106 NULL
, /* init_input */
107 NULL
, /* start_output */
108 NULL
, /* start_input */
109 cs4231_ebus_halt_output
,
110 cs4231_ebus_halt_input
,
111 NULL
, /* speaker_ctl */
116 cs4231_query_devinfo
,
119 NULL
, /* round_buffersize */
122 cs4231_ebus_trigger_output
,
123 cs4231_ebus_trigger_input
,
124 NULL
, /* dev_ioctl */
125 NULL
, /* powerstate */
129 static void cs4231_ebus_regdump(char *, struct cs4231_ebus_softc
*);
132 static int cs4231_ebus_dma_reset(bus_space_tag_t
, bus_space_handle_t
);
133 static int cs4231_ebus_trigger_transfer(struct cs4231_softc
*,
134 struct cs_transfer
*,
135 bus_space_tag_t
, bus_space_handle_t
,
136 int, void *, void *, int, void (*)(void *), void *,
137 const audio_params_t
*);
138 static void cs4231_ebus_dma_advance(struct cs_transfer
*,
139 bus_space_tag_t
, bus_space_handle_t
);
140 static int cs4231_ebus_dma_intr(struct cs_transfer
*,
141 bus_space_tag_t
, bus_space_handle_t
,
143 static int cs4231_ebus_intr(void *);
147 cs4231_ebus_match(device_t parent
, cfdata_t cf
, void *aux
)
149 struct ebus_attach_args
*ea
;
154 if (strcmp(ea
->ea_name
, AUDIOCS_PROM_NAME
) == 0)
158 if (prom_getprop(ea
->ea_node
, "compatible", 1, &total_size
, &compat
) == 0) {
160 if (strcmp(compat
, AUDIOCS_PROM_NAME
) == 0)
163 /* on KRUPS compatible lists: "cs4231", "ad1848",
164 * "mwave", and "pnpPNP,b007" */
165 if (strcmp(compat
, "cs4231") == 0)
168 len
= strlen(compat
) + 1;
171 } while (total_size
> 0);
179 cs4231_ebus_attach(device_t parent
, device_t self
, void *aux
)
181 struct cs4231_ebus_softc
*ebsc
;
182 struct cs4231_softc
*sc
;
183 struct ebus_attach_args
*ea
;
184 bus_space_handle_t bh
;
187 ebsc
= device_private(self
);
188 sc
= &ebsc
->sc_cs4231
;
190 sc
->sc_bustag
= ebsc
->sc_bt
= ea
->ea_bustag
;
191 sc
->sc_dmatag
= ea
->ea_dmatag
;
193 ebsc
->sc_pint
= sparc_softintr_establish(IPL_VM
,
194 (void *)cs4231_ebus_pint
, sc
);
195 ebsc
->sc_rint
= sparc_softintr_establish(IPL_VM
,
196 (void *)cs4231_ebus_rint
, sc
);
199 * These are the register we get from the prom:
201 * - Playback EBus DMA controller
202 * - Capture EBus DMA controller
203 * - AUXIO audio register (codec powerdown)
205 * Map my registers in, if they aren't already in virtual
208 if (bus_space_map(ea
->ea_bustag
, EBUS_ADDR_FROM_REG(&ea
->ea_reg
[0]),
209 ea
->ea_reg
[0].size
, 0, &bh
) != 0) {
210 printf(": unable to map registers\n");
214 if (bus_space_map(ea
->ea_bustag
,
215 #ifdef MSIIEP /* XXX: Krups */
217 * XXX: map playback DMA registers
218 * (we just know where they are)
220 BUS_ADDR(0x14, 0x702000), /* XXX: magic num */
223 EBUS_ADDR_FROM_REG(&ea
->ea_reg
[1]),
226 0, &ebsc
->sc_pdmareg
) != 0)
228 printf(": unable to map playback DMA registers\n");
232 if (bus_space_map(ea
->ea_bustag
,
233 #ifdef MSIIEP /* XXX: Krups */
235 * XXX: map capture DMA registers
236 * (we just know where they are)
238 BUS_ADDR(0x14, 0x704000), /* XXX: magic num */
241 EBUS_ADDR_FROM_REG(&ea
->ea_reg
[2]),
244 0, &ebsc
->sc_cdmareg
) != 0)
246 printf(": unable to map capture DMA registers\n");
250 /* establish interrupt channels */
251 for (i
= 0; i
< ea
->ea_nintr
; ++i
)
252 bus_intr_establish(ea
->ea_bustag
,
253 ea
->ea_intr
[i
], IPL_SCHED
,
254 cs4231_ebus_intr
, ebsc
);
256 cs4231_common_attach(sc
, bh
);
259 /* XXX: todo: move to cs4231_common_attach, pass hw_if as arg? */
260 audio_attach_mi(&audiocs_ebus_hw_if
, sc
, &sc
->sc_ad1848
.sc_dev
);
265 cs4231_ebus_round_blocksize(void *addr
, int blk
, int mode
,
266 const audio_params_t
*param
)
269 /* we want to use DMA burst size of 16 words */
276 cs4231_ebus_regdump(char *label
, struct cs4231_ebus_softc
*ebsc
)
278 /* char bits[128]; */
280 printf("cs4231regdump(%s): regs:", label
);
281 /* XXX: dump ebus DMA and aux registers */
282 ad1848_dump_regs(&ebsc
->sc_cs4231
.sc_ad1848
);
284 #endif /* AUDIO_DEBUG */
287 /* XXX: nothing CS4231-specific in this code... */
289 cs4231_ebus_dma_reset(bus_space_tag_t dt
, bus_space_handle_t dh
)
294 /* reset, also clear TC, just in case */
295 bus_space_write_4(dt
, dh
, EBUS_DMAC_DCSR
, EBDMA_RESET
| EBDMA_TC
);
297 for (timo
= 50000; timo
!= 0; --timo
) {
298 csr
= bus_space_read_4(dt
, dh
, EBUS_DMAC_DCSR
);
299 if ((csr
& (EBDMA_CYC_PEND
| EBDMA_DRAIN
)) == 0)
305 snprintb(bits
, sizeof(bits
), EBUS_DCSR_BITS
, csr
);
306 printf("cs4231_ebus_dma_reset: timed out: csr=%s\n", bits
);
310 bus_space_write_4(dt
, dh
, EBUS_DMAC_DCSR
, csr
& ~EBDMA_RESET
);
316 cs4231_ebus_dma_advance(struct cs_transfer
*t
, bus_space_tag_t dt
,
317 bus_space_handle_t dh
)
322 cs4231_transfer_advance(t
, &dmaaddr
, &dmasize
);
324 bus_space_write_4(dt
, dh
, EBUS_DMAC_DNBR
, (u_int32_t
)dmasize
);
325 bus_space_write_4(dt
, dh
, EBUS_DMAC_DNAR
, (u_int32_t
)dmaaddr
);
330 * Trigger transfer "t" using DMA controller at "dt"/"dh".
331 * "iswrite" defines direction of the transfer.
334 cs4231_ebus_trigger_transfer(
335 struct cs4231_softc
*sc
,
336 struct cs_transfer
*t
,
338 bus_space_handle_t dh
,
340 void *start
, void *end
,
342 void (*intr
)(void *),
344 const audio_params_t
*param
)
351 ret
= cs4231_transfer_init(sc
, t
, &dmaaddr
, &dmasize
,
352 start
, end
, blksize
, intr
, arg
);
356 ret
= cs4231_ebus_dma_reset(dt
, dh
);
360 csr
= bus_space_read_4(dt
, dh
, EBUS_DMAC_DCSR
);
361 bus_space_write_4(dt
, dh
, EBUS_DMAC_DCSR
,
362 csr
| EBDMA_EN_NEXT
| (iswrite
? EBDMA_WRITE
: 0)
363 | EBDMA_EN_DMA
| EBDMA_EN_CNT
| EBDMA_INT_EN
364 | EBDMA_BURST_SIZE_16
);
366 /* first load: propagated to DACR/DBCR */
367 bus_space_write_4(dt
, dh
, EBUS_DMAC_DNBR
, (uint32_t)dmasize
);
368 bus_space_write_4(dt
, dh
, EBUS_DMAC_DNAR
, (uint32_t)dmaaddr
);
370 /* next load: goes to DNAR/DNBR */
371 cs4231_ebus_dma_advance(t
, dt
, dh
);
378 cs4231_ebus_trigger_output(void *addr
, void *start
, void *end
, int blksize
,
379 void (*intr
)(void *), void *arg
,
380 const audio_params_t
*param
)
382 struct cs4231_ebus_softc
*ebsc
;
383 struct cs4231_softc
*sc
;
387 sc
= &ebsc
->sc_cs4231
;
388 ret
= cs4231_ebus_trigger_transfer(sc
, &sc
->sc_playback
,
389 ebsc
->sc_bt
, ebsc
->sc_pdmareg
,
396 ad_write(&sc
->sc_ad1848
, SP_LOWER_BASE_COUNT
, 0xff);
397 ad_write(&sc
->sc_ad1848
, SP_UPPER_BASE_COUNT
, 0xff);
399 cfg
= ad_read(&sc
->sc_ad1848
, SP_INTERFACE_CONFIG
);
400 ad_write(&sc
->sc_ad1848
, SP_INTERFACE_CONFIG
, cfg
| PLAYBACK_ENABLE
);
407 cs4231_ebus_trigger_input(void *addr
, void *start
, void *end
, int blksize
,
408 void (*intr
)(void *), void *arg
,
409 const audio_params_t
*param
)
411 struct cs4231_ebus_softc
*ebsc
;
412 struct cs4231_softc
*sc
;
416 sc
= &ebsc
->sc_cs4231
;
417 ret
= cs4231_ebus_trigger_transfer(sc
, &sc
->sc_capture
,
418 ebsc
->sc_bt
, ebsc
->sc_cdmareg
,
425 ad_write(&sc
->sc_ad1848
, CS_LOWER_REC_CNT
, 0xff);
426 ad_write(&sc
->sc_ad1848
, CS_UPPER_REC_CNT
, 0xff);
428 cfg
= ad_read(&sc
->sc_ad1848
, SP_INTERFACE_CONFIG
);
429 ad_write(&sc
->sc_ad1848
, SP_INTERFACE_CONFIG
, cfg
| CAPTURE_ENABLE
);
436 cs4231_ebus_halt_output(void *addr
)
438 struct cs4231_ebus_softc
*ebsc
;
439 struct cs4231_softc
*sc
;
444 sc
= &ebsc
->sc_cs4231
;
445 sc
->sc_playback
.t_active
= 0;
447 csr
= bus_space_read_4(ebsc
->sc_bt
, ebsc
->sc_pdmareg
, EBUS_DMAC_DCSR
);
448 bus_space_write_4(ebsc
->sc_bt
, ebsc
->sc_pdmareg
, EBUS_DMAC_DCSR
,
449 csr
& ~EBDMA_EN_DMA
);
451 cfg
= ad_read(&sc
->sc_ad1848
, SP_INTERFACE_CONFIG
);
452 ad_write(&sc
->sc_ad1848
, SP_INTERFACE_CONFIG
,
453 cfg
& ~PLAYBACK_ENABLE
);
460 cs4231_ebus_halt_input(void *addr
)
462 struct cs4231_ebus_softc
*ebsc
;
463 struct cs4231_softc
*sc
;
468 sc
= &ebsc
->sc_cs4231
;
469 sc
->sc_capture
.t_active
= 0;
471 csr
= bus_space_read_4(ebsc
->sc_bt
, ebsc
->sc_cdmareg
, EBUS_DMAC_DCSR
);
472 bus_space_write_4(ebsc
->sc_bt
, ebsc
->sc_cdmareg
, EBUS_DMAC_DCSR
,
473 csr
& ~EBDMA_EN_DMA
);
475 cfg
= ad_read(&sc
->sc_ad1848
, SP_INTERFACE_CONFIG
);
476 ad_write(&sc
->sc_ad1848
, SP_INTERFACE_CONFIG
,
477 cfg
& ~CAPTURE_ENABLE
);
484 cs4231_ebus_dma_intr(struct cs_transfer
*t
, bus_space_tag_t dt
,
485 bus_space_handle_t dh
, void *sih
)
492 /* read DMA status, clear TC bit by writing it back */
493 csr
= bus_space_read_4(dt
, dh
, EBUS_DMAC_DCSR
);
494 bus_space_write_4(dt
, dh
, EBUS_DMAC_DCSR
, csr
);
496 snprintb(bits
, sizeof(bits
), EBUS_DCSR_BITS
, csr
);
497 DPRINTF(("audiocs: %s dcsr=%s\n", t
->t_name
, bits
));
500 if (csr
& EBDMA_ERR_PEND
) {
501 ++t
->t_ierrcnt
.ev_count
;
502 printf("audiocs: %s DMA error, resetting\n", t
->t_name
);
503 cs4231_ebus_dma_reset(dt
, dh
);
504 /* how to notify audio(9)??? */
508 if ((csr
& EBDMA_INT_PEND
) == 0)
511 ++t
->t_intrcnt
.ev_count
;
513 if ((csr
& EBDMA_TC
) == 0) { /* can this happen? */
514 printf("audiocs: %s INT_PEND but !TC\n", t
->t_name
);
521 cs4231_ebus_dma_advance(t
, dt
, dh
);
523 /* call audio(9) framework while DMA is chugging along */
524 if (t
->t_intr
!= NULL
)
525 sparc_softintr_schedule(sih
);
531 cs4231_ebus_intr(void *arg
)
533 struct cs4231_ebus_softc
*ebsc
;
534 struct cs4231_softc
*sc
;
542 sc
= &ebsc
->sc_cs4231
;
543 status
= ADREAD(&sc
->sc_ad1848
, AD1848_STATUS
);
546 if (cs4231_ebus_debug
> 1)
547 cs4231_ebus_regdump("audiointr", ebsc
);
549 snprintb(bits
, sizeof(bits
), AD_R2_BITS
, status
);
550 DPRINTF(("%s: status: %s\n", device_xname(&sc
->sc_ad1848
.sc_dev
),
554 if (status
& INTERRUPT_STATUS
) {
558 reason
= ad_read(&sc
->sc_ad1848
, CS_IRQ_STATUS
);
559 snprintb(bits
, sizeof(bits
), CS_I24_BITS
, reason
);
560 DPRINTF(("%s: i24: %s\n", device_xname(&sc
->sc_ad1848
.sc_dev
),
563 /* clear interrupt from ad1848 */
564 ADWRITE(&sc
->sc_ad1848
, AD1848_STATUS
, 0);
569 if (cs4231_ebus_dma_intr(&sc
->sc_capture
, ebsc
->sc_bt
,
570 ebsc
->sc_cdmareg
, ebsc
->sc_rint
) != 0)
572 ++sc
->sc_intrcnt
.ev_count
;
576 if (cs4231_ebus_dma_intr(&sc
->sc_playback
, ebsc
->sc_bt
,
577 ebsc
->sc_pdmareg
, ebsc
->sc_pint
) != 0)
579 ++sc
->sc_intrcnt
.ev_count
;
588 cs4231_ebus_pint(void *cookie
)
590 struct cs4231_softc
*sc
= cookie
;
591 struct cs_transfer
*t
= &sc
->sc_playback
;
593 KERNEL_LOCK(1, NULL
);
594 if (t
->t_intr
!= NULL
)
595 (*t
->t_intr
)(t
->t_arg
);
596 KERNEL_UNLOCK_ONE(NULL
);
601 cs4231_ebus_rint(void *cookie
)
603 struct cs4231_softc
*sc
= cookie
;
604 struct cs_transfer
*t
= &sc
->sc_capture
;
606 KERNEL_LOCK(1, NULL
);
607 if (t
->t_intr
!= NULL
)
608 (*t
->t_intr
)(t
->t_arg
);
609 KERNEL_UNLOCK_ONE(NULL
);