1/*	$NetBSD$	*/
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$");
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
56int tav_open(void *, int);
57void tav_close(void *);
58int tav_drain(void *);
59int tav_query_encoding(void *, struct audio_encoding *);
60int tav_set_params(void *, int, int, audio_params_t *, audio_params_t *,
61    stream_filter_list_t *, stream_filter_list_t *);
62int tav_round_blocksize(void *, int, int, const audio_params_t *);
63int tav_init_output(void *, void *, int);
64int tav_start_output(void *, void *, int, void (*)(void *), void *);
65int tav_start_input(void *, void *, int, void (*)(void *), void *);
66int tav_halt_output(void *);
67int tav_halt_input(void *);
68int tav_speaker_ctl(void *, int);
69int tav_getdev(void *, struct audio_device *);
70int tav_setfd(void *, int);
71int tav_set_port(void *, mixer_ctrl_t *);
72int tav_get_port(void *, mixer_ctrl_t *);
73int tav_query_devinfo(void *, mixer_devinfo_t *);
74int tav_get_props(void *);
75void tav_get_locks(void *, kmutex_t **, kmutex_t **);
76
77const 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
108void
109tms320av110_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
146int
147tms320av110_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
179struct 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
186int
187tav_open(void *hdl, int flags)
188{
189
190	/* dummy */
191	return 0;
192}
193
194void
195tav_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
211int
212tav_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
251int
252tav_query_encoding(void *hdl, struct audio_encoding *ae)
253{
254	struct tav_softc *sc;
255
256	sc = hdl;
257	if (ae->index >= sizeof(tav_encodings)/sizeof(*ae))
258		return EINVAL;
259
260	*ae = tav_encodings[ae->index];
261
262	return 0;
263}
264
265int
266tav_start_input(void *hdl, void *block, int bsize,
267    void (*intr)(void *), void *intrarg)
268{
269
270	return ENOTTY;
271}
272
273int
274tav_halt_input(void *hdl)
275{
276
277	return ENOTTY;
278}
279
280int
281tav_start_output(void *hdl, void *block, int bsize,
282    void (*intr)(void *), void *intrarg)
283{
284	struct tav_softc *sc;
285	bus_space_tag_t iot;
286	bus_space_handle_t ioh;
287	uint8_t *ptr;
288	int count;
289
290	sc = hdl;
291	iot = sc->sc_iot;
292	ioh = sc->sc_ioh;
293	ptr = block;
294	count = bsize;
295
296	sc->sc_intr = intr;
297	sc->sc_intrarg = intrarg;
298
299	bus_space_write_multi_1(iot, ioh, TAV_DATAIN, ptr, count);
300	tav_write_short(iot, ioh, TAV_INTR_EN, TAV_INTR_LOWWATER);
301
302	return 0;
303}
304
305int
306tav_init_output(void *hdl, void *buffer, int size)
307{
308	struct tav_softc *sc;
309	bus_space_tag_t iot;
310	bus_space_handle_t ioh;
311
312	sc = hdl;
313	iot = sc->sc_iot;
314	ioh = sc->sc_ioh;
315
316	tav_write_byte(iot, ioh, TAV_PLAY, 1);
317	tav_write_byte(iot, ioh, TAV_MUTE, 0);
318
319	return 0;
320}
321
322int
323tav_halt_output(void *hdl)
324{
325	struct tav_softc *sc;
326	bus_space_tag_t iot;
327	bus_space_handle_t ioh;
328
329	sc = hdl;
330	iot = sc->sc_iot;
331	ioh = sc->sc_ioh;
332
333	tav_write_byte(iot, ioh, TAV_PLAY, 0);
334
335	return 0;
336}
337
338int
339tav_getdev(void *hdl, struct audio_device *ret)
340{
341	struct tav_softc *sc;
342	bus_space_tag_t iot;
343	bus_space_handle_t ioh;
344
345	sc = hdl;
346	iot = sc->sc_iot;
347	ioh = sc->sc_ioh;
348
349	strlcpy(ret->name, "tms320av110", sizeof(ret->name));
350	/* guaranteed to be <= 4 in length */
351	snprintf(ret->version, sizeof(ret->version), "%u",
352	    tav_read_byte(iot, ioh, TAV_VERSION));
353	strlcpy(ret->config, device_xname(&sc->sc_dev), sizeof(ret->config));
354
355	return 0;
356}
357
358int
359tav_round_blocksize(void *hdl, int size, int mode, const audio_params_t *param)
360{
361	struct tav_softc *sc;
362	bus_space_tag_t iot;
363	bus_space_handle_t ioh;
364	int maxhalf;
365
366	sc = hdl;
367	iot = sc->sc_iot;
368	ioh = sc->sc_ioh;
369
370	maxhalf = TAV_DRAM_HSIZE(tav_read_byte(iot, ioh, TAV_DRAM_EXT));
371	if (size > maxhalf)
372		size = maxhalf;
373
374	/* XXX should round to 128 bytes limits for audio bypass */
375	size &= ~3;
376
377	tav_write_short(iot, ioh, TAV_BALE_LIM, size/8);
378
379	/* the buffer limits are in units of 4 bytes */
380	return (size);
381}
382
383int
384tav_get_props(void *hdl)
385{
386	return 0;
387}
388
389void
390tav_get_locks(void *hdl, kmutex_t **intr, kmutex_t **thread)
391{
392	struct tav_softc *sc;
393
394	sc = hdl;
395	*intr = &sc->sc_intr_lock;
396	*thread = &sc->sc_lock;
397}
398
399int
400tav_set_params(void *hdl, int setmode, int usemode, audio_params_t *p,
401    audio_params_t *r, stream_filter_list_t *pfil, stream_filter_list_t *rfil)
402{
403	struct tav_softc *sc;
404	bus_space_tag_t iot;
405	bus_space_handle_t ioh;
406
407	sc = hdl;
408	iot = sc->sc_iot;
409	ioh = sc->sc_ioh;
410
411	if (!(setmode & AUMODE_PLAY))
412		return 0;
413
414	if (p->encoding == AUDIO_ENCODING_ULAW)
415		p->encoding = AUDIO_ENCODING_MPEG_L2_STREAM;
416
417	switch(p->encoding) {
418	default:
419		return EINVAL;
420
421	case AUDIO_ENCODING_SLINEAR_BE:
422
423		/* XXX: todo: add 8bit and mono using software */
424		p->precision = 16;
425		p->channels = 2;
426
427		/* XXX: this might depend on the specific board.
428		   should be handled by the backend */
429
430		p->sample_rate = 44100;
431
432		bus_space_write_1(iot, ioh, TAV_STR_SEL,
433		    TAV_STR_SEL_AUDIO_BYPASS);
434		break;
435
436	/* XXX: later: add ULINEAR, and LE using software encoding */
437
438	case AUDIO_ENCODING_MPEG_L1_STREAM:
439		/* FALLTHROUGH */
440	case AUDIO_ENCODING_MPEG_L2_STREAM:
441		bus_space_write_1(iot, ioh, TAV_STR_SEL,
442		    TAV_STR_SEL_MPEG_AUDIO_STREAM);
443		p->sample_rate = 44100;
444		p->precision = 1;
445		break;
446
447	case AUDIO_ENCODING_MPEG_L1_PACKETS:
448		/* FALLTHROUGH */
449	case AUDIO_ENCODING_MPEG_L2_PACKETS:
450		bus_space_write_1(iot, ioh, TAV_STR_SEL,
451		    TAV_STR_SEL_MPEG_AUDIO_PACKETS);
452		p->sample_rate = 44100;
453		p->precision = 1;
454		break;
455
456	case AUDIO_ENCODING_MPEG_L1_SYSTEM:
457		/* FALLTHROUGH */
458	case AUDIO_ENCODING_MPEG_L2_SYSTEM:
459		bus_space_write_1(iot, ioh, TAV_STR_SEL,
460		    TAV_STR_SEL_MPEG_SYSTEM_STREAM);
461		p->sample_rate = 44100;
462		p->precision = 1;
463		break;
464	}
465	tav_write_byte(iot, ioh, TAV_RESTART, 1);
466	do {
467		delay(10);
468	} while (tav_read_byte(iot, ioh, TAV_RESTART));
469
470	return 0;
471}
472
473int
474tav_set_port(void *hdl, mixer_ctrl_t *mc)
475{
476	struct tav_softc *sc;
477
478	sc = hdl;
479	/* dummy */
480	return 0;
481}
482
483int
484tav_get_port(void *hdl, mixer_ctrl_t *mc)
485{
486	struct tav_softc *sc;
487
488	sc = hdl;
489	/* dummy */
490	return 0;
491}
492
493int
494tav_query_devinfo(void *hdl, mixer_devinfo_t *di)
495{
496	return ENXIO;
497}
498
499int
500tav_speaker_ctl(void *hdl, int value)
501{
502	struct tav_softc *sc;
503	bus_space_tag_t iot;
504	bus_space_handle_t ioh;
505
506	sc = hdl;
507	iot = sc->sc_iot;
508	ioh = sc->sc_ioh;
509
510	tav_write_byte(iot, ioh, TAV_MUTE, !value);
511
512	return 0;
513}
514