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