1 /* $NetBSD: tms320av110.c,v 1.10 2001/11/13 13:14:45 lukem 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/cdefs.h> 47 __KERNEL_RCSID(0, "$NetBSD: tms320av110.c,v 1.10 2001/11/13 13:14:45 lukem Exp $"); 48 49 #include <sys/types.h> 50 #include <sys/param.h> 51 #include <sys/systm.h> 52 #include <sys/kernel.h> 53 #include <sys/device.h> 54 #include <sys/proc.h> 55 56 #include <sys/audioio.h> 57 #include <dev/audio_if.h> 58 59 #include <dev/ic/tms320av110reg.h> 60 #include <dev/ic/tms320av110var.h> 61 62 #include <machine/bus.h> 63 64 int tav_open __P((void*, int)); 65 void tav_close __P((void *)); 66 int tav_drain __P((void *)); 67 int tav_query_encoding __P((void *, struct audio_encoding *)); 68 int tav_set_params __P((void *, int, int, struct audio_params *, 69 struct audio_params *)); 70 int tav_round_blocksize __P((void *, int)); 71 int tav_init_output __P((void *, void *, int)); 72 int tav_start_output __P((void *, void *, int, void (*)(void *), void *)); 73 int tav_start_input __P((void *, void *, int, void (*)(void *), void *)); 74 int tav_halt_output __P((void *)); 75 int tav_halt_input __P((void *)); 76 int tav_speaker_ctl __P((void *, int)); 77 int tav_getdev __P((void *, struct audio_device *)); 78 int tav_setfd __P((void *, int)); 79 int tav_set_port __P((void *, mixer_ctrl_t *)); 80 int tav_get_port __P((void *, mixer_ctrl_t *)); 81 int tav_query_devinfo __P((void *, mixer_devinfo_t *)); 82 int tav_get_props __P((void *)); 83 84 struct audio_hw_if tav_audio_if = { 85 tav_open, 86 tav_close, 87 0 /* tav_drain*/, /* optional */ 88 tav_query_encoding, 89 tav_set_params, 90 tav_round_blocksize, 91 0 /* commit_settings */, /* optional */ 92 tav_init_output, /* optional */ 93 0 /* tav_init_input */, /* optional */ 94 tav_start_output, 95 tav_start_input, 96 tav_halt_output, 97 tav_halt_input, 98 tav_speaker_ctl, /* optional */ 99 tav_getdev, 100 0 /* setfd */, /* optional */ 101 tav_set_port, 102 tav_get_port, 103 tav_query_devinfo, 104 0 /* alloc */, /* optional */ 105 0 /* free */, /* optional */ 106 0 /* round_buffersize */, /* optional */ 107 0 /* mappage */, /* optional */ 108 tav_get_props, 109 0 /* dev_ioctl */ /* optional */ 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_short(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, 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, AudioEmpeg_l2_stream, AUDIO_ENCODING_MPEG_L2_STREAM, 1, 0,}, 179 {1, AudioEmpeg_l2_packets, AUDIO_ENCODING_MPEG_L2_PACKETS, 1, 0,}, 180 {2, AudioEmpeg_l2_system, AUDIO_ENCODING_MPEG_L2_SYSTEM, 1, 0,}, 181 {3, AudioEslinear_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 bus_space_write_multi_1(iot, ioh, TAV_DATAIN, ptr, count); 309 tav_write_short(iot, ioh, TAV_INTR_EN, TAV_INTR_LOWWATER); 310 311 return 0; 312 } 313 314 int 315 tav_init_output(hdl, buffer, size) 316 void *hdl; 317 void *buffer; 318 int size; 319 { 320 struct tav_softc *sc; 321 bus_space_tag_t iot; 322 bus_space_handle_t ioh; 323 324 sc = hdl; 325 iot = sc->sc_iot; 326 ioh = sc->sc_ioh; 327 328 tav_write_byte(iot, ioh, TAV_PLAY, 1); 329 tav_write_byte(iot, ioh, TAV_MUTE, 0); 330 331 return 0; 332 } 333 334 int 335 tav_halt_output(hdl) 336 void *hdl; 337 { 338 struct tav_softc *sc; 339 bus_space_tag_t iot; 340 bus_space_handle_t ioh; 341 342 sc = hdl; 343 iot = sc->sc_iot; 344 ioh = sc->sc_ioh; 345 346 tav_write_byte(iot, ioh, TAV_PLAY, 0); 347 348 return 0; 349 } 350 351 int 352 tav_getdev(hdl, ret) 353 void *hdl; 354 struct audio_device *ret; 355 { 356 struct tav_softc *sc; 357 bus_space_tag_t iot; 358 bus_space_handle_t ioh; 359 360 sc = hdl; 361 iot = sc->sc_iot; 362 ioh = sc->sc_ioh; 363 364 strncpy(ret->name, "tms320av110", MAX_AUDIO_DEV_LEN); 365 sprintf(ret->version, "%u", /* guaranteed to be <= 4 in length */ 366 tav_read_byte(iot, ioh, TAV_VERSION)); 367 strncpy(ret->config, sc->sc_dev.dv_xname, MAX_AUDIO_DEV_LEN); 368 369 return 0; 370 } 371 372 int 373 tav_round_blocksize(hdl, size) 374 void *hdl; 375 int size; 376 { 377 struct tav_softc *sc; 378 bus_space_tag_t iot; 379 bus_space_handle_t ioh; 380 int maxhalf; 381 382 sc = hdl; 383 iot = sc->sc_iot; 384 ioh = sc->sc_ioh; 385 386 maxhalf = TAV_DRAM_HSIZE(tav_read_byte(iot, ioh, TAV_DRAM_EXT)); 387 if (size > maxhalf) 388 size = maxhalf; 389 390 /* XXX should round to 128 bytes limits for audio bypass */ 391 size &= ~3; 392 393 tav_write_short(iot, ioh, TAV_BALE_LIM, size/8); 394 395 /* the buffer limits are in units of 4 bytes */ 396 return (size); 397 } 398 399 int 400 tav_get_props(hdl) 401 void *hdl; 402 { 403 return 0; 404 } 405 406 int 407 tav_set_params(hdl, setmode, usemode, p, r) 408 void *hdl; 409 int setmode, usemode; 410 struct audio_params *p, *r; 411 { 412 struct tav_softc *sc; 413 bus_space_tag_t iot; 414 bus_space_handle_t ioh; 415 416 sc = hdl; 417 iot = sc->sc_iot; 418 ioh = sc->sc_ioh; 419 420 if (!(setmode & AUMODE_PLAY)) 421 return 0; 422 423 if (p->encoding == AUDIO_ENCODING_ULAW) 424 p->encoding = AUDIO_ENCODING_MPEG_L2_STREAM; 425 426 switch(p->encoding) { 427 default: 428 return EINVAL; 429 430 case AUDIO_ENCODING_SLINEAR_BE: 431 432 /* XXX: todo: add 8bit and mono using software */ 433 p->precision = 16; 434 p->channels = 2; 435 436 /* XXX: this might depend on the specific board. 437 should be handled by the backend */ 438 439 p->sample_rate = 44100; 440 441 bus_space_write_1(iot, ioh, TAV_STR_SEL, 442 TAV_STR_SEL_AUDIO_BYPASS); 443 break; 444 445 /* XXX: later: add ULINEAR, and LE using software encoding */ 446 447 case AUDIO_ENCODING_MPEG_L1_STREAM: 448 /* FALLTHROUGH */ 449 case AUDIO_ENCODING_MPEG_L2_STREAM: 450 bus_space_write_1(iot, ioh, TAV_STR_SEL, 451 TAV_STR_SEL_MPEG_AUDIO_STREAM); 452 p->sample_rate = 44100; 453 p->precision = 1; 454 break; 455 456 case AUDIO_ENCODING_MPEG_L1_PACKETS: 457 /* FALLTHROUGH */ 458 case AUDIO_ENCODING_MPEG_L2_PACKETS: 459 bus_space_write_1(iot, ioh, TAV_STR_SEL, 460 TAV_STR_SEL_MPEG_AUDIO_PACKETS); 461 p->sample_rate = 44100; 462 p->precision = 1; 463 break; 464 465 case AUDIO_ENCODING_MPEG_L1_SYSTEM: 466 /* FALLTHROUGH */ 467 case AUDIO_ENCODING_MPEG_L2_SYSTEM: 468 bus_space_write_1(iot, ioh, TAV_STR_SEL, 469 TAV_STR_SEL_MPEG_SYSTEM_STREAM); 470 p->sample_rate = 44100; 471 p->precision = 1; 472 break; 473 } 474 tav_write_byte(iot, ioh, TAV_RESTART, 1); 475 do { 476 delay(10); 477 } while (tav_read_byte(iot, ioh, TAV_RESTART)); 478 479 return 0; 480 } 481 482 int 483 tav_set_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_get_port(hdl, mc) 496 void *hdl; 497 mixer_ctrl_t *mc; 498 { 499 struct tav_softc *sc; 500 501 sc = hdl; 502 /* dummy */ 503 return 0; 504 } 505 506 int 507 tav_query_devinfo(hdl, di) 508 void *hdl; 509 mixer_devinfo_t *di; 510 { 511 return ENXIO; 512 } 513 514 int 515 tav_speaker_ctl(hdl, value) 516 void *hdl; 517 int value; 518 { 519 struct tav_softc *sc; 520 bus_space_tag_t iot; 521 bus_space_handle_t ioh; 522 523 sc = hdl; 524 iot = sc->sc_iot; 525 ioh = sc->sc_ioh; 526 527 tav_write_byte(iot, ioh, TAV_MUTE, !value); 528 529 return 0; 530 } 531