tms320av110.c revision 1.21.36.1 1 /* $NetBSD: tms320av110.c,v 1.21.36.1 2011/11/20 15:48:52 jmcneill Exp $ */
2
3 /*-
4 * Copyright (c) 1997 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Ignatios Souvatzis.
9 *
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.
18 *
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.
30 */
31
32 /*
33 * Machine independent part of TMS320AV110 driver.
34 *
35 * Currently, only minimum support for audio output. For audio/video
36 * synchronization, more is needed.
37 */
38
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: tms320av110.c,v 1.21.36.1 2011/11/20 15:48:52 jmcneill Exp $");
41
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>
47
48 #include <sys/audioio.h>
49 #include <dev/audio_if.h>
50
51 #include <dev/ic/tms320av110reg.h>
52 #include <dev/ic/tms320av110var.h>
53
54 #include <sys/bus.h>
55
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 *);
75 void tav_get_locks(void *, kmutex_t **, kmutex_t **);
76
77 const struct audio_hw_if tav_audio_if = {
78 tav_open,
79 tav_close,
80 0 /* tav_drain*/, /* optional */
81 tav_query_encoding,
82 tav_set_params,
83 tav_round_blocksize,
84 0 /* commit_settings */, /* optional */
85 tav_init_output, /* optional */
86 0 /* tav_init_input */, /* optional */
87 tav_start_output,
88 tav_start_input,
89 tav_halt_output,
90 tav_halt_input,
91 tav_speaker_ctl, /* optional */
92 tav_getdev,
93 0 /* setfd */, /* optional */
94 tav_set_port,
95 tav_get_port,
96 tav_query_devinfo,
97 0 /* alloc */, /* optional */
98 0 /* free */, /* optional */
99 0 /* round_buffersize */, /* optional */
100 0 /* mappage */, /* optional */
101 tav_get_props,
102 0, /* trigger_output */
103 0, /* trigger_input */
104 0, /* dev_ioctl */ /* optional */
105 0, /* powerhook */ /* optional */
106 tav_get_locks,
107 };
108
109 void
110 tms320av110_attach_mi(struct tav_softc *sc)
111 {
112 bus_space_tag_t iot;
113 bus_space_handle_t ioh;
114
115 iot = sc->sc_iot;
116 ioh = sc->sc_ioh;
117 tav_write_byte(iot, ioh, TAV_RESET, 1);
118 while (tav_read_byte(iot, ioh, TAV_RESET))
119 delay(250);
120
121 tav_write_byte(iot, ioh, TAV_PCM_ORD, sc->sc_pcm_ord);
122 tav_write_byte(iot, ioh, TAV_PCM_18, sc->sc_pcm_18);
123 tav_write_byte(iot, ioh, TAV_DIF, sc->sc_dif);
124 tav_write_byte(iot, ioh, TAV_PCM_DIV, sc->sc_pcm_div);
125
126 printf(": chip rev. %d, %d bytes buffer\n",
127 tav_read_byte(iot, ioh, TAV_VERSION),
128 TAV_DRAM_SIZE(tav_read_byte(iot, ioh, TAV_DRAM_EXT)));
129
130 tav_write_byte(iot, ioh, TAV_AUD_ID_EN, 0);
131 tav_write_byte(iot, ioh, TAV_SKIP, 0);
132 tav_write_byte(iot, ioh, TAV_REPEAT, 0);
133 tav_write_byte(iot, ioh, TAV_MUTE, 0);
134 tav_write_byte(iot, ioh, TAV_PLAY, 1);
135 tav_write_byte(iot, ioh, TAV_SYNC_ECM, 0);
136 tav_write_byte(iot, ioh, TAV_CRC_ECM, 0);
137 tav_write_byte(iot, ioh, TAV_ATTEN_L, 0);
138 tav_write_byte(iot, ioh, TAV_ATTEN_R, 0);
139 tav_write_short(iot, ioh, TAV_FREE_FORM, 0);
140 tav_write_byte(iot, ioh, TAV_SIN_EN, 0);
141 tav_write_byte(iot, ioh, TAV_SYNC_ECM, TAV_ECM_REPEAT);
142 tav_write_byte(iot, ioh, TAV_CRC_ECM, TAV_ECM_REPEAT);
143
144 audio_attach_mi(&tav_audio_if, sc, &sc->sc_dev);
145 }
146
147 int
148 tms320av110_intr(void *p)
149 {
150 struct tav_softc *sc;
151 uint16_t intlist;
152
153 sc = p;
154
155 mutex_spin_enter(&sc->sc_intr_lock);
156
157 intlist = tav_read_short(sc->sc_iot, sc->sc_ioh, TAV_INTR)
158 /* & tav_read_short(sc->sc_iot, sc->sc_ioh, TAV_INTR_EN)*/;
159
160 if (!intlist)
161 return 0;
162
163 /* ack now, so that we don't miss later interrupts */
164 if (sc->sc_intack)
165 (sc->sc_intack)(sc);
166
167 if (intlist & TAV_INTR_LOWWATER) {
168 (*sc->sc_intr)(sc->sc_intrarg);
169 }
170
171 if (intlist & TAV_INTR_PCM_OUTPUT_UNDERFLOW) {
172 cv_broadcast(&sc->sc_cv);
173 }
174
175 mutex_spin_exit(&sc->sc_intr_lock);
176
177 return 1;
178 }
179
180 struct audio_encoding tav_encodings[] = {
181 {0, AudioEmpeg_l2_stream, AUDIO_ENCODING_MPEG_L2_STREAM, 1, 0,},
182 {1, AudioEmpeg_l2_packets, AUDIO_ENCODING_MPEG_L2_PACKETS, 1, 0,},
183 {2, AudioEmpeg_l2_system, AUDIO_ENCODING_MPEG_L2_SYSTEM, 1, 0,},
184 {3, AudioEslinear_be, AUDIO_ENCODING_SLINEAR_BE, 16, 0,},
185 };
186
187 int
188 tav_open(void *hdl, int flags)
189 {
190
191 /* dummy */
192 return 0;
193 }
194
195 void
196 tav_close(void *hdl)
197 {
198 struct tav_softc *sc;
199 bus_space_tag_t iot;
200 bus_space_handle_t ioh;
201
202 sc = hdl;
203 iot = sc->sc_iot;
204 ioh = sc->sc_ioh;
205
206 /* re"start" chip, also clears interrupts and interrupt enable */
207 tav_write_short(iot, ioh, TAV_INTR_EN, 0);
208 if (sc->sc_intack)
209 (*sc->sc_intack)(sc);
210 }
211
212 int
213 tav_drain(void *hdl)
214 {
215 struct tav_softc *sc;
216 bus_space_tag_t iot;
217 bus_space_handle_t ioh;
218 u_int16_t mask;
219
220 sc = hdl;
221 iot = sc->sc_iot;
222 ioh = sc->sc_ioh;
223
224 mutex_spin_enter(&sc->sc_intr_lock);
225
226 /*
227 * wait for underflow interrupt.
228 */
229 if (tav_read_short(iot, ioh, TAV_BUFF)) {
230 mask = tav_read_short(iot, ioh, TAV_INTR_EN);
231 tav_write_short(iot, ioh, TAV_INTR_EN,
232 mask|TAV_INTR_PCM_OUTPUT_UNDERFLOW);
233
234 /* still more than zero? */
235 if (tav_read_short(iot, ioh, TAV_BUFF)) {
236 (void)cv_timedwait_sig(&sc->sc_cv,
237 &sc->sc_intr_lock, 32*hz);
238 }
239
240 /* can be really that long for mpeg */
241
242 mask = tav_read_short(iot, ioh, TAV_INTR_EN);
243 tav_write_short(iot, ioh, TAV_INTR_EN,
244 mask & ~TAV_INTR_PCM_OUTPUT_UNDERFLOW);
245 }
246
247 mutex_spin_exit(&sc->sc_intr_lock);
248
249 return 0;
250 }
251
252 int
253 tav_query_encoding(void *hdl, struct audio_encoding *ae)
254 {
255 struct tav_softc *sc;
256
257 sc = hdl;
258 if (ae->index >= sizeof(tav_encodings)/sizeof(*ae))
259 return EINVAL;
260
261 *ae = tav_encodings[ae->index];
262
263 return 0;
264 }
265
266 int
267 tav_start_input(void *hdl, void *block, int bsize,
268 void (*intr)(void *), void *intrarg)
269 {
270
271 return ENOTTY;
272 }
273
274 int
275 tav_halt_input(void *hdl)
276 {
277
278 return ENOTTY;
279 }
280
281 int
282 tav_start_output(void *hdl, void *block, int bsize,
283 void (*intr)(void *), void *intrarg)
284 {
285 struct tav_softc *sc;
286 bus_space_tag_t iot;
287 bus_space_handle_t ioh;
288 uint8_t *ptr;
289 int count;
290
291 sc = hdl;
292 iot = sc->sc_iot;
293 ioh = sc->sc_ioh;
294 ptr = block;
295 count = bsize;
296
297 sc->sc_intr = intr;
298 sc->sc_intrarg = intrarg;
299
300 bus_space_write_multi_1(iot, ioh, TAV_DATAIN, ptr, count);
301 tav_write_short(iot, ioh, TAV_INTR_EN, TAV_INTR_LOWWATER);
302
303 return 0;
304 }
305
306 int
307 tav_init_output(void *hdl, void *buffer, int size)
308 {
309 struct tav_softc *sc;
310 bus_space_tag_t iot;
311 bus_space_handle_t ioh;
312
313 sc = hdl;
314 iot = sc->sc_iot;
315 ioh = sc->sc_ioh;
316
317 tav_write_byte(iot, ioh, TAV_PLAY, 1);
318 tav_write_byte(iot, ioh, TAV_MUTE, 0);
319
320 return 0;
321 }
322
323 int
324 tav_halt_output(void *hdl)
325 {
326 struct tav_softc *sc;
327 bus_space_tag_t iot;
328 bus_space_handle_t ioh;
329
330 sc = hdl;
331 iot = sc->sc_iot;
332 ioh = sc->sc_ioh;
333
334 tav_write_byte(iot, ioh, TAV_PLAY, 0);
335
336 return 0;
337 }
338
339 int
340 tav_getdev(void *hdl, struct audio_device *ret)
341 {
342 struct tav_softc *sc;
343 bus_space_tag_t iot;
344 bus_space_handle_t ioh;
345
346 sc = hdl;
347 iot = sc->sc_iot;
348 ioh = sc->sc_ioh;
349
350 strlcpy(ret->name, "tms320av110", sizeof(ret->name));
351 /* guaranteed to be <= 4 in length */
352 snprintf(ret->version, sizeof(ret->version), "%u",
353 tav_read_byte(iot, ioh, TAV_VERSION));
354 strlcpy(ret->config, device_xname(&sc->sc_dev), sizeof(ret->config));
355
356 return 0;
357 }
358
359 int
360 tav_round_blocksize(void *hdl, int size, int mode, const audio_params_t *param)
361 {
362 struct tav_softc *sc;
363 bus_space_tag_t iot;
364 bus_space_handle_t ioh;
365 int maxhalf;
366
367 sc = hdl;
368 iot = sc->sc_iot;
369 ioh = sc->sc_ioh;
370
371 maxhalf = TAV_DRAM_HSIZE(tav_read_byte(iot, ioh, TAV_DRAM_EXT));
372 if (size > maxhalf)
373 size = maxhalf;
374
375 /* XXX should round to 128 bytes limits for audio bypass */
376 size &= ~3;
377
378 tav_write_short(iot, ioh, TAV_BALE_LIM, size/8);
379
380 /* the buffer limits are in units of 4 bytes */
381 return (size);
382 }
383
384 int
385 tav_get_props(void *hdl)
386 {
387 return 0;
388 }
389
390 void
391 tav_get_locks(void *hdl, kmutex_t **intr, kmutex_t **thread)
392 {
393 struct tav_softc *sc;
394
395 sc = hdl;
396 *intr = &sc->sc_intr_lock;
397 *thread = &sc->sc_lock;
398 }
399
400 int
401 tav_set_params(void *hdl, int setmode, int usemode, audio_params_t *p,
402 audio_params_t *r, stream_filter_list_t *pfil, stream_filter_list_t *rfil)
403 {
404 struct tav_softc *sc;
405 bus_space_tag_t iot;
406 bus_space_handle_t ioh;
407
408 sc = hdl;
409 iot = sc->sc_iot;
410 ioh = sc->sc_ioh;
411
412 if (!(setmode & AUMODE_PLAY))
413 return 0;
414
415 if (p->encoding == AUDIO_ENCODING_ULAW)
416 p->encoding = AUDIO_ENCODING_MPEG_L2_STREAM;
417
418 switch(p->encoding) {
419 default:
420 return EINVAL;
421
422 case AUDIO_ENCODING_SLINEAR_BE:
423
424 /* XXX: todo: add 8bit and mono using software */
425 p->precision = 16;
426 p->channels = 2;
427
428 /* XXX: this might depend on the specific board.
429 should be handled by the backend */
430
431 p->sample_rate = 44100;
432
433 bus_space_write_1(iot, ioh, TAV_STR_SEL,
434 TAV_STR_SEL_AUDIO_BYPASS);
435 break;
436
437 /* XXX: later: add ULINEAR, and LE using software encoding */
438
439 case AUDIO_ENCODING_MPEG_L1_STREAM:
440 /* FALLTHROUGH */
441 case AUDIO_ENCODING_MPEG_L2_STREAM:
442 bus_space_write_1(iot, ioh, TAV_STR_SEL,
443 TAV_STR_SEL_MPEG_AUDIO_STREAM);
444 p->sample_rate = 44100;
445 p->precision = 1;
446 break;
447
448 case AUDIO_ENCODING_MPEG_L1_PACKETS:
449 /* FALLTHROUGH */
450 case AUDIO_ENCODING_MPEG_L2_PACKETS:
451 bus_space_write_1(iot, ioh, TAV_STR_SEL,
452 TAV_STR_SEL_MPEG_AUDIO_PACKETS);
453 p->sample_rate = 44100;
454 p->precision = 1;
455 break;
456
457 case AUDIO_ENCODING_MPEG_L1_SYSTEM:
458 /* FALLTHROUGH */
459 case AUDIO_ENCODING_MPEG_L2_SYSTEM:
460 bus_space_write_1(iot, ioh, TAV_STR_SEL,
461 TAV_STR_SEL_MPEG_SYSTEM_STREAM);
462 p->sample_rate = 44100;
463 p->precision = 1;
464 break;
465 }
466 tav_write_byte(iot, ioh, TAV_RESTART, 1);
467 do {
468 delay(10);
469 } while (tav_read_byte(iot, ioh, TAV_RESTART));
470
471 return 0;
472 }
473
474 int
475 tav_set_port(void *hdl, mixer_ctrl_t *mc)
476 {
477 struct tav_softc *sc;
478
479 sc = hdl;
480 /* dummy */
481 return 0;
482 }
483
484 int
485 tav_get_port(void *hdl, mixer_ctrl_t *mc)
486 {
487 struct tav_softc *sc;
488
489 sc = hdl;
490 /* dummy */
491 return 0;
492 }
493
494 int
495 tav_query_devinfo(void *hdl, mixer_devinfo_t *di)
496 {
497 return ENXIO;
498 }
499
500 int
501 tav_speaker_ctl(void *hdl, int value)
502 {
503 struct tav_softc *sc;
504 bus_space_tag_t iot;
505 bus_space_handle_t ioh;
506
507 sc = hdl;
508 iot = sc->sc_iot;
509 ioh = sc->sc_ioh;
510
511 tav_write_byte(iot, ioh, TAV_MUTE, !value);
512
513 return 0;
514 }
515