1 /* $NetBSD: aica.c,v 1.17 2008/01/06 10:33:24 he Exp $ */
4 * Copyright (c) 2003 SHIMIZU Ryo <ryo@misakimix.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: aica.c,v 1.17 2008/01/06 10:33:24 he Exp $");
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/device.h>
37 #include <sys/kernel.h>
39 #include <sys/audioio.h>
41 #include <dev/audio_if.h>
42 #include <dev/mulaw.h>
43 #include <dev/auconv.h>
45 #include <machine/bus.h>
46 #include <machine/sysasicvar.h>
48 #include <dreamcast/dev/g2/g2busvar.h>
49 #include <dreamcast/dev/g2/aicavar.h>
50 #include <dreamcast/dev/microcode/aica_armcode.h>
52 #define AICA_REG_ADDR 0x00700000
53 #define AICA_RAM_START 0x00800000
54 #define AICA_RAM_SIZE 0x00200000
56 #define AICA_TIMEOUT 0x1800
59 struct device sc_dev
; /* base device */
60 bus_space_tag_t sc_memt
;
61 bus_space_handle_t sc_aica_regh
;
62 bus_space_handle_t sc_aica_memh
;
70 void (*sc_intr
)(void *);
74 int sc_output_gain
[2];
75 #define AICA_VOLUME_LEFT 0
76 #define AICA_VOLUME_RIGHT 1
80 void *sc_buffer_start
;
90 } aica_encodings
[] = {
91 {AudioEadpcm
, AUDIO_ENCODING_ADPCM
, 4},
92 {AudioEslinear
, AUDIO_ENCODING_SLINEAR
, 8},
93 {AudioEulinear
, AUDIO_ENCODING_ULINEAR
, 8},
94 {AudioEmulaw
, AUDIO_ENCODING_ULAW
, 8},
95 {AudioEalaw
, AUDIO_ENCODING_ALAW
, 8},
96 {AudioEslinear_be
, AUDIO_ENCODING_SLINEAR_BE
, 16},
97 {AudioEslinear_le
, AUDIO_ENCODING_SLINEAR_LE
, 16},
98 {AudioEulinear_be
, AUDIO_ENCODING_ULINEAR_BE
, 16},
99 {AudioEulinear_le
, AUDIO_ENCODING_ULINEAR_LE
, 16},
102 #define AICA_NFORMATS 5
103 static const struct audio_format aica_formats
[AICA_NFORMATS
] = {
104 {NULL
, AUMODE_PLAY
, AUDIO_ENCODING_ADPCM
, 4, 4,
105 1, AUFMT_MONAURAL
, 0, {1, 65536}},
106 {NULL
, AUMODE_PLAY
, AUDIO_ENCODING_SLINEAR_LE
, 16, 16,
107 1, AUFMT_MONAURAL
, 0, {1, 65536}},
108 {NULL
, AUMODE_PLAY
, AUDIO_ENCODING_SLINEAR_LE
, 16, 16,
109 2, AUFMT_STEREO
, 0, {1, 65536}},
110 {NULL
, AUMODE_PLAY
, AUDIO_ENCODING_SLINEAR_LE
, 8, 8,
111 1, AUFMT_MONAURAL
, 0, {1, 65536}},
112 {NULL
, AUMODE_PLAY
, AUDIO_ENCODING_SLINEAR_LE
, 8, 8,
113 2, AUFMT_STEREO
, 0, {1, 65536}},
116 int aica_match(struct device
*, struct cfdata
*, void *);
117 void aica_attach(struct device
*, struct device
*, void *);
118 int aica_print(void *, const char *);
120 CFATTACH_DECL(aica
, sizeof(struct aica_softc
), aica_match
, aica_attach
,
123 const struct audio_device aica_device
= {
129 inline static void aica_g2fifo_wait(void);
130 void aica_enable(struct aica_softc
*);
131 void aica_disable(struct aica_softc
*);
132 void aica_memwrite(struct aica_softc
*, bus_size_t
, uint32_t *, int);
133 void aica_ch2p16write(struct aica_softc
*, bus_size_t
, uint16_t *, int);
134 void aica_ch2p8write(struct aica_softc
*, bus_size_t
, uint8_t *, int);
135 void aica_command(struct aica_softc
*, uint32_t);
136 void aica_sendparam(struct aica_softc
*, uint32_t, int, int);
137 void aica_play(struct aica_softc
*, int, int, int, int);
138 void aica_fillbuffer(struct aica_softc
*);
141 int aica_intr(void *);
144 int aica_open(void *, int);
145 void aica_close(void *);
146 int aica_query_encoding(void *, struct audio_encoding
*);
147 int aica_set_params(void *, int, int, audio_params_t
*,
148 audio_params_t
*, stream_filter_list_t
*, stream_filter_list_t
*);
149 int aica_round_blocksize(void *, int, int, const audio_params_t
*);
150 size_t aica_round_buffersize(void *, int, size_t);
151 int aica_trigger_output(void *, void *, void *, int, void (*)(void *), void *,
152 const audio_params_t
*);
153 int aica_trigger_input(void *, void *, void *, int, void (*)(void *), void *,
154 const audio_params_t
*);
155 int aica_halt_output(void *);
156 int aica_halt_input(void *);
157 int aica_getdev(void *, struct audio_device
*);
158 int aica_set_port(void *, mixer_ctrl_t
*);
159 int aica_get_port(void *, mixer_ctrl_t
*);
160 int aica_query_devinfo(void *, mixer_devinfo_t
*);
161 void aica_encode(int, int, int, int, u_char
*, u_short
**);
162 int aica_get_props(void *);
164 const struct audio_hw_if aica_hw_if
= {
167 NULL
, /* aica_drain */
170 aica_round_blocksize
,
171 NULL
, /* aica_commit_setting */
172 NULL
, /* aica_init_output */
173 NULL
, /* aica_init_input */
174 NULL
, /* aica_start_output */
175 NULL
, /* aica_start_input */
178 NULL
, /* aica_speaker_ctl */
180 NULL
, /* aica_setfd */
184 NULL
, /* aica_allocm */
185 NULL
, /* aica_freem */
187 aica_round_buffersize
, /* aica_round_buffersize */
189 NULL
, /* aica_mappage */
193 NULL
, /* aica_dev_ioctl */
197 aica_match(struct device
*parent
, struct cfdata
*cf
, void *aux
)
199 static int aica_matched
= 0;
209 aica_attach(struct device
*parent
, struct device
*self
, void *aux
)
211 struct aica_softc
*sc
;
212 struct g2bus_attach_args
*ga
;
215 sc
= (struct aica_softc
*)self
;
217 sc
->sc_memt
= ga
->ga_memt
;
219 if (bus_space_map(sc
->sc_memt
, AICA_REG_ADDR
, 0x3000, 0,
220 &sc
->sc_aica_regh
) != 0) {
221 printf(": can't map AICA register space\n");
225 if (bus_space_map(sc
->sc_memt
, AICA_RAM_START
, AICA_RAM_SIZE
, 0,
226 &sc
->sc_aica_memh
) != 0) {
227 printf(": can't map AICA memory space\n");
231 printf(": ARM7 Sound Processing Unit\n");
235 for (i
= 0; i
< AICA_NCHAN
; i
++)
236 bus_space_write_4(sc
->sc_memt
,sc
->sc_aica_regh
, i
<< 7,
237 ((bus_space_read_4(sc
->sc_memt
, sc
->sc_aica_regh
, i
<< 7)
238 & ~0x4000) | 0x8000));
240 /* load microcode, and clear memory */
241 bus_space_set_region_4(sc
->sc_memt
, sc
->sc_aica_memh
,
242 0, 0, AICA_RAM_SIZE
/ 4);
244 aica_memwrite(sc
, 0, aica_armcode
, sizeof(aica_armcode
));
248 printf("%s: interrupting at %s\n", sc
->sc_dev
.dv_xname
,
249 sysasic_intr_string(SYSASIC_IRL9
));
250 sysasic_intr_establish(SYSASIC_EVENT_AICA
, IPL_BIO
, SYSASIC_IRL9
,
253 audio_attach_mi(&aica_hw_if
, sc
, &sc
->sc_dev
);
255 /* init parameters */
256 sc
->sc_output_master
= 255;
257 sc
->sc_output_gain
[AICA_VOLUME_LEFT
] = 255;
258 sc
->sc_output_gain
[AICA_VOLUME_RIGHT
] = 255;
262 aica_enable(struct aica_softc
*sc
)
265 bus_space_write_4(sc
->sc_memt
, sc
->sc_aica_regh
, 0x28a8, 24);
266 bus_space_write_4(sc
->sc_memt
, sc
->sc_aica_regh
, 0x2c00,
267 bus_space_read_4(sc
->sc_memt
, sc
->sc_aica_regh
, 0x2c00) & ~1);
271 aica_disable(struct aica_softc
*sc
)
274 bus_space_write_4(sc
->sc_memt
, sc
->sc_aica_regh
, 0x2c00,
275 bus_space_read_4(sc
->sc_memt
, sc
->sc_aica_regh
, 0x2c00) | 1);
279 aica_g2fifo_wait(void)
285 if ((*(volatile uint32_t *)0xa05f688c) & 0x11)
290 aica_memwrite(struct aica_softc
*sc
, bus_size_t offset
, uint32_t *src
, int len
)
294 KASSERT((offset
& 3) == 0);
295 n
= (len
+ 3) / 4; /* uint32_t * n (aligned) */
298 bus_space_write_region_4(sc
->sc_memt
, sc
->sc_aica_memh
,
303 aica_ch2p16write(struct aica_softc
*sc
, bus_size_t offset
, uint16_t *src
,
313 KASSERT((offset
& 3) == 0);
317 *p
++ = *src
++; src
++;
318 *p
++ = *src
++; src
++;
319 *p
++ = *src
++; src
++;
320 *p
++ = *src
++; src
++;
321 *p
++ = *src
++; src
++;
322 *p
++ = *src
++; src
++;
323 *p
++ = *src
++; src
++;
324 *p
++ = *src
++; src
++;
325 *p
++ = *src
++; src
++;
326 *p
++ = *src
++; src
++;
327 *p
++ = *src
++; src
++;
328 *p
++ = *src
++; src
++;
329 *p
++ = *src
++; src
++;
330 *p
++ = *src
++; src
++;
331 *p
++ = *src
++; src
++;
332 *p
++ = *src
++; src
++;
335 bus_space_write_region_4(sc
->sc_memt
, sc
->sc_aica_memh
,
336 offset
, buf
.w
, 32 / 4);
338 offset
+= sizeof(uint16_t) * 16;
344 for (i
= 0; i
< len
/ 2; i
++) {
345 *p
++ = *src
++; src
++;
349 bus_space_write_region_4(sc
->sc_memt
, sc
->sc_aica_memh
,
350 offset
, buf
.w
, len
/ 4);
355 aica_ch2p8write(struct aica_softc
*sc
, bus_size_t offset
, uint8_t *src
,
362 KASSERT((offset
& 3) == 0);
366 *p
++ = *src
++; src
++;
367 *p
++ = *src
++; src
++;
368 *p
++ = *src
++; src
++;
369 *p
++ = *src
++; src
++;
370 *p
++ = *src
++; src
++;
371 *p
++ = *src
++; src
++;
372 *p
++ = *src
++; src
++;
373 *p
++ = *src
++; src
++;
374 *p
++ = *src
++; src
++;
375 *p
++ = *src
++; src
++;
376 *p
++ = *src
++; src
++;
377 *p
++ = *src
++; src
++;
378 *p
++ = *src
++; src
++;
379 *p
++ = *src
++; src
++;
380 *p
++ = *src
++; src
++;
381 *p
++ = *src
++; src
++;
382 *p
++ = *src
++; src
++;
383 *p
++ = *src
++; src
++;
384 *p
++ = *src
++; src
++;
385 *p
++ = *src
++; src
++;
386 *p
++ = *src
++; src
++;
387 *p
++ = *src
++; src
++;
388 *p
++ = *src
++; src
++;
389 *p
++ = *src
++; src
++;
390 *p
++ = *src
++; src
++;
391 *p
++ = *src
++; src
++;
392 *p
++ = *src
++; src
++;
393 *p
++ = *src
++; src
++;
394 *p
++ = *src
++; src
++;
395 *p
++ = *src
++; src
++;
396 *p
++ = *src
++; src
++;
397 *p
++ = *src
++; src
++;
400 bus_space_write_region_4(sc
->sc_memt
, sc
->sc_aica_memh
,
401 offset
, buf
, 32 / 4);
409 for (i
= 0; i
< len
; i
++)
410 *p
++ = *src
++; src
++;
413 bus_space_write_region_4(sc
->sc_memt
, sc
->sc_aica_memh
,
414 offset
, buf
, len
/ 4);
419 aica_open(void *addr
, int flags
)
421 struct aica_softc
*sc
;
434 aica_close(void *addr
)
436 struct aica_softc
*sc
;
444 aica_query_encoding(void *addr
, struct audio_encoding
*fp
)
446 if (fp
->index
>= sizeof(aica_encodings
) / sizeof(aica_encodings
[0]))
449 strcpy(fp
->name
, aica_encodings
[fp
->index
].name
);
450 fp
->encoding
= aica_encodings
[fp
->index
].encoding
;
451 fp
->precision
= aica_encodings
[fp
->index
].precision
;
458 aica_set_params(void *addr
, int setmode
, int usemode
,
459 audio_params_t
*play
, audio_params_t
*rec
,
460 stream_filter_list_t
*pfil
, stream_filter_list_t
*rfil
)
462 struct aica_softc
*sc
;
463 const audio_params_t
*hw
;
466 i
= auconv_set_converter(aica_formats
, AICA_NFORMATS
,
467 AUMODE_PLAY
, play
, false, pfil
);
470 hw
= pfil
->req_size
> 0 ? &pfil
->filters
[0].param
: play
;
472 sc
->sc_precision
= hw
->precision
;
473 sc
->sc_channels
= hw
->channels
;
474 sc
->sc_rate
= hw
->sample_rate
;
475 sc
->sc_encodings
= hw
->encoding
;
480 aica_round_blocksize(void *addr
, int blk
, int mode
, const audio_params_t
*param
)
482 struct aica_softc
*sc
;
485 switch (sc
->sc_precision
) {
487 if (sc
->sc_channels
== 1)
488 return AICA_DMABUF_SIZE
/ 4;
490 return AICA_DMABUF_SIZE
/ 2;
493 if (sc
->sc_channels
== 1)
494 return AICA_DMABUF_SIZE
/ 2;
496 return AICA_DMABUF_SIZE
;
499 if (sc
->sc_channels
== 1)
500 return AICA_DMABUF_SIZE
;
502 return AICA_DMABUF_SIZE
* 2;
508 return AICA_DMABUF_SIZE
/ 4;
512 aica_round_buffersize(void *addr
, int dir
, size_t bufsize
)
515 if (dir
== AUMODE_PLAY
)
518 return 512; /* XXX: AUMINBUF */
522 aica_command(struct aica_softc
*sc
, uint32_t command
)
525 bus_space_write_4(sc
->sc_memt
, sc
->sc_aica_memh
,
526 AICA_ARM_CMD_COMMAND
, command
);
527 bus_space_write_4(sc
->sc_memt
,sc
->sc_aica_memh
, AICA_ARM_CMD_SERIAL
,
528 bus_space_read_4(sc
->sc_memt
, sc
->sc_aica_memh
,
529 AICA_ARM_CMD_SERIAL
) + 1);
533 aica_sendparam(struct aica_softc
*sc
, uint32_t command
,
534 int32_t lparam
, int32_t rparam
)
537 bus_space_write_4(sc
->sc_memt
,sc
->sc_aica_memh
,
538 AICA_ARM_CMD_LPARAM
, lparam
);
539 bus_space_write_4(sc
->sc_memt
,sc
->sc_aica_memh
,
540 AICA_ARM_CMD_RPARAM
, rparam
);
542 aica_command(sc
, command
);
546 aica_play(struct aica_softc
*sc
, int blksize
, int channel
, int rate
, int prec
)
549 bus_space_write_4(sc
->sc_memt
,sc
->sc_aica_memh
,
550 AICA_ARM_CMD_BLOCKSIZE
, blksize
);
551 bus_space_write_4(sc
->sc_memt
,sc
->sc_aica_memh
,
552 AICA_ARM_CMD_CHANNEL
, channel
);
553 bus_space_write_4(sc
->sc_memt
,sc
->sc_aica_memh
,
554 AICA_ARM_CMD_RATE
, rate
);
555 bus_space_write_4(sc
->sc_memt
,sc
->sc_aica_memh
,
556 AICA_ARM_CMD_PRECISION
, prec
);
558 aica_command(sc
, AICA_COMMAND_PLAY
);
562 aica_fillbuffer(struct aica_softc
*sc
)
565 if (sc
->sc_channels
== 2) {
566 if (sc
->sc_precision
== 16) {
568 AICA_DMABUF_LEFT
+ sc
->sc_nextfill
,
569 (uint16_t *)sc
->sc_buffer
+ 0, sc
->sc_blksize
/ 2);
571 AICA_DMABUF_RIGHT
+ sc
->sc_nextfill
,
572 (uint16_t *)sc
->sc_buffer
+ 1, sc
->sc_blksize
/ 2);
573 } else if (sc
->sc_precision
== 8) {
574 aica_ch2p8write(sc
, AICA_DMABUF_LEFT
+ sc
->sc_nextfill
,
575 (uint8_t *)sc
->sc_buffer
+ 0, sc
->sc_blksize
/ 2);
576 aica_ch2p8write(sc
, AICA_DMABUF_RIGHT
+ sc
->sc_nextfill
,
577 (uint8_t *)sc
->sc_buffer
+ 1, sc
->sc_blksize
/ 2);
580 aica_memwrite(sc
, AICA_DMABUF_MONO
+ sc
->sc_nextfill
,
581 sc
->sc_buffer
, sc
->sc_blksize
);
584 sc
->sc_buffer
= (int8_t *)sc
->sc_buffer
+ sc
->sc_blksize
;
585 if (sc
->sc_buffer
>= sc
->sc_buffer_end
)
586 sc
->sc_buffer
= sc
->sc_buffer_start
;
588 sc
->sc_nextfill
^= sc
->sc_blksize
/ sc
->sc_channels
;
594 struct aica_softc
*sc
;
599 /* call audio interrupt handler (audio_pint()) */
600 if (sc
->sc_open
&& sc
->sc_intr
!= NULL
) {
601 (*(sc
->sc_intr
))(sc
->sc_intr_arg
);
604 /* clear SPU interrupt */
605 bus_space_write_4(sc
->sc_memt
, sc
->sc_aica_regh
, 0x28bc, 0x20);
610 aica_trigger_output(void *addr
, void *start
, void *end
, int blksize
,
611 void (*intr
)(void *), void *arg
, const audio_params_t
*param
)
613 struct aica_softc
*sc
;
616 aica_command(sc
, AICA_COMMAND_INIT
);
617 tsleep(aica_trigger_output
, PWAIT
, "aicawait", hz
/ 20);
619 sc
->sc_buffer_start
= sc
->sc_buffer
= start
;
620 sc
->sc_buffer_end
= end
;
621 sc
->sc_blksize
= blksize
;
625 sc
->sc_intr_arg
= arg
;
627 /* fill buffers in advance */
631 /* ...and start playing */
632 aica_play(sc
, blksize
/ sc
->sc_channels
, sc
->sc_channels
, sc
->sc_rate
,
639 aica_trigger_input(void *addr
, void *start
, void *end
, int blksize
,
640 void (*intr
)(void *), void *arg
, const audio_params_t
*param
)
647 aica_halt_output(void *addr
)
649 struct aica_softc
*sc
;
652 aica_command(sc
, AICA_COMMAND_STOP
);
657 aica_halt_input(void *addr
)
664 aica_getdev(void *addr
, struct audio_device
*ret
)
672 aica_set_port(void *addr
, mixer_ctrl_t
*mc
)
674 struct aica_softc
*sc
;
678 case AICA_MASTER_VOL
:
679 sc
->sc_output_master
=
680 mc
->un
.value
.level
[AUDIO_MIXER_LEVEL_MONO
] & 0xff;
681 aica_sendparam(sc
, AICA_COMMAND_MVOL
,
682 sc
->sc_output_master
, sc
->sc_output_master
);
684 case AICA_OUTPUT_GAIN
:
685 sc
->sc_output_gain
[AICA_VOLUME_LEFT
] =
686 mc
->un
.value
.level
[AUDIO_MIXER_LEVEL_LEFT
] & 0xff;
687 sc
->sc_output_gain
[AICA_VOLUME_RIGHT
] =
688 mc
->un
.value
.level
[AUDIO_MIXER_LEVEL_RIGHT
] & 0xff;
689 aica_sendparam(sc
, AICA_COMMAND_VOL
,
690 sc
->sc_output_gain
[AICA_VOLUME_LEFT
],
691 sc
->sc_output_gain
[AICA_VOLUME_RIGHT
]);
701 aica_get_port(void *addr
, mixer_ctrl_t
*mc
)
703 struct aica_softc
*sc
;
707 case AICA_MASTER_VOL
:
708 if (mc
->un
.value
.num_channels
!= 1)
710 mc
->un
.value
.level
[AUDIO_MIXER_LEVEL_MONO
] =
711 L16TO256(L256TO16(sc
->sc_output_master
));
713 case AICA_OUTPUT_GAIN
:
714 mc
->un
.value
.level
[AUDIO_MIXER_LEVEL_LEFT
] =
715 sc
->sc_output_gain
[AICA_VOLUME_LEFT
];
716 mc
->un
.value
.level
[AUDIO_MIXER_LEVEL_RIGHT
] =
717 sc
->sc_output_gain
[AICA_VOLUME_RIGHT
];
726 aica_query_devinfo(void *addr
, mixer_devinfo_t
*md
)
730 case AICA_MASTER_VOL
:
731 md
->type
= AUDIO_MIXER_VALUE
;
732 md
->mixer_class
= AICA_OUTPUT_CLASS
;
733 md
->prev
= md
->next
= AUDIO_MIXER_LAST
;
734 strcpy(md
->label
.name
, AudioNmaster
);
735 md
->un
.v
.num_channels
= 1;
736 strcpy(md
->un
.v
.units
.name
, AudioNvolume
);
738 case AICA_OUTPUT_GAIN
:
739 md
->type
= AUDIO_MIXER_VALUE
;
740 md
->mixer_class
= AICA_OUTPUT_CLASS
;
741 md
->prev
= md
->next
= AUDIO_MIXER_LAST
;
742 strcpy(md
->label
.name
, AudioNoutput
);
743 md
->un
.v
.num_channels
= 2;
744 strcpy(md
->label
.name
, AudioNvolume
);
746 case AICA_OUTPUT_CLASS
:
747 md
->type
= AUDIO_MIXER_CLASS
;
748 md
->mixer_class
= AICA_OUTPUT_CLASS
;
749 md
->next
= md
->prev
= AUDIO_MIXER_LAST
;
750 strcpy(md
->label
.name
, AudioCoutputs
);
758 aica_get_props(void *addr
)