1 /* $NetBSD: tms320av110.c,v 1.9 2001/10/03 00:04:50 augustss 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 0 /* dev_ioctl */ /* optional */ 107 }; 108 109 void 110 tms320av110_attach_mi(sc) 111 struct tav_softc *sc; 112 { 113 bus_space_tag_t iot = sc->sc_iot; 114 bus_space_handle_t ioh = sc->sc_ioh; 115 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 146 int 147 tms320av110_intr(p) 148 void *p; 149 { 150 struct tav_softc *sc = p; 151 u_int16_t intlist; 152 153 intlist = tav_read_short(sc->sc_iot, sc->sc_ioh, TAV_INTR) 154 /* & tav_read_short(sc->sc_iot, sc->sc_ioh, TAV_INTR_EN)*/; 155 156 if (!intlist) 157 return 0; 158 159 /* ack now, so that we don't miss later interupts */ 160 if (sc->sc_intack) 161 (sc->sc_intack)(sc); 162 163 if (intlist & TAV_INTR_LOWWATER) { 164 (*sc->sc_intr)(sc->sc_intrarg); 165 } 166 167 if (intlist & TAV_INTR_PCM_OUTPUT_UNDERFLOW) { 168 wakeup(sc); 169 } 170 171 return 1; 172 } 173 174 struct audio_encoding tav_encodings[] = { 175 {0, AudioEmpeg_l2_stream, AUDIO_ENCODING_MPEG_L2_STREAM, 1, 0,}, 176 {1, AudioEmpeg_l2_packets, AUDIO_ENCODING_MPEG_L2_PACKETS, 1, 0,}, 177 {2, AudioEmpeg_l2_system, AUDIO_ENCODING_MPEG_L2_SYSTEM, 1, 0,}, 178 {3, AudioEslinear_be, AUDIO_ENCODING_SLINEAR_BE, 16, 0,}, 179 }; 180 181 int 182 tav_open(hdl, flags) 183 void *hdl; 184 int flags; 185 { 186 struct tav_softc *sc; 187 188 sc = hdl; 189 190 /* dummy */ 191 return 0; 192 } 193 194 void 195 tav_close(hdl) 196 void *hdl; 197 { 198 struct tav_softc *sc; 199 bus_space_tag_t iot; 200 bus_space_handle_t ioh; 201 202 sc = hdl; 203 iot = sc->sc_iot; 204 ioh = sc->sc_ioh; 205 206 /* re"start" chip, also clears interupts and interupt enable */ 207 tav_write_short(iot, ioh, TAV_INTR_EN, 0); 208 if (sc->sc_intack) 209 (*sc->sc_intack)(sc); 210 } 211 212 int 213 tav_drain(hdl) 214 void *hdl; 215 { 216 struct tav_softc *sc; 217 bus_space_tag_t iot; 218 bus_space_handle_t ioh; 219 u_int16_t mask; 220 221 sc = hdl; 222 iot = sc->sc_iot; 223 ioh = sc->sc_ioh; 224 225 /* 226 * tsleep waiting for underflow interupt. 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)tsleep(sc, PCATCH, "tavdrain", 32*hz); 236 237 /* can be really that long for mpeg */ 238 239 mask = tav_read_short(iot, ioh, TAV_INTR_EN); 240 tav_write_short(iot, ioh, TAV_INTR_EN, 241 mask & ~TAV_INTR_PCM_OUTPUT_UNDERFLOW); 242 } 243 244 return 0; 245 } 246 247 int 248 tav_query_encoding(hdl, ae) 249 void *hdl; 250 struct audio_encoding *ae; 251 { 252 struct tav_softc *sc; 253 254 sc = hdl; 255 if (ae->index >= sizeof(tav_encodings)/sizeof(*ae)) 256 return EINVAL; 257 258 *ae = tav_encodings[ae->index]; 259 260 return 0; 261 } 262 263 int 264 tav_start_input(hdl, block, bsize, intr, intrarg) 265 void *hdl; 266 void *block; 267 int bsize; 268 void (*intr) __P((void *)); 269 void *intrarg; 270 { 271 return ENOTTY; 272 } 273 274 int 275 tav_halt_input(hdl) 276 void *hdl; 277 { 278 return ENOTTY; 279 } 280 281 int 282 tav_start_output(hdl, block, bsize, intr, intrarg) 283 void *hdl; 284 void *block; 285 int bsize; 286 void (*intr) __P((void *)); 287 void *intrarg; 288 { 289 struct tav_softc *sc; 290 bus_space_tag_t iot; 291 bus_space_handle_t ioh; 292 u_int8_t *ptr; 293 int count; 294 295 296 sc = hdl; 297 iot = sc->sc_iot; 298 ioh = sc->sc_ioh; 299 ptr = block; 300 count = bsize; 301 302 sc->sc_intr = intr; 303 sc->sc_intrarg = intrarg; 304 305 bus_space_write_multi_1(iot, ioh, TAV_DATAIN, ptr, count); 306 tav_write_short(iot, ioh, TAV_INTR_EN, TAV_INTR_LOWWATER); 307 308 return 0; 309 } 310 311 int 312 tav_init_output(hdl, buffer, size) 313 void *hdl; 314 void *buffer; 315 int size; 316 { 317 struct tav_softc *sc; 318 bus_space_tag_t iot; 319 bus_space_handle_t ioh; 320 321 sc = hdl; 322 iot = sc->sc_iot; 323 ioh = sc->sc_ioh; 324 325 tav_write_byte(iot, ioh, TAV_PLAY, 1); 326 tav_write_byte(iot, ioh, TAV_MUTE, 0); 327 328 return 0; 329 } 330 331 int 332 tav_halt_output(hdl) 333 void *hdl; 334 { 335 struct tav_softc *sc; 336 bus_space_tag_t iot; 337 bus_space_handle_t ioh; 338 339 sc = hdl; 340 iot = sc->sc_iot; 341 ioh = sc->sc_ioh; 342 343 tav_write_byte(iot, ioh, TAV_PLAY, 0); 344 345 return 0; 346 } 347 348 int 349 tav_getdev(hdl, ret) 350 void *hdl; 351 struct audio_device *ret; 352 { 353 struct tav_softc *sc; 354 bus_space_tag_t iot; 355 bus_space_handle_t ioh; 356 357 sc = hdl; 358 iot = sc->sc_iot; 359 ioh = sc->sc_ioh; 360 361 strncpy(ret->name, "tms320av110", MAX_AUDIO_DEV_LEN); 362 sprintf(ret->version, "%u", /* guaranteed to be <= 4 in length */ 363 tav_read_byte(iot, ioh, TAV_VERSION)); 364 strncpy(ret->config, sc->sc_dev.dv_xname, MAX_AUDIO_DEV_LEN); 365 366 return 0; 367 } 368 369 int 370 tav_round_blocksize(hdl, size) 371 void *hdl; 372 int size; 373 { 374 struct tav_softc *sc; 375 bus_space_tag_t iot; 376 bus_space_handle_t ioh; 377 int maxhalf; 378 379 sc = hdl; 380 iot = sc->sc_iot; 381 ioh = sc->sc_ioh; 382 383 maxhalf = TAV_DRAM_HSIZE(tav_read_byte(iot, ioh, TAV_DRAM_EXT)); 384 if (size > maxhalf) 385 size = maxhalf; 386 387 /* XXX should round to 128 bytes limits for audio bypass */ 388 size &= ~3; 389 390 tav_write_short(iot, ioh, TAV_BALE_LIM, size/8); 391 392 /* the buffer limits are in units of 4 bytes */ 393 return (size); 394 } 395 396 int 397 tav_get_props(hdl) 398 void *hdl; 399 { 400 return 0; 401 } 402 403 int 404 tav_set_params(hdl, setmode, usemode, p, r) 405 void *hdl; 406 int setmode, usemode; 407 struct audio_params *p, *r; 408 { 409 struct tav_softc *sc; 410 bus_space_tag_t iot; 411 bus_space_handle_t ioh; 412 413 sc = hdl; 414 iot = sc->sc_iot; 415 ioh = sc->sc_ioh; 416 417 if (!(setmode & AUMODE_PLAY)) 418 return 0; 419 420 if (p->encoding == AUDIO_ENCODING_ULAW) 421 p->encoding = AUDIO_ENCODING_MPEG_L2_STREAM; 422 423 switch(p->encoding) { 424 default: 425 return EINVAL; 426 427 case AUDIO_ENCODING_SLINEAR_BE: 428 429 /* XXX: todo: add 8bit and mono using software */ 430 p->precision = 16; 431 p->channels = 2; 432 433 /* XXX: this might depend on the specific board. 434 should be handled by the backend */ 435 436 p->sample_rate = 44100; 437 438 bus_space_write_1(iot, ioh, TAV_STR_SEL, 439 TAV_STR_SEL_AUDIO_BYPASS); 440 break; 441 442 /* XXX: later: add ULINEAR, and LE using software encoding */ 443 444 case AUDIO_ENCODING_MPEG_L1_STREAM: 445 /* FALLTHROUGH */ 446 case AUDIO_ENCODING_MPEG_L2_STREAM: 447 bus_space_write_1(iot, ioh, TAV_STR_SEL, 448 TAV_STR_SEL_MPEG_AUDIO_STREAM); 449 p->sample_rate = 44100; 450 p->precision = 1; 451 break; 452 453 case AUDIO_ENCODING_MPEG_L1_PACKETS: 454 /* FALLTHROUGH */ 455 case AUDIO_ENCODING_MPEG_L2_PACKETS: 456 bus_space_write_1(iot, ioh, TAV_STR_SEL, 457 TAV_STR_SEL_MPEG_AUDIO_PACKETS); 458 p->sample_rate = 44100; 459 p->precision = 1; 460 break; 461 462 case AUDIO_ENCODING_MPEG_L1_SYSTEM: 463 /* FALLTHROUGH */ 464 case AUDIO_ENCODING_MPEG_L2_SYSTEM: 465 bus_space_write_1(iot, ioh, TAV_STR_SEL, 466 TAV_STR_SEL_MPEG_SYSTEM_STREAM); 467 p->sample_rate = 44100; 468 p->precision = 1; 469 break; 470 } 471 tav_write_byte(iot, ioh, TAV_RESTART, 1); 472 do { 473 delay(10); 474 } while (tav_read_byte(iot, ioh, TAV_RESTART)); 475 476 return 0; 477 } 478 479 int 480 tav_set_port(hdl, mc) 481 void *hdl; 482 mixer_ctrl_t *mc; 483 { 484 struct tav_softc *sc; 485 486 sc = hdl; 487 /* dummy */ 488 return 0; 489 } 490 491 int 492 tav_get_port(hdl, mc) 493 void *hdl; 494 mixer_ctrl_t *mc; 495 { 496 struct tav_softc *sc; 497 498 sc = hdl; 499 /* dummy */ 500 return 0; 501 } 502 503 int 504 tav_query_devinfo(hdl, di) 505 void *hdl; 506 mixer_devinfo_t *di; 507 { 508 return ENXIO; 509 } 510 511 int 512 tav_speaker_ctl(hdl, value) 513 void *hdl; 514 int value; 515 { 516 struct tav_softc *sc; 517 bus_space_tag_t iot; 518 bus_space_handle_t ioh; 519 520 sc = hdl; 521 iot = sc->sc_iot; 522 ioh = sc->sc_ioh; 523 524 tav_write_byte(iot, ioh, TAV_MUTE, !value); 525 526 return 0; 527 } 528