vraiu.c revision 1.1 1 /* $NetBSD: vraiu.c,v 1.1 2002/03/23 09:02:02 hamajima 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/param.h>
29 #include <sys/systm.h>
30 #include <sys/device.h>
31 #include <sys/malloc.h>
32 #include <sys/bswap.h>
33
34 #include <machine/cpu.h>
35 #include <machine/intr.h>
36 #include <machine/bus.h>
37 #include <machine/platid.h>
38 #include <machine/platid_mask.h>
39 #include <machine/config_hook.h>
40
41 #include <sys/audioio.h>
42 #include <dev/audio_if.h>
43
44 #include <hpcmips/vr/vr.h>
45 #include <hpcmips/vr/vripif.h>
46 #include <hpcmips/vr/icureg.h>
47 #include <hpcmips/vr/cmureg.h>
48 #include <hpcmips/vr/vraiureg.h>
49
50 #ifdef VRAIU_DEBUG
51 int vraiu_debug = VRAIU_DEBUG;
52 #define DPRINTFN(n,x) if (vraiu_debug>(n)) printf x;
53 #else
54 #define DPRINTFN(n,x)
55 #endif
56
57 #define AUDIO_BUF_SIZE 2048
58
59 struct vraiu_softc {
60 struct device sc_dev;
61 bus_space_tag_t sc_iot;
62 bus_space_handle_t sc_ioh;
63 bus_dma_tag_t sc_dmat;
64 bus_dmamap_t sc_dmap;
65 vrip_chipset_tag_t sc_vrip;
66 vrdcu_chipset_tag_t sc_dc;
67 vrdmaau_chipset_tag_t sc_ac;
68 vrcmu_chipset_tag_t sc_cc;
69 void *sc_handler;
70 u_short *sc_buf; /* dma buffer pointer */
71 int sc_status; /* status */
72 u_int sc_rate; /* sampling rate */
73 u_int sc_channels; /* # of channels used */
74 u_int sc_encoding; /* encoding type */
75 int sc_precision; /* 8 or 16 bits */
76 /* pointer to format conversion routine */
77 void (*sc_decodefunc)(struct vraiu_softc *, u_short *, void *, int);
78 void (*sc_intr)(void *); /* interrupt routine */
79 void *sc_intrdata; /* interrupt data */
80 };
81
82 int vraiu_match(struct device *, struct cfdata *, void *);
83 void vraiu_attach(struct device *, struct device *, void *);
84 int vraiu_intr(void *);
85
86 struct cfattach vraiu_ca = {
87 sizeof(struct vraiu_softc), vraiu_match, vraiu_attach
88 };
89
90 struct audio_device aiu_device = {
91 "VR4121 AIU",
92 "0.1",
93 "aiu"
94 };
95
96 /*
97 * Define our interface to the higher level audio driver.
98 */
99 int vraiu_open(void *, int);
100 void vraiu_close(void *);
101 int vraiu_query_encoding(void *, struct audio_encoding *);
102 int vraiu_round_blocksize(void *, int);
103 int vraiu_commit_settings(void *);
104 int vraiu_init_output(void *, void*, int);
105 int vraiu_start_output(void *, void *, int, void (*)(void *), void *);
106 int vraiu_start_input(void *, void *, int, void (*)(void *), void *);
107 int vraiu_halt_output(void *);
108 int vraiu_halt_input(void *);
109 int vraiu_getdev(void *, struct audio_device *);
110 int vraiu_set_port(void *, mixer_ctrl_t *);
111 int vraiu_get_port(void *, mixer_ctrl_t *);
112 int vraiu_query_devinfo(void *, mixer_devinfo_t *);
113 int vraiu_set_params(void *, int, int, struct audio_params *,
114 struct audio_params *);
115 int vraiu_get_props(void *);
116
117 struct audio_hw_if vraiu_hw_if = {
118 vraiu_open,
119 vraiu_close,
120 NULL,
121 vraiu_query_encoding,
122 vraiu_set_params,
123 vraiu_round_blocksize,
124 vraiu_commit_settings,
125 vraiu_init_output,
126 NULL,
127 vraiu_start_output,
128 vraiu_start_input,
129 vraiu_halt_output,
130 vraiu_halt_input,
131 NULL,
132 vraiu_getdev,
133 NULL,
134 vraiu_set_port,
135 vraiu_get_port,
136 vraiu_query_devinfo,
137 NULL,
138 NULL,
139 NULL,
140 NULL,
141 vraiu_get_props,
142 };
143
144 /*
145 * convert to 1ch 10bit unsigned PCM data.
146 */
147 static void vraiu_slinear8_1(struct vraiu_softc *, u_short *, void *, int);
148 static void vraiu_slinear8_2(struct vraiu_softc *, u_short *, void *, int);
149 static void vraiu_ulinear8_1(struct vraiu_softc *, u_short *, void *, int);
150 static void vraiu_ulinear8_2(struct vraiu_softc *, u_short *, void *, int);
151 static void vraiu_ulaw_1(struct vraiu_softc *, u_short *, void *, int);
152 static void vraiu_ulaw_2(struct vraiu_softc *, u_short *, void *, int);
153 static void vraiu_slinear16_1(struct vraiu_softc *, u_short *, void *, int);
154 static void vraiu_slinear16_2(struct vraiu_softc *, u_short *, void *, int);
155 static void vraiu_slinear16sw_1(struct vraiu_softc *, u_short *, void *, int);
156 static void vraiu_slinear16sw_2(struct vraiu_softc *, u_short *, void *, int);
157
158 int
159 vraiu_match(struct device *parent, struct cfdata *cf, void *aux)
160 {
161 return 1;
162 }
163
164 void
165 vraiu_attach(struct device *parent, struct device *self, void *aux)
166 {
167 struct vrip_attach_args *va = aux;
168 struct vraiu_softc *sc = (void*)self;
169 bus_dma_segment_t segs;
170 int rsegs;
171
172 sc->sc_status = ENXIO;
173 sc->sc_intr = NULL;
174 sc->sc_iot = va->va_iot;
175 sc->sc_vrip = va->va_vc;
176 sc->sc_cc = va->va_cc;
177 sc->sc_dc = va->va_dc;
178 sc->sc_ac = va->va_ac;
179 sc->sc_dmat = &vrdcu_bus_dma_tag;
180
181 if (!sc->sc_cc) {
182 printf(" not configured: cmu not found\n");
183 return;
184 }
185 if (!sc->sc_dc) {
186 printf(" not configured: dcu not found\n");
187 return;
188 }
189 if (!sc->sc_ac) {
190 printf(" not configured: dmaau not found\n");
191 return;
192 }
193 if (bus_space_map(sc->sc_iot, va->va_addr, va->va_size,
194 0 /* no flags */, &sc->sc_ioh)) {
195 printf(": can't map i/o space\n");
196 return;
197 }
198
199 /* install interrupt handler and enable interrupt */
200 if (!(sc->sc_handler = vrip_intr_establish(va->va_vc, va->va_unit,
201 0, IPL_AUDIO,
202 vraiu_intr, sc))) {
203 printf(": can't map interrupt line.\n");
204 return;
205 }
206 vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, (AIUINT_INTMEND | \
207 AIUINT_INTM | \
208 AIUINT_INTMIDLE | \
209 AIUINT_INTMST | \
210 AIUINT_INTSEND | \
211 AIUINT_INTS | \
212 AIUINT_INTSIDLE), 0);
213
214 if (bus_dmamem_alloc(sc->sc_dmat, AUDIO_BUF_SIZE, 0, 0, &segs, 1,
215 &rsegs, BUS_DMA_NOWAIT)) {
216 printf(": can't allocate memory.\n");
217 return;
218 }
219 if (bus_dmamem_map(sc->sc_dmat, &segs, rsegs, AUDIO_BUF_SIZE,
220 (caddr_t *)&sc->sc_buf,
221 BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) {
222 printf(": can't map memory.\n");
223 bus_dmamem_free(sc->sc_dmat, &segs, rsegs);
224 return;
225 }
226 if (bus_dmamap_create(sc->sc_dmat, AUDIO_BUF_SIZE, 1, AUDIO_BUF_SIZE,
227 0, BUS_DMA_NOWAIT, &sc->sc_dmap)) {
228 printf(": can't create DMA map.\n");
229 bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_buf,
230 AUDIO_BUF_SIZE);
231 bus_dmamem_free(sc->sc_dmat, &segs, rsegs);
232 return;
233 }
234 if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmap, sc->sc_buf,
235 AUDIO_BUF_SIZE, NULL, BUS_DMA_NOWAIT)) {
236 printf(": can't load DMA map.\n");
237 bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmap);
238 bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_buf,
239 AUDIO_BUF_SIZE);
240 bus_dmamem_free(sc->sc_dmat, &segs, rsegs);
241 return;
242 }
243 if (sc->sc_ac->ac_set_aiuout(sc->sc_ac, sc->sc_buf)) {
244 printf(": can't set DMA address.\n");
245 bus_dmamap_unload(sc->sc_dmat, sc->sc_dmap);
246 bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmap);
247 bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_buf,
248 AUDIO_BUF_SIZE);
249 bus_dmamem_free(sc->sc_dmat, &segs, rsegs);
250 return;
251 }
252 printf("\n");
253
254 sc->sc_status = 0;
255 sc->sc_rate = SPS8000;
256 sc->sc_channels = 1;
257 sc->sc_precision = 8;
258 sc->sc_encoding = AUDIO_ENCODING_ULAW;
259 sc->sc_decodefunc = vraiu_ulaw_1;
260 DPRINTFN(1, ("vraiu_attach: reset AIU\n"))
261 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SEQ_REG_W, AIURST);
262 /* attach audio subsystem */
263 audio_attach_mi(&vraiu_hw_if, sc, &sc->sc_dev);
264 }
265
266 int
267 vraiu_open(void *self, int flags)
268 {
269 struct vraiu_softc *sc = (void*)self;
270
271 DPRINTFN(1, ("vraiu_open\n"));
272
273 if (sc->sc_status) {
274 DPRINTFN(0, ("vraiu_open: device error\n"));
275 return sc->sc_status;
276 }
277 sc->sc_status = EBUSY;
278 return 0;
279 }
280
281 void
282 vraiu_close(void *self)
283 {
284 struct vraiu_softc *sc = (void*)self;
285
286 DPRINTFN(1, ("vraiu_close\n"));
287
288 vraiu_halt_output(self);
289 sc->sc_status = 0;
290 }
291
292 int
293 vraiu_query_encoding(void *self, struct audio_encoding *ae)
294 {
295 DPRINTFN(3, ("vraiu_query_encoding\n"));
296
297 switch (ae->index) {
298 case 0:
299 strcpy(ae->name, AudioEslinear);
300 ae->encoding = AUDIO_ENCODING_SLINEAR;
301 ae->precision = 8;
302 ae->flags = AUDIO_ENCODINGFLAG_EMULATED;
303 break;
304 case 1:
305 strcpy(ae->name, AudioEmulaw);
306 ae->encoding = AUDIO_ENCODING_ULAW;
307 ae->precision = 8;
308 ae->flags = AUDIO_ENCODINGFLAG_EMULATED;
309 break;
310 case 2:
311 strcpy(ae->name, AudioEulinear);
312 ae->encoding = AUDIO_ENCODING_ULINEAR;
313 ae->precision = 8;
314 ae->flags = AUDIO_ENCODINGFLAG_EMULATED;
315 break;
316 case 3:
317 strcpy(ae->name, AudioEslinear);
318 ae->encoding = AUDIO_ENCODING_SLINEAR;
319 ae->precision = 16;
320 ae->flags = AUDIO_ENCODINGFLAG_EMULATED;
321 break;
322 case 4:
323 strcpy(ae->name, AudioEslinear_be);
324 ae->encoding = AUDIO_ENCODING_SLINEAR_BE;
325 ae->precision = 16;
326 ae->flags = AUDIO_ENCODINGFLAG_EMULATED;
327 break;
328 case 5:
329 strcpy(ae->name, AudioEslinear_le);
330 ae->encoding = AUDIO_ENCODING_SLINEAR_LE;
331 ae->precision = 16;
332 ae->flags = AUDIO_ENCODINGFLAG_EMULATED;
333 break;
334 case 6:
335 strcpy(ae->name, AudioEslinear);
336 ae->encoding = AUDIO_ENCODING_ULINEAR;
337 ae->precision = 16;
338 ae->flags = AUDIO_ENCODINGFLAG_EMULATED;
339 break;
340 case 7:
341 strcpy(ae->name, AudioEslinear_be);
342 ae->encoding = AUDIO_ENCODING_ULINEAR_BE;
343 ae->precision = 16;
344 ae->flags = AUDIO_ENCODINGFLAG_EMULATED;
345 break;
346 case 8:
347 strcpy(ae->name, AudioEslinear_le);
348 ae->encoding = AUDIO_ENCODING_ULINEAR_LE;
349 ae->precision = 16;
350 ae->flags = AUDIO_ENCODINGFLAG_EMULATED;
351 break;
352 default:
353 DPRINTFN(0, ("vraiu_query_encoding: param error"
354 " (%d)\n", ae->index));
355 return EINVAL;
356 }
357 return 0;
358 }
359
360 int
361 vraiu_set_params(void *self, int setmode, int usemode,
362 struct audio_params *play, struct audio_params *rec)
363 {
364 struct vraiu_softc *sc = (void*)self;
365
366 DPRINTFN(1, ("vraiu_set_params: %dbit, %dch, %ldHz, encoding %d\n",
367 play->precision, play->channels, play->sample_rate,
368 play->encoding));
369
370 switch (play->sample_rate) {
371 case 8000:
372 sc->sc_rate = SPS8000;
373 break;
374 case 11025:
375 sc->sc_rate = SPS11025;
376 break;
377 case 22050:
378 sc->sc_rate = SPS22050;
379 break;
380 case 44100:
381 sc->sc_rate = SPS44100;
382 break;
383 default:
384 DPRINTFN(0, ("vraiu_set_params: rate error (%ld)\n",
385 play->sample_rate));
386 return EINVAL;
387 }
388
389 switch (play->precision) {
390 case 8:
391 switch (play->encoding) {
392 case AUDIO_ENCODING_ULAW:
393 switch (play->channels) {
394 case 1:
395 sc->sc_decodefunc = vraiu_ulaw_1;
396 break;
397 case 2:
398 sc->sc_decodefunc = vraiu_ulaw_2;
399 break;
400 default:
401 DPRINTFN(0, ("vraiu_set_params: channel error"
402 " (%d)\n", play->channels));
403 return EINVAL;
404 }
405 break;
406 case AUDIO_ENCODING_SLINEAR:
407 case AUDIO_ENCODING_SLINEAR_BE:
408 case AUDIO_ENCODING_SLINEAR_LE:
409 switch (play->channels) {
410 case 1:
411 sc->sc_decodefunc = vraiu_slinear8_1;
412 break;
413 case 2:
414 sc->sc_decodefunc = vraiu_slinear8_2;
415 break;
416 default:
417 DPRINTFN(0, ("vraiu_set_params: channel error"
418 " (%d)\n", play->channels));
419 return EINVAL;
420 }
421 break;
422 case AUDIO_ENCODING_ULINEAR:
423 case AUDIO_ENCODING_ULINEAR_BE:
424 case AUDIO_ENCODING_ULINEAR_LE:
425 switch (play->channels) {
426 case 1:
427 sc->sc_decodefunc = vraiu_ulinear8_1;
428 break;
429 case 2:
430 sc->sc_decodefunc = vraiu_ulinear8_2;
431 break;
432 default:
433 DPRINTFN(0, ("vraiu_set_params: channel error"
434 " (%d)\n", play->channels));
435 return EINVAL;
436 }
437 break;
438 default:
439 DPRINTFN(0, ("vraiu_set_params: encoding error"
440 " (%d)\n", play->encoding));
441 return EINVAL;
442 }
443 break;
444 case 16:
445 switch (play->encoding) {
446 #if BYTE_ORDER == BIG_ENDIAN
447 case AUDIO_ENCODING_SLINEAR:
448 #endif
449 case AUDIO_ENCODING_SLINEAR_BE:
450 switch (play->channels) {
451 case 1:
452 #if BYTE_ORDER == BIG_ENDIAN
453 sc->sc_decodefunc = vraiu_slinear16_1;
454 #else
455 sc->sc_decodefunc = vraiu_slinear16sw_1;
456 #endif
457 break;
458 case 2:
459 #if BYTE_ORDER == BIG_ENDIAN
460 sc->sc_decodefunc = vraiu_slinear16_2;
461 #else
462 sc->sc_decodefunc = vraiu_slinear16sw_2;
463 #endif
464 break;
465 default:
466 DPRINTFN(0, ("vraiu_set_params: channel error"
467 " (%d)\n", play->channels));
468 return EINVAL;
469 }
470 break;
471 #if BYTE_ORDER == LITTLE_ENDIAN
472 case AUDIO_ENCODING_SLINEAR:
473 #endif
474 case AUDIO_ENCODING_SLINEAR_LE:
475 switch (play->channels) {
476 case 1:
477 #if BYTE_ORDER == LITTLE_ENDIAN
478 sc->sc_decodefunc = vraiu_slinear16_1;
479 #else
480 sc->sc_decodefunc = vraiu_slinear16sw_1;
481 #endif
482 break;
483 case 2:
484 #if BYTE_ORDER == LITTLE_ENDIAN
485 sc->sc_decodefunc = vraiu_slinear16_2;
486 #else
487 sc->sc_decodefunc = vraiu_slinear16sw_2;
488 #endif
489 break;
490 default:
491 DPRINTFN(0, ("vraiu_set_params: channel error"
492 " (%d)\n", play->channels));
493 return EINVAL;
494 }
495 break;
496 default:
497 DPRINTFN(0, ("vraiu_set_params: encoding error"
498 " (%d)\n", play->encoding));
499 return EINVAL;
500 }
501 break;
502 default:
503 DPRINTFN(0, ("vraiu_set_params: precision error (%d)\n",
504 play->precision));
505 return EINVAL;
506 }
507
508 sc->sc_encoding = play->encoding;
509 sc->sc_precision = play->precision;
510 sc->sc_channels = play->channels;
511 return 0;
512 }
513
514 int
515 vraiu_round_blocksize(void *self, int bs)
516 {
517 struct vraiu_softc *sc = (void*)self;
518 int n = AUDIO_BUF_SIZE;
519
520 if (sc->sc_precision == 8)
521 n /= 2;
522 n *= sc->sc_channels;
523
524 DPRINTFN(1, ("vraiu_round_blocksize: upper %d, lower %d\n",
525 bs, n));
526
527 return n;
528 }
529
530 int
531 vraiu_commit_settings(void *self)
532 {
533 struct vraiu_softc *sc = (void*)self;
534 int err;
535
536 DPRINTFN(1, ("vraiu_commit_settings\n"));
537
538 if (sc->sc_status != EBUSY)
539 return sc->sc_status;
540
541 DPRINTFN(1, ("vraiu_commit_settings: set conversion rate %d\n",
542 sc->sc_rate))
543 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCNVR_REG_W, sc->sc_rate);
544 DPRINTFN(1, ("vraiu_commit_settings: clock supply start\n"))
545 if ((err = sc->sc_cc->cc_clock(sc->sc_cc, VR4102_CMUMSKAIU, 1))) {
546 DPRINTFN(0, ("vraiu_commit_settings: clock supply error\n"));
547 return err;
548 }
549 DPRINTFN(1, ("vraiu_commit_settings: enable DMA\n"))
550 if ((err = sc->sc_dc->dc_enable_aiuout(sc->sc_dc))) {
551 sc->sc_cc->cc_clock(sc->sc_cc, VR4102_CMUMSKAIU, 0);
552 DPRINTFN(0, ("vraiu_commit_settings: enable dma error\n"));
553 return err;
554 }
555 DPRINTFN(1, ("vraiu_commit_settings: Vref on\n"))
556 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCNT_REG_W, DAENAIU);
557 return 0;
558 }
559
560 int
561 vraiu_init_output(void *self, void *buffer, int size)
562 {
563 struct vraiu_softc *sc = (void*)self;
564
565 DPRINTFN(1, ("vraiu_init_output: buffer %p, size %d\n", buffer, size));
566
567 sc->sc_intr = NULL;
568 DPRINTFN(1, ("vraiu_init_output: speaker power on\n"))
569 config_hook_call(CONFIG_HOOK_POWERCONTROL,
570 CONFIG_HOOK_POWERCONTROL_SPEAKER, (void*)1);
571 DPRINTFN(1, ("vraiu_init_output: start output\n"))
572 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SEQ_REG_W, AIUSEN);
573 return 0;
574 }
575
576 int
577 vraiu_start_output(void *self, void *block, int bsize,
578 void (*intr)(void *), void *intrarg)
579 {
580 struct vraiu_softc *sc = (void*)self;
581
582 DPRINTFN(2, ("vraiu_start_output: block %p, bsize %d\n",
583 block, bsize));
584 sc->sc_decodefunc(sc, sc->sc_buf, block, bsize);
585 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmap, 0, AUDIO_BUF_SIZE,
586 BUS_DMASYNC_PREWRITE);
587 sc->sc_intr = intr;
588 sc->sc_intrdata = intrarg;
589 /* clear interrupt status */
590 bus_space_write_2(sc->sc_iot, sc->sc_ioh, INT_REG_W,
591 SENDINTR | SINTR | SIDLEINTR);
592 /* enable interrupt */
593 vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AIUINT_INTSEND, 1);
594 return 0;
595 }
596
597 int
598 vraiu_start_input(void *self, void *block, int bsize,
599 void (*intr)(void *), void *intrarg)
600 {
601 DPRINTFN(3, ("vraiu_start_input\n"));
602
603 /* no input */
604 return ENXIO;
605 }
606
607 int
608 vraiu_intr(void* self)
609 {
610 struct vraiu_softc *sc = (void*)self;
611 u_int32_t reg;
612
613 DPRINTFN(2, ("vraiu_intr"));
614
615 vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AIUINT_INTSEND, 0);
616 vrip_intr_getstatus2(sc->sc_vrip, sc->sc_handler, ®);
617 if (reg & AIUINT_INTSEND) {
618 DPRINTFN(2, (": AIUINT_INTSEND"));
619 if (sc->sc_intr) {
620 void (*intr)(void *) = sc->sc_intr;
621 sc->sc_intr = NULL;
622 (*(intr))(sc->sc_intrdata);
623 }
624 bus_space_write_2(sc->sc_iot, sc->sc_ioh, INT_REG_W, SENDINTR);
625 }
626 DPRINTFN(2, ("\n"));
627 return 0;
628 }
629
630 int
631 vraiu_halt_output(void *self)
632 {
633 struct vraiu_softc *sc = (void*)self;
634
635 DPRINTFN(1, ("vraiu_halt_output\n"));
636
637 DPRINTFN(1, ("vraiu_halt_output: disable interrupt\n"))
638 vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AIUINT_INTSEND, 0);
639 DPRINTFN(1, ("vraiu_halt_output: stop output\n"))
640 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SEQ_REG_W, 0);
641 DPRINTFN(1, ("vraiu_halt_output: speaker power off\n"))
642 config_hook_call(CONFIG_HOOK_POWERCONTROL,
643 CONFIG_HOOK_POWERCONTROL_SPEAKER, (void*)0);
644 DPRINTFN(1, ("vraiu_halt_output: Vref off\n"))
645 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCNT_REG_W, 0);
646 DPRINTFN(1, ("vraiu_halt_output: disable DMA\n"))
647 sc->sc_dc->dc_disable(sc->sc_dc);
648 DPRINTFN(1, ("vraiu_halt_output: clock supply stop\n"))
649 sc->sc_cc->cc_clock(sc->sc_cc, VR4102_CMUMSKAIU, 0);
650 sc->sc_intr = NULL;
651 return 0;
652 }
653
654 int
655 vraiu_halt_input(void *self)
656 {
657 DPRINTFN(3, ("vraiu_halt_input\n"));
658
659 /* no input */
660 return ENXIO;
661 }
662
663
664 int
665 vraiu_getdev(void *self, struct audio_device *ret)
666 {
667 DPRINTFN(3, ("vraiu_getdev\n"));
668
669 *ret = aiu_device;
670 return 0;
671 }
672
673 int
674 vraiu_set_port(void *self, mixer_ctrl_t *mc)
675 {
676 DPRINTFN(3, ("vraiu_set_port\n"));
677
678 /* no mixer */
679 return EINVAL;
680 }
681
682 int
683 vraiu_get_port(void *self, mixer_ctrl_t *mc)
684 {
685 DPRINTFN(3, ("vraiu_get_port\n"));
686
687 /* no mixer */
688 return EINVAL;
689 }
690
691 int
692 vraiu_query_devinfo(void *self, mixer_devinfo_t *di)
693 {
694 DPRINTFN(3, ("vraiu_query_devinfo\n"));
695
696 /* no mixer */
697 return ENXIO;
698 }
699
700 int
701 vraiu_get_props(void *self)
702 {
703 DPRINTFN(3, ("vraiu_get_props\n"));
704
705 return 0;
706 }
707
708 unsigned char ulaw_to_lin[] = {
709 0x02, 0x06, 0x0a, 0x0e, 0x12, 0x16, 0x1a, 0x1e,
710 0x22, 0x26, 0x2a, 0x2e, 0x32, 0x36, 0x3a, 0x3e,
711 0x41, 0x43, 0x45, 0x47, 0x49, 0x4b, 0x4d, 0x4f,
712 0x51, 0x53, 0x55, 0x57, 0x59, 0x5b, 0x5d, 0x5f,
713 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
714 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
715 0x70, 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x74,
716 0x74, 0x75, 0x75, 0x76, 0x76, 0x77, 0x77, 0x78,
717 0x78, 0x78, 0x79, 0x79, 0x79, 0x79, 0x7a, 0x7a,
718 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c,
719 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7d,
720 0x7d, 0x7d, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7e,
721 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e,
722 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
723 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
724 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80,
725 0xfd, 0xf9, 0xf5, 0xf1, 0xed, 0xe9, 0xe5, 0xe1,
726 0xdd, 0xd9, 0xd5, 0xd1, 0xcd, 0xc9, 0xc5, 0xc1,
727 0xbe, 0xbc, 0xba, 0xb8, 0xb6, 0xb4, 0xb2, 0xb0,
728 0xae, 0xac, 0xaa, 0xa8, 0xa6, 0xa4, 0xa2, 0xa0,
729 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97,
730 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f,
731 0x8f, 0x8e, 0x8e, 0x8d, 0x8d, 0x8c, 0x8c, 0x8b,
732 0x8b, 0x8a, 0x8a, 0x89, 0x89, 0x88, 0x88, 0x87,
733 0x87, 0x87, 0x86, 0x86, 0x86, 0x86, 0x85, 0x85,
734 0x85, 0x85, 0x84, 0x84, 0x84, 0x84, 0x83, 0x83,
735 0x83, 0x83, 0x83, 0x83, 0x82, 0x82, 0x82, 0x82,
736 0x82, 0x82, 0x82, 0x82, 0x81, 0x81, 0x81, 0x81,
737 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
738 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
739 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
740 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
741 };
742
743 static void
744 vraiu_slinear8_1(struct vraiu_softc *sc, u_short *dmap, void *p, int n)
745 {
746 char *q = (char*)p;
747
748 DPRINTFN(3, ("vraiu_slinear8_1\n"));
749
750 #ifdef DIAGNOSTIC
751 if (n > AUDIO_BUF_SIZE/2) {
752 printf("%s: output data too large (%d > %d)\n",
753 sc->sc_dev.dv_xname, n, AUDIO_BUF_SIZE/2);
754 n = AUDIO_BUF_SIZE/2;
755 }
756 #endif
757 while (n--) {
758 short i = *q++;
759 *dmap++ = (i << 2) + 0x200;
760 }
761 }
762
763 static void
764 vraiu_slinear8_2(struct vraiu_softc *sc, u_short *dmap, void *p, int n)
765 {
766 char *q = (char*)p;
767
768 DPRINTFN(3, ("vraiu_slinear8_2\n"));
769
770 #ifdef DIAGNOSTIC
771 if (n > AUDIO_BUF_SIZE) {
772 printf("%s: output data too large (%d > %d)\n",
773 sc->sc_dev.dv_xname, n, AUDIO_BUF_SIZE);
774 n = AUDIO_BUF_SIZE;
775 }
776 #endif
777 n /= 2;
778 while (n--) {
779 short i = *q++;
780 short j = *q++;
781 *dmap++ = ((i + j) << 1) + 0x200;
782 }
783 }
784
785 static void
786 vraiu_ulinear8_1(struct vraiu_softc *sc, u_short *dmap, void *p, int n)
787 {
788 u_char *q = (u_char*)p;
789
790 DPRINTFN(3, ("vraiu_ulinear8_1\n"));
791
792 #ifdef DIAGNOSTIC
793 if (n > AUDIO_BUF_SIZE/2) {
794 printf("%s: output data too large (%d > %d)\n",
795 sc->sc_dev.dv_xname, n, AUDIO_BUF_SIZE/2);
796 n = AUDIO_BUF_SIZE/2;
797 }
798 #endif
799 while (n--) {
800 short i = *q++;
801 *dmap++ = i << 2;
802 }
803 }
804
805 static void
806 vraiu_ulinear8_2(struct vraiu_softc *sc, u_short *dmap, void *p, int n)
807 {
808 u_char *q = (u_char*)p;
809
810 DPRINTFN(3, ("vraiu_ulinear8_2\n"));
811
812 #ifdef DIAGNOSTIC
813 if (n > AUDIO_BUF_SIZE) {
814 printf("%s: output data too large (%d > %d)\n",
815 sc->sc_dev.dv_xname, n, AUDIO_BUF_SIZE);
816 n = AUDIO_BUF_SIZE;
817 }
818 #endif
819 n /= 2;
820 while (n--) {
821 short i = *q++;
822 short j = *q++;
823 *dmap++ = (i + j) << 1;
824 }
825 }
826
827 static void
828 vraiu_ulaw_1(struct vraiu_softc *sc, u_short *dmap, void *p, int n)
829 {
830 u_char *q = (u_char*)p;
831
832 DPRINTFN(3, ("vraiu_ulaw_1\n"));
833
834 #ifdef DIAGNOSTIC
835 if (n > AUDIO_BUF_SIZE/2) {
836 printf("%s: output data too large (%d > %d)\n",
837 sc->sc_dev.dv_xname, n, AUDIO_BUF_SIZE/2);
838 n = AUDIO_BUF_SIZE/2;
839 }
840 #endif
841 while (n--) {
842 short i = ulaw_to_lin[*q++];
843 *dmap++ = i << 2;
844 }
845 }
846
847 static void
848 vraiu_ulaw_2(struct vraiu_softc *sc, u_short *dmap, void *p, int n)
849 {
850 u_char *q = (u_char*)p;
851
852 DPRINTFN(3, ("vraiu_ulaw_2\n"));
853
854 #ifdef DIAGNOSTIC
855 if (n > AUDIO_BUF_SIZE) {
856 printf("%s: output data too large (%d > %d)\n",
857 sc->sc_dev.dv_xname, n, AUDIO_BUF_SIZE);
858 n = AUDIO_BUF_SIZE;
859 }
860 #endif
861 n /= 2;
862 while (n--) {
863 short i = ulaw_to_lin[*q++];
864 short j = ulaw_to_lin[*q++];
865 *dmap++ = (i + j) << 1;
866 }
867 }
868
869 static void
870 vraiu_slinear16_1(struct vraiu_softc *sc, u_short *dmap, void *p, int n)
871 {
872 short *q = (short*)p;
873
874 DPRINTFN(3, ("vraiu_slinear16_1\n"));
875
876 #ifdef DIAGNOSTIC
877 if (n > AUDIO_BUF_SIZE) {
878 printf("%s: output data too large (%d > %d)\n",
879 sc->sc_dev.dv_xname, n, AUDIO_BUF_SIZE);
880 n = AUDIO_BUF_SIZE;
881 }
882 #endif
883 n /= 2;
884 while (n--) {
885 short i = *q++;
886 *dmap++ = (i >> 6) + 0x200;
887 }
888 }
889
890 static void
891 vraiu_slinear16_2(struct vraiu_softc *sc, u_short *dmap, void *p, int n)
892 {
893 short *q = (short*)p;
894
895 DPRINTFN(3, ("vraiu_slinear16_2\n"));
896
897 #ifdef DIAGNOSTIC
898 if (n > AUDIO_BUF_SIZE*2) {
899 printf("%s: output data too large (%d > %d)\n",
900 sc->sc_dev.dv_xname, n, AUDIO_BUF_SIZE*2);
901 n = AUDIO_BUF_SIZE*2;
902 }
903 #endif
904 n /= 4;
905 while (n--) {
906 short i = *q++;
907 short j = *q++;
908 *dmap++ = (i >> 7) + (j >> 7) + 0x200;
909 }
910 }
911
912 static void
913 vraiu_slinear16sw_1(struct vraiu_softc *sc, u_short *dmap, void *p, int n)
914 {
915 short *q = (short*)p;
916
917 DPRINTFN(3, ("vraiu_slinear16sw_1\n"));
918
919 #ifdef DIAGNOSTIC
920 if (n > AUDIO_BUF_SIZE) {
921 printf("%s: output data too large (%d > %d)\n",
922 sc->sc_dev.dv_xname, n, AUDIO_BUF_SIZE);
923 n = AUDIO_BUF_SIZE;
924 }
925 #endif
926 n /= 2;
927 while (n--) {
928 short i = bswap16(*q++);
929 *dmap++ = (i >> 6) + 0x200;
930 }
931 }
932
933 static void
934 vraiu_slinear16sw_2(struct vraiu_softc *sc, u_short *dmap, void *p, int n)
935 {
936 short *q = (short*)p;
937
938 DPRINTFN(3, ("vraiu_slinear16sw_2\n"));
939
940 #ifdef DIAGNOSTIC
941 if (n > AUDIO_BUF_SIZE*2) {
942 printf("%s: output data too large (%d > %d)\n",
943 sc->sc_dev.dv_xname, n, AUDIO_BUF_SIZE*2);
944 n = AUDIO_BUF_SIZE*2;
945 }
946 #endif
947 n /= 4;
948 while (n--) {
949 short i = bswap16(*q++);
950 short j = bswap16(*q++);
951 *dmap++ = (i >> 7) + (j >> 7) + 0x200;
952 }
953 }
954