1 /* $NetBSD: tms320av110.c,v 1.6 1998/08/17 21:16:13 augustss 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, 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 bus_space_write_multi_1(iot, ioh, TAV_DATAIN, ptr, count); 297 tav_write_short(iot, ioh, TAV_INTR_EN, TAV_INTR_LOWWATER); 298 299 return 0; 300 } 301 302 int 303 tav_init_output(hdl, buffer, size) 304 void *hdl; 305 void *buffer; 306 int size; 307 { 308 struct tav_softc *sc; 309 bus_space_tag_t iot; 310 bus_space_handle_t ioh; 311 312 sc = hdl; 313 iot = sc->sc_iot; 314 ioh = sc->sc_ioh; 315 316 tav_write_byte(iot, ioh, TAV_PLAY, 1); 317 tav_write_byte(iot, ioh, TAV_MUTE, 0); 318 319 return 0; 320 } 321 322 int 323 tav_halt_output(hdl) 324 void *hdl; 325 { 326 struct tav_softc *sc; 327 bus_space_tag_t iot; 328 bus_space_handle_t ioh; 329 330 sc = hdl; 331 iot = sc->sc_iot; 332 ioh = sc->sc_ioh; 333 334 tav_write_byte(iot, ioh, TAV_PLAY, 0); 335 336 return 0; 337 } 338 339 int 340 tav_getdev(hdl, ret) 341 void *hdl; 342 struct audio_device *ret; 343 { 344 struct tav_softc *sc; 345 bus_space_tag_t iot; 346 bus_space_handle_t ioh; 347 348 sc = hdl; 349 iot = sc->sc_iot; 350 ioh = sc->sc_ioh; 351 352 strncpy(ret->name, "tms320av110", MAX_AUDIO_DEV_LEN); 353 sprintf(ret->version, "%u", /* guaranteed to be <= 4 in length */ 354 tav_read_byte(iot, ioh, TAV_VERSION)); 355 strncpy(ret->config, sc->sc_dev.dv_xname, MAX_AUDIO_DEV_LEN); 356 357 return 0; 358 } 359 360 int 361 tav_round_blocksize(hdl, size) 362 void *hdl; 363 int size; 364 { 365 struct tav_softc *sc; 366 bus_space_tag_t iot; 367 bus_space_handle_t ioh; 368 int maxhalf; 369 370 sc = hdl; 371 iot = sc->sc_iot; 372 ioh = sc->sc_ioh; 373 374 maxhalf = TAV_DRAM_HSIZE(tav_read_byte(iot, ioh, TAV_DRAM_EXT)); 375 if (size > maxhalf) 376 size = maxhalf; 377 378 /* XXX should round to 128 bytes limits for audio bypass */ 379 size &= ~3; 380 381 tav_write_short(iot, ioh, TAV_BALE_LIM, size/8); 382 383 /* the buffer limits are in units of 4 bytes */ 384 return (size); 385 } 386 387 int 388 tav_get_props(hdl) 389 void *hdl; 390 { 391 return 0; 392 } 393 394 int 395 tav_set_params(hdl, setmode, usemode, p, r) 396 void *hdl; 397 int setmode, usemode; 398 struct audio_params *p, *r; 399 { 400 struct tav_softc *sc; 401 bus_space_tag_t iot; 402 bus_space_handle_t ioh; 403 404 sc = hdl; 405 iot = sc->sc_iot; 406 ioh = sc->sc_ioh; 407 408 if (!(setmode & AUMODE_PLAY)) 409 return 0; 410 411 if (p->encoding == AUDIO_ENCODING_ULAW) 412 p->encoding = AUDIO_ENCODING_MPEG_L2_STREAM; 413 414 switch(p->encoding) { 415 default: 416 return EINVAL; 417 418 case AUDIO_ENCODING_SLINEAR_BE: 419 420 /* XXX: todo: add 8bit and mono using software */ 421 p->precision = 16; 422 p->channels = 2; 423 424 /* XXX: this might depend on the specific board. 425 should be handled by the backend */ 426 427 p->sample_rate = 44100; 428 429 bus_space_write_1(iot, ioh, TAV_STR_SEL, 430 TAV_STR_SEL_AUDIO_BYPASS); 431 break; 432 433 /* XXX: later: add ULINEAR, and LE using software encoding */ 434 435 case AUDIO_ENCODING_MPEG_L1_STREAM: 436 /* FALLTHROUGH */ 437 case AUDIO_ENCODING_MPEG_L2_STREAM: 438 bus_space_write_1(iot, ioh, TAV_STR_SEL, 439 TAV_STR_SEL_MPEG_AUDIO_STREAM); 440 p->sample_rate = 44100; 441 p->precision = 1; 442 break; 443 444 case AUDIO_ENCODING_MPEG_L1_PACKETS: 445 /* FALLTHROUGH */ 446 case AUDIO_ENCODING_MPEG_L2_PACKETS: 447 bus_space_write_1(iot, ioh, TAV_STR_SEL, 448 TAV_STR_SEL_MPEG_AUDIO_PACKETS); 449 p->sample_rate = 44100; 450 p->precision = 1; 451 break; 452 453 case AUDIO_ENCODING_MPEG_L1_SYSTEM: 454 /* FALLTHROUGH */ 455 case AUDIO_ENCODING_MPEG_L2_SYSTEM: 456 bus_space_write_1(iot, ioh, TAV_STR_SEL, 457 TAV_STR_SEL_MPEG_SYSTEM_STREAM); 458 p->sample_rate = 44100; 459 p->precision = 1; 460 break; 461 } 462 tav_write_byte(iot, ioh, TAV_RESTART, 1); 463 do { 464 delay(10); 465 } while (tav_read_byte(iot, ioh, TAV_RESTART)); 466 467 return 0; 468 } 469 470 int 471 tav_set_port(hdl, mc) 472 void *hdl; 473 mixer_ctrl_t *mc; 474 { 475 struct tav_softc *sc; 476 477 sc = hdl; 478 /* dummy */ 479 return 0; 480 } 481 482 int 483 tav_get_port(hdl, mc) 484 void *hdl; 485 mixer_ctrl_t *mc; 486 { 487 struct tav_softc *sc; 488 489 sc = hdl; 490 /* dummy */ 491 return 0; 492 } 493 494 int 495 tav_query_devinfo(hdl, di) 496 void *hdl; 497 mixer_devinfo_t *di; 498 { 499 return ENXIO; 500 } 501 502 int 503 tav_speaker_ctl(hdl, value) 504 void *hdl; 505 int value; 506 { 507 struct tav_softc *sc; 508 bus_space_tag_t iot; 509 bus_space_handle_t ioh; 510 511 sc = hdl; 512 iot = sc->sc_iot; 513 ioh = sc->sc_ioh; 514 515 tav_write_byte(iot, ioh, TAV_MUTE, !value); 516 517 return 0; 518 } 519