1 /* $NetBSD: tms320av110.c,v 1.4 1997/10/19 20:46:32 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_init_output __P((void *, void *, int)); 61 int tav_start_output __P((void *, void *, int, void (*)(void *), void *)); 62 int tav_start_input __P((void *, void *, int, void (*)(void *), void *)); 63 int tav_halt_output __P((void *)); 64 int tav_halt_input __P((void *)); 65 int tav_speaker_ctl __P((void *, int)); 66 int tav_getdev __P((void *, struct audio_device *)); 67 int tav_setfd __P((void *, int)); 68 int tav_set_port __P((void *, mixer_ctrl_t *)); 69 int tav_get_port __P((void *, mixer_ctrl_t *)); 70 int tav_query_devinfo __P((void *, mixer_devinfo_t *)); 71 int tav_get_props __P((void *)); 72 73 struct audio_hw_if tav_audio_if = { 74 tav_open, 75 tav_close, 76 0 /* tav_drain*/, /* optional */ 77 tav_query_encoding, 78 tav_set_params, 79 tav_round_blocksize, 80 0 /* commit_settings */, /* optional */ 81 tav_init_output, /* optional */ 82 0 /* tav_init_input */, /* optional */ 83 tav_start_output, 84 tav_start_input, 85 tav_halt_output, 86 tav_halt_input, 87 tav_speaker_ctl, /* optional */ 88 tav_getdev, 89 0 /* setfd */, /* optional */ 90 tav_set_port, 91 tav_get_port, 92 tav_query_devinfo, 93 0 /* alloc */, /* optional */ 94 0 /* free */, /* optional */ 95 0 /* round_buffersize */, /* optional */ 96 0 /* mappage */, /* optional */ 97 tav_get_props 98 }; 99 100 void 101 tms320av110_attach_mi(sc) 102 struct tav_softc *sc; 103 { 104 bus_space_tag_t iot = sc->sc_iot; 105 bus_space_handle_t ioh = sc->sc_ioh; 106 107 tav_write_byte(iot, ioh, TAV_RESET, 1); 108 while (tav_read_byte(iot, ioh, TAV_RESET)) 109 delay(250); 110 111 tav_write_byte(iot, ioh, TAV_PCM_ORD, sc->sc_pcm_ord); 112 tav_write_byte(iot, ioh, TAV_PCM_18, sc->sc_pcm_18); 113 tav_write_byte(iot, ioh, TAV_DIF, sc->sc_dif); 114 tav_write_byte(iot, ioh, TAV_PCM_DIV, sc->sc_pcm_div); 115 116 printf(": chip rev. %d, %d bytes buffer\n", 117 tav_read_byte(iot, ioh, TAV_VERSION), 118 TAV_DRAM_SIZE(tav_read_byte(iot, ioh, TAV_DRAM_EXT))); 119 120 tav_write_byte(iot, ioh, TAV_AUD_ID_EN, 0); 121 tav_write_byte(iot, ioh, TAV_SKIP, 0); 122 tav_write_byte(iot, ioh, TAV_REPEAT, 0); 123 tav_write_byte(iot, ioh, TAV_MUTE, 0); 124 tav_write_byte(iot, ioh, TAV_PLAY, 1); 125 tav_write_byte(iot, ioh, TAV_SYNC_ECM, 0); 126 tav_write_byte(iot, ioh, TAV_CRC_ECM, 0); 127 tav_write_byte(iot, ioh, TAV_ATTEN_L, 0); 128 tav_write_byte(iot, ioh, TAV_ATTEN_R, 0); 129 tav_write_short(iot, ioh, TAV_FREE_FORM, 0); 130 tav_write_byte(iot, ioh, TAV_SIN_EN, 0); 131 tav_write_byte(iot, ioh, TAV_SYNC_ECM, TAV_ECM_REPEAT); 132 tav_write_byte(iot, ioh, TAV_CRC_ECM, TAV_ECM_REPEAT); 133 134 audio_attach_mi(&tav_audio_if, 0, sc, &sc->sc_dev); 135 } 136 137 int 138 tms320av110_intr(p) 139 void *p; 140 { 141 struct tav_softc *sc = p; 142 u_int16_t intlist; 143 144 intlist = tav_read_short(sc->sc_iot, sc->sc_ioh, TAV_INTR) 145 /* & tav_read_short(sc->sc_iot, sc->sc_ioh, TAV_INTR_EN)*/; 146 147 if (!intlist) 148 return 0; 149 150 /* ack now, so that we don't miss later interupts */ 151 if (sc->sc_intack) 152 (sc->sc_intack)(sc); 153 154 if (intlist & TAV_INTR_LOWWATER) { 155 (*sc->sc_intr)(sc->sc_intrarg); 156 } 157 158 if (intlist & TAV_INTR_PCM_OUTPUT_UNDERFLOW) { 159 wakeup(sc); 160 } 161 162 return 1; 163 } 164 165 struct audio_encoding tav_encodings[] = { 166 {0, AudioEmpeg_l2_stream, AUDIO_ENCODING_MPEG_L2_STREAM, 1, 0,}, 167 {1, AudioEmpeg_l2_packets, AUDIO_ENCODING_MPEG_L2_PACKETS, 1, 0,}, 168 {2, AudioEmpeg_l2_system, AUDIO_ENCODING_MPEG_L2_SYSTEM, 1, 0,}, 169 {3, AudioEslinear_be, AUDIO_ENCODING_SLINEAR_BE, 16, 0,}, 170 }; 171 172 int 173 tav_open(hdl, flags) 174 void *hdl; 175 int flags; 176 { 177 struct tav_softc *sc; 178 179 sc = hdl; 180 181 /* dummy */ 182 return 0; 183 } 184 185 void 186 tav_close(hdl) 187 void *hdl; 188 { 189 struct tav_softc *sc; 190 bus_space_tag_t iot; 191 bus_space_handle_t ioh; 192 193 sc = hdl; 194 iot = sc->sc_iot; 195 ioh = sc->sc_ioh; 196 197 /* re"start" chip, also clears interupts and interupt enable */ 198 tav_write_short(iot, ioh, TAV_INTR_EN, 0); 199 if (sc->sc_intack) 200 (*sc->sc_intack)(sc); 201 } 202 203 int 204 tav_drain(hdl) 205 void *hdl; 206 { 207 struct tav_softc *sc; 208 bus_space_tag_t iot; 209 bus_space_handle_t ioh; 210 u_int16_t mask; 211 212 sc = hdl; 213 iot = sc->sc_iot; 214 ioh = sc->sc_ioh; 215 216 /* 217 * tsleep waiting for underflow interupt. 218 */ 219 if (tav_read_short(iot, ioh, TAV_BUFF)) { 220 mask = tav_read_short(iot, ioh, TAV_INTR_EN); 221 tav_write_short(iot, ioh, TAV_INTR_EN, 222 mask|TAV_INTR_PCM_OUTPUT_UNDERFLOW); 223 224 /* still more than zero? */ 225 if (tav_read_short(iot, ioh, TAV_BUFF)) 226 (void)tsleep(sc, PCATCH, "tavdrain", 32*hz); 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 return 0; 236 } 237 238 int 239 tav_query_encoding(hdl, ae) 240 void *hdl; 241 struct audio_encoding *ae; 242 { 243 struct tav_softc *sc; 244 245 sc = hdl; 246 if (ae->index >= sizeof(tav_encodings)/sizeof(*ae)) 247 return EINVAL; 248 249 *ae = tav_encodings[ae->index]; 250 251 return 0; 252 } 253 254 int 255 tav_start_input(hdl, block, bsize, intr, intrarg) 256 void *hdl; 257 void *block; 258 int bsize; 259 void (*intr) __P((void *)); 260 void *intrarg; 261 { 262 return ENOTTY; 263 } 264 265 int 266 tav_halt_input(hdl) 267 void *hdl; 268 { 269 return ENOTTY; 270 } 271 272 int 273 tav_start_output(hdl, block, bsize, intr, intrarg) 274 void *hdl; 275 void *block; 276 int bsize; 277 void (*intr) __P((void *)); 278 void *intrarg; 279 { 280 struct tav_softc *sc; 281 bus_space_tag_t iot; 282 bus_space_handle_t ioh; 283 u_int8_t *ptr; 284 int count; 285 286 287 sc = hdl; 288 iot = sc->sc_iot; 289 ioh = sc->sc_ioh; 290 ptr = block; 291 count = bsize; 292 293 sc->sc_intr = intr; 294 sc->sc_intrarg = intrarg; 295 296 while (--count >= 0) { 297 bus_space_write_1(iot, ioh, TAV_DATAIN, *ptr++); 298 delay(1); 299 } 300 tav_write_short(iot, ioh, TAV_INTR_EN, TAV_INTR_LOWWATER); 301 302 return 0; 303 } 304 305 int 306 tav_init_output(hdl, buffer, size) 307 void *hdl; 308 void *buffer; 309 int size; 310 { 311 struct tav_softc *sc; 312 bus_space_tag_t iot; 313 bus_space_handle_t ioh; 314 315 sc = hdl; 316 iot = sc->sc_iot; 317 ioh = sc->sc_ioh; 318 319 tav_write_byte(iot, ioh, TAV_PLAY, 1); 320 tav_write_byte(iot, ioh, TAV_MUTE, 0); 321 322 return 0; 323 } 324 325 int 326 tav_halt_output(hdl) 327 void *hdl; 328 { 329 struct tav_softc *sc; 330 bus_space_tag_t iot; 331 bus_space_handle_t ioh; 332 333 sc = hdl; 334 iot = sc->sc_iot; 335 ioh = sc->sc_ioh; 336 337 tav_write_byte(iot, ioh, TAV_PLAY, 0); 338 339 return 0; 340 } 341 342 int 343 tav_getdev(hdl, ret) 344 void *hdl; 345 struct audio_device *ret; 346 { 347 struct tav_softc *sc; 348 bus_space_tag_t iot; 349 bus_space_handle_t ioh; 350 351 sc = hdl; 352 iot = sc->sc_iot; 353 ioh = sc->sc_ioh; 354 355 strncpy(ret->name, "tms320av110", MAX_AUDIO_DEV_LEN); 356 sprintf(ret->version, "%u", /* guaranteed to be <= 4 in length */ 357 tav_read_byte(iot, ioh, TAV_VERSION)); 358 strncpy(ret->config, sc->sc_dev.dv_xname, MAX_AUDIO_DEV_LEN); 359 360 return 0; 361 } 362 363 int 364 tav_round_blocksize(hdl, size) 365 void *hdl; 366 int size; 367 { 368 struct tav_softc *sc; 369 bus_space_tag_t iot; 370 bus_space_handle_t ioh; 371 int maxhalf; 372 373 sc = hdl; 374 iot = sc->sc_iot; 375 ioh = sc->sc_ioh; 376 377 maxhalf = TAV_DRAM_HSIZE(tav_read_byte(iot, ioh, TAV_DRAM_EXT)); 378 if (size > maxhalf) 379 size = maxhalf; 380 381 /* XXX should round to 128 bytes limits for audio bypass */ 382 size &= ~3; 383 384 tav_write_short(iot, ioh, TAV_BALE_LIM, size/8); 385 386 /* the buffer limits are in units of 4 bytes */ 387 return (size); 388 } 389 390 int 391 tav_get_props(hdl) 392 void *hdl; 393 { 394 return 0; 395 } 396 397 int 398 tav_set_params(hdl, setmode, usemode, p, r) 399 void *hdl; 400 int setmode, usemode; 401 struct audio_params *p, *r; 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 473 int 474 tav_set_port(hdl, mc) 475 void *hdl; 476 mixer_ctrl_t *mc; 477 { 478 struct tav_softc *sc; 479 480 sc = hdl; 481 /* dummy */ 482 return 0; 483 } 484 485 int 486 tav_get_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_query_devinfo(hdl, di) 499 void *hdl; 500 mixer_devinfo_t *di; 501 { 502 return ENXIO; 503 } 504 505 int 506 tav_speaker_ctl(hdl, value) 507 void *hdl; 508 int value; 509 { 510 struct tav_softc *sc; 511 bus_space_tag_t iot; 512 bus_space_handle_t ioh; 513 514 sc = hdl; 515 iot = sc->sc_iot; 516 ioh = sc->sc_ioh; 517 518 tav_write_byte(iot, ioh, TAV_MUTE, !value); 519 520 return 0; 521 } 522