1 /* $NetBSD: tms320av110.c,v 1.20 2008/04/08 12:07:27 cegger Exp $ */
4 * Copyright (c) 1997 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Ignatios Souvatzis.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * Machine independent part of TMS320AV110 driver.
35 * Currently, only minimum support for audio output. For audio/video
36 * synchronization, more is needed.
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: tms320av110.c,v 1.20 2008/04/08 12:07:27 cegger Exp $");
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/device.h>
48 #include <sys/audioio.h>
49 #include <dev/audio_if.h>
51 #include <dev/ic/tms320av110reg.h>
52 #include <dev/ic/tms320av110var.h>
56 int tav_open(void *, int);
57 void tav_close(void *);
58 int tav_drain(void *);
59 int tav_query_encoding(void *, struct audio_encoding
*);
60 int tav_set_params(void *, int, int, audio_params_t
*, audio_params_t
*,
61 stream_filter_list_t
*, stream_filter_list_t
*);
62 int tav_round_blocksize(void *, int, int, const audio_params_t
*);
63 int tav_init_output(void *, void *, int);
64 int tav_start_output(void *, void *, int, void (*)(void *), void *);
65 int tav_start_input(void *, void *, int, void (*)(void *), void *);
66 int tav_halt_output(void *);
67 int tav_halt_input(void *);
68 int tav_speaker_ctl(void *, int);
69 int tav_getdev(void *, struct audio_device
*);
70 int tav_setfd(void *, int);
71 int tav_set_port(void *, mixer_ctrl_t
*);
72 int tav_get_port(void *, mixer_ctrl_t
*);
73 int tav_query_devinfo(void *, mixer_devinfo_t
*);
74 int tav_get_props(void *);
76 const struct audio_hw_if tav_audio_if
= {
79 0 /* tav_drain*/, /* optional */
83 0 /* commit_settings */, /* optional */
84 tav_init_output
, /* optional */
85 0 /* tav_init_input */, /* optional */
90 tav_speaker_ctl
, /* optional */
92 0 /* setfd */, /* optional */
96 0 /* alloc */, /* optional */
97 0 /* free */, /* optional */
98 0 /* round_buffersize */, /* optional */
99 0 /* mappage */, /* optional */
101 0 /* dev_ioctl */ /* optional */
105 tms320av110_attach_mi(struct tav_softc
*sc
)
108 bus_space_handle_t ioh
;
112 tav_write_byte(iot
, ioh
, TAV_RESET
, 1);
113 while (tav_read_byte(iot
, ioh
, TAV_RESET
))
116 tav_write_byte(iot
, ioh
, TAV_PCM_ORD
, sc
->sc_pcm_ord
);
117 tav_write_byte(iot
, ioh
, TAV_PCM_18
, sc
->sc_pcm_18
);
118 tav_write_byte(iot
, ioh
, TAV_DIF
, sc
->sc_dif
);
119 tav_write_byte(iot
, ioh
, TAV_PCM_DIV
, sc
->sc_pcm_div
);
121 printf(": chip rev. %d, %d bytes buffer\n",
122 tav_read_byte(iot
, ioh
, TAV_VERSION
),
123 TAV_DRAM_SIZE(tav_read_byte(iot
, ioh
, TAV_DRAM_EXT
)));
125 tav_write_byte(iot
, ioh
, TAV_AUD_ID_EN
, 0);
126 tav_write_byte(iot
, ioh
, TAV_SKIP
, 0);
127 tav_write_byte(iot
, ioh
, TAV_REPEAT
, 0);
128 tav_write_byte(iot
, ioh
, TAV_MUTE
, 0);
129 tav_write_byte(iot
, ioh
, TAV_PLAY
, 1);
130 tav_write_byte(iot
, ioh
, TAV_SYNC_ECM
, 0);
131 tav_write_byte(iot
, ioh
, TAV_CRC_ECM
, 0);
132 tav_write_byte(iot
, ioh
, TAV_ATTEN_L
, 0);
133 tav_write_byte(iot
, ioh
, TAV_ATTEN_R
, 0);
134 tav_write_short(iot
, ioh
, TAV_FREE_FORM
, 0);
135 tav_write_byte(iot
, ioh
, TAV_SIN_EN
, 0);
136 tav_write_byte(iot
, ioh
, TAV_SYNC_ECM
, TAV_ECM_REPEAT
);
137 tav_write_byte(iot
, ioh
, TAV_CRC_ECM
, TAV_ECM_REPEAT
);
139 audio_attach_mi(&tav_audio_if
, sc
, &sc
->sc_dev
);
143 tms320av110_intr(void *p
)
145 struct tav_softc
*sc
;
149 intlist
= tav_read_short(sc
->sc_iot
, sc
->sc_ioh
, TAV_INTR
)
150 /* & tav_read_short(sc->sc_iot, sc->sc_ioh, TAV_INTR_EN)*/;
155 /* ack now, so that we don't miss later interrupts */
159 if (intlist
& TAV_INTR_LOWWATER
) {
160 (*sc
->sc_intr
)(sc
->sc_intrarg
);
163 if (intlist
& TAV_INTR_PCM_OUTPUT_UNDERFLOW
) {
170 struct audio_encoding tav_encodings
[] = {
171 {0, AudioEmpeg_l2_stream
, AUDIO_ENCODING_MPEG_L2_STREAM
, 1, 0,},
172 {1, AudioEmpeg_l2_packets
, AUDIO_ENCODING_MPEG_L2_PACKETS
, 1, 0,},
173 {2, AudioEmpeg_l2_system
, AUDIO_ENCODING_MPEG_L2_SYSTEM
, 1, 0,},
174 {3, AudioEslinear_be
, AUDIO_ENCODING_SLINEAR_BE
, 16, 0,},
178 tav_open(void *hdl
, int flags
)
188 struct tav_softc
*sc
;
190 bus_space_handle_t ioh
;
196 /* re"start" chip, also clears interrupts and interrupt enable */
197 tav_write_short(iot
, ioh
, TAV_INTR_EN
, 0);
199 (*sc
->sc_intack
)(sc
);
205 struct tav_softc
*sc
;
207 bus_space_handle_t ioh
;
215 * tsleep waiting for underflow interrupt.
217 if (tav_read_short(iot
, ioh
, TAV_BUFF
)) {
218 mask
= tav_read_short(iot
, ioh
, TAV_INTR_EN
);
219 tav_write_short(iot
, ioh
, TAV_INTR_EN
,
220 mask
|TAV_INTR_PCM_OUTPUT_UNDERFLOW
);
222 /* still more than zero? */
223 if (tav_read_short(iot
, ioh
, TAV_BUFF
))
224 (void)tsleep(sc
, PCATCH
, "tavdrain", 32*hz
);
226 /* can be really that long for mpeg */
228 mask
= tav_read_short(iot
, ioh
, TAV_INTR_EN
);
229 tav_write_short(iot
, ioh
, TAV_INTR_EN
,
230 mask
& ~TAV_INTR_PCM_OUTPUT_UNDERFLOW
);
237 tav_query_encoding(void *hdl
, struct audio_encoding
*ae
)
239 struct tav_softc
*sc
;
242 if (ae
->index
>= sizeof(tav_encodings
)/sizeof(*ae
))
245 *ae
= tav_encodings
[ae
->index
];
251 tav_start_input(void *hdl
, void *block
, int bsize
,
252 void (*intr
)(void *), void *intrarg
)
259 tav_halt_input(void *hdl
)
266 tav_start_output(void *hdl
, void *block
, int bsize
,
267 void (*intr
)(void *), void *intrarg
)
269 struct tav_softc
*sc
;
271 bus_space_handle_t ioh
;
282 sc
->sc_intrarg
= intrarg
;
284 bus_space_write_multi_1(iot
, ioh
, TAV_DATAIN
, ptr
, count
);
285 tav_write_short(iot
, ioh
, TAV_INTR_EN
, TAV_INTR_LOWWATER
);
291 tav_init_output(void *hdl
, void *buffer
, int size
)
293 struct tav_softc
*sc
;
295 bus_space_handle_t ioh
;
301 tav_write_byte(iot
, ioh
, TAV_PLAY
, 1);
302 tav_write_byte(iot
, ioh
, TAV_MUTE
, 0);
308 tav_halt_output(void *hdl
)
310 struct tav_softc
*sc
;
312 bus_space_handle_t ioh
;
318 tav_write_byte(iot
, ioh
, TAV_PLAY
, 0);
324 tav_getdev(void *hdl
, struct audio_device
*ret
)
326 struct tav_softc
*sc
;
328 bus_space_handle_t ioh
;
334 strlcpy(ret
->name
, "tms320av110", sizeof(ret
->name
));
335 /* guaranteed to be <= 4 in length */
336 snprintf(ret
->version
, sizeof(ret
->version
), "%u",
337 tav_read_byte(iot
, ioh
, TAV_VERSION
));
338 strlcpy(ret
->config
, device_xname(&sc
->sc_dev
), sizeof(ret
->config
));
344 tav_round_blocksize(void *hdl
, int size
, int mode
, const audio_params_t
*param
)
346 struct tav_softc
*sc
;
348 bus_space_handle_t ioh
;
355 maxhalf
= TAV_DRAM_HSIZE(tav_read_byte(iot
, ioh
, TAV_DRAM_EXT
));
359 /* XXX should round to 128 bytes limits for audio bypass */
362 tav_write_short(iot
, ioh
, TAV_BALE_LIM
, size
/8);
364 /* the buffer limits are in units of 4 bytes */
369 tav_get_props(void *hdl
)
375 tav_set_params(void *hdl
, int setmode
, int usemode
, audio_params_t
*p
,
376 audio_params_t
*r
, stream_filter_list_t
*pfil
, stream_filter_list_t
*rfil
)
378 struct tav_softc
*sc
;
380 bus_space_handle_t ioh
;
386 if (!(setmode
& AUMODE_PLAY
))
389 if (p
->encoding
== AUDIO_ENCODING_ULAW
)
390 p
->encoding
= AUDIO_ENCODING_MPEG_L2_STREAM
;
392 switch(p
->encoding
) {
396 case AUDIO_ENCODING_SLINEAR_BE
:
398 /* XXX: todo: add 8bit and mono using software */
402 /* XXX: this might depend on the specific board.
403 should be handled by the backend */
405 p
->sample_rate
= 44100;
407 bus_space_write_1(iot
, ioh
, TAV_STR_SEL
,
408 TAV_STR_SEL_AUDIO_BYPASS
);
411 /* XXX: later: add ULINEAR, and LE using software encoding */
413 case AUDIO_ENCODING_MPEG_L1_STREAM
:
415 case AUDIO_ENCODING_MPEG_L2_STREAM
:
416 bus_space_write_1(iot
, ioh
, TAV_STR_SEL
,
417 TAV_STR_SEL_MPEG_AUDIO_STREAM
);
418 p
->sample_rate
= 44100;
422 case AUDIO_ENCODING_MPEG_L1_PACKETS
:
424 case AUDIO_ENCODING_MPEG_L2_PACKETS
:
425 bus_space_write_1(iot
, ioh
, TAV_STR_SEL
,
426 TAV_STR_SEL_MPEG_AUDIO_PACKETS
);
427 p
->sample_rate
= 44100;
431 case AUDIO_ENCODING_MPEG_L1_SYSTEM
:
433 case AUDIO_ENCODING_MPEG_L2_SYSTEM
:
434 bus_space_write_1(iot
, ioh
, TAV_STR_SEL
,
435 TAV_STR_SEL_MPEG_SYSTEM_STREAM
);
436 p
->sample_rate
= 44100;
440 tav_write_byte(iot
, ioh
, TAV_RESTART
, 1);
443 } while (tav_read_byte(iot
, ioh
, TAV_RESTART
));
449 tav_set_port(void *hdl
, mixer_ctrl_t
*mc
)
451 struct tav_softc
*sc
;
459 tav_get_port(void *hdl
, mixer_ctrl_t
*mc
)
461 struct tav_softc
*sc
;
469 tav_query_devinfo(void *hdl
, mixer_devinfo_t
*di
)
475 tav_speaker_ctl(void *hdl
, int value
)
477 struct tav_softc
*sc
;
479 bus_space_handle_t ioh
;
485 tav_write_byte(iot
, ioh
, TAV_MUTE
, !value
);