Home | History | Annotate | Line # | Download | only in ic
tms320av110.c revision 1.1
      1 /*	$NetBSD: tms320av110.c,v 1.1 1997/10/16 23:58:16 is Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1997 Ignatios Souvatzis. All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. Neither the name of the author nor the names of contributors
     15  *    may be used to endorse or promote products derived from this software
     16  *    without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     28  * SUCH DAMAGE.
     29  */
     30 
     31 /*
     32  * Machine independent part of TMS320AV110 driver.
     33  *
     34  * Currently, only minimum support for audio output. For audio/video
     35  * synchronization, more is needed.
     36  */
     37 
     38 #include <sys/types.h>
     39 #include <sys/param.h>
     40 #include <sys/systm.h>
     41 #include <sys/kernel.h>
     42 #include <sys/device.h>
     43 #include <sys/proc.h>
     44 
     45 #include <sys/audioio.h>
     46 #include <dev/audio_if.h>
     47 
     48 #include <dev/ic/tms320av110reg.h>
     49 #include <dev/ic/tms320av110var.h>
     50 
     51 #include <machine/bus.h>
     52 
     53 int tav_open __P((void*, int));
     54 void tav_close __P((void *));
     55 int tav_drain __P((void *));
     56 int tav_query_encoding __P((void *, struct audio_encoding *));
     57 int tav_set_params __P((void *, int, int, struct audio_params *,
     58     struct audio_params *));
     59 int tav_round_blocksize __P((void *, int));
     60 int tav_set_out_port __P((void *, int));
     61 int tav_get_out_port __P((void *));
     62 int tav_set_in_port __P((void *, int));
     63 int tav_get_in_port __P((void *));
     64 int tav_init_output __P((void *, void *, int));
     65 int tav_start_output __P((void *, void *, int, void (*)(void *), void *));
     66 int tav_start_input __P((void *, void *, int, void (*)(void *), void *));
     67 int tav_halt_output __P((void *));
     68 int tav_halt_input __P((void *));
     69 int tav_cont_output __P((void *));
     70 int tav_cont_input __P((void *));
     71 int tav_speaker_ctl __P((void *, int));
     72 int tav_getdev __P((void *, struct audio_device *));
     73 int tav_setfd __P((void *, int));
     74 int tav_set_port __P((void *, mixer_ctrl_t *));
     75 int tav_get_port __P((void *, mixer_ctrl_t *));
     76 int tav_query_devinfo __P((void *, mixer_devinfo_t *));
     77 int tav_get_props __P((void *));
     78 
     79 struct audio_hw_if tav_audio_if = {
     80 	tav_open,
     81 	tav_close,
     82 	0 /* tav_drain*/,		/* optional */
     83 	tav_query_encoding,
     84 	tav_set_params,
     85 	tav_round_blocksize,
     86 	tav_set_out_port,
     87 	tav_get_out_port,
     88 	tav_set_in_port,
     89 	tav_get_in_port,
     90 	0 /* commit_settings */,	/* optional */
     91 	tav_init_output,		/* optional */
     92 	0 /* tav_init_input */,		/* optional */
     93 	tav_start_output,
     94 	tav_start_input,
     95 	tav_halt_output,
     96 	tav_halt_input,
     97 	tav_cont_output,
     98 	tav_cont_input,
     99 	tav_speaker_ctl,		/* optional */
    100 	tav_getdev,
    101 	0 /* setfd */,			/* optional */
    102 	tav_set_port,
    103 	tav_get_port,
    104 	tav_query_devinfo,
    105 	0 /* alloc */,			/* optional */
    106 	0 /* free */,			/* optional */
    107 	0 /* round_buffersize */,	/* optional */
    108 	0 /* mappage */,		/* optional */
    109 	tav_get_props
    110 };
    111 
    112 void
    113 tms320av110_attach_mi(sc)
    114 	struct tav_softc *sc;
    115 {
    116 	bus_space_tag_t iot = sc->sc_iot;
    117 	bus_space_handle_t ioh = sc->sc_ioh;
    118 
    119 	tav_write_byte(iot, ioh, TAV_RESET, 1);
    120 	while (tav_read_byte(iot, ioh, TAV_RESET))
    121 		delay(250);
    122 
    123 	tav_write_byte(iot, ioh, TAV_PCM_ORD, sc->sc_pcm_ord);
    124 	tav_write_byte(iot, ioh, TAV_PCM_18, sc->sc_pcm_18);
    125 	tav_write_byte(iot, ioh, TAV_DIF, sc->sc_dif);
    126 	tav_write_byte(iot, ioh, TAV_PCM_DIV, sc->sc_pcm_div);
    127 
    128 	printf(": chip rev. %d, %d bytes buffer\n",
    129 	    tav_read_byte(iot, ioh, TAV_VERSION),
    130 	    TAV_DRAM_SIZE(tav_read_byte(iot, ioh, TAV_DRAM_EXT)));
    131 
    132 	tav_write_byte(iot, ioh, TAV_AUD_ID_EN, 0);
    133 	tav_write_byte(iot, ioh, TAV_SKIP, 0);
    134 	tav_write_byte(iot, ioh, TAV_REPEAT, 0);
    135 	tav_write_byte(iot, ioh, TAV_MUTE, 0);
    136 	tav_write_byte(iot, ioh, TAV_PLAY, 1);
    137 	tav_write_byte(iot, ioh, TAV_SYNC_ECM, 0);
    138 	tav_write_byte(iot, ioh, TAV_CRC_ECM, 0);
    139 	tav_write_byte(iot, ioh, TAV_ATTEN_L, 0);
    140 	tav_write_byte(iot, ioh, TAV_ATTEN_R, 0);
    141 	tav_write_word(iot, ioh, TAV_FREE_FORM, 0);
    142 	tav_write_byte(iot, ioh, TAV_SIN_EN, 0);
    143 	tav_write_byte(iot, ioh, TAV_SYNC_ECM, TAV_ECM_REPEAT);
    144 	tav_write_byte(iot, ioh, TAV_CRC_ECM, TAV_ECM_REPEAT);
    145 
    146 	audio_attach_mi(&tav_audio_if, 0, sc, &sc->sc_dev);
    147 }
    148 
    149 int
    150 tms320av110_intr(p)
    151 	void *p;
    152 {
    153         struct tav_softc *sc = p;
    154 	u_int16_t intlist;
    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 interupts */
    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 		 wakeup(sc);
    172 	}
    173 
    174 	return 1;
    175 }
    176 
    177 struct audio_encoding tav_encodings[] = {
    178 	{0, "mpg_l2_str", AUDIO_ENCODING_MPEG_L2_STREAM, 1, 0,},
    179 	{1, "mpg_l2_pkt", AUDIO_ENCODING_MPEG_L2_PACKETS, 1, 0,},
    180 	{2, "mpg_l2_sys", AUDIO_ENCODING_MPEG_L2_SYSTEM, 1, 0,},
    181 	{3, "slinear_be", AUDIO_ENCODING_SLINEAR_BE, 16, 0,},
    182 };
    183 
    184 int
    185 tav_open(hdl, flags)
    186 	void *hdl;
    187 	int flags;
    188 {
    189         struct tav_softc *sc;
    190 
    191 	sc = hdl;
    192 
    193 	/* dummy */
    194 	return 0;
    195 }
    196 
    197 void
    198 tav_close(hdl)
    199         void *hdl;
    200 {
    201         struct tav_softc *sc;
    202 	bus_space_tag_t iot;
    203 	bus_space_handle_t ioh;
    204 
    205 	sc = hdl;
    206 	iot = sc->sc_iot;
    207 	ioh = sc->sc_ioh;
    208 
    209 	/* re"start" chip, also clears interupts and interupt enable */
    210 	tav_write_short(iot, ioh, TAV_INTR_EN, 0);
    211 	if (sc->sc_intack)
    212 		(*sc->sc_intack)(sc);
    213 }
    214 
    215 int
    216 tav_drain(hdl)
    217         void *hdl;
    218 {
    219         struct tav_softc *sc;
    220 	bus_space_tag_t iot;
    221 	bus_space_handle_t ioh;
    222 	u_int16_t mask;
    223 
    224         sc = hdl;
    225 	iot = sc->sc_iot;
    226 	ioh = sc->sc_ioh;
    227 
    228 	/*
    229 	 * tsleep waiting for underflow interupt.
    230 	 */
    231 	if (tav_read_short(iot, ioh, TAV_BUFF)) {
    232 		mask = tav_read_short(iot, ioh, TAV_INTR_EN);
    233 		tav_write_short(iot, ioh, TAV_INTR_EN,
    234 		    mask|TAV_INTR_PCM_OUTPUT_UNDERFLOW);
    235 
    236 		/* still more than zero? */
    237 		if (tav_read_short(iot, ioh, TAV_BUFF))
    238 			(void)tsleep(sc, PCATCH, "tavdrain", 32*hz);
    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 	return 0;
    248 }
    249 
    250 int
    251 tav_query_encoding(hdl, ae)
    252         void *hdl;
    253 	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(hdl, block, bsize, intr, intrarg)
    268 	void *hdl;
    269 	void *block;
    270 	int bsize;
    271 	void (*intr) __P((void *));
    272 	void *intrarg;
    273 {
    274 	return ENOTTY;
    275 }
    276 
    277 int
    278 tav_halt_input(hdl)
    279 	void *hdl;
    280 {
    281 	return ENOTTY;
    282 }
    283 
    284 int
    285 tav_start_output(hdl, block, bsize, intr, intrarg)
    286 	void *hdl;
    287 	void *block;
    288 	int bsize;
    289 	void (*intr) __P((void *));
    290 	void *intrarg;
    291 {
    292         struct tav_softc *sc;
    293 	bus_space_tag_t iot;
    294 	bus_space_handle_t ioh;
    295 	u_int8_t *ptr;
    296 	int count;
    297 
    298 
    299         sc = hdl;
    300 	iot = sc->sc_iot;
    301 	ioh = sc->sc_ioh;
    302 	ptr = block;
    303 	count = bsize;
    304 
    305 	sc->sc_intr = intr;
    306 	sc->sc_intrarg = intrarg;
    307 
    308 	while (--count >= 0) {
    309 		bus_space_write_1(iot, ioh, TAV_DATAIN, *ptr++);
    310 		delay(1);
    311 	}
    312 	tav_write_short(iot, ioh, TAV_INTR_EN, TAV_INTR_LOWWATER);
    313 
    314 	return 0;
    315 }
    316 
    317 int
    318 tav_init_output(hdl, buffer, size)
    319 	void *hdl;
    320 	void *buffer;
    321 	int size;
    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, 1);
    332 	tav_write_byte(iot, ioh, TAV_MUTE, 0);
    333 
    334 	return 0;
    335 }
    336 
    337 int
    338 tav_halt_output(hdl)
    339 	void *hdl;
    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 	tav_write_byte(iot, ioh, TAV_PLAY, 0);
    350 
    351 	return 0;
    352 }
    353 
    354 int
    355 tav_getdev(hdl, ret)
    356 	void *hdl;
    357 	struct audio_device *ret;
    358 {
    359         struct tav_softc *sc;
    360 	bus_space_tag_t iot;
    361 	bus_space_handle_t ioh;
    362 
    363         sc = hdl;
    364 	iot = sc->sc_iot;
    365 	ioh = sc->sc_ioh;
    366 
    367 	strncpy(ret->name, "tms320av110", MAX_AUDIO_DEV_LEN);
    368 	sprintf(ret->version, "%u", /* guaranteed to be <= 4 in length */
    369 	    tav_read_byte(iot, ioh, TAV_VERSION));
    370 	strncpy(ret->config, sc->sc_dev.dv_xname, MAX_AUDIO_DEV_LEN);
    371 
    372 	return 0;
    373 }
    374 
    375 int
    376 tav_round_blocksize(hdl, size)
    377 	void *hdl;
    378 	int size;
    379 {
    380         struct tav_softc *sc;
    381 	bus_space_tag_t iot;
    382 	bus_space_handle_t ioh;
    383 	int maxhalf;
    384 
    385         sc = hdl;
    386 	iot = sc->sc_iot;
    387 	ioh = sc->sc_ioh;
    388 
    389 	maxhalf = TAV_DRAM_HSIZE(tav_read_byte(iot, ioh, TAV_DRAM_EXT));
    390 	if (size > maxhalf)
    391 		size = maxhalf;
    392 
    393 	/* XXX should round to 128 bytes limits for audio bypass */
    394 	size &= ~3;
    395 
    396 	tav_write_short(iot, ioh, TAV_BALE_LIM, size/8);
    397 
    398 	/* the buffer limits are in units of 4 bytes */
    399 	return (size);
    400 }
    401 
    402 int
    403 tav_get_props(hdl)
    404         void *hdl;
    405 {
    406 	return 0;
    407 }
    408 
    409 int
    410 tav_set_params(hdl, setmode, usemode, p, r)
    411 	void *hdl;
    412         int setmode, usemode;
    413         struct  audio_params *p, *r;
    414 {
    415         struct tav_softc *sc;
    416 	bus_space_tag_t iot;
    417 	bus_space_handle_t ioh;
    418 
    419         sc = hdl;
    420 	iot = sc->sc_iot;
    421 	ioh = sc->sc_ioh;
    422 
    423 	if (!(setmode & AUMODE_PLAY))
    424 		return 0;
    425 
    426 	if (p->encoding == AUDIO_ENCODING_ULAW)
    427 		p->encoding = AUDIO_ENCODING_MPEG_L2_STREAM;
    428 
    429 	switch(p->encoding) {
    430 	default:
    431 		return EINVAL;
    432 
    433 	case AUDIO_ENCODING_SLINEAR_BE:
    434 
    435 		/* XXX: todo: add 8bit and mono using software */
    436 		p->precision = 16;
    437 		p->channels = 2;
    438 
    439 		/* XXX: this might depend on the specific board.
    440 		   should be handled by the backend */
    441 
    442 		p->sample_rate = 44100;
    443 
    444 		bus_space_write_1(iot, ioh, TAV_STR_SEL,
    445 		    TAV_STR_SEL_AUDIO_BYPASS);
    446 		break;
    447 
    448 	/* XXX: later: add ULINEAR, and LE using software encoding */
    449 
    450 	case AUDIO_ENCODING_MPEG_L1_STREAM:
    451 		/* FALLTHROUGH */
    452 	case AUDIO_ENCODING_MPEG_L2_STREAM:
    453 		bus_space_write_1(iot, ioh, TAV_STR_SEL,
    454 		    TAV_STR_SEL_MPEG_AUDIO_STREAM);
    455 		p->sample_rate = 44100;
    456 		p->precision = 1;
    457 		break;
    458 
    459 	case AUDIO_ENCODING_MPEG_L1_PACKETS:
    460 		/* FALLTHROUGH */
    461 	case AUDIO_ENCODING_MPEG_L2_PACKETS:
    462 		bus_space_write_1(iot, ioh, TAV_STR_SEL,
    463 		    TAV_STR_SEL_MPEG_AUDIO_PACKETS);
    464 		p->sample_rate = 44100;
    465 		p->precision = 1;
    466 		break;
    467 
    468 	case AUDIO_ENCODING_MPEG_L1_SYSTEM:
    469 		/* FALLTHROUGH */
    470 	case AUDIO_ENCODING_MPEG_L2_SYSTEM:
    471 		bus_space_write_1(iot, ioh, TAV_STR_SEL,
    472 		    TAV_STR_SEL_MPEG_SYSTEM_STREAM);
    473 		p->sample_rate = 44100;
    474 		p->precision = 1;
    475 		break;
    476 	}
    477 	tav_write_byte(iot, ioh, TAV_RESTART, 1);
    478 	do {
    479 		delay(10);
    480 	} while (tav_read_byte(iot, ioh, TAV_RESTART));
    481 
    482 	return 0;
    483 }
    484 
    485 int
    486 tav_set_port(hdl, mc)
    487         void *hdl;
    488 	mixer_ctrl_t *mc;
    489 {
    490         struct tav_softc *sc;
    491 
    492 	sc = hdl;
    493 	/* dummy */
    494 	return 0;
    495 }
    496 
    497 int
    498 tav_get_port(hdl, mc)
    499         void *hdl;
    500 	mixer_ctrl_t *mc;
    501 {
    502         struct tav_softc *sc;
    503 
    504 	sc = hdl;
    505 	/* dummy */
    506 	return 0;
    507 }
    508 
    509 int
    510 tav_query_devinfo(hdl, di)
    511 	void *hdl;
    512 	mixer_devinfo_t *di;
    513 {
    514 	return EINVAL;
    515 }
    516 
    517 int
    518 tav_get_in_port(hdl)
    519 	void *hdl;
    520 {
    521 	return -1;
    522 }
    523 
    524 int
    525 tav_set_in_port(hdl, port)
    526 	void *hdl;
    527 	int port;
    528 {
    529 	return EINVAL;
    530 }
    531 
    532 int
    533 tav_get_out_port(hdl)
    534 	void *hdl;
    535 {
    536 	return 0;
    537 }
    538 
    539 int
    540 tav_set_out_port(hdl, port)
    541 	void *hdl;
    542 	int port;
    543 {
    544 	if (port)
    545 		return EINVAL;
    546 	return 0;
    547 }
    548 
    549 int
    550 tav_cont_input(hdl)
    551 	void *hdl;
    552 {
    553 	return EINVAL;
    554 }
    555 
    556 int
    557 tav_cont_output(hdl)
    558 	void *hdl;
    559 {
    560 	return EINVAL;
    561 }
    562 
    563 int
    564 tav_speaker_ctl(hdl, value)
    565 	void *hdl;
    566 	int value;
    567 {
    568         struct tav_softc *sc;
    569 	bus_space_tag_t iot;
    570 	bus_space_handle_t ioh;
    571 
    572 	sc = hdl;
    573 	iot = sc->sc_iot;
    574 	ioh = sc->sc_ioh;
    575 
    576 	tav_write_byte(iot, ioh, TAV_MUTE, !value);
    577 
    578 	return 0;
    579 }
    580