1 /* $NetBSD: tms320av110.c,v 1.18 2005/12/11 12:21:28 christos 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.18 2005/12/11 12:21:28 christos 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(void *, int); 64 void tav_close(void *); 65 int tav_drain(void *); 66 int tav_query_encoding(void *, struct audio_encoding *); 67 int tav_set_params(void *, int, int, audio_params_t *, audio_params_t *, 68 stream_filter_list_t *, stream_filter_list_t *); 69 int tav_round_blocksize(void *, int, int, const audio_params_t *); 70 int tav_init_output(void *, void *, int); 71 int tav_start_output(void *, void *, int, void (*)(void *), void *); 72 int tav_start_input(void *, void *, int, void (*)(void *), void *); 73 int tav_halt_output(void *); 74 int tav_halt_input(void *); 75 int tav_speaker_ctl(void *, int); 76 int tav_getdev(void *, struct audio_device *); 77 int tav_setfd(void *, int); 78 int tav_set_port(void *, mixer_ctrl_t *); 79 int tav_get_port(void *, mixer_ctrl_t *); 80 int tav_query_devinfo(void *, mixer_devinfo_t *); 81 int tav_get_props(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(struct tav_softc *sc) 113 { 114 bus_space_tag_t iot; 115 bus_space_handle_t ioh; 116 117 iot = sc->sc_iot; 118 ioh = sc->sc_ioh; 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(void *p) 151 { 152 struct tav_softc *sc; 153 uint16_t intlist; 154 155 sc = p; 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 interrupts */ 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(void *hdl, int flags) 186 { 187 188 /* dummy */ 189 return 0; 190 } 191 192 void 193 tav_close(void *hdl) 194 { 195 struct tav_softc *sc; 196 bus_space_tag_t iot; 197 bus_space_handle_t ioh; 198 199 sc = hdl; 200 iot = sc->sc_iot; 201 ioh = sc->sc_ioh; 202 203 /* re"start" chip, also clears interrupts and interrupt enable */ 204 tav_write_short(iot, ioh, TAV_INTR_EN, 0); 205 if (sc->sc_intack) 206 (*sc->sc_intack)(sc); 207 } 208 209 int 210 tav_drain(void *hdl) 211 { 212 struct tav_softc *sc; 213 bus_space_tag_t iot; 214 bus_space_handle_t ioh; 215 u_int16_t mask; 216 217 sc = hdl; 218 iot = sc->sc_iot; 219 ioh = sc->sc_ioh; 220 221 /* 222 * tsleep waiting for underflow interrupt. 223 */ 224 if (tav_read_short(iot, ioh, TAV_BUFF)) { 225 mask = tav_read_short(iot, ioh, TAV_INTR_EN); 226 tav_write_short(iot, ioh, TAV_INTR_EN, 227 mask|TAV_INTR_PCM_OUTPUT_UNDERFLOW); 228 229 /* still more than zero? */ 230 if (tav_read_short(iot, ioh, TAV_BUFF)) 231 (void)tsleep(sc, PCATCH, "tavdrain", 32*hz); 232 233 /* can be really that long for mpeg */ 234 235 mask = tav_read_short(iot, ioh, TAV_INTR_EN); 236 tav_write_short(iot, ioh, TAV_INTR_EN, 237 mask & ~TAV_INTR_PCM_OUTPUT_UNDERFLOW); 238 } 239 240 return 0; 241 } 242 243 int 244 tav_query_encoding(void *hdl, struct audio_encoding *ae) 245 { 246 struct tav_softc *sc; 247 248 sc = hdl; 249 if (ae->index >= sizeof(tav_encodings)/sizeof(*ae)) 250 return EINVAL; 251 252 *ae = tav_encodings[ae->index]; 253 254 return 0; 255 } 256 257 int 258 tav_start_input(void *hdl, void *block, int bsize, 259 void (*intr)(void *), void *intrarg) 260 { 261 262 return ENOTTY; 263 } 264 265 int 266 tav_halt_input(void *hdl) 267 { 268 269 return ENOTTY; 270 } 271 272 int 273 tav_start_output(void *hdl, void *block, int bsize, 274 void (*intr)(void *), void *intrarg) 275 { 276 struct tav_softc *sc; 277 bus_space_tag_t iot; 278 bus_space_handle_t ioh; 279 uint8_t *ptr; 280 int count; 281 282 sc = hdl; 283 iot = sc->sc_iot; 284 ioh = sc->sc_ioh; 285 ptr = block; 286 count = bsize; 287 288 sc->sc_intr = intr; 289 sc->sc_intrarg = intrarg; 290 291 bus_space_write_multi_1(iot, ioh, TAV_DATAIN, ptr, count); 292 tav_write_short(iot, ioh, TAV_INTR_EN, TAV_INTR_LOWWATER); 293 294 return 0; 295 } 296 297 int 298 tav_init_output(void *hdl, void *buffer, int size) 299 { 300 struct tav_softc *sc; 301 bus_space_tag_t iot; 302 bus_space_handle_t ioh; 303 304 sc = hdl; 305 iot = sc->sc_iot; 306 ioh = sc->sc_ioh; 307 308 tav_write_byte(iot, ioh, TAV_PLAY, 1); 309 tav_write_byte(iot, ioh, TAV_MUTE, 0); 310 311 return 0; 312 } 313 314 int 315 tav_halt_output(void *hdl) 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, 0); 326 327 return 0; 328 } 329 330 int 331 tav_getdev(void *hdl, struct audio_device *ret) 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 strlcpy(ret->name, "tms320av110", sizeof(ret->name)); 342 /* guaranteed to be <= 4 in length */ 343 snprintf(ret->version, sizeof(ret->version), "%u", 344 tav_read_byte(iot, ioh, TAV_VERSION)); 345 strlcpy(ret->config, sc->sc_dev.dv_xname, sizeof(ret->config)); 346 347 return 0; 348 } 349 350 int 351 tav_round_blocksize(void *hdl, int size, int mode, const audio_params_t *param) 352 { 353 struct tav_softc *sc; 354 bus_space_tag_t iot; 355 bus_space_handle_t ioh; 356 int maxhalf; 357 358 sc = hdl; 359 iot = sc->sc_iot; 360 ioh = sc->sc_ioh; 361 362 maxhalf = TAV_DRAM_HSIZE(tav_read_byte(iot, ioh, TAV_DRAM_EXT)); 363 if (size > maxhalf) 364 size = maxhalf; 365 366 /* XXX should round to 128 bytes limits for audio bypass */ 367 size &= ~3; 368 369 tav_write_short(iot, ioh, TAV_BALE_LIM, size/8); 370 371 /* the buffer limits are in units of 4 bytes */ 372 return (size); 373 } 374 375 int 376 tav_get_props(void *hdl) 377 { 378 return 0; 379 } 380 381 int 382 tav_set_params(void *hdl, int setmode, int usemode, audio_params_t *p, 383 audio_params_t *r, stream_filter_list_t *pfil, stream_filter_list_t *rfil) 384 { 385 struct tav_softc *sc; 386 bus_space_tag_t iot; 387 bus_space_handle_t ioh; 388 389 sc = hdl; 390 iot = sc->sc_iot; 391 ioh = sc->sc_ioh; 392 393 if (!(setmode & AUMODE_PLAY)) 394 return 0; 395 396 if (p->encoding == AUDIO_ENCODING_ULAW) 397 p->encoding = AUDIO_ENCODING_MPEG_L2_STREAM; 398 399 switch(p->encoding) { 400 default: 401 return EINVAL; 402 403 case AUDIO_ENCODING_SLINEAR_BE: 404 405 /* XXX: todo: add 8bit and mono using software */ 406 p->precision = 16; 407 p->channels = 2; 408 409 /* XXX: this might depend on the specific board. 410 should be handled by the backend */ 411 412 p->sample_rate = 44100; 413 414 bus_space_write_1(iot, ioh, TAV_STR_SEL, 415 TAV_STR_SEL_AUDIO_BYPASS); 416 break; 417 418 /* XXX: later: add ULINEAR, and LE using software encoding */ 419 420 case AUDIO_ENCODING_MPEG_L1_STREAM: 421 /* FALLTHROUGH */ 422 case AUDIO_ENCODING_MPEG_L2_STREAM: 423 bus_space_write_1(iot, ioh, TAV_STR_SEL, 424 TAV_STR_SEL_MPEG_AUDIO_STREAM); 425 p->sample_rate = 44100; 426 p->precision = 1; 427 break; 428 429 case AUDIO_ENCODING_MPEG_L1_PACKETS: 430 /* FALLTHROUGH */ 431 case AUDIO_ENCODING_MPEG_L2_PACKETS: 432 bus_space_write_1(iot, ioh, TAV_STR_SEL, 433 TAV_STR_SEL_MPEG_AUDIO_PACKETS); 434 p->sample_rate = 44100; 435 p->precision = 1; 436 break; 437 438 case AUDIO_ENCODING_MPEG_L1_SYSTEM: 439 /* FALLTHROUGH */ 440 case AUDIO_ENCODING_MPEG_L2_SYSTEM: 441 bus_space_write_1(iot, ioh, TAV_STR_SEL, 442 TAV_STR_SEL_MPEG_SYSTEM_STREAM); 443 p->sample_rate = 44100; 444 p->precision = 1; 445 break; 446 } 447 tav_write_byte(iot, ioh, TAV_RESTART, 1); 448 do { 449 delay(10); 450 } while (tav_read_byte(iot, ioh, TAV_RESTART)); 451 452 return 0; 453 } 454 455 int 456 tav_set_port(void *hdl, mixer_ctrl_t *mc) 457 { 458 struct tav_softc *sc; 459 460 sc = hdl; 461 /* dummy */ 462 return 0; 463 } 464 465 int 466 tav_get_port(void *hdl, mixer_ctrl_t *mc) 467 { 468 struct tav_softc *sc; 469 470 sc = hdl; 471 /* dummy */ 472 return 0; 473 } 474 475 int 476 tav_query_devinfo(void *hdl, mixer_devinfo_t *di) 477 { 478 return ENXIO; 479 } 480 481 int 482 tav_speaker_ctl(void *hdl, int value) 483 { 484 struct tav_softc *sc; 485 bus_space_tag_t iot; 486 bus_space_handle_t ioh; 487 488 sc = hdl; 489 iot = sc->sc_iot; 490 ioh = sc->sc_ioh; 491 492 tav_write_byte(iot, ioh, TAV_MUTE, !value); 493 494 return 0; 495 } 496