Home | History | Annotate | Line # | Download | only in ic
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