1 /* $NetBSD: repulse.c,v 1.15 2005/12/11 12:16:28 christos Exp $ */
4 * Copyright (c) 2001 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Ignatios Souvatzis.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: repulse.c,v 1.15 2005/12/11 12:16:28 christos Exp $");
35 #include <sys/types.h>
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/device.h>
40 #include <sys/fcntl.h> /* FREAD */
42 #include <machine/bus.h>
44 #include <sys/audioio.h>
45 #include <dev/audio_if.h>
46 #include <dev/mulaw.h>
48 #include <dev/ic/ac97reg.h>
49 #include <dev/ic/ac97var.h>
51 #include <amiga/dev/zbusvar.h>
52 #include <amiga/amiga/isr.h>
54 #include <amiga/dev/repulse_firmware.h>
57 #define vu_int8_t volatile uint8_t
60 #define vu_int16_t volatile uint16_t
63 #define vu_int32_t volatile uint32_t
66 /* ac97 attachment functions */
68 int repac_attach(void *, struct ac97_codec_if
*);
69 int repac_read(void *, uint8_t, uint16_t *);
70 int repac_write(void *, uint8_t, uint16_t);
71 int repac_reset(void *);
72 enum ac97_host_flag
repac_flags(void *);
74 /* audio attachment functions */
76 void rep_close(void *);
77 int rep_getdev(void *, struct audio_device
*);
78 int rep_get_props(void *);
79 int rep_halt_output(void *);
80 int rep_halt_input(void *);
81 int rep_query_encoding(void *, struct audio_encoding
*);
82 int rep_set_params(void *, int, int, audio_params_t
*,
83 audio_params_t
*, stream_filter_list_t
*, stream_filter_list_t
*);
84 int rep_round_blocksize(void *, int, int, const audio_params_t
*);
85 int rep_set_port(void *, mixer_ctrl_t
*);
86 int rep_get_port(void *, mixer_ctrl_t
*);
87 int rep_query_devinfo(void *, mixer_devinfo_t
*);
88 size_t rep_round_buffersize(void *, int, size_t);
90 int rep_start_input(void *, void *, int, void (*)(void *), void *);
91 int rep_start_output(void *, void *, int, void (*)(void *), void *);
96 /* audio attachment */
98 const struct audio_hw_if rep_hw_if
= {
105 /* commit_setting */ 0,
120 rep_round_buffersize
,
123 /* trigger_output */ 0,
124 /* trigger_input */ 0,
128 /* hardware registers */
131 vu_int16_t rhw_status
;
132 vu_int16_t rhw_fifostatus
; /* 0xrrrrpppp0000flag */
133 vu_int16_t rhw_reg_address
;
134 vu_int16_t rhw_reg_data
;
136 vu_int16_t rhw_fifo_lh
;
137 vu_int16_t rhw_fifo_ll
;
138 vu_int16_t rhw_fifo_rh
;
139 vu_int16_t rhw_fifo_rl
;
141 vu_int16_t rhw_fifo_pack
;
142 vu_int16_t rhw_play_fifosz
;
143 vu_int32_t rhw_spdifin_stat
;
144 #define rhw_spdifout_stat rhw_spdifin_stat;
147 vu_int16_t rhw_capt_fifosz
;
148 vu_int16_t rhw_version
;
149 vu_int16_t rhw_dummy1
;
150 vu_int8_t rhw_firmwareload
;
152 vu_int8_t rhw_dummy2
[66 - 31];
154 vu_int16_t rhw_reset
;
155 } /* __attribute__((packed)) */;
157 #define REPSTATUS_PLAY 0x0001
158 #define REPSTATUS_RECORD 0x0002
159 #define REPSTATUS_PLAYFIFORST 0x0004
160 #define REPSTATUS_RECFIFORST 0x0008
162 #define REPSTATUS_REGSENDBUSY 0x0010
163 #define REPSTATUS_LOOPBACK 0x0020
164 #define REPSTATUS_ENSPDIFIN 0x0040
165 #define REPSTATUS_ENSPDIFOUT 0x0080
167 #define REPSTATUS_CODECRESET 0x0200
168 #define REPSTATUS_SPDIFOUT24 0x0400
169 #define REPSTATUS_SPDIFIN24 0x0800
171 #define REPSTATUS_RECIRQENABLE 0x1000
172 #define REPSTATUS_RECIRQACK 0x2000
173 #define REPSTATUS_PLAYIRQENABLE 0x4000
174 #define REPSTATUS_PLAYIRQACK 0x8000
176 #define REPFIFO_PLAYFIFOFULL 0x0001
177 #define REPFIFO_PLAYFIFOEMPTY 0x0002
178 #define REPFIFO_RECFIFOFULL 0x0004
179 #define REPFIFO_RECFIFOEMPTY 0x0008
180 #define REPFIFO_PLAYFIFOGAUGE(x) ((x << 4) & 0xf000)
181 #define REPFIFO_RECFIFOGAUGE(x) (x & 0xf000)
183 /* ac97 data stream transfer functions */
184 void rep_read_16_stereo(struct repulse_hw
*, uint8_t *, int, unsigned);
185 void rep_read_16_mono(struct repulse_hw
*, uint8_t *, int, unsigned);
186 void rep_write_16_stereo(struct repulse_hw
*, uint8_t *, int, unsigned);
187 void rep_write_16_mono(struct repulse_hw
*, uint8_t *, int, unsigned);
188 void rep_read_8_stereo(struct repulse_hw
*, uint8_t *, int, unsigned);
189 void rep_read_8_mono(struct repulse_hw
*, uint8_t *, int, unsigned);
190 void rep_write_8_stereo(struct repulse_hw
*, uint8_t *, int, unsigned);
191 void rep_write_8_mono(struct repulse_hw
*, uint8_t *, int, unsigned);
193 /* AmigaDOS Delay() ticks */
195 #define USECPERTICK (1000000/50)
197 /* NetBSD device attachment */
199 struct repulse_softc
{
200 struct device sc_dev
;
202 struct ac97_host_if sc_achost
;
203 struct ac97_codec_if
*sc_codec_if
;
205 struct repulse_hw
*sc_boardp
;
207 void (*sc_captmore
)(void *);
210 void (*sc_captfun
)(struct repulse_hw
*, uint8_t *, int, unsigned);
214 unsigned sc_captflags
;
217 void (*sc_playmore
)(void *);
219 void (*sc_playfun
)(struct repulse_hw
*, uint8_t *, int, unsigned);
221 unsigned sc_playflags
;
225 int repulse_match (struct device
*, struct cfdata
*, void *);
226 void repulse_attach (struct device
*, struct device
*, void *);
228 CFATTACH_DECL(repulse
, sizeof(struct repulse_softc
),
229 repulse_match
, repulse_attach
, NULL
, NULL
);
232 repulse_match(struct device
*parent
, struct cfdata
*cfp
, void *aux
)
234 struct zbus_args
*zap
;
238 if (zap
->manid
!= 0x4144)
241 if (zap
->prodid
!= 0)
248 repulse_attach(struct device
*parent
, struct device
*self
, void *aux
)
250 struct repulse_softc
*sc
;
251 struct zbus_args
*zap
;
252 struct repulse_hw
*bp
;
257 sc
= (struct repulse_softc
*)self
;
259 bp
= (struct repulse_hw
*)zap
->va
;
263 if (bp
->rhw_fifostatus
& 0x00f0)
266 bp
->rhw_status
= 0x000c;
267 if (bp
->rhw_status
!= 0 || bp
->rhw_fifostatus
!= 0x0f0a)
272 if (needs_firmware
) {
276 delay(1 * USECPERTICK
);
278 for (fwp
= (const uint8_t *)repulse_firmware
;
279 fwp
< (repulse_firmware_size
+
280 (const uint8_t *)repulse_firmware
); fwp
++)
281 bp
->rhw_firmwareload
= *fwp
;
283 delay(1 * USECPERTICK
);
285 if (bp
->rhw_fifostatus
& 0x00f0)
288 a
= /* bp->rhw_status;
289 a |= */ REPSTATUS_CODECRESET
;
293 if ((a
& REPSTATUS_CODECRESET
) == 0)
296 (void)bp
->rhw_status
;
297 (void)bp
->rhw_status
;
298 (void)bp
->rhw_status
;
300 a
&= ~REPSTATUS_CODECRESET
;
304 printf("firmware version 0x%x\n", bp
->rhw_version
);
306 sc
->sc_achost
.arg
= sc
;
308 sc
->sc_achost
.reset
= repac_reset
;
309 sc
->sc_achost
.read
= repac_read
;
310 sc
->sc_achost
.write
= repac_write
;
311 sc
->sc_achost
.attach
= repac_attach
;
312 sc
->sc_achost
.flags
= 0;
314 if (ac97_attach(&sc
->sc_achost
, self
)) {
315 printf("%s: error attaching codec\n", self
->dv_xname
);
321 * Print a warning if the codec doesn't support hardware variable
322 * rate audio. As the initial incarnations of the Repulse board
323 * are AC'97 2.1, it is epxected that we'll always have VRA.
326 * XXX this should be a panic(). OTOH, audio codec speed is not
327 * important enough to do this.
329 a
= sc
->sc_codec_if
->vtbl
->get_extcaps(sc
->sc_codec_if
);
330 if (!(a
& AC97_EXT_AUDIO_VRA
)) {
331 printf("%s: warning: codec doesn't support "
332 "hardware AC'97 2.0 Variable Rate Audio\n",
333 sc
->sc_dev
.dv_xname
);
337 sc
->sc_isr
.isr_ipl
= 2;
338 sc
->sc_isr
.isr_arg
= sc
;
339 sc
->sc_isr
.isr_intr
= rep_intr
;
340 add_isr(&sc
->sc_isr
);
342 audio_attach_mi(&rep_hw_if
, sc
, &sc
->sc_dev
);
347 printf("\n%s: firmware not successfully loaded\n", self
->dv_xname
);
353 repac_reset(void *arg
)
355 struct repulse_softc
*sc
;
356 struct repulse_hw
*bp
;
362 a
|= REPSTATUS_CODECRESET
;
367 if ((a
& REPSTATUS_CODECRESET
) == 0)
368 panic("%s: cannot set reset bit", sc
->sc_dev
.dv_xname
);
375 a
&= ~REPSTATUS_CODECRESET
;
381 repac_read(void *arg
, u_int8_t reg
, u_int16_t
*valuep
)
383 struct repulse_softc
*sc
;
384 struct repulse_hw
*bp
;
388 while (bp
->rhw_status
& REPSTATUS_REGSENDBUSY
)
390 bp
->rhw_reg_address
= (reg
& 0x7F) | 0x80;
392 while (bp
->rhw_status
& REPSTATUS_REGSENDBUSY
)
395 *valuep
= bp
->rhw_reg_data
;
401 repac_write(void *arg
, uint8_t reg
, uint16_t value
)
403 struct repulse_softc
*sc
;
404 struct repulse_hw
*bp
;
408 bp
->rhw_reg_data
= value
;
409 bp
->rhw_reg_address
= reg
& 0x7F;
411 while (bp
->rhw_status
& REPSTATUS_REGSENDBUSY
)
418 repac_attach(void *arg
, struct ac97_codec_if
*acip
)
420 struct repulse_softc
*sc
;
423 sc
->sc_codec_if
= acip
;
428 /* audio(9) support stuff which is not ac97-constant */
433 struct repulse_softc
*sc
;
441 rep_getdev(void *arg
, struct audio_device
*retp
)
443 struct repulse_softc
*sc
;
444 struct repulse_hw
*bp
;
449 strncpy(retp
->name
, "Repulse", sizeof(retp
->name
));
450 snprintf(retp
->version
, sizeof(retp
->version
), "0x%x",
452 strncpy(retp
->config
, "", sizeof(retp
->config
));
459 rep_get_props(void *v
)
461 return AUDIO_PROP_INDEPENDENT
| AUDIO_PROP_FULLDUPLEX
;
465 rep_halt_output(void *arg
)
467 struct repulse_softc
*sc
;
468 struct repulse_hw
*bp
;
472 bp
->rhw_status
&= ~(REPSTATUS_PLAYIRQENABLE
|REPSTATUS_PLAY
);
479 rep_halt_input(void *arg
)
481 struct repulse_softc
*sc
;
482 struct repulse_hw
*bp
;
486 bp
->rhw_status
&= ~(REPSTATUS_RECIRQENABLE
|REPSTATUS_RECORD
);
494 * TODO: add 24bit and 32bit modes here and in setparams.
497 const struct repulse_encoding_query
{
499 int encoding
, precision
, flags
;
500 } rep_encoding_queries
[] = {
501 { AudioEulinear
, AUDIO_ENCODING_ULINEAR
, 8, 0},
502 { AudioEmulaw
, AUDIO_ENCODING_ULAW
, 8, AUDIO_ENCODINGFLAG_EMULATED
},
503 { AudioEalaw
, AUDIO_ENCODING_ALAW
, 8, AUDIO_ENCODINGFLAG_EMULATED
},
504 { AudioEslinear
, AUDIO_ENCODING_SLINEAR
, 8, 0},
505 { AudioEslinear_le
, AUDIO_ENCODING_SLINEAR_LE
, 16, 0},
506 { AudioEulinear_le
, AUDIO_ENCODING_ULINEAR_LE
, 16, 0},
507 { AudioEulinear_be
, AUDIO_ENCODING_ULINEAR_BE
, 16, 0},
508 { AudioEslinear_be
, AUDIO_ENCODING_SLINEAR_BE
, 16, 0},
512 rep_query_encoding(void *arg
, struct audio_encoding
*fp
)
515 const struct repulse_encoding_query
*p
;
519 if (i
>= sizeof(rep_encoding_queries
) /
520 sizeof(struct repulse_encoding_query
))
523 p
= &rep_encoding_queries
[i
];
525 strncpy (fp
->name
, p
->name
, sizeof(fp
->name
));
526 fp
->encoding
= p
->encoding
;
527 fp
->precision
= p
->precision
;
528 fp
->flags
= p
->flags
;
534 * XXX the following three functions need to be enhanced for the FPGA s/pdif
535 * mode. Generic ac97 versions for now.
539 rep_get_port(void *arg
, mixer_ctrl_t
*cp
)
541 struct repulse_softc
*sc
;
544 return sc
->sc_codec_if
->vtbl
->mixer_get_port(sc
->sc_codec_if
, cp
);
548 rep_set_port(void *arg
, mixer_ctrl_t
*cp
)
550 struct repulse_softc
*sc
;
553 return sc
->sc_codec_if
->vtbl
->mixer_set_port(sc
->sc_codec_if
, cp
);
557 rep_query_devinfo(void *arg
, mixer_devinfo_t
*dip
)
559 struct repulse_softc
*sc
;
562 return sc
->sc_codec_if
->vtbl
->query_devinfo(sc
->sc_codec_if
, dip
);
566 rep_round_blocksize(void *arg
, int blk
, int mode
, const audio_params_t
*param
)
572 if (b1
> 65536 / 2 / 2 /* channels */ / 4 /* bytes per channel */)
573 b1
= 65536 / 2 / 2 / 4;
578 rep_round_buffersize(void *arg
, int direction
, size_t size
)
585 rep_set_params(void *addr
, int setmode
, int usemode
,
586 audio_params_t
*play
, audio_params_t
*rec
,
587 stream_filter_list_t
*pfil
, stream_filter_list_t
*rfil
)
590 struct repulse_softc
*sc
;
597 /* for mode in (RECORD, PLAY) */
598 for (mode
= AUMODE_RECORD
; mode
!= -1;
599 mode
= mode
== AUMODE_RECORD
? AUMODE_PLAY
: -1) {
601 if ((setmode
& mode
) == 0)
604 p
= mode
== AUMODE_PLAY
? play
: rec
;
606 /* TODO XXX we can do upto 32bit, 96000 */
607 if (p
->sample_rate
< 4000 || p
->sample_rate
> 48000 ||
608 (p
->precision
!= 8 && p
->precision
!= 16) ||
609 (p
->channels
!= 1 && p
->channels
!= 2))
612 reg
= mode
== AUMODE_PLAY
?
613 AC97_REG_PCM_FRONT_DAC_RATE
: AC97_REG_PCM_LR_ADC_RATE
;
615 repac_write(sc
, reg
, (uint16_t) p
->sample_rate
);
616 repac_read(sc
, reg
, &a
);
619 if (mode
== AUMODE_PLAY
)
620 sc
->sc_playscale
= p
->channels
* p
->precision
/ 8;
622 sc
->sc_captscale
= p
->channels
* p
->precision
/ 8;
626 /* everything else is software, alas... */
627 /* XXX TBD signed/unsigned, *law, etc */
630 if (p
->encoding
== AUDIO_ENCODING_ULINEAR_LE
||
631 p
->encoding
== AUDIO_ENCODING_ULINEAR_BE
||
632 p
->encoding
== AUDIO_ENCODING_ULINEAR
)
635 if (p
->encoding
== AUDIO_ENCODING_SLINEAR_LE
||
636 p
->encoding
== AUDIO_ENCODING_ULINEAR_LE
)
639 if (mode
== AUMODE_PLAY
) {
640 sc
->sc_playflags
= flags
;
641 if (p
->encoding
== AUDIO_ENCODING_ULAW
) {
642 sc
->sc_playfun
= p
->channels
== 1 ?
645 sc
->sc_playflags
= 0;
646 sc
->sc_playscale
= p
->channels
* 2;
647 hw
.encoding
= AUDIO_ENCODING_SLINEAR_BE
;
648 hw
.precision
= hw
.validbits
= 16;
649 pfil
->append(pfil
, mulaw_to_linear16
, &hw
);
651 if (p
->encoding
== AUDIO_ENCODING_ALAW
) {
652 sc
->sc_playfun
= p
->channels
== 1 ?
655 sc
->sc_playflags
= 0;
656 sc
->sc_playscale
= p
->channels
* 2;
657 hw
.encoding
= AUDIO_ENCODING_SLINEAR_BE
;
658 hw
.precision
= hw
.validbits
= 16;
659 pfil
->append(pfil
, alaw_to_linear16
, &hw
);
661 if (p
->precision
== 8 && p
->channels
== 1)
662 sc
->sc_playfun
= rep_write_8_mono
;
663 else if (p
->precision
== 8 && p
->channels
== 2)
664 sc
->sc_playfun
= rep_write_8_stereo
;
665 else if (p
->precision
== 16 && p
->channels
== 1)
666 sc
->sc_playfun
= rep_write_16_mono
;
667 else if (p
->precision
== 16 && p
->channels
== 2)
668 sc
->sc_playfun
= rep_write_16_stereo
;
670 sc
->sc_captflags
= flags
;
671 if (p
->encoding
== AUDIO_ENCODING_ULAW
) {
672 sc
->sc_captfun
= p
->channels
== 1 ?
675 sc
->sc_captflags
= 0;
676 hw
.encoding
= AUDIO_ENCODING_SLINEAR_LE
;
677 rfil
->append(rfil
, linear8_to_mulaw
, &hw
);
679 if (p
->encoding
== AUDIO_ENCODING_ALAW
) {
680 sc
->sc_captfun
= p
->channels
== 1 ?
683 sc
->sc_captflags
= 0;
684 rfil
->append(rfil
, linear8_to_alaw
, &hw
);
686 if (p
->precision
== 8 && p
->channels
== 1)
687 sc
->sc_captfun
= rep_read_8_mono
;
688 else if (p
->precision
== 8 && p
->channels
== 2)
689 sc
->sc_captfun
= rep_read_8_stereo
;
690 else if (p
->precision
== 16 && p
->channels
== 1)
691 sc
->sc_captfun
= rep_read_16_mono
;
692 else if (p
->precision
== 16 && p
->channels
== 2)
693 sc
->sc_captfun
= rep_read_16_stereo
;
695 /* TBD: mu-law, A-law */
701 rep_write_8_mono(struct repulse_hw
*bp
, uint8_t *p
, int length
, unsigned flags
)
706 xor = flags
& 1 ? 0x8000 : 0;
708 bp
->rhw_fifo_pack
= 0;
710 while (length
-- > 0) {
711 sample
= ((*p
++) << 8) ^ xor;
712 bp
->rhw_fifo_lh
= sample
;
713 bp
->rhw_fifo_rh
= sample
;
718 rep_write_8_stereo(struct repulse_hw
*bp
, uint8_t *p
, int length
,
723 xor = flags
& 1 ? 0x8000 : 0;
725 bp
->rhw_fifo_pack
= 0;
727 while (length
-- > 0) {
728 bp
->rhw_fifo_lh
= ((*p
++) << 8) ^ xor;
729 bp
->rhw_fifo_rh
= ((*p
++) << 8) ^ xor;
734 rep_write_16_mono(struct repulse_hw
*bp
, uint8_t *p
, int length
,
742 xor = flags
& 1 ? 0x8000 : 0;
744 bp
->rhw_fifo_pack
= 0;
748 sample
= bswap16(*q
++) ^ xor;
749 bp
->rhw_fifo_lh
= sample
;
750 bp
->rhw_fifo_rh
= sample
;
757 sample
= (*q
++) ^ xor;
758 bp
->rhw_fifo_lh
= sample
;
759 bp
->rhw_fifo_rh
= sample
;
765 rep_write_16_stereo(struct repulse_hw
*bp
, uint8_t *p
, int length
,
772 xor = flags
& 1 ? 0x8000 : 0;
774 bp
->rhw_fifo_pack
= 0;
778 bp
->rhw_fifo_lh
= bswap16(*q
++) ^ xor;
779 bp
->rhw_fifo_rh
= bswap16(*q
++) ^ xor;
785 bp
->rhw_fifo_lh
= (*q
++) ^ xor;
786 bp
->rhw_fifo_rh
= (*q
++) ^ xor;
792 rep_read_8_mono(struct repulse_hw
*bp
, uint8_t *p
, int length
, unsigned flags
)
797 xor = flags
& 1 ? 0x8000 : 0;
800 *p
++ = (bp
->rhw_fifo_lh
^ xor) >> 8;
807 rep_read_16_mono(struct repulse_hw
*bp
, uint8_t *p
, int length
, unsigned flags
)
814 xor = flags
& 1 ? 0x8000 : 0;
818 *q
++ = bswap16(bp
->rhw_fifo_lh
^ xor);
826 *q
++ = bp
->rhw_fifo_lh
^ xor;
833 rep_read_8_stereo(struct repulse_hw
*bp
, uint8_t *p
, int length
,
838 xor = flags
& 1 ? 0x8000 : 0;
840 *p
++ = (bp
->rhw_fifo_lh
^ xor) >> 8;
841 *p
++ = (bp
->rhw_fifo_rh
^ xor) >> 8;
847 rep_read_16_stereo(struct repulse_hw
*bp
, uint8_t *p
, int length
,
854 xor = flags
& 1 ? 0x8000 : 0;
858 *q
++ = bswap16(bp
->rhw_fifo_lh
^ xor);
859 *q
++ = bswap16(bp
->rhw_fifo_rh
^ xor);
865 *q
++ = bp
->rhw_fifo_lh
^ xor;
866 *q
++ = bp
->rhw_fifo_rh
^ xor;
872 * At this point the transfer function is set.
876 rep_start_output(void *addr
, void *block
, int blksize
,
877 void (*intr
)(void*), void *intrarg
)
879 struct repulse_softc
*sc
;
881 struct repulse_hw
*bp
;
889 /* TODO: prepare hw if necessary */
890 status
= bp
->rhw_status
;
891 if (!(status
& REPSTATUS_PLAY
))
892 bp
->rhw_status
= status
|
893 REPSTATUS_PLAY
| REPSTATUS_PLAYFIFORST
;
896 (*sc
->sc_playfun
)(bp
, buf
, blksize
, sc
->sc_playflags
);
898 /* TODO: set hw if necessary */
900 bp
->rhw_status
|= REPSTATUS_PLAYIRQENABLE
;
901 bp
->rhw_play_fifosz
= blksize
/ sc
->sc_playscale
/ 2;
902 /* /2: give us time to return on the first call */
905 /* save callback function */
906 sc
->sc_playarg
= intrarg
;
907 sc
->sc_playmore
= intr
;
913 rep_start_input(void *addr
, void *block
, int blksize
,
914 void (*intr
)(void*), void *intrarg
)
916 struct repulse_softc
*sc
;
917 struct repulse_hw
*bp
;
923 sc
->sc_captbuf
= block
;
924 sc
->sc_captbufsz
= blksize
;
925 sc
->sc_captarg
= intrarg
;
926 sc
->sc_captmore
= intr
;
928 status
= bp
->rhw_status
;
929 if (!(status
& REPSTATUS_RECORD
))
930 bp
->rhw_status
= status
| REPSTATUS_RECORD
931 | REPSTATUS_RECFIFORST
;
933 bp
->rhw_status
|= REPSTATUS_RECIRQENABLE
;
934 bp
->rhw_capt_fifosz
= blksize
/ sc
->sc_captscale
;
944 struct repulse_softc
*sc
;
945 struct repulse_hw
*bp
;
953 status
= bp
->rhw_status
;
955 if (status
& REPSTATUS_PLAYIRQACK
) {
957 status
&= ~REPSTATUS_PLAYIRQENABLE
;
958 bp
->rhw_status
= status
;
959 (*sc
->sc_playmore
)(sc
->sc_playarg
);
962 if (status
& REPSTATUS_RECIRQACK
) {
964 status
&= ~REPSTATUS_RECIRQENABLE
;
965 bp
->rhw_status
= status
;
966 (*sc
->sc_captfun
)(bp
, sc
->sc_captbuf
, sc
->sc_captbufsz
,
968 (*sc
->sc_captmore
)(sc
->sc_captarg
);