Home | History | Annotate | Line # | Download | only in vr
vraiu.c revision 1.15.38.2
      1  1.15.38.2    martin /*	$NetBSD: vraiu.c,v 1.15.38.2 2020/04/08 14:07:39 martin Exp $	*/
      2        1.1  hamajima 
      3        1.1  hamajima /*
      4        1.1  hamajima  * Copyright (c) 2001 HAMAJIMA Katsuomi. All rights reserved.
      5        1.1  hamajima  *
      6        1.1  hamajima  * Redistribution and use in source and binary forms, with or without
      7        1.1  hamajima  * modification, are permitted provided that the following conditions
      8        1.1  hamajima  * are met:
      9        1.1  hamajima  * 1. Redistributions of source code must retain the above copyright
     10        1.1  hamajima  *    notice, this list of conditions and the following disclaimer.
     11        1.1  hamajima  * 2. Redistributions in binary form must reproduce the above copyright
     12        1.1  hamajima  *    notice, this list of conditions and the following disclaimer in the
     13        1.1  hamajima  *    documentation and/or other materials provided with the distribution.
     14        1.1  hamajima  *
     15        1.1  hamajima  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     16        1.1  hamajima  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     17        1.1  hamajima  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     18        1.1  hamajima  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     19        1.1  hamajima  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     20        1.1  hamajima  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     21        1.1  hamajima  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22        1.1  hamajima  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     23        1.1  hamajima  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     24        1.1  hamajima  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     25        1.1  hamajima  * SUCH DAMAGE.
     26        1.1  hamajima  */
     27        1.6     lukem 
     28        1.6     lukem #include <sys/cdefs.h>
     29  1.15.38.2    martin __KERNEL_RCSID(0, "$NetBSD: vraiu.c,v 1.15.38.2 2020/04/08 14:07:39 martin Exp $");
     30        1.1  hamajima 
     31        1.1  hamajima #include <sys/param.h>
     32        1.1  hamajima #include <sys/systm.h>
     33        1.1  hamajima #include <sys/device.h>
     34        1.1  hamajima #include <sys/bswap.h>
     35        1.1  hamajima 
     36        1.1  hamajima #include <machine/cpu.h>
     37        1.1  hamajima #include <machine/intr.h>
     38        1.1  hamajima #include <machine/bus.h>
     39        1.1  hamajima #include <machine/platid.h>
     40        1.1  hamajima #include <machine/platid_mask.h>
     41        1.1  hamajima #include <machine/config_hook.h>
     42        1.1  hamajima 
     43        1.1  hamajima #include <sys/audioio.h>
     44  1.15.38.1  christos #include <dev/audio/audio_if.h>
     45        1.1  hamajima 
     46        1.1  hamajima #include <hpcmips/vr/vr.h>
     47        1.1  hamajima #include <hpcmips/vr/vripif.h>
     48        1.1  hamajima #include <hpcmips/vr/icureg.h>
     49        1.1  hamajima #include <hpcmips/vr/cmureg.h>
     50        1.1  hamajima #include <hpcmips/vr/vraiureg.h>
     51        1.1  hamajima 
     52        1.1  hamajima #ifdef VRAIU_DEBUG
     53        1.1  hamajima int vraiu_debug = VRAIU_DEBUG;
     54        1.1  hamajima #define DPRINTFN(n,x) if (vraiu_debug>(n)) printf x;
     55        1.1  hamajima #else
     56        1.1  hamajima #define DPRINTFN(n,x)
     57        1.1  hamajima #endif
     58        1.1  hamajima 
     59        1.1  hamajima #define AUDIO_BUF_SIZE 2048
     60        1.1  hamajima 
     61        1.1  hamajima struct vraiu_softc {
     62       1.15       chs 	device_t		sc_dev;
     63       1.13  jmcneill 	kmutex_t		sc_lock;
     64       1.13  jmcneill 	kmutex_t		sc_intr_lock;
     65        1.1  hamajima 	bus_space_tag_t		sc_iot;
     66        1.1  hamajima 	bus_space_handle_t	sc_ioh;
     67        1.1  hamajima 	bus_dma_tag_t		sc_dmat;
     68        1.1  hamajima 	bus_dmamap_t		sc_dmap;
     69        1.1  hamajima 	vrip_chipset_tag_t	sc_vrip;
     70        1.1  hamajima 	vrdcu_chipset_tag_t	sc_dc;
     71        1.1  hamajima 	vrdmaau_chipset_tag_t	sc_ac;
     72        1.1  hamajima 	vrcmu_chipset_tag_t	sc_cc;
     73        1.1  hamajima 	void			*sc_handler;
     74        1.5       wiz 	u_short	*sc_buf;	/* DMA buffer pointer */
     75        1.1  hamajima 	u_int	sc_rate;	/* sampling rate */
     76        1.7  jmcneill 	u_char	sc_volume;	/* volume */
     77        1.1  hamajima 	void	(*sc_intr)(void *);	/* interrupt routine */
     78        1.1  hamajima 	void	*sc_intrdata;		/* interrupt data */
     79        1.1  hamajima };
     80        1.1  hamajima 
     81       1.15       chs int vraiu_match(device_t, cfdata_t, void *);
     82       1.15       chs void vraiu_attach(device_t, device_t, void *);
     83        1.1  hamajima int vraiu_intr(void *);
     84        1.1  hamajima 
     85       1.15       chs CFATTACH_DECL_NEW(vraiu, sizeof(struct vraiu_softc),
     86        1.3   thorpej     vraiu_match, vraiu_attach, NULL, NULL);
     87        1.1  hamajima 
     88        1.1  hamajima struct audio_device aiu_device = {
     89        1.1  hamajima 	"VR4121 AIU",
     90        1.1  hamajima 	"0.1",
     91        1.1  hamajima 	"aiu"
     92        1.1  hamajima };
     93        1.1  hamajima 
     94  1.15.38.1  christos const struct audio_format vraiu_formats = {
     95  1.15.38.1  christos 	.mode		= AUMODE_PLAY,
     96  1.15.38.1  christos 	.encoding	= AUDIO_ENCODING_SLINEAR_NE,
     97  1.15.38.1  christos 	.validbits	= 10,
     98  1.15.38.1  christos 	.precision	= 16,
     99  1.15.38.1  christos 	.channels	= 1,
    100  1.15.38.1  christos 	.channel_mask	= AUFMT_MONAURAL,
    101  1.15.38.1  christos 	.frequency_type	= 4,
    102  1.15.38.1  christos 	.frequency	= { 8000, 11025, 22050, 44100 },
    103  1.15.38.1  christos };
    104  1.15.38.1  christos 
    105        1.1  hamajima /*
    106        1.1  hamajima  * Define our interface to the higher level audio driver.
    107        1.1  hamajima  */
    108  1.15.38.1  christos int vraiu_query_format(void *, audio_format_query_t *);
    109        1.9      kent int vraiu_round_blocksize(void *, int, int, const audio_params_t *);
    110        1.1  hamajima int vraiu_commit_settings(void *);
    111        1.1  hamajima int vraiu_init_output(void *, void*, int);
    112        1.1  hamajima int vraiu_start_output(void *, void *, int, void (*)(void *), void *);
    113        1.1  hamajima int vraiu_halt_output(void *);
    114        1.1  hamajima int vraiu_getdev(void *, struct audio_device *);
    115        1.1  hamajima int vraiu_set_port(void *, mixer_ctrl_t *);
    116        1.1  hamajima int vraiu_get_port(void *, mixer_ctrl_t *);
    117        1.1  hamajima int vraiu_query_devinfo(void *, mixer_devinfo_t *);
    118  1.15.38.1  christos int vraiu_set_format(void *, int,
    119  1.15.38.1  christos     const audio_params_t *, const audio_params_t *,
    120  1.15.38.1  christos     audio_filter_reg_t *, audio_filter_reg_t *);
    121        1.1  hamajima int vraiu_get_props(void *);
    122       1.13  jmcneill void vraiu_get_locks(void *, kmutex_t **, kmutex_t **);
    123        1.1  hamajima 
    124        1.8      yamt const struct audio_hw_if vraiu_hw_if = {
    125  1.15.38.1  christos 	.query_format		= vraiu_query_format,
    126  1.15.38.1  christos 	.set_format		= vraiu_set_format,
    127  1.15.38.1  christos 	.round_blocksize	= vraiu_round_blocksize,
    128  1.15.38.1  christos 	.commit_settings	= vraiu_commit_settings,
    129  1.15.38.1  christos 	.init_output		= vraiu_init_output,
    130  1.15.38.1  christos 	.start_output		= vraiu_start_output,
    131  1.15.38.1  christos 	.halt_output		= vraiu_halt_output,
    132  1.15.38.1  christos 	.getdev			= vraiu_getdev,
    133  1.15.38.1  christos 	.set_port		= vraiu_set_port,
    134  1.15.38.1  christos 	.get_port		= vraiu_get_port,
    135  1.15.38.1  christos 	.query_devinfo		= vraiu_query_devinfo,
    136  1.15.38.1  christos 	.get_props		= vraiu_get_props,
    137  1.15.38.1  christos 	.get_locks		= vraiu_get_locks,
    138        1.1  hamajima };
    139        1.1  hamajima 
    140        1.1  hamajima /*
    141        1.1  hamajima  * convert to 1ch 10bit unsigned PCM data.
    142        1.1  hamajima  */
    143        1.1  hamajima static void vraiu_slinear16_1(struct vraiu_softc *, u_short *, void *, int);
    144        1.1  hamajima 
    145        1.1  hamajima int
    146       1.15       chs vraiu_match(device_t parent, cfdata_t cf, void *aux)
    147        1.1  hamajima {
    148        1.1  hamajima 	return 1;
    149        1.1  hamajima }
    150        1.1  hamajima 
    151        1.1  hamajima void
    152       1.15       chs vraiu_attach(device_t parent, device_t self, void *aux)
    153        1.1  hamajima {
    154       1.10      kent 	struct vrip_attach_args *va;
    155       1.10      kent 	struct vraiu_softc *sc;
    156        1.1  hamajima 	bus_dma_segment_t segs;
    157        1.1  hamajima 	int rsegs;
    158        1.1  hamajima 
    159       1.10      kent 	va = aux;
    160       1.15       chs 	sc = device_private(self);
    161       1.15       chs 	sc->sc_dev = self;
    162        1.1  hamajima 	sc->sc_intr = NULL;
    163        1.1  hamajima 	sc->sc_iot = va->va_iot;
    164        1.1  hamajima 	sc->sc_vrip = va->va_vc;
    165        1.1  hamajima 	sc->sc_cc = va->va_cc;
    166        1.1  hamajima 	sc->sc_dc = va->va_dc;
    167        1.1  hamajima 	sc->sc_ac = va->va_ac;
    168        1.1  hamajima 	sc->sc_dmat = &vrdcu_bus_dma_tag;
    169        1.7  jmcneill 	sc->sc_volume = 127;
    170       1.13  jmcneill 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
    171       1.14       mrg 	mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO);
    172        1.1  hamajima 
    173        1.1  hamajima 	if (!sc->sc_cc) {
    174        1.1  hamajima 		printf(" not configured: cmu not found\n");
    175        1.1  hamajima 		return;
    176        1.1  hamajima 	}
    177        1.1  hamajima 	if (!sc->sc_dc) {
    178        1.1  hamajima 		printf(" not configured: dcu not found\n");
    179        1.1  hamajima 		return;
    180        1.1  hamajima 	}
    181        1.1  hamajima 	if (!sc->sc_ac) {
    182        1.1  hamajima 		printf(" not configured: dmaau not found\n");
    183        1.1  hamajima 		return;
    184        1.1  hamajima 	}
    185        1.1  hamajima 	if (bus_space_map(sc->sc_iot, va->va_addr, va->va_size,
    186        1.1  hamajima 			  0 /* no flags */, &sc->sc_ioh)) {
    187        1.1  hamajima 		printf(": can't map i/o space\n");
    188        1.1  hamajima 		return;
    189        1.1  hamajima 	}
    190        1.1  hamajima 
    191        1.1  hamajima 	/* install interrupt handler and enable interrupt */
    192        1.1  hamajima 	if (!(sc->sc_handler = vrip_intr_establish(va->va_vc, va->va_unit,
    193       1.14       mrg 	    0, IPL_AUDIO, vraiu_intr, sc))) {
    194        1.1  hamajima 		printf(": can't map interrupt line.\n");
    195        1.1  hamajima 		return;
    196        1.1  hamajima 	}
    197        1.1  hamajima 	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, (AIUINT_INTMEND | \
    198        1.1  hamajima 							 AIUINT_INTM | \
    199        1.1  hamajima 							 AIUINT_INTMIDLE | \
    200        1.1  hamajima 							 AIUINT_INTMST | \
    201        1.1  hamajima 							 AIUINT_INTSEND | \
    202        1.1  hamajima 							 AIUINT_INTS | \
    203        1.1  hamajima 							 AIUINT_INTSIDLE), 0);
    204        1.1  hamajima 
    205        1.1  hamajima 	if (bus_dmamem_alloc(sc->sc_dmat, AUDIO_BUF_SIZE, 0, 0, &segs, 1,
    206       1.13  jmcneill 			     &rsegs, BUS_DMA_WAITOK)) {
    207        1.1  hamajima 		printf(": can't allocate memory.\n");
    208        1.1  hamajima 		return;
    209        1.1  hamajima 	}
    210        1.1  hamajima 	if (bus_dmamem_map(sc->sc_dmat, &segs, rsegs, AUDIO_BUF_SIZE,
    211       1.12  christos 			   (void **)&sc->sc_buf,
    212       1.13  jmcneill 			   BUS_DMA_WAITOK | BUS_DMA_COHERENT)) {
    213        1.1  hamajima 		printf(": can't map memory.\n");
    214        1.1  hamajima 		bus_dmamem_free(sc->sc_dmat, &segs, rsegs);
    215        1.1  hamajima 		return;
    216        1.1  hamajima 	}
    217        1.1  hamajima 	if (bus_dmamap_create(sc->sc_dmat, AUDIO_BUF_SIZE, 1, AUDIO_BUF_SIZE,
    218       1.13  jmcneill 			      0, BUS_DMA_WAITOK, &sc->sc_dmap)) {
    219        1.1  hamajima 		printf(": can't create DMA map.\n");
    220       1.12  christos 		bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_buf,
    221        1.1  hamajima 				 AUDIO_BUF_SIZE);
    222        1.1  hamajima 		bus_dmamem_free(sc->sc_dmat, &segs, rsegs);
    223        1.1  hamajima 		return;
    224        1.1  hamajima 	}
    225        1.1  hamajima 	if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmap, sc->sc_buf,
    226       1.13  jmcneill 				   AUDIO_BUF_SIZE, NULL, BUS_DMA_WAITOK)) {
    227        1.1  hamajima 		printf(": can't load DMA map.\n");
    228        1.1  hamajima 		bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmap);
    229       1.12  christos 		bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_buf,
    230        1.1  hamajima 				 AUDIO_BUF_SIZE);
    231        1.1  hamajima 		bus_dmamem_free(sc->sc_dmat, &segs, rsegs);
    232        1.1  hamajima 		return;
    233        1.1  hamajima 	}
    234        1.1  hamajima 	if (sc->sc_ac->ac_set_aiuout(sc->sc_ac, sc->sc_buf)) {
    235        1.1  hamajima 		printf(": can't set DMA address.\n");
    236        1.1  hamajima 		bus_dmamap_unload(sc->sc_dmat, sc->sc_dmap);
    237        1.1  hamajima 		bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmap);
    238       1.12  christos 		bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_buf,
    239        1.1  hamajima 				 AUDIO_BUF_SIZE);
    240        1.1  hamajima 		bus_dmamem_free(sc->sc_dmat, &segs, rsegs);
    241        1.1  hamajima 		return;
    242        1.1  hamajima 	}
    243        1.1  hamajima 	printf("\n");
    244        1.1  hamajima 
    245        1.1  hamajima 	sc->sc_rate = SPS8000;
    246        1.1  hamajima 	DPRINTFN(1, ("vraiu_attach: reset AIU\n"))
    247        1.1  hamajima 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, SEQ_REG_W, AIURST);
    248        1.1  hamajima 	/* attach audio subsystem */
    249       1.15       chs 	audio_attach_mi(&vraiu_hw_if, sc, self);
    250        1.1  hamajima }
    251        1.1  hamajima 
    252        1.1  hamajima int
    253  1.15.38.1  christos vraiu_query_format(void *self, audio_format_query_t *afp)
    254        1.1  hamajima {
    255        1.1  hamajima 
    256  1.15.38.1  christos 	return audio_query_format(&vraiu_formats, 1, afp);
    257        1.1  hamajima }
    258        1.1  hamajima 
    259        1.1  hamajima int
    260  1.15.38.1  christos vraiu_set_format(void *self, int setmode,
    261  1.15.38.1  christos 		 const audio_params_t *play, const audio_params_t *rec,
    262  1.15.38.1  christos 		 audio_filter_reg_t *pfil, audio_filter_reg_t *rfil)
    263        1.1  hamajima {
    264       1.10      kent 	struct vraiu_softc *sc;
    265        1.1  hamajima 
    266  1.15.38.1  christos 	DPRINTFN(1, ("%s: %ubit, %uch, %uHz, encoding %u\n", __func__,
    267        1.1  hamajima 		     play->precision, play->channels, play->sample_rate,
    268        1.1  hamajima 		     play->encoding));
    269       1.10      kent 	sc = self;
    270  1.15.38.1  christos 
    271        1.1  hamajima 	switch (play->sample_rate) {
    272        1.1  hamajima 	case 8000:
    273        1.1  hamajima 		sc->sc_rate = SPS8000;
    274        1.1  hamajima 		break;
    275        1.1  hamajima 	case 11025:
    276        1.1  hamajima 		sc->sc_rate = SPS11025;
    277        1.1  hamajima 		break;
    278        1.1  hamajima 	case 22050:
    279        1.1  hamajima 		sc->sc_rate = SPS22050;
    280        1.1  hamajima 		break;
    281        1.1  hamajima 	case 44100:
    282        1.1  hamajima 		sc->sc_rate = SPS44100;
    283        1.1  hamajima 		break;
    284        1.1  hamajima 	default:
    285  1.15.38.1  christos 		/* NOTREACHED */
    286  1.15.38.1  christos 		panic("%s: rate error (%d)\n", __func__, play->sample_rate);
    287        1.1  hamajima 	}
    288        1.1  hamajima 
    289        1.1  hamajima 	return 0;
    290        1.1  hamajima }
    291        1.1  hamajima 
    292        1.1  hamajima int
    293        1.9      kent vraiu_round_blocksize(void *self, int bs, int mode, const audio_params_t *param)
    294        1.1  hamajima {
    295  1.15.38.1  christos 	return AUDIO_BUF_SIZE;
    296        1.1  hamajima }
    297        1.1  hamajima 
    298        1.1  hamajima int
    299        1.1  hamajima vraiu_commit_settings(void *self)
    300        1.1  hamajima {
    301       1.10      kent 	struct vraiu_softc *sc;
    302        1.1  hamajima 	int err;
    303        1.1  hamajima 
    304        1.1  hamajima 	DPRINTFN(1, ("vraiu_commit_settings\n"));
    305       1.10      kent 	sc = self;
    306        1.1  hamajima 
    307        1.1  hamajima 	DPRINTFN(1, ("vraiu_commit_settings: set conversion rate %d\n",
    308        1.1  hamajima 		     sc->sc_rate))
    309        1.1  hamajima 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCNVR_REG_W, sc->sc_rate);
    310        1.1  hamajima 	DPRINTFN(1, ("vraiu_commit_settings: clock supply start\n"))
    311        1.1  hamajima 	if ((err = sc->sc_cc->cc_clock(sc->sc_cc, VR4102_CMUMSKAIU, 1))) {
    312        1.1  hamajima 		DPRINTFN(0, ("vraiu_commit_settings: clock supply error\n"));
    313        1.1  hamajima 		return err;
    314        1.1  hamajima 	}
    315        1.1  hamajima 	DPRINTFN(1, ("vraiu_commit_settings: enable DMA\n"))
    316        1.1  hamajima 	if ((err = sc->sc_dc->dc_enable_aiuout(sc->sc_dc))) {
    317        1.1  hamajima 		sc->sc_cc->cc_clock(sc->sc_cc, VR4102_CMUMSKAIU, 0);
    318        1.5       wiz 		DPRINTFN(0, ("vraiu_commit_settings: enable DMA error\n"));
    319        1.1  hamajima 		return err;
    320        1.1  hamajima 	}
    321        1.1  hamajima 	DPRINTFN(1, ("vraiu_commit_settings: Vref on\n"))
    322        1.1  hamajima 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCNT_REG_W, DAENAIU);
    323        1.1  hamajima 	return 0;
    324        1.1  hamajima }
    325        1.1  hamajima 
    326        1.1  hamajima int
    327        1.1  hamajima vraiu_init_output(void *self, void *buffer, int size)
    328        1.1  hamajima {
    329       1.10      kent 	struct vraiu_softc *sc;
    330        1.1  hamajima 
    331        1.1  hamajima 	DPRINTFN(1, ("vraiu_init_output: buffer %p, size %d\n", buffer, size));
    332       1.10      kent 	sc = self;
    333        1.1  hamajima 	sc->sc_intr = NULL;
    334        1.1  hamajima 	DPRINTFN(1, ("vraiu_init_output: speaker power on\n"))
    335        1.1  hamajima 	config_hook_call(CONFIG_HOOK_POWERCONTROL,
    336        1.1  hamajima 			 CONFIG_HOOK_POWERCONTROL_SPEAKER, (void*)1);
    337        1.1  hamajima 	DPRINTFN(1, ("vraiu_init_output: start output\n"))
    338        1.1  hamajima 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, SEQ_REG_W, AIUSEN);
    339        1.1  hamajima 	return 0;
    340        1.1  hamajima }
    341        1.1  hamajima 
    342        1.1  hamajima int
    343        1.1  hamajima vraiu_start_output(void *self, void *block, int bsize,
    344        1.1  hamajima 		   void (*intr)(void *), void *intrarg)
    345        1.1  hamajima {
    346       1.10      kent 	struct vraiu_softc *sc;
    347        1.1  hamajima 
    348        1.1  hamajima 	DPRINTFN(2, ("vraiu_start_output: block %p, bsize %d\n",
    349        1.1  hamajima 		     block, bsize));
    350       1.10      kent 	sc = self;
    351  1.15.38.1  christos 	vraiu_slinear16_1(sc, sc->sc_buf, block, bsize);
    352        1.1  hamajima 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dmap, 0, AUDIO_BUF_SIZE,
    353        1.1  hamajima 			BUS_DMASYNC_PREWRITE);
    354        1.1  hamajima 	sc->sc_intr = intr;
    355        1.1  hamajima 	sc->sc_intrdata = intrarg;
    356        1.1  hamajima 	/* clear interrupt status */
    357        1.1  hamajima 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, INT_REG_W,
    358        1.1  hamajima 			  SENDINTR | SINTR | SIDLEINTR);
    359        1.1  hamajima 	/* enable interrupt */
    360        1.1  hamajima 	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AIUINT_INTSEND, 1);
    361        1.1  hamajima 	return 0;
    362        1.1  hamajima }
    363        1.1  hamajima 
    364        1.1  hamajima int
    365        1.1  hamajima vraiu_intr(void* self)
    366        1.1  hamajima {
    367       1.10      kent 	struct vraiu_softc *sc;
    368       1.10      kent 	uint32_t reg;
    369        1.1  hamajima 
    370        1.1  hamajima 	DPRINTFN(2, ("vraiu_intr"));
    371       1.10      kent 	sc = self;
    372       1.13  jmcneill 
    373       1.13  jmcneill 	mutex_spin_enter(&sc->sc_intr_lock);
    374       1.13  jmcneill 
    375        1.1  hamajima 	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AIUINT_INTSEND, 0);
    376        1.1  hamajima 	vrip_intr_getstatus2(sc->sc_vrip, sc->sc_handler, &reg);
    377        1.1  hamajima 	if (reg & AIUINT_INTSEND) {
    378        1.1  hamajima 		DPRINTFN(2, (": AIUINT_INTSEND"));
    379        1.1  hamajima 		if (sc->sc_intr) {
    380       1.10      kent 			void (*intr)(void *);
    381       1.10      kent 			intr = sc->sc_intr;
    382        1.1  hamajima 			sc->sc_intr = NULL;
    383        1.1  hamajima 			(*(intr))(sc->sc_intrdata);
    384        1.1  hamajima 		}
    385        1.1  hamajima 		bus_space_write_2(sc->sc_iot, sc->sc_ioh, INT_REG_W, SENDINTR);
    386        1.1  hamajima 	}
    387        1.1  hamajima 	DPRINTFN(2, ("\n"));
    388       1.13  jmcneill 
    389       1.13  jmcneill 	mutex_spin_exit(&sc->sc_intr_lock);
    390       1.13  jmcneill 
    391        1.1  hamajima 	return 0;
    392        1.1  hamajima }
    393        1.1  hamajima 
    394        1.1  hamajima int
    395        1.1  hamajima vraiu_halt_output(void *self)
    396        1.1  hamajima {
    397       1.10      kent 	struct vraiu_softc *sc;
    398        1.1  hamajima 
    399        1.1  hamajima 	DPRINTFN(1, ("vraiu_halt_output\n"));
    400       1.10      kent 	sc =self;
    401        1.1  hamajima 	DPRINTFN(1, ("vraiu_halt_output: disable interrupt\n"))
    402        1.1  hamajima 	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AIUINT_INTSEND, 0);
    403        1.1  hamajima 	DPRINTFN(1, ("vraiu_halt_output: stop output\n"))
    404        1.1  hamajima 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, SEQ_REG_W, 0);
    405        1.1  hamajima 	DPRINTFN(1, ("vraiu_halt_output: speaker power off\n"))
    406        1.1  hamajima 	config_hook_call(CONFIG_HOOK_POWERCONTROL,
    407        1.1  hamajima 			 CONFIG_HOOK_POWERCONTROL_SPEAKER, (void*)0);
    408        1.1  hamajima 	DPRINTFN(1, ("vraiu_halt_output: Vref off\n"))
    409        1.1  hamajima 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCNT_REG_W, 0);
    410        1.1  hamajima 	DPRINTFN(1, ("vraiu_halt_output: disable DMA\n"))
    411        1.1  hamajima 	sc->sc_dc->dc_disable(sc->sc_dc);
    412        1.1  hamajima 	DPRINTFN(1, ("vraiu_halt_output: clock supply stop\n"))
    413        1.1  hamajima 	sc->sc_cc->cc_clock(sc->sc_cc, VR4102_CMUMSKAIU, 0);
    414        1.1  hamajima 	sc->sc_intr = NULL;
    415        1.1  hamajima 	return 0;
    416        1.1  hamajima }
    417        1.1  hamajima 
    418        1.1  hamajima int
    419        1.1  hamajima vraiu_getdev(void *self, struct audio_device *ret)
    420        1.1  hamajima {
    421       1.10      kent 
    422        1.1  hamajima 	DPRINTFN(3, ("vraiu_getdev\n"));
    423        1.1  hamajima 	*ret = aiu_device;
    424        1.1  hamajima 	return 0;
    425        1.1  hamajima }
    426        1.1  hamajima 
    427        1.1  hamajima int
    428        1.1  hamajima vraiu_set_port(void *self, mixer_ctrl_t *mc)
    429        1.1  hamajima {
    430       1.10      kent 	struct vraiu_softc *sc;
    431       1.10      kent 
    432        1.1  hamajima 	DPRINTFN(3, ("vraiu_set_port\n"));
    433       1.10      kent 	sc = self;
    434        1.7  jmcneill 	/* software mixer, 1ch */
    435        1.7  jmcneill 	if (mc->dev == 0) {
    436        1.7  jmcneill 		if (mc->type != AUDIO_MIXER_VALUE)
    437        1.7  jmcneill 			return EINVAL;
    438        1.7  jmcneill 		if (mc->un.value.num_channels != 1)
    439        1.7  jmcneill 			return EINVAL;
    440        1.7  jmcneill 		sc->sc_volume = mc->un.value.level[AUDIO_MIXER_LEVEL_MONO];
    441        1.7  jmcneill 		return 0;
    442        1.7  jmcneill 	}
    443        1.7  jmcneill 
    444        1.1  hamajima 	return EINVAL;
    445        1.1  hamajima }
    446        1.1  hamajima 
    447        1.1  hamajima int
    448        1.1  hamajima vraiu_get_port(void *self, mixer_ctrl_t *mc)
    449        1.1  hamajima {
    450       1.10      kent 	struct vraiu_softc *sc;
    451       1.10      kent 
    452        1.1  hamajima 	DPRINTFN(3, ("vraiu_get_port\n"));
    453       1.10      kent 	sc = self;
    454        1.7  jmcneill 	/* software mixer, 1ch */
    455        1.7  jmcneill 	if (mc->dev == 0) {
    456        1.7  jmcneill 		if (mc->un.value.num_channels != 1)
    457        1.7  jmcneill 			return EINVAL;
    458        1.7  jmcneill 		mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_volume;
    459        1.7  jmcneill 		return 0;
    460        1.7  jmcneill 	}
    461       1.10      kent 
    462        1.1  hamajima 	return EINVAL;
    463        1.1  hamajima }
    464        1.1  hamajima 
    465        1.1  hamajima int
    466        1.1  hamajima vraiu_query_devinfo(void *self, mixer_devinfo_t *di)
    467        1.1  hamajima {
    468       1.10      kent 
    469        1.1  hamajima 	DPRINTFN(3, ("vraiu_query_devinfo\n"));
    470        1.7  jmcneill 	/* software mixer, 1ch */
    471        1.7  jmcneill 	switch (di->index) {
    472        1.7  jmcneill 	case 0: /* inputs.dac mixer value */
    473        1.7  jmcneill 		di->mixer_class = 1;
    474        1.7  jmcneill 		di->next = di->prev = AUDIO_MIXER_LAST;
    475        1.7  jmcneill 		strcpy(di->label.name, AudioNdac);
    476        1.7  jmcneill 		di->type = AUDIO_MIXER_VALUE;
    477        1.7  jmcneill 		di->un.v.num_channels = 1;
    478        1.7  jmcneill 		strcpy(di->un.v.units.name, AudioNvolume);
    479        1.7  jmcneill 		return 0;
    480        1.7  jmcneill 	case 1: /* outputs class */
    481        1.7  jmcneill 		di->mixer_class = 1;
    482        1.7  jmcneill 		di->next = di->prev = AUDIO_MIXER_LAST;
    483        1.7  jmcneill 		strcpy(di->label.name, AudioCinputs);
    484        1.7  jmcneill 		di->type = AUDIO_MIXER_CLASS;
    485        1.7  jmcneill 		return 0;
    486        1.7  jmcneill 	}
    487        1.7  jmcneill 
    488        1.1  hamajima 	return ENXIO;
    489        1.1  hamajima }
    490        1.1  hamajima 
    491        1.1  hamajima int
    492        1.1  hamajima vraiu_get_props(void *self)
    493        1.1  hamajima {
    494        1.1  hamajima 	DPRINTFN(3, ("vraiu_get_props\n"));
    495        1.1  hamajima 
    496  1.15.38.1  christos 	return AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE;
    497        1.1  hamajima }
    498        1.1  hamajima 
    499       1.13  jmcneill void
    500       1.13  jmcneill vraiu_get_locks(void *self, kmutex_t **intr, kmutex_t **thread)
    501       1.13  jmcneill {
    502       1.13  jmcneill 	struct vraiu_softc *sc;
    503       1.13  jmcneill 
    504       1.13  jmcneill 	DPRINTFN(3, ("vraiu_get_locks\n"));
    505       1.13  jmcneill 	sc = self;
    506       1.13  jmcneill 
    507       1.13  jmcneill 	*intr = &sc->sc_intr_lock;
    508       1.13  jmcneill 	*thread = &sc->sc_lock;
    509       1.13  jmcneill }
    510       1.13  jmcneill 
    511  1.15.38.1  christos /* slinear16/mono -> ulinear10/mono with volume */
    512        1.1  hamajima static void
    513        1.1  hamajima vraiu_slinear16_1(struct vraiu_softc *sc, u_short *dmap, void *p, int n)
    514        1.1  hamajima {
    515       1.10      kent 	short *q;
    516        1.1  hamajima 
    517        1.1  hamajima 	DPRINTFN(3, ("vraiu_slinear16_1\n"));
    518       1.10      kent 	q = p;
    519        1.1  hamajima #ifdef DIAGNOSTIC
    520        1.1  hamajima 	if (n > AUDIO_BUF_SIZE) {
    521        1.1  hamajima 		printf("%s: output data too large (%d > %d)\n",
    522       1.15       chs 		       device_xname(sc->sc_dev), n, AUDIO_BUF_SIZE);
    523        1.1  hamajima 		n = AUDIO_BUF_SIZE;
    524        1.1  hamajima 	}
    525        1.1  hamajima #endif
    526        1.1  hamajima 	n /= 2;
    527        1.1  hamajima 	while (n--) {
    528  1.15.38.1  christos 		int i = *q++;
    529  1.15.38.1  christos 		i = i * sc->sc_volume / 255;
    530        1.1  hamajima 		*dmap++ = (i >> 6) + 0x200;
    531        1.1  hamajima 	}
    532        1.1  hamajima }
    533