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