1 /* $NetBSD: tms320av110.c,v 1.11 2001/11/15 09:48:08 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.11 2001/11/15 09:48:08 lukem Exp $"); 48 49 #include <sys/param.h> 50 #include <sys/systm.h> 51 #include <sys/kernel.h> 52 #include <sys/device.h> 53 #include <sys/proc.h> 54 55 #include <sys/audioio.h> 56 #include <dev/audio_if.h> 57 58 #include <dev/ic/tms320av110reg.h> 59 #include <dev/ic/tms320av110var.h> 60 61 #include <machine/bus.h> 62 63 int tav_open __P((void*, int)); 64 void tav_close __P((void *)); 65 int tav_drain __P((void *)); 66 int tav_query_encoding __P((void *, struct audio_encoding *)); 67 int tav_set_params __P((void *, int, int, struct audio_params *, 68 struct audio_params *)); 69 int tav_round_blocksize __P((void *, int)); 70 int tav_init_output __P((void *, void *, int)); 71 int tav_start_output __P((void *, void *, int, void (*)(void *), void *)); 72 int tav_start_input __P((void *, void *, int, void (*)(void *), void *)); 73 int tav_halt_output __P((void *)); 74 int tav_halt_input __P((void *)); 75 int tav_speaker_ctl __P((void *, int)); 76 int tav_getdev __P((void *, struct audio_device *)); 77 int tav_setfd __P((void *, int)); 78 int tav_set_port __P((void *, mixer_ctrl_t *)); 79 int tav_get_port __P((void *, mixer_ctrl_t *)); 80 int tav_query_devinfo __P((void *, mixer_devinfo_t *)); 81 int tav_get_props __P((void *)); 82 83 struct audio_hw_if tav_audio_if = { 84 tav_open, 85 tav_close, 86 0 /* tav_drain*/, /* optional */ 87 tav_query_encoding, 88 tav_set_params, 89 tav_round_blocksize, 90 0 /* commit_settings */, /* optional */ 91 tav_init_output, /* optional */ 92 0 /* tav_init_input */, /* optional */ 93 tav_start_output, 94 tav_start_input, 95 tav_halt_output, 96 tav_halt_input, 97 tav_speaker_ctl, /* optional */ 98 tav_getdev, 99 0 /* setfd */, /* optional */ 100 tav_set_port, 101 tav_get_port, 102 tav_query_devinfo, 103 0 /* alloc */, /* optional */ 104 0 /* free */, /* optional */ 105 0 /* round_buffersize */, /* optional */ 106 0 /* mappage */, /* optional */ 107 tav_get_props, 108 0 /* dev_ioctl */ /* optional */ 109 }; 110 111 void 112 tms320av110_attach_mi(sc) 113 struct tav_softc *sc; 114 { 115 bus_space_tag_t iot = sc->sc_iot; 116 bus_space_handle_t ioh = sc->sc_ioh; 117 118 tav_write_byte(iot, ioh, TAV_RESET, 1); 119 while (tav_read_byte(iot, ioh, TAV_RESET)) 120 delay(250); 121 122 tav_write_byte(iot, ioh, TAV_PCM_ORD, sc->sc_pcm_ord); 123 tav_write_byte(iot, ioh, TAV_PCM_18, sc->sc_pcm_18); 124 tav_write_byte(iot, ioh, TAV_DIF, sc->sc_dif); 125 tav_write_byte(iot, ioh, TAV_PCM_DIV, sc->sc_pcm_div); 126 127 printf(": chip rev. %d, %d bytes buffer\n", 128 tav_read_byte(iot, ioh, TAV_VERSION), 129 TAV_DRAM_SIZE(tav_read_byte(iot, ioh, TAV_DRAM_EXT))); 130 131 tav_write_byte(iot, ioh, TAV_AUD_ID_EN, 0); 132 tav_write_byte(iot, ioh, TAV_SKIP, 0); 133 tav_write_byte(iot, ioh, TAV_REPEAT, 0); 134 tav_write_byte(iot, ioh, TAV_MUTE, 0); 135 tav_write_byte(iot, ioh, TAV_PLAY, 1); 136 tav_write_byte(iot, ioh, TAV_SYNC_ECM, 0); 137 tav_write_byte(iot, ioh, TAV_CRC_ECM, 0); 138 tav_write_byte(iot, ioh, TAV_ATTEN_L, 0); 139 tav_write_byte(iot, ioh, TAV_ATTEN_R, 0); 140 tav_write_short(iot, ioh, TAV_FREE_FORM, 0); 141 tav_write_byte(iot, ioh, TAV_SIN_EN, 0); 142 tav_write_byte(iot, ioh, TAV_SYNC_ECM, TAV_ECM_REPEAT); 143 tav_write_byte(iot, ioh, TAV_CRC_ECM, TAV_ECM_REPEAT); 144 145 audio_attach_mi(&tav_audio_if, sc, &sc->sc_dev); 146 } 147 148 int 149 tms320av110_intr(p) 150 void *p; 151 { 152 struct tav_softc *sc = p; 153 u_int16_t intlist; 154 155 intlist = tav_read_short(sc->sc_iot, sc->sc_ioh, TAV_INTR) 156 /* & tav_read_short(sc->sc_iot, sc->sc_ioh, TAV_INTR_EN)*/; 157 158 if (!intlist) 159 return 0; 160 161 /* ack now, so that we don't miss later interupts */ 162 if (sc->sc_intack) 163 (sc->sc_intack)(sc); 164 165 if (intlist & TAV_INTR_LOWWATER) { 166 (*sc->sc_intr)(sc->sc_intrarg); 167 } 168 169 if (intlist & TAV_INTR_PCM_OUTPUT_UNDERFLOW) { 170 wakeup(sc); 171 } 172 173 return 1; 174 } 175 176 struct audio_encoding tav_encodings[] = { 177 {0, AudioEmpeg_l2_stream, AUDIO_ENCODING_MPEG_L2_STREAM, 1, 0,}, 178 {1, AudioEmpeg_l2_packets, AUDIO_ENCODING_MPEG_L2_PACKETS, 1, 0,}, 179 {2, AudioEmpeg_l2_system, AUDIO_ENCODING_MPEG_L2_SYSTEM, 1, 0,}, 180 {3, AudioEslinear_be, AUDIO_ENCODING_SLINEAR_BE, 16, 0,}, 181 }; 182 183 int 184 tav_open(hdl, flags) 185 void *hdl; 186 int flags; 187 { 188 struct tav_softc *sc; 189 190 sc = hdl; 191 192 /* dummy */ 193 return 0; 194 } 195 196 void 197 tav_close(hdl) 198 void *hdl; 199 { 200 struct tav_softc *sc; 201 bus_space_tag_t iot; 202 bus_space_handle_t ioh; 203 204 sc = hdl; 205 iot = sc->sc_iot; 206 ioh = sc->sc_ioh; 207 208 /* re"start" chip, also clears interupts and interupt enable */ 209 tav_write_short(iot, ioh, TAV_INTR_EN, 0); 210 if (sc->sc_intack) 211 (*sc->sc_intack)(sc); 212 } 213 214 int 215 tav_drain(hdl) 216 void *hdl; 217 { 218 struct tav_softc *sc; 219 bus_space_tag_t iot; 220 bus_space_handle_t ioh; 221 u_int16_t mask; 222 223 sc = hdl; 224 iot = sc->sc_iot; 225 ioh = sc->sc_ioh; 226 227 /* 228 * tsleep waiting for underflow interupt. 229 */ 230 if (tav_read_short(iot, ioh, TAV_BUFF)) { 231 mask = tav_read_short(iot, ioh, TAV_INTR_EN); 232 tav_write_short(iot, ioh, TAV_INTR_EN, 233 mask|TAV_INTR_PCM_OUTPUT_UNDERFLOW); 234 235 /* still more than zero? */ 236 if (tav_read_short(iot, ioh, TAV_BUFF)) 237 (void)tsleep(sc, PCATCH, "tavdrain", 32*hz); 238 239 /* can be really that long for mpeg */ 240 241 mask = tav_read_short(iot, ioh, TAV_INTR_EN); 242 tav_write_short(iot, ioh, TAV_INTR_EN, 243 mask & ~TAV_INTR_PCM_OUTPUT_UNDERFLOW); 244 } 245 246 return 0; 247 } 248 249 int 250 tav_query_encoding(hdl, ae) 251 void *hdl; 252 struct audio_encoding *ae; 253 { 254 struct tav_softc *sc; 255 256 sc = hdl; 257 if (ae->index >= sizeof(tav_encodings)/sizeof(*ae)) 258 return EINVAL; 259 260 *ae = tav_encodings[ae->index]; 261 262 return 0; 263 } 264 265 int 266 tav_start_input(hdl, block, bsize, intr, intrarg) 267 void *hdl; 268 void *block; 269 int bsize; 270 void (*intr) __P((void *)); 271 void *intrarg; 272 { 273 return ENOTTY; 274 } 275 276 int 277 tav_halt_input(hdl) 278 void *hdl; 279 { 280 return ENOTTY; 281 } 282 283 int 284 tav_start_output(hdl, block, bsize, intr, intrarg) 285 void *hdl; 286 void *block; 287 int bsize; 288 void (*intr) __P((void *)); 289 void *intrarg; 290 { 291 struct tav_softc *sc; 292 bus_space_tag_t iot; 293 bus_space_handle_t ioh; 294 u_int8_t *ptr; 295 int count; 296 297 298 sc = hdl; 299 iot = sc->sc_iot; 300 ioh = sc->sc_ioh; 301 ptr = block; 302 count = bsize; 303 304 sc->sc_intr = intr; 305 sc->sc_intrarg = intrarg; 306 307 bus_space_write_multi_1(iot, ioh, TAV_DATAIN, ptr, count); 308 tav_write_short(iot, ioh, TAV_INTR_EN, TAV_INTR_LOWWATER); 309 310 return 0; 311 } 312 313 int 314 tav_init_output(hdl, buffer, size) 315 void *hdl; 316 void *buffer; 317 int size; 318 { 319 struct tav_softc *sc; 320 bus_space_tag_t iot; 321 bus_space_handle_t ioh; 322 323 sc = hdl; 324 iot = sc->sc_iot; 325 ioh = sc->sc_ioh; 326 327 tav_write_byte(iot, ioh, TAV_PLAY, 1); 328 tav_write_byte(iot, ioh, TAV_MUTE, 0); 329 330 return 0; 331 } 332 333 int 334 tav_halt_output(hdl) 335 void *hdl; 336 { 337 struct tav_softc *sc; 338 bus_space_tag_t iot; 339 bus_space_handle_t ioh; 340 341 sc = hdl; 342 iot = sc->sc_iot; 343 ioh = sc->sc_ioh; 344 345 tav_write_byte(iot, ioh, TAV_PLAY, 0); 346 347 return 0; 348 } 349 350 int 351 tav_getdev(hdl, ret) 352 void *hdl; 353 struct audio_device *ret; 354 { 355 struct tav_softc *sc; 356 bus_space_tag_t iot; 357 bus_space_handle_t ioh; 358 359 sc = hdl; 360 iot = sc->sc_iot; 361 ioh = sc->sc_ioh; 362 363 strncpy(ret->name, "tms320av110", MAX_AUDIO_DEV_LEN); 364 sprintf(ret->version, "%u", /* guaranteed to be <= 4 in length */ 365 tav_read_byte(iot, ioh, TAV_VERSION)); 366 strncpy(ret->config, sc->sc_dev.dv_xname, MAX_AUDIO_DEV_LEN); 367 368 return 0; 369 } 370 371 int 372 tav_round_blocksize(hdl, size) 373 void *hdl; 374 int size; 375 { 376 struct tav_softc *sc; 377 bus_space_tag_t iot; 378 bus_space_handle_t ioh; 379 int maxhalf; 380 381 sc = hdl; 382 iot = sc->sc_iot; 383 ioh = sc->sc_ioh; 384 385 maxhalf = TAV_DRAM_HSIZE(tav_read_byte(iot, ioh, TAV_DRAM_EXT)); 386 if (size > maxhalf) 387 size = maxhalf; 388 389 /* XXX should round to 128 bytes limits for audio bypass */ 390 size &= ~3; 391 392 tav_write_short(iot, ioh, TAV_BALE_LIM, size/8); 393 394 /* the buffer limits are in units of 4 bytes */ 395 return (size); 396 } 397 398 int 399 tav_get_props(hdl) 400 void *hdl; 401 { 402 return 0; 403 } 404 405 int 406 tav_set_params(hdl, setmode, usemode, p, r) 407 void *hdl; 408 int setmode, usemode; 409 struct audio_params *p, *r; 410 { 411 struct tav_softc *sc; 412 bus_space_tag_t iot; 413 bus_space_handle_t ioh; 414 415 sc = hdl; 416 iot = sc->sc_iot; 417 ioh = sc->sc_ioh; 418 419 if (!(setmode & AUMODE_PLAY)) 420 return 0; 421 422 if (p->encoding == AUDIO_ENCODING_ULAW) 423 p->encoding = AUDIO_ENCODING_MPEG_L2_STREAM; 424 425 switch(p->encoding) { 426 default: 427 return EINVAL; 428 429 case AUDIO_ENCODING_SLINEAR_BE: 430 431 /* XXX: todo: add 8bit and mono using software */ 432 p->precision = 16; 433 p->channels = 2; 434 435 /* XXX: this might depend on the specific board. 436 should be handled by the backend */ 437 438 p->sample_rate = 44100; 439 440 bus_space_write_1(iot, ioh, TAV_STR_SEL, 441 TAV_STR_SEL_AUDIO_BYPASS); 442 break; 443 444 /* XXX: later: add ULINEAR, and LE using software encoding */ 445 446 case AUDIO_ENCODING_MPEG_L1_STREAM: 447 /* FALLTHROUGH */ 448 case AUDIO_ENCODING_MPEG_L2_STREAM: 449 bus_space_write_1(iot, ioh, TAV_STR_SEL, 450 TAV_STR_SEL_MPEG_AUDIO_STREAM); 451 p->sample_rate = 44100; 452 p->precision = 1; 453 break; 454 455 case AUDIO_ENCODING_MPEG_L1_PACKETS: 456 /* FALLTHROUGH */ 457 case AUDIO_ENCODING_MPEG_L2_PACKETS: 458 bus_space_write_1(iot, ioh, TAV_STR_SEL, 459 TAV_STR_SEL_MPEG_AUDIO_PACKETS); 460 p->sample_rate = 44100; 461 p->precision = 1; 462 break; 463 464 case AUDIO_ENCODING_MPEG_L1_SYSTEM: 465 /* FALLTHROUGH */ 466 case AUDIO_ENCODING_MPEG_L2_SYSTEM: 467 bus_space_write_1(iot, ioh, TAV_STR_SEL, 468 TAV_STR_SEL_MPEG_SYSTEM_STREAM); 469 p->sample_rate = 44100; 470 p->precision = 1; 471 break; 472 } 473 tav_write_byte(iot, ioh, TAV_RESTART, 1); 474 do { 475 delay(10); 476 } while (tav_read_byte(iot, ioh, TAV_RESTART)); 477 478 return 0; 479 } 480 481 int 482 tav_set_port(hdl, mc) 483 void *hdl; 484 mixer_ctrl_t *mc; 485 { 486 struct tav_softc *sc; 487 488 sc = hdl; 489 /* dummy */ 490 return 0; 491 } 492 493 int 494 tav_get_port(hdl, mc) 495 void *hdl; 496 mixer_ctrl_t *mc; 497 { 498 struct tav_softc *sc; 499 500 sc = hdl; 501 /* dummy */ 502 return 0; 503 } 504 505 int 506 tav_query_devinfo(hdl, di) 507 void *hdl; 508 mixer_devinfo_t *di; 509 { 510 return ENXIO; 511 } 512 513 int 514 tav_speaker_ctl(hdl, value) 515 void *hdl; 516 int value; 517 { 518 struct tav_softc *sc; 519 bus_space_tag_t iot; 520 bus_space_handle_t ioh; 521 522 sc = hdl; 523 iot = sc->sc_iot; 524 ioh = sc->sc_ioh; 525 526 tav_write_byte(iot, ioh, TAV_MUTE, !value); 527 528 return 0; 529 } 530