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