No empty .Rs/.Re
[netbsd-mini2440.git] / sys / dev / ic / tms320av110.c
blob8315be09adef6518eeabbd490fe1c9aed420b911
1 /* $NetBSD: tms320av110.c,v 1.20 2008/04/08 12:07:27 cegger Exp $ */
3 /*-
4 * Copyright (c) 1997 The NetBSD Foundation, Inc.
5 * All rights reserved.
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
12 * are met:
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>
46 #include <sys/proc.h>
48 #include <sys/audioio.h>
49 #include <dev/audio_if.h>
51 #include <dev/ic/tms320av110reg.h>
52 #include <dev/ic/tms320av110var.h>
54 #include <sys/bus.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 = {
77 tav_open,
78 tav_close,
79 0 /* tav_drain*/, /* optional */
80 tav_query_encoding,
81 tav_set_params,
82 tav_round_blocksize,
83 0 /* commit_settings */, /* optional */
84 tav_init_output, /* optional */
85 0 /* tav_init_input */, /* optional */
86 tav_start_output,
87 tav_start_input,
88 tav_halt_output,
89 tav_halt_input,
90 tav_speaker_ctl, /* optional */
91 tav_getdev,
92 0 /* setfd */, /* optional */
93 tav_set_port,
94 tav_get_port,
95 tav_query_devinfo,
96 0 /* alloc */, /* optional */
97 0 /* free */, /* optional */
98 0 /* round_buffersize */, /* optional */
99 0 /* mappage */, /* optional */
100 tav_get_props,
101 0 /* dev_ioctl */ /* optional */
104 void
105 tms320av110_attach_mi(struct tav_softc *sc)
107 bus_space_tag_t iot;
108 bus_space_handle_t ioh;
110 iot = sc->sc_iot;
111 ioh = sc->sc_ioh;
112 tav_write_byte(iot, ioh, TAV_RESET, 1);
113 while (tav_read_byte(iot, ioh, TAV_RESET))
114 delay(250);
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;
146 uint16_t intlist;
148 sc = p;
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)*/;
152 if (!intlist)
153 return 0;
155 /* ack now, so that we don't miss later interrupts */
156 if (sc->sc_intack)
157 (sc->sc_intack)(sc);
159 if (intlist & TAV_INTR_LOWWATER) {
160 (*sc->sc_intr)(sc->sc_intrarg);
163 if (intlist & TAV_INTR_PCM_OUTPUT_UNDERFLOW) {
164 wakeup(sc);
167 return 1;
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)
181 /* dummy */
182 return 0;
185 void
186 tav_close(void *hdl)
188 struct tav_softc *sc;
189 bus_space_tag_t iot;
190 bus_space_handle_t ioh;
192 sc = hdl;
193 iot = sc->sc_iot;
194 ioh = sc->sc_ioh;
196 /* re"start" chip, also clears interrupts and interrupt enable */
197 tav_write_short(iot, ioh, TAV_INTR_EN, 0);
198 if (sc->sc_intack)
199 (*sc->sc_intack)(sc);
203 tav_drain(void *hdl)
205 struct tav_softc *sc;
206 bus_space_tag_t iot;
207 bus_space_handle_t ioh;
208 u_int16_t mask;
210 sc = hdl;
211 iot = sc->sc_iot;
212 ioh = sc->sc_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);
233 return 0;
237 tav_query_encoding(void *hdl, struct audio_encoding *ae)
239 struct tav_softc *sc;
241 sc = hdl;
242 if (ae->index >= sizeof(tav_encodings)/sizeof(*ae))
243 return EINVAL;
245 *ae = tav_encodings[ae->index];
247 return 0;
251 tav_start_input(void *hdl, void *block, int bsize,
252 void (*intr)(void *), void *intrarg)
255 return ENOTTY;
259 tav_halt_input(void *hdl)
262 return ENOTTY;
266 tav_start_output(void *hdl, void *block, int bsize,
267 void (*intr)(void *), void *intrarg)
269 struct tav_softc *sc;
270 bus_space_tag_t iot;
271 bus_space_handle_t ioh;
272 uint8_t *ptr;
273 int count;
275 sc = hdl;
276 iot = sc->sc_iot;
277 ioh = sc->sc_ioh;
278 ptr = block;
279 count = bsize;
281 sc->sc_intr = intr;
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);
287 return 0;
291 tav_init_output(void *hdl, void *buffer, int size)
293 struct tav_softc *sc;
294 bus_space_tag_t iot;
295 bus_space_handle_t ioh;
297 sc = hdl;
298 iot = sc->sc_iot;
299 ioh = sc->sc_ioh;
301 tav_write_byte(iot, ioh, TAV_PLAY, 1);
302 tav_write_byte(iot, ioh, TAV_MUTE, 0);
304 return 0;
308 tav_halt_output(void *hdl)
310 struct tav_softc *sc;
311 bus_space_tag_t iot;
312 bus_space_handle_t ioh;
314 sc = hdl;
315 iot = sc->sc_iot;
316 ioh = sc->sc_ioh;
318 tav_write_byte(iot, ioh, TAV_PLAY, 0);
320 return 0;
324 tav_getdev(void *hdl, struct audio_device *ret)
326 struct tav_softc *sc;
327 bus_space_tag_t iot;
328 bus_space_handle_t ioh;
330 sc = hdl;
331 iot = sc->sc_iot;
332 ioh = sc->sc_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));
340 return 0;
344 tav_round_blocksize(void *hdl, int size, int mode, const audio_params_t *param)
346 struct tav_softc *sc;
347 bus_space_tag_t iot;
348 bus_space_handle_t ioh;
349 int maxhalf;
351 sc = hdl;
352 iot = sc->sc_iot;
353 ioh = sc->sc_ioh;
355 maxhalf = TAV_DRAM_HSIZE(tav_read_byte(iot, ioh, TAV_DRAM_EXT));
356 if (size > maxhalf)
357 size = maxhalf;
359 /* XXX should round to 128 bytes limits for audio bypass */
360 size &= ~3;
362 tav_write_short(iot, ioh, TAV_BALE_LIM, size/8);
364 /* the buffer limits are in units of 4 bytes */
365 return (size);
369 tav_get_props(void *hdl)
371 return 0;
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;
379 bus_space_tag_t iot;
380 bus_space_handle_t ioh;
382 sc = hdl;
383 iot = sc->sc_iot;
384 ioh = sc->sc_ioh;
386 if (!(setmode & AUMODE_PLAY))
387 return 0;
389 if (p->encoding == AUDIO_ENCODING_ULAW)
390 p->encoding = AUDIO_ENCODING_MPEG_L2_STREAM;
392 switch(p->encoding) {
393 default:
394 return EINVAL;
396 case AUDIO_ENCODING_SLINEAR_BE:
398 /* XXX: todo: add 8bit and mono using software */
399 p->precision = 16;
400 p->channels = 2;
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);
409 break;
411 /* XXX: later: add ULINEAR, and LE using software encoding */
413 case AUDIO_ENCODING_MPEG_L1_STREAM:
414 /* FALLTHROUGH */
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;
419 p->precision = 1;
420 break;
422 case AUDIO_ENCODING_MPEG_L1_PACKETS:
423 /* FALLTHROUGH */
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;
428 p->precision = 1;
429 break;
431 case AUDIO_ENCODING_MPEG_L1_SYSTEM:
432 /* FALLTHROUGH */
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;
437 p->precision = 1;
438 break;
440 tav_write_byte(iot, ioh, TAV_RESTART, 1);
441 do {
442 delay(10);
443 } while (tav_read_byte(iot, ioh, TAV_RESTART));
445 return 0;
449 tav_set_port(void *hdl, mixer_ctrl_t *mc)
451 struct tav_softc *sc;
453 sc = hdl;
454 /* dummy */
455 return 0;
459 tav_get_port(void *hdl, mixer_ctrl_t *mc)
461 struct tav_softc *sc;
463 sc = hdl;
464 /* dummy */
465 return 0;
469 tav_query_devinfo(void *hdl, mixer_devinfo_t *di)
471 return ENXIO;
475 tav_speaker_ctl(void *hdl, int value)
477 struct tav_softc *sc;
478 bus_space_tag_t iot;
479 bus_space_handle_t ioh;
481 sc = hdl;
482 iot = sc->sc_iot;
483 ioh = sc->sc_ioh;
485 tav_write_byte(iot, ioh, TAV_MUTE, !value);
487 return 0;