Home | History | Annotate | Line # | Download | only in dev
repulse.c revision 1.8.4.1
      1  1.8.4.1       jmc /*	$NetBSD: repulse.c,v 1.8.4.1 2004/09/22 20:58:01 jmc Exp $ */
      2      1.1        is 
      3      1.1        is /*-
      4      1.1        is  * Copyright (c) 2001 The NetBSD Foundation, Inc.
      5      1.1        is  * All rights reserved.
      6      1.1        is  *
      7      1.1        is  * This code is derived from software contributed to The NetBSD Foundation
      8      1.1        is  * by Ignatios Souvatzis.
      9      1.1        is  *
     10      1.1        is  * Redistribution and use in source and binary forms, with or without
     11      1.1        is  * modification, are permitted provided that the following conditions
     12      1.1        is  * are met:
     13      1.1        is  * 1. Redistributions of source code must retain the above copyright
     14      1.1        is  *    notice, this list of conditions and the following disclaimer.
     15      1.1        is  * 2. Redistributions in binary form must reproduce the above copyright
     16      1.1        is  *    notice, this list of conditions and the following disclaimer in the
     17      1.1        is  *    documentation and/or other materials provided with the distribution.
     18      1.1        is  * 3. All advertising materials mentioning features or use of this software
     19      1.1        is  *    must display the following acknowledgement:
     20      1.1        is  *	  This product includes software developed by the NetBSD
     21      1.1        is  *	  Foundation, Inc. and its contributors.
     22      1.1        is  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23      1.1        is  *    contributors may be used to endorse or promote products derived
     24      1.1        is  *    from this software without specific prior written permission.
     25      1.1        is  *
     26      1.1        is  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27      1.1        is  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28      1.1        is  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29      1.1        is  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30      1.1        is  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31      1.1        is  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32      1.1        is  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33      1.1        is  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34      1.1        is  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35      1.1        is  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36      1.1        is  * POSSIBILITY OF SUCH DAMAGE.
     37      1.1        is  */
     38      1.1        is 
     39      1.4   aymeric #include <sys/cdefs.h>
     40  1.8.4.1       jmc __KERNEL_RCSID(0, "$NetBSD: repulse.c,v 1.8.4.1 2004/09/22 20:58:01 jmc Exp $");
     41      1.1        is 
     42      1.1        is #include <sys/types.h>
     43      1.1        is #include <sys/param.h>
     44      1.1        is #include <sys/systm.h>
     45      1.1        is #include <sys/kernel.h>
     46      1.3   aymeric #include <sys/device.h>
     47      1.1        is #include <sys/fcntl.h>		/* FREAD */
     48      1.1        is 
     49      1.1        is #include <machine/bus.h>
     50      1.1        is 
     51      1.1        is #include <sys/audioio.h>
     52      1.1        is #include <dev/audio_if.h>
     53      1.1        is #include <dev/mulaw.h>
     54      1.3   aymeric 
     55      1.1        is #include <dev/ic/ac97reg.h>
     56      1.1        is #include <dev/ic/ac97var.h>
     57      1.1        is 
     58      1.1        is #include <amiga/dev/zbusvar.h>
     59      1.1        is #include <amiga/amiga/isr.h>
     60      1.1        is 
     61      1.1        is #include <amiga/dev/repulse_firmware.h>
     62      1.1        is 
     63      1.1        is #ifndef vu_int8_t
     64      1.1        is #define vu_int8_t volatile u_int8_t
     65      1.1        is #endif
     66      1.1        is #ifndef vu_int16_t
     67      1.1        is #define vu_int16_t volatile u_int16_t
     68      1.1        is #endif
     69      1.1        is #ifndef vu_int32_t
     70      1.1        is #define vu_int32_t volatile u_int32_t
     71      1.1        is #endif
     72      1.1        is 
     73      1.1        is /* ac97 attachment functions */
     74      1.1        is 
     75      1.1        is int repac_attach(void *, struct ac97_codec_if *);
     76      1.1        is int repac_read(void *, u_int8_t, u_int16_t *);
     77      1.1        is int repac_write(void *, u_int8_t, u_int16_t);
     78  1.8.4.1       jmc int repac_reset(void *);
     79      1.1        is enum ac97_host_flag repac_flags(void *);
     80      1.1        is 
     81      1.1        is /* audio attachment functions */
     82      1.1        is 
     83      1.1        is int rep_open(void *, int);
     84      1.1        is void rep_close(void *);
     85      1.1        is int rep_getdev(void *, struct audio_device *);
     86      1.1        is int rep_get_props(void *);
     87      1.1        is int rep_halt_output(void *);
     88      1.1        is int rep_halt_input(void *);
     89      1.1        is int rep_query_encoding(void *, struct audio_encoding *);
     90      1.1        is int rep_set_params(void *, int, int, struct audio_params *,
     91      1.1        is     struct audio_params *);
     92      1.1        is int rep_round_blocksize(void *, int);
     93      1.1        is int rep_set_port(void *, mixer_ctrl_t *);
     94      1.1        is int rep_get_port(void *, mixer_ctrl_t *);
     95      1.1        is int rep_query_devinfo(void *, mixer_devinfo_t *);
     96      1.1        is size_t rep_round_buffersize(void *, int, size_t);
     97      1.1        is 
     98      1.1        is int rep_start_input(void *, void *, int, void (*)(void *), void *);
     99      1.1        is int rep_start_output(void *, void *, int, void (*)(void *), void *);
    100      1.1        is 
    101      1.1        is int rep_intr(void *tag);
    102      1.1        is 
    103      1.1        is 
    104      1.1        is /* audio attachment */
    105      1.1        is 
    106      1.1        is struct audio_hw_if rep_hw_if = {
    107      1.1        is 	rep_open,
    108      1.1        is 	rep_close,
    109      1.1        is 	/* drain */ 0,
    110      1.1        is 	rep_query_encoding,
    111      1.1        is 	rep_set_params,
    112      1.1        is 	rep_round_blocksize,
    113      1.1        is 	/* commit_setting */ 0,
    114      1.1        is 	/* init_output */ 0,
    115      1.1        is 	/* init_input */ 0,
    116      1.1        is 	rep_start_output,
    117      1.1        is 	rep_start_input,
    118      1.1        is 	rep_halt_output,
    119      1.1        is 	rep_halt_input,
    120      1.1        is 	/* speaker_ctl */ 0,
    121      1.1        is 	rep_getdev,
    122      1.1        is 	/* getfd */ 0,
    123      1.1        is 	rep_set_port,
    124      1.1        is 	rep_get_port,
    125      1.1        is 	rep_query_devinfo,
    126      1.1        is 	/* allocm */ 0,
    127      1.1        is 	/* freem */ 0,
    128      1.1        is 	rep_round_buffersize,
    129      1.1        is 	/* mappage */ 0,
    130      1.1        is 	rep_get_props,
    131      1.1        is 	/* trigger_output */ 0,
    132      1.1        is 	/* trigger_input */ 0,
    133      1.2  augustss 	/* dev_ioctl */ 0,
    134      1.1        is };
    135      1.1        is 
    136      1.1        is /* hardware registers */
    137      1.1        is 
    138      1.1        is struct repulse_hw {
    139      1.1        is 	vu_int16_t	rhw_status;
    140      1.1        is 	vu_int16_t	rhw_fifostatus;		/* 0xrrrrpppp0000flag */
    141      1.1        is 	vu_int16_t	rhw_reg_address;
    142      1.1        is 	vu_int16_t	rhw_reg_data;
    143      1.1        is /* 0x08 */
    144      1.1        is 	vu_int16_t	rhw_fifo_lh;
    145      1.1        is 	vu_int16_t	rhw_fifo_ll;
    146      1.1        is 	vu_int16_t	rhw_fifo_rh;
    147      1.1        is 	vu_int16_t	rhw_fifo_rl;
    148      1.1        is /* 0x10 */
    149      1.1        is 	vu_int16_t	rhw_fifo_pack;
    150      1.1        is 	vu_int16_t	rhw_play_fifosz;
    151      1.1        is 	vu_int32_t	rhw_spdifin_stat;
    152      1.1        is #define	rhw_spdifout_stat rhw_spdifin_stat;
    153      1.1        is 
    154      1.1        is /* 0x18 */
    155      1.1        is 	vu_int16_t	rhw_capt_fifosz;
    156      1.1        is 	vu_int16_t	rhw_version;
    157      1.1        is 	vu_int16_t	rhw_dummy1;
    158      1.1        is 	vu_int8_t	rhw_firmwareload;
    159      1.1        is /* 0x1F */
    160      1.1        is 	vu_int8_t	rhw_dummy2[66 - 31];
    161      1.1        is /* 0x42 */
    162      1.1        is 	vu_int16_t	rhw_reset;
    163      1.1        is } /* __attribute__((packed)) */;
    164      1.1        is 
    165      1.1        is #define REPSTATUS_PLAY		0x0001
    166      1.1        is #define REPSTATUS_RECORD	0x0002
    167      1.1        is #define REPSTATUS_PLAYFIFORST	0x0004
    168      1.1        is #define REPSTATUS_RECFIFORST	0x0008
    169      1.1        is 
    170      1.1        is #define REPSTATUS_REGSENDBUSY	0x0010
    171      1.1        is #define REPSTATUS_LOOPBACK	0x0020
    172      1.1        is #define REPSTATUS_ENSPDIFIN	0x0040
    173      1.1        is #define REPSTATUS_ENSPDIFOUT	0x0080
    174      1.1        is 
    175      1.1        is #define REPSTATUS_CODECRESET	0x0200
    176      1.1        is #define REPSTATUS_SPDIFOUT24	0x0400
    177      1.1        is #define REPSTATUS_SPDIFIN24	0x0800
    178      1.1        is 
    179      1.1        is #define REPSTATUS_RECIRQENABLE	0x1000
    180      1.1        is #define REPSTATUS_RECIRQACK	0x2000
    181      1.1        is #define REPSTATUS_PLAYIRQENABLE	0x4000
    182      1.1        is #define REPSTATUS_PLAYIRQACK	0x8000
    183      1.1        is 
    184      1.1        is #define REPFIFO_PLAYFIFOFULL	0x0001
    185      1.1        is #define REPFIFO_PLAYFIFOEMPTY	0x0002
    186      1.1        is #define REPFIFO_RECFIFOFULL	0x0004
    187      1.1        is #define REPFIFO_RECFIFOEMPTY	0x0008
    188      1.1        is #define REPFIFO_PLAYFIFOGAUGE(x) ((x << 4) & 0xf000)
    189      1.1        is #define REPFIFO_RECFIFOGAUGE(x)		(x & 0xf000)
    190      1.1        is 
    191      1.1        is /* ac97 data stream transfer functions */
    192      1.1        is void rep_read_16_stereo(struct repulse_hw *, u_int8_t *, int, unsigned);
    193      1.1        is void rep_read_16_mono(struct repulse_hw *, u_int8_t *, int, unsigned);
    194      1.1        is void rep_write_16_stereo(struct repulse_hw *, u_int8_t *, int, unsigned);
    195      1.1        is void rep_write_16_mono(struct repulse_hw *, u_int8_t *, int, unsigned);
    196      1.1        is void rep_read_8_stereo(struct repulse_hw *, u_int8_t *, int, unsigned);
    197      1.1        is void rep_read_8_mono(struct repulse_hw *, u_int8_t *, int, unsigned);
    198      1.1        is void rep_write_8_stereo(struct repulse_hw *, u_int8_t *, int, unsigned);
    199      1.1        is void rep_write_8_mono(struct repulse_hw *, u_int8_t *, int, unsigned);
    200      1.1        is 
    201      1.1        is /* AmigaDOS Delay() ticks */
    202      1.1        is 
    203      1.1        is #define USECPERTICK	(1000000/50)
    204      1.1        is 
    205      1.1        is /* NetBSD device attachment */
    206      1.1        is 
    207      1.1        is struct repulse_softc {
    208      1.1        is 	struct device		sc_dev;
    209      1.1        is 	struct isr		sc_isr;
    210      1.1        is 	struct ac97_host_if	sc_achost;
    211      1.1        is 	struct ac97_codec_if	*sc_codec_if;
    212      1.1        is 
    213      1.1        is 	struct repulse_hw	*sc_boardp;
    214      1.1        is 
    215      1.1        is 	void	(*sc_captmore)(void *);
    216      1.1        is 	void	 *sc_captarg;
    217      1.1        is 
    218      1.1        is 	void	(*sc_captfun)(struct repulse_hw *, u_int8_t *, int, unsigned);
    219      1.1        is 	void	 *sc_captbuf;
    220      1.1        is 	int	  sc_captscale;
    221      1.1        is 	int	  sc_captbufsz;
    222      1.1        is 	unsigned  sc_captflags;
    223      1.1        is 
    224      1.1        is 
    225      1.1        is 	void	(*sc_playmore)(void *);
    226      1.1        is 	void	 *sc_playarg;
    227      1.1        is 	void	(*sc_playfun)(struct repulse_hw *, u_int8_t *, int, unsigned);
    228      1.1        is 	int	  sc_playscale;
    229      1.1        is 	unsigned  sc_playflags;
    230      1.1        is 
    231      1.1        is };
    232      1.1        is 
    233      1.1        is int repulse_match (struct device *, struct cfdata *, void *);
    234      1.1        is void repulse_attach (struct device *, struct device *, void *);
    235      1.1        is 
    236      1.6   thorpej CFATTACH_DECL(repulse, sizeof(struct repulse_softc),
    237      1.6   thorpej     repulse_match, repulse_attach, NULL, NULL);
    238      1.1        is 
    239      1.1        is int
    240      1.1        is repulse_match(struct device *parent, struct cfdata *cfp, void *aux) {
    241      1.1        is 	struct zbus_args *zap;
    242      1.1        is 
    243      1.1        is 	zap = aux;
    244      1.1        is 
    245      1.1        is 	if (zap->manid != 0x4144)
    246      1.1        is 		return (0);
    247      1.1        is 
    248      1.1        is 	if (zap->prodid != 0)
    249      1.1        is 		return (0);
    250      1.1        is 
    251      1.1        is 	return (1);
    252      1.1        is }
    253      1.1        is 
    254      1.1        is void
    255      1.1        is repulse_attach(struct device *parent, struct device *self, void *aux) {
    256      1.1        is 	struct repulse_softc *sc;
    257      1.1        is 	struct zbus_args *zap;
    258      1.1        is 	struct repulse_hw *bp;
    259      1.1        is         struct mixer_ctrl ctl;
    260      1.1        is 	u_int8_t *fwp;
    261      1.1        is 	int needs_firmware;
    262      1.1        is 	int i;
    263      1.1        is 
    264      1.1        is 	u_int16_t a;
    265      1.1        is 
    266      1.1        is 	sc = (struct repulse_softc *)self;
    267      1.1        is 	zap = aux;
    268      1.1        is 	bp = (struct repulse_hw *)zap->va;
    269      1.1        is 	sc->sc_boardp = bp;
    270      1.1        is 
    271      1.1        is 	needs_firmware = 0;
    272      1.1        is 	if (bp->rhw_fifostatus & 0x00f0)
    273      1.1        is 		needs_firmware = 1;
    274      1.1        is 	else {
    275      1.1        is 		bp->rhw_status = 0x000c;
    276      1.1        is 		if (bp->rhw_status != 0 || bp->rhw_fifostatus != 0x0f0a)
    277      1.1        is 			needs_firmware = 1;
    278      1.1        is 	}
    279      1.1        is 
    280      1.1        is 	printf(": ");
    281      1.1        is 	if (needs_firmware) {
    282      1.1        is 		printf("loading ");
    283      1.1        is 		bp->rhw_reset = 0;
    284      1.1        is 
    285      1.1        is 		delay(1 * USECPERTICK);
    286      1.3   aymeric 
    287      1.1        is 		for (fwp = (u_int8_t *)repulse_firmware;
    288      1.1        is 		    fwp < (repulse_firmware_size +
    289      1.1        is 		    (u_int8_t *)repulse_firmware); fwp++)
    290      1.1        is 			bp->rhw_firmwareload = *fwp;
    291      1.1        is 
    292      1.1        is 		delay(1 * USECPERTICK);
    293      1.1        is 
    294      1.1        is 		if (bp->rhw_fifostatus & 0x00f0)
    295      1.1        is 			goto Initerr;
    296      1.1        is 
    297      1.1        is 		a = /* bp->rhw_status;
    298      1.1        is 		a |= */ REPSTATUS_CODECRESET;
    299      1.1        is 		bp->rhw_status = a;
    300      1.1        is 
    301      1.1        is 		a = bp->rhw_status;
    302      1.1        is 		if ((a & REPSTATUS_CODECRESET) == 0)
    303      1.1        is 			goto Initerr;
    304      1.1        is 
    305      1.1        is 		(void)bp->rhw_status;
    306      1.1        is 		(void)bp->rhw_status;
    307      1.1        is 		(void)bp->rhw_status;
    308      1.1        is 		a = bp->rhw_status;
    309      1.1        is 		a &= ~REPSTATUS_CODECRESET;
    310      1.1        is 		bp->rhw_status = a;
    311      1.1        is 	}
    312      1.1        is 
    313      1.1        is 	printf("firmware version 0x%x\n", bp->rhw_version);
    314      1.1        is 
    315      1.1        is 	sc->sc_achost.arg = sc;
    316      1.1        is 
    317      1.1        is 	sc->sc_achost.reset = repac_reset;
    318      1.1        is 	sc->sc_achost.read = repac_read;
    319      1.1        is 	sc->sc_achost.write = repac_write;
    320      1.1        is 	sc->sc_achost.attach = repac_attach;
    321      1.1        is 	sc->sc_achost.flags = 0;
    322      1.1        is 
    323      1.1        is 	if (ac97_attach(&sc->sc_achost)) {
    324      1.1        is 		printf("%s: error attaching codec\n", self->dv_xname);
    325      1.1        is 		return;
    326      1.1        is 	}
    327      1.1        is 
    328      1.1        is #ifdef DIAGNOSTIC
    329      1.3   aymeric 	/*
    330      1.1        is 	 * Print a warning if the codec doesn't support hardware variable
    331      1.1        is 	 * rate audio. As the initial incarnations of the Repulse board
    332      1.1        is 	 * are AC'97 2.1, it is epxected that we'll always have VRA.
    333      1.1        is 	 */
    334      1.1        is 	/*
    335      1.1        is 	 * XXX this should be a panic(). OTOH, audio codec speed is not
    336      1.1        is 	 * important enough to do this.
    337      1.1        is 	 */
    338      1.7      kent 	a = sc->sc_codec_if->vtbl->get_extcaps(sc->sc_codec_if);
    339      1.7      kent 	if (!(a & AC97_EXT_AUDIO_VRA)) {
    340      1.1        is 		printf("%s: warning: codec doesn't support "
    341      1.1        is 		    "hardware AC'97 2.0 Variable Rate Audio\n",
    342      1.1        is 			sc->sc_dev.dv_xname);
    343      1.1        is 	}
    344      1.1        is #endif
    345      1.1        is 
    346      1.1        is 	/*
    347      1.1        is 	 * from auvia.c: disable mutes ...
    348      1.1        is 	 * XXX maybe this should happen in MI code?
    349      1.1        is 	 */
    350      1.1        is 
    351      1.1        is 	for (i = 0; i < 5; i++) {
    352      1.1        is 		static struct {
    353      1.1        is 			char *class, *device;
    354      1.1        is 		} d[] = {
    355      1.3   aymeric 			{ AudioCoutputs, AudioNmaster},
    356      1.1        is                         { AudioCinputs, AudioNdac},
    357      1.1        is                         { AudioCinputs, AudioNcd},
    358      1.1        is                         { AudioCinputs, AudioNline},
    359      1.1        is                         { AudioCrecord, AudioNvolume},
    360      1.1        is 		};
    361      1.1        is 
    362      1.1        is 		ctl.type = AUDIO_MIXER_ENUM;
    363      1.1        is 		ctl.un.ord = 0;
    364      1.1        is 		ctl.dev = sc->sc_codec_if->vtbl->get_portnum_by_name(
    365      1.1        is 			sc->sc_codec_if, d[i].class, d[i].device, AudioNmute);
    366      1.1        is 		rep_set_port(sc, &ctl);
    367      1.1        is 	}
    368      1.1        is 
    369      1.1        is 	sc->sc_isr.isr_ipl = 2;
    370      1.1        is 	sc->sc_isr.isr_arg = sc;
    371      1.1        is 	sc->sc_isr.isr_intr = rep_intr;
    372      1.1        is 	add_isr(&sc->sc_isr);
    373      1.1        is 
    374      1.1        is 	audio_attach_mi(&rep_hw_if, sc, &sc->sc_dev);
    375      1.1        is 
    376      1.1        is 	return;
    377      1.1        is 
    378      1.1        is Initerr:
    379      1.1        is 	printf("\n%s: firmware not successfully loaded\n", self->dv_xname);
    380      1.1        is 	return;
    381      1.3   aymeric 
    382      1.1        is }
    383      1.1        is 
    384  1.8.4.1       jmc int repac_reset(void *arg) {
    385      1.1        is 	struct repulse_softc *sc = arg;
    386      1.1        is 	struct repulse_hw *bp = sc->sc_boardp;
    387      1.1        is 
    388      1.1        is 	u_int16_t a;
    389      1.3   aymeric 
    390      1.1        is 	a = bp->rhw_status;
    391      1.1        is 	a |= REPSTATUS_CODECRESET;
    392      1.1        is 	bp->rhw_status = a;
    393      1.1        is 
    394      1.1        is 	a = bp->rhw_status;
    395      1.1        is #ifdef DIAGNOSTIC
    396      1.1        is 	if ((a & REPSTATUS_CODECRESET) == 0)
    397      1.1        is 		panic("%s: cannot set reset bit", sc->sc_dev.dv_xname);
    398      1.1        is #endif
    399      1.1        is 
    400      1.1        is 	a = bp->rhw_status;
    401      1.1        is 	a = bp->rhw_status;
    402      1.1        is 	a = bp->rhw_status;
    403      1.1        is 	a = bp->rhw_status;
    404      1.1        is 	a &= ~REPSTATUS_CODECRESET;
    405      1.1        is 	bp->rhw_status = a;
    406  1.8.4.1       jmc 	return 0;
    407      1.1        is }
    408      1.1        is 
    409      1.1        is int repac_read(void *arg, u_int8_t reg, u_int16_t *valuep) {
    410      1.1        is 	struct repulse_softc *sc = arg;
    411      1.1        is 	struct repulse_hw *bp = sc->sc_boardp;
    412      1.1        is 
    413      1.1        is 	while (bp->rhw_status & REPSTATUS_REGSENDBUSY);
    414      1.1        is 	bp->rhw_reg_address = (reg & 0x7F) | 0x80;
    415      1.1        is 
    416      1.1        is 	while (bp->rhw_status & REPSTATUS_REGSENDBUSY);
    417      1.1        is 
    418      1.1        is 	*valuep = bp->rhw_reg_data;
    419      1.1        is 
    420      1.1        is 	return 0;
    421      1.1        is }
    422      1.1        is 
    423      1.1        is int repac_write(void *arg, u_int8_t reg, u_int16_t value) {
    424      1.1        is 	struct repulse_softc *sc = arg;
    425      1.1        is 	struct repulse_hw *bp = sc->sc_boardp;
    426      1.1        is 
    427      1.1        is 	bp->rhw_reg_data = value;
    428      1.1        is 	bp->rhw_reg_address = reg & 0x7F;
    429      1.1        is 
    430      1.1        is 	while (bp->rhw_status & REPSTATUS_REGSENDBUSY);
    431      1.1        is 
    432      1.1        is 	return 0;
    433      1.1        is }
    434      1.1        is 
    435      1.1        is int repac_attach(void *arg, struct ac97_codec_if *acip){
    436      1.1        is 
    437      1.1        is 	struct repulse_softc *sc;
    438      1.1        is 
    439      1.1        is 	sc = arg;
    440      1.1        is 	sc->sc_codec_if = acip;
    441      1.1        is 
    442      1.1        is 	return 0;
    443      1.1        is }
    444      1.1        is 
    445      1.1        is /* audio(9) support stuff which is not ac97-constant */
    446      1.1        is 
    447      1.1        is int
    448      1.3   aymeric rep_open(void *arg, int flags)
    449      1.1        is {
    450      1.1        is 	return 0;
    451      1.1        is }
    452      1.1        is 
    453      1.1        is void
    454      1.1        is rep_close(void *arg)
    455      1.1        is {
    456      1.1        is 	struct repulse_softc *sc = arg;
    457      1.1        is 
    458      1.1        is 	rep_halt_output(sc);
    459      1.1        is 	rep_halt_input(sc);
    460      1.1        is }
    461      1.1        is 
    462      1.1        is int
    463      1.1        is rep_getdev(void *arg, struct audio_device *retp)
    464      1.1        is {
    465      1.1        is 	struct repulse_softc *sc = arg;
    466      1.1        is 	struct repulse_hw *bp = sc->sc_boardp;
    467      1.1        is 
    468      1.1        is 	if (retp) {
    469      1.1        is 		strncpy(retp->name, "Repulse", sizeof(retp->name));
    470      1.1        is 		snprintf(retp->version, sizeof(retp->version), "0x%x",
    471      1.1        is 			bp->rhw_version);
    472      1.1        is 		strncpy(retp->config, "", sizeof(retp->config));
    473      1.1        is 	}
    474      1.1        is 
    475      1.1        is 	return 0;
    476      1.1        is }
    477      1.1        is 
    478      1.3   aymeric int
    479      1.1        is rep_get_props(void *v)
    480      1.1        is {
    481      1.1        is 	return (AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX);
    482      1.3   aymeric }
    483      1.1        is 
    484      1.1        is int
    485      1.1        is rep_halt_output(void *arg)
    486      1.1        is {
    487      1.1        is 	struct repulse_softc *sc = arg;
    488      1.1        is 	struct repulse_hw *bp = sc->sc_boardp;
    489      1.1        is 
    490      1.1        is 	bp->rhw_status &= ~(REPSTATUS_PLAYIRQENABLE|REPSTATUS_PLAY);
    491      1.1        is 
    492      1.1        is 
    493      1.1        is 	return 0;
    494      1.1        is }
    495      1.1        is 
    496      1.1        is int
    497      1.1        is rep_halt_input(void *arg)
    498      1.1        is {
    499      1.1        is 	struct repulse_softc *sc = arg;
    500      1.1        is 	struct repulse_hw *bp = sc->sc_boardp;
    501      1.1        is 
    502      1.1        is 	bp->rhw_status &= ~(REPSTATUS_RECIRQENABLE|REPSTATUS_RECORD);
    503      1.1        is 
    504      1.1        is 	return 0;
    505      1.1        is }
    506      1.1        is 
    507      1.1        is /*
    508      1.1        is  * Encoding support.
    509      1.1        is  *
    510      1.1        is  * TODO: add 24bit and 32bit modes here and in setparams.
    511      1.1        is  */
    512      1.1        is 
    513      1.1        is const struct repulse_encoding_query {
    514      1.1        is 	const char *name;
    515      1.1        is 	int encoding, precision, flags;
    516      1.1        is } rep_encoding_queries[] = {
    517      1.1        is 	{ AudioEulinear, AUDIO_ENCODING_ULINEAR, 8, 0},
    518      1.1        is 	{ AudioEmulaw,	AUDIO_ENCODING_ULAW, 8, AUDIO_ENCODINGFLAG_EMULATED},
    519      1.1        is 	{ AudioEalaw,	AUDIO_ENCODING_ALAW, 8, AUDIO_ENCODINGFLAG_EMULATED},
    520      1.1        is 	{ AudioEslinear, AUDIO_ENCODING_SLINEAR, 8, 0},
    521      1.1        is 	{ AudioEslinear_le, AUDIO_ENCODING_SLINEAR_LE, 16, 0},
    522      1.1        is 	{ AudioEulinear_le, AUDIO_ENCODING_ULINEAR_LE, 16, 0},
    523      1.1        is 	{ AudioEulinear_be, AUDIO_ENCODING_ULINEAR_BE, 16, 0},
    524      1.1        is 	{ AudioEslinear_be, AUDIO_ENCODING_SLINEAR_BE, 16, 0},
    525      1.1        is };
    526      1.1        is 
    527      1.1        is int
    528      1.1        is rep_query_encoding(void *arg, struct audio_encoding *fp)
    529      1.1        is {
    530      1.1        is 	int i;
    531      1.1        is 	const struct repulse_encoding_query *p;
    532      1.1        is 
    533      1.1        is 	i = fp->index;
    534      1.1        is 
    535      1.1        is 	if (i >= sizeof(rep_encoding_queries) /
    536      1.1        is 	    sizeof(struct repulse_encoding_query))
    537      1.1        is 		return (EINVAL);
    538      1.1        is 
    539      1.1        is 	p = &rep_encoding_queries[i];
    540      1.1        is 
    541      1.1        is 	strncpy (fp->name, p->name, sizeof(fp->name));
    542      1.1        is 	fp->encoding = p->encoding;
    543      1.1        is 	fp->precision = p->precision;
    544      1.1        is 	fp->flags = p->flags;
    545      1.1        is 
    546      1.1        is 	return (0);
    547      1.1        is }
    548      1.1        is 
    549      1.1        is /*
    550      1.1        is  * XXX the following three functions need to be enhanced for the FPGA s/pdif
    551      1.1        is  * mode. Generic ac97 versions for now.
    552      1.1        is  */
    553      1.1        is 
    554      1.3   aymeric int
    555      1.1        is rep_get_port(void *arg, mixer_ctrl_t *cp)
    556      1.1        is {
    557      1.1        is 	struct repulse_softc *sc = arg;
    558      1.1        is 
    559      1.1        is 	return (sc->sc_codec_if->vtbl->mixer_get_port(sc->sc_codec_if, cp));
    560      1.1        is }
    561      1.1        is 
    562      1.3   aymeric int
    563      1.1        is rep_set_port(void *arg, mixer_ctrl_t *cp)
    564      1.1        is {
    565      1.1        is 	struct repulse_softc *sc = arg;
    566      1.1        is 
    567      1.1        is 	return (sc->sc_codec_if->vtbl->mixer_set_port(sc->sc_codec_if, cp));
    568      1.1        is }
    569      1.1        is 
    570      1.1        is int
    571      1.1        is rep_query_devinfo (void *arg, mixer_devinfo_t *dip)
    572      1.1        is {
    573      1.1        is 	struct repulse_softc *sc = arg;
    574      1.1        is 
    575      1.1        is 	return (sc->sc_codec_if->vtbl->query_devinfo(sc->sc_codec_if, dip));
    576      1.1        is }
    577      1.1        is 
    578      1.1        is int
    579      1.1        is rep_round_blocksize(void *arg, int blk)
    580      1.1        is {
    581      1.1        is 	int b1;
    582      1.1        is 
    583      1.1        is 	b1 = (blk & -32);
    584      1.1        is 
    585      1.1        is 	if (b1 > 65536 / 2 / 2 /* channels */ / 4 /* bytes per channel */)
    586      1.1        is 		b1 =  65536 / 2 / 2 / 4;
    587      1.1        is 	return (b1);
    588      1.1        is }
    589      1.1        is 
    590      1.3   aymeric size_t
    591      1.1        is rep_round_buffersize(void *arg, int direction, size_t size)
    592      1.1        is {
    593      1.1        is 	return size;
    594      1.1        is }
    595      1.1        is 
    596      1.1        is 
    597      1.1        is int
    598      1.1        is rep_set_params(void *addr, int setmode, int usemode,
    599      1.1        is 	struct audio_params *play, struct audio_params *rec)
    600      1.1        is {
    601      1.1        is 	struct repulse_softc *sc = addr;
    602      1.1        is 	struct audio_params *p;
    603      1.1        is 	int mode, reg;
    604      1.1        is 	unsigned  flags;
    605      1.1        is 	u_int16_t a;
    606      1.1        is 
    607      1.1        is 	/* for mode in (RECORD, PLAY) */
    608      1.1        is 	for (mode = AUMODE_RECORD; mode != -1;
    609      1.1        is 	    mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
    610      1.1        is 
    611      1.1        is 		if ((setmode & mode) == 0)
    612      1.1        is 		     continue;
    613      1.1        is 
    614      1.1        is 		p = mode == AUMODE_PLAY ? play : rec;
    615      1.1        is 
    616      1.1        is 		/* TODO XXX we can do upto 32bit, 96000 */
    617      1.1        is 		if (p->sample_rate < 4000 || p->sample_rate > 48000 ||
    618      1.1        is 		    (p->precision != 8 && p->precision != 16) ||
    619      1.1        is 		    (p->channels != 1 && p->channels != 2))
    620      1.1        is 			return (EINVAL);
    621      1.1        is 
    622      1.1        is 		reg = mode == AUMODE_PLAY ?
    623      1.1        is 			AC97_REG_PCM_FRONT_DAC_RATE : AC97_REG_PCM_LR_ADC_RATE;
    624      1.1        is 
    625      1.1        is 		repac_write(sc, reg, (u_int16_t) p->sample_rate);
    626      1.1        is 		repac_read(sc, reg, &a);
    627      1.1        is 		p->sample_rate = a;
    628      1.1        is 
    629      1.1        is 		if (mode == AUMODE_PLAY)
    630      1.1        is 			sc->sc_playscale = p->channels * p->precision / 8;
    631      1.1        is 		else
    632      1.1        is 			sc->sc_captscale = p->channels * p->precision / 8;
    633      1.1        is 
    634      1.1        is 		p->factor = 1;
    635      1.1        is 		p->sw_code = 0;
    636      1.1        is 
    637      1.1        is 		/* everything else is software, alas... */
    638      1.1        is 		/* XXX TBD signed/unsigned, *law, etc */
    639      1.1        is 
    640      1.1        is 		flags = 0;
    641      1.1        is 		if (p->encoding == AUDIO_ENCODING_ULINEAR_LE ||
    642      1.1        is 		    p->encoding == AUDIO_ENCODING_ULINEAR_BE ||
    643      1.1        is 		    p->encoding == AUDIO_ENCODING_ULINEAR)
    644      1.1        is 			flags |= 1;
    645      1.1        is 
    646      1.1        is 		if (p->encoding == AUDIO_ENCODING_SLINEAR_LE ||
    647      1.1        is 		    p->encoding == AUDIO_ENCODING_ULINEAR_LE)
    648      1.1        is 			flags |= 2;
    649      1.1        is 
    650      1.1        is 		if (mode == AUMODE_PLAY) {
    651      1.1        is 			sc->sc_playflags = flags;
    652      1.1        is 			if (p->encoding == AUDIO_ENCODING_ULAW) {
    653      1.1        is 				sc->sc_playfun = p->channels == 1 ?
    654      1.1        is 					rep_write_16_mono :
    655      1.1        is 					rep_write_16_stereo;
    656      1.1        is 				sc->sc_playflags = 0;
    657      1.1        is 				sc->sc_playscale = p->channels * 2;
    658      1.1        is 				p->sw_code = mulaw_to_slinear16_be;
    659      1.1        is 				p->factor = 2;
    660      1.1        is 			} else
    661      1.1        is 			if (p->encoding == AUDIO_ENCODING_ALAW) {
    662      1.1        is 				sc->sc_playfun = p->channels == 1 ?
    663      1.1        is 					rep_write_16_mono :
    664      1.1        is 					rep_write_16_stereo;
    665      1.1        is 				sc->sc_playflags = 0;
    666      1.1        is 				sc->sc_playscale = p->channels * 2;
    667      1.1        is 				p->sw_code = alaw_to_slinear16_be;
    668      1.1        is 				p->factor = 2;
    669      1.1        is 			} else
    670      1.1        is 			if (p->precision == 8 && p->channels == 1)
    671      1.1        is 				sc->sc_playfun = rep_write_8_mono;
    672      1.1        is 			else if (p->precision == 8 && p->channels == 2)
    673      1.1        is 				sc->sc_playfun = rep_write_8_stereo;
    674      1.1        is 			else if (p->precision == 16 && p->channels == 1)
    675      1.1        is 				sc->sc_playfun = rep_write_16_mono;
    676      1.1        is 			else if (p->precision == 16 && p->channels == 2)
    677      1.1        is 				sc->sc_playfun = rep_write_16_stereo;
    678      1.1        is 		} else {
    679      1.1        is 			sc->sc_captflags = flags;
    680      1.1        is 			if (p->encoding == AUDIO_ENCODING_ULAW) {
    681      1.1        is 				sc->sc_captfun = p->channels == 1 ?
    682      1.1        is 					rep_read_8_mono :
    683      1.1        is 					rep_read_8_stereo;
    684      1.1        is 				sc->sc_captflags = 0;
    685      1.1        is 				p->sw_code = slinear8_to_mulaw;
    686      1.1        is 				p->factor = 1;
    687      1.1        is 			} else
    688      1.1        is 			if (p->encoding == AUDIO_ENCODING_ALAW) {
    689      1.1        is 				sc->sc_captfun = p->channels == 1 ?
    690      1.1        is 					rep_read_8_mono :
    691      1.1        is 					rep_read_8_stereo;
    692      1.1        is 				sc->sc_captflags = 0;
    693      1.1        is 				p->sw_code = slinear8_to_alaw;
    694      1.1        is 				p->factor = 1;
    695      1.1        is 			} else
    696      1.1        is 			if (p->precision == 8 && p->channels == 1)
    697      1.1        is 				sc->sc_captfun = rep_read_8_mono;
    698      1.1        is 			else if (p->precision == 8 && p->channels == 2)
    699      1.1        is 				sc->sc_captfun = rep_read_8_stereo;
    700      1.1        is 			else if (p->precision == 16 && p->channels == 1)
    701      1.1        is 				sc->sc_captfun = rep_read_16_mono;
    702      1.1        is 			else if (p->precision == 16 && p->channels == 2)
    703      1.1        is 				sc->sc_captfun = rep_read_16_stereo;
    704      1.1        is 		}
    705      1.8       wiz 		/* TBD: mu-law, A-law */
    706      1.1        is 	}
    707      1.3   aymeric 	return 0;
    708      1.1        is }
    709      1.1        is 
    710      1.1        is void
    711      1.1        is rep_write_8_mono(struct repulse_hw *bp, u_int8_t *p, int length,
    712      1.1        is 	unsigned flags)
    713      1.1        is {
    714      1.1        is 	u_int16_t sample;
    715      1.1        is 	u_int16_t xor;
    716      1.1        is 
    717      1.1        is 	xor = flags & 1 ? 0x8000 : 0;
    718      1.1        is 
    719      1.1        is 	bp->rhw_fifo_pack = 0;
    720      1.1        is 
    721      1.1        is 	while (length-- > 0) {
    722      1.1        is 		sample = ((*p++) << 8) ^ xor;
    723      1.1        is 		bp->rhw_fifo_lh = sample;
    724      1.1        is 		bp->rhw_fifo_rh = sample;
    725      1.1        is 	}
    726      1.1        is }
    727      1.1        is 
    728      1.1        is void
    729      1.1        is rep_write_8_stereo(struct repulse_hw *bp, u_int8_t *p, int length,
    730      1.1        is 	unsigned flags)
    731      1.1        is {
    732      1.1        is 	u_int16_t xor;
    733      1.1        is 
    734      1.1        is 	xor = flags & 1 ? 0x8000 : 0;
    735      1.1        is 
    736      1.1        is 	bp->rhw_fifo_pack = 0;
    737      1.1        is 
    738      1.1        is 	while (length-- > 0) {
    739      1.1        is 		bp->rhw_fifo_lh = ((*p++) << 8) ^ xor;
    740      1.1        is 		bp->rhw_fifo_rh = ((*p++) << 8) ^ xor;
    741      1.1        is 	}
    742      1.1        is }
    743      1.1        is 
    744      1.1        is void
    745      1.1        is rep_write_16_mono(struct repulse_hw *bp, u_int8_t *p, int length,
    746      1.1        is 	unsigned flags)
    747      1.1        is {
    748      1.1        is 	u_int16_t *q = (u_int16_t *)p;
    749      1.1        is 	u_int16_t sample;
    750      1.1        is 	u_int16_t xor;
    751      1.1        is 
    752      1.1        is 	xor = flags & 1 ? 0x8000 : 0;
    753      1.1        is 
    754      1.1        is 	bp->rhw_fifo_pack = 0;
    755      1.1        is 
    756      1.1        is 	if (flags & 2) {
    757      1.1        is 		while (length > 0) {
    758      1.1        is 			sample = bswap16(*q++) ^ xor;
    759      1.1        is 			bp->rhw_fifo_lh = sample;
    760      1.1        is 			bp->rhw_fifo_rh = sample;
    761      1.1        is 			length -= 2;
    762      1.1        is 		}
    763      1.1        is 		return;
    764      1.1        is 	}
    765      1.1        is 
    766      1.1        is 	while (length > 0) {
    767      1.1        is 		sample = (*q++) ^ xor;
    768      1.1        is 		bp->rhw_fifo_lh = sample;
    769      1.1        is 		bp->rhw_fifo_rh = sample;
    770      1.1        is 		length -= 2;
    771      1.1        is 	}
    772      1.1        is }
    773      1.1        is 
    774      1.1        is void
    775      1.1        is rep_write_16_stereo(struct repulse_hw *bp, u_int8_t *p, int length,
    776      1.1        is 	unsigned flags)
    777      1.1        is {
    778      1.1        is 	u_int16_t *q = (u_int16_t *)p;
    779      1.1        is 	u_int16_t xor;
    780      1.1        is 
    781      1.1        is 	xor = flags & 1 ? 0x8000 : 0;
    782      1.1        is 
    783      1.1        is 	bp->rhw_fifo_pack = 0;
    784      1.1        is 
    785      1.1        is 	if (flags & 2) {
    786      1.1        is 		while (length > 0) {
    787      1.1        is 			bp->rhw_fifo_lh = bswap16(*q++) ^ xor;
    788      1.1        is 			bp->rhw_fifo_rh = bswap16(*q++) ^ xor;
    789      1.1        is 			length -= 4;
    790      1.1        is 		}
    791      1.1        is 		return;
    792      1.1        is 	}
    793      1.1        is 	while (length > 0) {
    794      1.1        is 		bp->rhw_fifo_lh = (*q++) ^ xor;
    795      1.1        is 		bp->rhw_fifo_rh = (*q++) ^ xor;
    796      1.1        is 		length -= 4;
    797      1.1        is 	}
    798      1.1        is }
    799      1.1        is 
    800      1.1        is void
    801      1.1        is rep_read_8_mono(struct	repulse_hw  *bp, u_int8_t *p, int length,
    802      1.1        is 	unsigned flags)
    803      1.1        is {
    804      1.1        is 	u_int16_t v;
    805      1.1        is 	u_int16_t xor;
    806      1.1        is 
    807      1.1        is 	xor = flags & 1 ? 0x8000 : 0;
    808      1.1        is 
    809      1.1        is 	while (length > 0) {
    810      1.1        is 		*p++ = (bp->rhw_fifo_lh ^ xor) >> 8;
    811      1.1        is 		v    = bp->rhw_fifo_rh;
    812      1.1        is 		length--;
    813      1.1        is 	}
    814      1.1        is }
    815      1.1        is 
    816      1.1        is void
    817      1.1        is rep_read_16_mono(struct	 repulse_hw  *bp, u_int8_t *p, int length,
    818      1.1        is 	unsigned flags)
    819      1.1        is {
    820      1.1        is 	u_int16_t *q = (u_int16_t *)p;
    821      1.1        is 	u_int16_t v;
    822      1.1        is 	u_int16_t xor;
    823      1.1        is 
    824      1.1        is 	xor = flags & 1 ? 0x8000 : 0;
    825      1.1        is 
    826      1.1        is 	if (flags & 2) {
    827      1.1        is 		while (length > 0) {
    828      1.1        is 			*q++ = bswap16(bp->rhw_fifo_lh ^ xor);
    829      1.1        is 			v    = bp->rhw_fifo_rh;
    830      1.1        is 			length -= 2;
    831      1.1        is 		}
    832      1.1        is 		return;
    833      1.1        is 	}
    834      1.1        is 
    835      1.1        is 	while (length > 0) {
    836      1.1        is 		*q++ = bp->rhw_fifo_lh ^ xor;
    837      1.1        is 		v    = bp->rhw_fifo_rh;
    838      1.1        is 		length -= 2;
    839      1.1        is 	}
    840      1.1        is }
    841      1.1        is 
    842      1.1        is void
    843      1.1        is rep_read_8_stereo(struct  repulse_hw  *bp, u_int8_t *p, int length,
    844      1.1        is 	unsigned flags)
    845      1.1        is {
    846      1.1        is 	u_int16_t xor;
    847      1.1        is 
    848      1.1        is 	xor = flags & 1 ? 0x8000 : 0;
    849      1.1        is 	while (length > 0) {
    850      1.1        is 		*p++ = (bp->rhw_fifo_lh ^ xor) >> 8;
    851      1.1        is 		*p++ = (bp->rhw_fifo_rh ^ xor) >> 8;
    852      1.1        is 		length -= 2;
    853      1.1        is 	}
    854      1.1        is }
    855      1.1        is 
    856      1.1        is void
    857      1.1        is rep_read_16_stereo(struct  repulse_hw  *bp, u_int8_t *p, int length,
    858      1.1        is 	unsigned flags)
    859      1.1        is {
    860      1.1        is 	u_int16_t *q = (u_int16_t *)p;
    861      1.1        is 	u_int16_t xor;
    862      1.1        is 
    863      1.1        is 	xor = flags & 1 ? 0x8000 : 0;
    864      1.1        is 
    865      1.1        is 	if (flags & 2) {
    866      1.1        is 		while (length > 0) {
    867      1.1        is 			*q++ = bswap16(bp->rhw_fifo_lh ^ xor);
    868      1.1        is 			*q++ = bswap16(bp->rhw_fifo_rh ^ xor);
    869      1.1        is 			length -= 4;
    870      1.1        is 		}
    871      1.1        is 		return;
    872      1.1        is 	}
    873      1.1        is 	while (length > 0) {
    874      1.1        is 		*q++ = bp->rhw_fifo_lh ^ xor;
    875      1.1        is 		*q++ = bp->rhw_fifo_rh ^ xor;
    876      1.1        is 		length -= 4;
    877      1.1        is 	}
    878      1.1        is }
    879      1.1        is 
    880      1.1        is /*
    881      1.1        is  * At this point the transfer function is set.
    882      1.1        is  */
    883      1.1        is 
    884      1.1        is int
    885      1.1        is rep_start_output(void *addr, void *block, int blksize,
    886      1.3   aymeric 	void (*intr)(void*), void *intrarg) {
    887      1.1        is 
    888      1.1        is 	struct repulse_softc *sc;
    889      1.1        is 	u_int8_t *buf;
    890      1.1        is 	struct repulse_hw *bp;
    891      1.1        is 	u_int16_t status;
    892      1.1        is 
    893      1.1        is 
    894      1.1        is 	sc = addr;
    895      1.1        is 	bp = sc->sc_boardp;
    896      1.1        is 	buf = block;
    897      1.1        is 
    898      1.1        is 	/* TODO: prepare hw if necessary */
    899      1.1        is 	status = bp->rhw_status;
    900      1.1        is 	if (!(status & REPSTATUS_PLAY))
    901      1.1        is 		bp->rhw_status = status |
    902      1.1        is 		    REPSTATUS_PLAY | REPSTATUS_PLAYFIFORST;
    903      1.1        is 
    904      1.1        is 	/* copy data */
    905      1.1        is 	(*sc->sc_playfun)(bp, buf, blksize, sc->sc_playflags);
    906      1.1        is 
    907      1.1        is 	/* TODO: set hw if necessary */
    908      1.1        is 	if (intr) {
    909      1.1        is 		bp->rhw_status |= REPSTATUS_PLAYIRQENABLE;
    910      1.1        is 		bp->rhw_play_fifosz = blksize / sc->sc_playscale / 2;
    911      1.1        is 		/* /2: give us time to return on the first call */
    912      1.1        is 	}
    913      1.1        is 
    914      1.1        is 	/* save callback function */
    915      1.1        is 	sc->sc_playarg = intrarg;
    916      1.1        is 	sc->sc_playmore = intr;
    917      1.1        is 
    918      1.1        is 	return 0;
    919      1.1        is }
    920      1.1        is 
    921      1.1        is int
    922      1.1        is rep_start_input(void *addr, void *block, int blksize,
    923      1.3   aymeric 	void (*intr)(void*), void *intrarg) {
    924      1.1        is 
    925      1.1        is 	struct repulse_softc *sc;
    926      1.1        is 	struct repulse_hw *bp;
    927      1.1        is 	u_int16_t status;
    928      1.1        is 
    929      1.1        is 	sc = addr;
    930      1.1        is 	bp = sc->sc_boardp;
    931      1.1        is 
    932      1.1        is 	sc->sc_captbuf = block;
    933      1.1        is 	sc->sc_captbufsz = blksize;
    934      1.1        is 	sc->sc_captarg = intrarg;
    935      1.1        is 	sc->sc_captmore = intr;
    936      1.1        is 
    937      1.1        is 	status = bp->rhw_status;
    938      1.1        is 	if (!(status & REPSTATUS_RECORD))
    939      1.1        is 		bp->rhw_status = status | REPSTATUS_RECORD
    940      1.1        is 			| REPSTATUS_RECFIFORST;
    941      1.1        is 
    942      1.1        is 	bp->rhw_status |= REPSTATUS_RECIRQENABLE;
    943      1.1        is 	bp->rhw_capt_fifosz = blksize / sc->sc_captscale;
    944      1.1        is 
    945      1.1        is 	return 0;
    946      1.1        is }
    947      1.1        is 
    948      1.1        is /* irq handler */
    949      1.1        is 
    950      1.1        is int
    951      1.1        is rep_intr(void *tag) {
    952      1.1        is 	struct repulse_softc *sc;
    953      1.1        is 	struct repulse_hw *bp;
    954      1.1        is 	int foundone;
    955      1.1        is 	u_int16_t status;
    956      1.1        is 
    957      1.1        is 	foundone = 0;
    958      1.1        is 
    959      1.1        is 	sc = tag;
    960      1.1        is 	bp = sc->sc_boardp;
    961      1.1        is 	status = bp->rhw_status;
    962      1.1        is 
    963      1.1        is 	if (status & REPSTATUS_PLAYIRQACK) {
    964      1.1        is 		foundone = 1;
    965      1.1        is 		status &= ~REPSTATUS_PLAYIRQENABLE;
    966      1.1        is 		bp->rhw_status = status;
    967      1.1        is 		(*sc->sc_playmore)(sc->sc_playarg);
    968      1.1        is 	}
    969      1.1        is 
    970      1.1        is 	if (status & REPSTATUS_RECIRQACK) {
    971      1.1        is 		foundone = 1;
    972      1.1        is 		status &= ~REPSTATUS_RECIRQENABLE;
    973      1.1        is 		bp->rhw_status = status;
    974      1.1        is 		(*sc->sc_captfun)(bp, sc->sc_captbuf, sc->sc_captbufsz,
    975      1.1        is 			sc->sc_captflags);
    976      1.1        is 		(*sc->sc_captmore)(sc->sc_captarg);
    977      1.1        is 	}
    978      1.1        is 
    979      1.1        is 	return foundone;
    980      1.1        is }
    981