1 /* $NetBSD: tms320av110.c,v 1.8 1999/02/16 23:34:13 is 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 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * Machine independent part of TMS320AV110 driver. 41 * 42 * Currently, only minimum support for audio output. For audio/video 43 * synchronization, more is needed. 44 */ 45 46 #include <sys/types.h> 47 #include <sys/param.h> 48 #include <sys/systm.h> 49 #include <sys/kernel.h> 50 #include <sys/device.h> 51 #include <sys/proc.h> 52 53 #include <sys/audioio.h> 54 #include <dev/audio_if.h> 55 56 #include <dev/ic/tms320av110reg.h> 57 #include <dev/ic/tms320av110var.h> 58 59 #include <machine/bus.h> 60 61 int tav_open __P((void*, int)); 62 void tav_close __P((void *)); 63 int tav_drain __P((void *)); 64 int tav_query_encoding __P((void *, struct audio_encoding *)); 65 int tav_set_params __P((void *, int, int, struct audio_params *, 66 struct audio_params *)); 67 int tav_round_blocksize __P((void *, int)); 68 int tav_init_output __P((void *, void *, int)); 69 int tav_start_output __P((void *, void *, int, void (*)(void *), void *)); 70 int tav_start_input __P((void *, void *, int, void (*)(void *), void *)); 71 int tav_halt_output __P((void *)); 72 int tav_halt_input __P((void *)); 73 int tav_speaker_ctl __P((void *, int)); 74 int tav_getdev __P((void *, struct audio_device *)); 75 int tav_setfd __P((void *, int)); 76 int tav_set_port __P((void *, mixer_ctrl_t *)); 77 int tav_get_port __P((void *, mixer_ctrl_t *)); 78 int tav_query_devinfo __P((void *, mixer_devinfo_t *)); 79 int tav_get_props __P((void *)); 80 81 struct audio_hw_if tav_audio_if = { 82 tav_open, 83 tav_close, 84 0 /* tav_drain*/, /* optional */ 85 tav_query_encoding, 86 tav_set_params, 87 tav_round_blocksize, 88 0 /* commit_settings */, /* optional */ 89 tav_init_output, /* optional */ 90 0 /* tav_init_input */, /* optional */ 91 tav_start_output, 92 tav_start_input, 93 tav_halt_output, 94 tav_halt_input, 95 tav_speaker_ctl, /* optional */ 96 tav_getdev, 97 0 /* setfd */, /* optional */ 98 tav_set_port, 99 tav_get_port, 100 tav_query_devinfo, 101 0 /* alloc */, /* optional */ 102 0 /* free */, /* optional */ 103 0 /* round_buffersize */, /* optional */ 104 0 /* mappage */, /* optional */ 105 tav_get_props 106 }; 107 108 void 109 tms320av110_attach_mi(sc) 110 struct tav_softc *sc; 111 { 112 bus_space_tag_t iot = sc->sc_iot; 113 bus_space_handle_t ioh = sc->sc_ioh; 114 115 tav_write_byte(iot, ioh, TAV_RESET, 1); 116 while (tav_read_byte(iot, ioh, TAV_RESET)) 117 delay(250); 118 119 tav_write_byte(iot, ioh, TAV_PCM_ORD, sc->sc_pcm_ord); 120 tav_write_byte(iot, ioh, TAV_PCM_18, sc->sc_pcm_18); 121 tav_write_byte(iot, ioh, TAV_DIF, sc->sc_dif); 122 tav_write_byte(iot, ioh, TAV_PCM_DIV, sc->sc_pcm_div); 123 124 printf(": chip rev. %d, %d bytes buffer\n", 125 tav_read_byte(iot, ioh, TAV_VERSION), 126 TAV_DRAM_SIZE(tav_read_byte(iot, ioh, TAV_DRAM_EXT))); 127 128 tav_write_byte(iot, ioh, TAV_AUD_ID_EN, 0); 129 tav_write_byte(iot, ioh, TAV_SKIP, 0); 130 tav_write_byte(iot, ioh, TAV_REPEAT, 0); 131 tav_write_byte(iot, ioh, TAV_MUTE, 0); 132 tav_write_byte(iot, ioh, TAV_PLAY, 1); 133 tav_write_byte(iot, ioh, TAV_SYNC_ECM, 0); 134 tav_write_byte(iot, ioh, TAV_CRC_ECM, 0); 135 tav_write_byte(iot, ioh, TAV_ATTEN_L, 0); 136 tav_write_byte(iot, ioh, TAV_ATTEN_R, 0); 137 tav_write_short(iot, ioh, TAV_FREE_FORM, 0); 138 tav_write_byte(iot, ioh, TAV_SIN_EN, 0); 139 tav_write_byte(iot, ioh, TAV_SYNC_ECM, TAV_ECM_REPEAT); 140 tav_write_byte(iot, ioh, TAV_CRC_ECM, TAV_ECM_REPEAT); 141 142 audio_attach_mi(&tav_audio_if, sc, &sc->sc_dev); 143 } 144 145 int 146 tms320av110_intr(p) 147 void *p; 148 { 149 struct tav_softc *sc = p; 150 u_int16_t intlist; 151 152 intlist = tav_read_short(sc->sc_iot, sc->sc_ioh, TAV_INTR) 153 /* & tav_read_short(sc->sc_iot, sc->sc_ioh, TAV_INTR_EN)*/; 154 155 if (!intlist) 156 return 0; 157 158 /* ack now, so that we don't miss later interupts */ 159 if (sc->sc_intack) 160 (sc->sc_intack)(sc); 161 162 if (intlist & TAV_INTR_LOWWATER) { 163 (*sc->sc_intr)(sc->sc_intrarg); 164 } 165 166 if (intlist & TAV_INTR_PCM_OUTPUT_UNDERFLOW) { 167 wakeup(sc); 168 } 169 170 return 1; 171 } 172 173 struct audio_encoding tav_encodings[] = { 174 {0, AudioEmpeg_l2_stream, AUDIO_ENCODING_MPEG_L2_STREAM, 1, 0,}, 175 {1, AudioEmpeg_l2_packets, AUDIO_ENCODING_MPEG_L2_PACKETS, 1, 0,}, 176 {2, AudioEmpeg_l2_system, AUDIO_ENCODING_MPEG_L2_SYSTEM, 1, 0,}, 177 {3, AudioEslinear_be, AUDIO_ENCODING_SLINEAR_BE, 16, 0,}, 178 }; 179 180 int 181 tav_open(hdl, flags) 182 void *hdl; 183 int flags; 184 { 185 struct tav_softc *sc; 186 187 sc = hdl; 188 189 /* dummy */ 190 return 0; 191 } 192 193 void 194 tav_close(hdl) 195 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 interupts and interupt 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(hdl) 213 void *hdl; 214 { 215 struct tav_softc *sc; 216 bus_space_tag_t iot; 217 bus_space_handle_t ioh; 218 u_int16_t mask; 219 220 sc = hdl; 221 iot = sc->sc_iot; 222 ioh = sc->sc_ioh; 223 224 /* 225 * tsleep waiting for underflow interupt. 226 */ 227 if (tav_read_short(iot, ioh, TAV_BUFF)) { 228 mask = tav_read_short(iot, ioh, TAV_INTR_EN); 229 tav_write_short(iot, ioh, TAV_INTR_EN, 230 mask|TAV_INTR_PCM_OUTPUT_UNDERFLOW); 231 232 /* still more than zero? */ 233 if (tav_read_short(iot, ioh, TAV_BUFF)) 234 (void)tsleep(sc, PCATCH, "tavdrain", 32*hz); 235 236 /* can be really that long for mpeg */ 237 238 mask = tav_read_short(iot, ioh, TAV_INTR_EN); 239 tav_write_short(iot, ioh, TAV_INTR_EN, 240 mask & ~TAV_INTR_PCM_OUTPUT_UNDERFLOW); 241 } 242 243 return 0; 244 } 245 246 int 247 tav_query_encoding(hdl, ae) 248 void *hdl; 249 struct audio_encoding *ae; 250 { 251 struct tav_softc *sc; 252 253 sc = hdl; 254 if (ae->index >= sizeof(tav_encodings)/sizeof(*ae)) 255 return EINVAL; 256 257 *ae = tav_encodings[ae->index]; 258 259 return 0; 260 } 261 262 int 263 tav_start_input(hdl, block, bsize, intr, intrarg) 264 void *hdl; 265 void *block; 266 int bsize; 267 void (*intr) __P((void *)); 268 void *intrarg; 269 { 270 return ENOTTY; 271 } 272 273 int 274 tav_halt_input(hdl) 275 void *hdl; 276 { 277 return ENOTTY; 278 } 279 280 int 281 tav_start_output(hdl, block, bsize, intr, intrarg) 282 void *hdl; 283 void *block; 284 int bsize; 285 void (*intr) __P((void *)); 286 void *intrarg; 287 { 288 struct tav_softc *sc; 289 bus_space_tag_t iot; 290 bus_space_handle_t ioh; 291 u_int8_t *ptr; 292 int count; 293 294 295 sc = hdl; 296 iot = sc->sc_iot; 297 ioh = sc->sc_ioh; 298 ptr = block; 299 count = bsize; 300 301 sc->sc_intr = intr; 302 sc->sc_intrarg = intrarg; 303 304 bus_space_write_multi_1(iot, ioh, TAV_DATAIN, ptr, count); 305 tav_write_short(iot, ioh, TAV_INTR_EN, TAV_INTR_LOWWATER); 306 307 return 0; 308 } 309 310 int 311 tav_init_output(hdl, buffer, size) 312 void *hdl; 313 void *buffer; 314 int size; 315 { 316 struct tav_softc *sc; 317 bus_space_tag_t iot; 318 bus_space_handle_t ioh; 319 320 sc = hdl; 321 iot = sc->sc_iot; 322 ioh = sc->sc_ioh; 323 324 tav_write_byte(iot, ioh, TAV_PLAY, 1); 325 tav_write_byte(iot, ioh, TAV_MUTE, 0); 326 327 return 0; 328 } 329 330 int 331 tav_halt_output(hdl) 332 void *hdl; 333 { 334 struct tav_softc *sc; 335 bus_space_tag_t iot; 336 bus_space_handle_t ioh; 337 338 sc = hdl; 339 iot = sc->sc_iot; 340 ioh = sc->sc_ioh; 341 342 tav_write_byte(iot, ioh, TAV_PLAY, 0); 343 344 return 0; 345 } 346 347 int 348 tav_getdev(hdl, ret) 349 void *hdl; 350 struct audio_device *ret; 351 { 352 struct tav_softc *sc; 353 bus_space_tag_t iot; 354 bus_space_handle_t ioh; 355 356 sc = hdl; 357 iot = sc->sc_iot; 358 ioh = sc->sc_ioh; 359 360 strncpy(ret->name, "tms320av110", MAX_AUDIO_DEV_LEN); 361 sprintf(ret->version, "%u", /* guaranteed to be <= 4 in length */ 362 tav_read_byte(iot, ioh, TAV_VERSION)); 363 strncpy(ret->config, sc->sc_dev.dv_xname, MAX_AUDIO_DEV_LEN); 364 365 return 0; 366 } 367 368 int 369 tav_round_blocksize(hdl, size) 370 void *hdl; 371 int size; 372 { 373 struct tav_softc *sc; 374 bus_space_tag_t iot; 375 bus_space_handle_t ioh; 376 int maxhalf; 377 378 sc = hdl; 379 iot = sc->sc_iot; 380 ioh = sc->sc_ioh; 381 382 maxhalf = TAV_DRAM_HSIZE(tav_read_byte(iot, ioh, TAV_DRAM_EXT)); 383 if (size > maxhalf) 384 size = maxhalf; 385 386 /* XXX should round to 128 bytes limits for audio bypass */ 387 size &= ~3; 388 389 tav_write_short(iot, ioh, TAV_BALE_LIM, size/8); 390 391 /* the buffer limits are in units of 4 bytes */ 392 return (size); 393 } 394 395 int 396 tav_get_props(hdl) 397 void *hdl; 398 { 399 return 0; 400 } 401 402 int 403 tav_set_params(hdl, setmode, usemode, p, r) 404 void *hdl; 405 int setmode, usemode; 406 struct audio_params *p, *r; 407 { 408 struct tav_softc *sc; 409 bus_space_tag_t iot; 410 bus_space_handle_t ioh; 411 412 sc = hdl; 413 iot = sc->sc_iot; 414 ioh = sc->sc_ioh; 415 416 if (!(setmode & AUMODE_PLAY)) 417 return 0; 418 419 if (p->encoding == AUDIO_ENCODING_ULAW) 420 p->encoding = AUDIO_ENCODING_MPEG_L2_STREAM; 421 422 switch(p->encoding) { 423 default: 424 return EINVAL; 425 426 case AUDIO_ENCODING_SLINEAR_BE: 427 428 /* XXX: todo: add 8bit and mono using software */ 429 p->precision = 16; 430 p->channels = 2; 431 432 /* XXX: this might depend on the specific board. 433 should be handled by the backend */ 434 435 p->sample_rate = 44100; 436 437 bus_space_write_1(iot, ioh, TAV_STR_SEL, 438 TAV_STR_SEL_AUDIO_BYPASS); 439 break; 440 441 /* XXX: later: add ULINEAR, and LE using software encoding */ 442 443 case AUDIO_ENCODING_MPEG_L1_STREAM: 444 /* FALLTHROUGH */ 445 case AUDIO_ENCODING_MPEG_L2_STREAM: 446 bus_space_write_1(iot, ioh, TAV_STR_SEL, 447 TAV_STR_SEL_MPEG_AUDIO_STREAM); 448 p->sample_rate = 44100; 449 p->precision = 1; 450 break; 451 452 case AUDIO_ENCODING_MPEG_L1_PACKETS: 453 /* FALLTHROUGH */ 454 case AUDIO_ENCODING_MPEG_L2_PACKETS: 455 bus_space_write_1(iot, ioh, TAV_STR_SEL, 456 TAV_STR_SEL_MPEG_AUDIO_PACKETS); 457 p->sample_rate = 44100; 458 p->precision = 1; 459 break; 460 461 case AUDIO_ENCODING_MPEG_L1_SYSTEM: 462 /* FALLTHROUGH */ 463 case AUDIO_ENCODING_MPEG_L2_SYSTEM: 464 bus_space_write_1(iot, ioh, TAV_STR_SEL, 465 TAV_STR_SEL_MPEG_SYSTEM_STREAM); 466 p->sample_rate = 44100; 467 p->precision = 1; 468 break; 469 } 470 tav_write_byte(iot, ioh, TAV_RESTART, 1); 471 do { 472 delay(10); 473 } while (tav_read_byte(iot, ioh, TAV_RESTART)); 474 475 return 0; 476 } 477 478 int 479 tav_set_port(hdl, mc) 480 void *hdl; 481 mixer_ctrl_t *mc; 482 { 483 struct tav_softc *sc; 484 485 sc = hdl; 486 /* dummy */ 487 return 0; 488 } 489 490 int 491 tav_get_port(hdl, mc) 492 void *hdl; 493 mixer_ctrl_t *mc; 494 { 495 struct tav_softc *sc; 496 497 sc = hdl; 498 /* dummy */ 499 return 0; 500 } 501 502 int 503 tav_query_devinfo(hdl, di) 504 void *hdl; 505 mixer_devinfo_t *di; 506 { 507 return ENXIO; 508 } 509 510 int 511 tav_speaker_ctl(hdl, value) 512 void *hdl; 513 int value; 514 { 515 struct tav_softc *sc; 516 bus_space_tag_t iot; 517 bus_space_handle_t ioh; 518 519 sc = hdl; 520 iot = sc->sc_iot; 521 ioh = sc->sc_ioh; 522 523 tav_write_byte(iot, ioh, TAV_MUTE, !value); 524 525 return 0; 526 } 527