1 /* $NetBSD: tms320av110.c,v 1.15 2004/10/29 12:57:17 yamt 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.15 2004/10/29 12:57:17 yamt 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 const 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 interrupts */ 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 /* dummy */ 189 return 0; 190 } 191 192 void 193 tav_close(hdl) 194 void *hdl; 195 { 196 struct tav_softc *sc; 197 bus_space_tag_t iot; 198 bus_space_handle_t ioh; 199 200 sc = hdl; 201 iot = sc->sc_iot; 202 ioh = sc->sc_ioh; 203 204 /* re"start" chip, also clears interrupts and interrupt enable */ 205 tav_write_short(iot, ioh, TAV_INTR_EN, 0); 206 if (sc->sc_intack) 207 (*sc->sc_intack)(sc); 208 } 209 210 int 211 tav_drain(hdl) 212 void *hdl; 213 { 214 struct tav_softc *sc; 215 bus_space_tag_t iot; 216 bus_space_handle_t ioh; 217 u_int16_t mask; 218 219 sc = hdl; 220 iot = sc->sc_iot; 221 ioh = sc->sc_ioh; 222 223 /* 224 * tsleep waiting for underflow interrupt. 225 */ 226 if (tav_read_short(iot, ioh, TAV_BUFF)) { 227 mask = tav_read_short(iot, ioh, TAV_INTR_EN); 228 tav_write_short(iot, ioh, TAV_INTR_EN, 229 mask|TAV_INTR_PCM_OUTPUT_UNDERFLOW); 230 231 /* still more than zero? */ 232 if (tav_read_short(iot, ioh, TAV_BUFF)) 233 (void)tsleep(sc, PCATCH, "tavdrain", 32*hz); 234 235 /* can be really that long for mpeg */ 236 237 mask = tav_read_short(iot, ioh, TAV_INTR_EN); 238 tav_write_short(iot, ioh, TAV_INTR_EN, 239 mask & ~TAV_INTR_PCM_OUTPUT_UNDERFLOW); 240 } 241 242 return 0; 243 } 244 245 int 246 tav_query_encoding(hdl, ae) 247 void *hdl; 248 struct audio_encoding *ae; 249 { 250 struct tav_softc *sc; 251 252 sc = hdl; 253 if (ae->index >= sizeof(tav_encodings)/sizeof(*ae)) 254 return EINVAL; 255 256 *ae = tav_encodings[ae->index]; 257 258 return 0; 259 } 260 261 int 262 tav_start_input(hdl, block, bsize, intr, intrarg) 263 void *hdl; 264 void *block; 265 int bsize; 266 void (*intr) __P((void *)); 267 void *intrarg; 268 { 269 return ENOTTY; 270 } 271 272 int 273 tav_halt_input(hdl) 274 void *hdl; 275 { 276 return ENOTTY; 277 } 278 279 int 280 tav_start_output(hdl, block, bsize, intr, intrarg) 281 void *hdl; 282 void *block; 283 int bsize; 284 void (*intr) __P((void *)); 285 void *intrarg; 286 { 287 struct tav_softc *sc; 288 bus_space_tag_t iot; 289 bus_space_handle_t ioh; 290 u_int8_t *ptr; 291 int count; 292 293 294 sc = hdl; 295 iot = sc->sc_iot; 296 ioh = sc->sc_ioh; 297 ptr = block; 298 count = bsize; 299 300 sc->sc_intr = intr; 301 sc->sc_intrarg = intrarg; 302 303 bus_space_write_multi_1(iot, ioh, TAV_DATAIN, ptr, count); 304 tav_write_short(iot, ioh, TAV_INTR_EN, TAV_INTR_LOWWATER); 305 306 return 0; 307 } 308 309 int 310 tav_init_output(hdl, buffer, size) 311 void *hdl; 312 void *buffer; 313 int size; 314 { 315 struct tav_softc *sc; 316 bus_space_tag_t iot; 317 bus_space_handle_t ioh; 318 319 sc = hdl; 320 iot = sc->sc_iot; 321 ioh = sc->sc_ioh; 322 323 tav_write_byte(iot, ioh, TAV_PLAY, 1); 324 tav_write_byte(iot, ioh, TAV_MUTE, 0); 325 326 return 0; 327 } 328 329 int 330 tav_halt_output(hdl) 331 void *hdl; 332 { 333 struct tav_softc *sc; 334 bus_space_tag_t iot; 335 bus_space_handle_t ioh; 336 337 sc = hdl; 338 iot = sc->sc_iot; 339 ioh = sc->sc_ioh; 340 341 tav_write_byte(iot, ioh, TAV_PLAY, 0); 342 343 return 0; 344 } 345 346 int 347 tav_getdev(hdl, ret) 348 void *hdl; 349 struct audio_device *ret; 350 { 351 struct tav_softc *sc; 352 bus_space_tag_t iot; 353 bus_space_handle_t ioh; 354 355 sc = hdl; 356 iot = sc->sc_iot; 357 ioh = sc->sc_ioh; 358 359 strlcpy(ret->name, "tms320av110", sizeof(ret->name)); 360 /* guaranteed to be <= 4 in length */ 361 snprintf(ret->version, sizeof(ret->version), "%u", 362 tav_read_byte(iot, ioh, TAV_VERSION)); 363 strlcpy(ret->config, sc->sc_dev.dv_xname, sizeof(ret->config)); 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