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