1/* $NetBSD$ */ 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 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32/* 33 * Machine independent part of TMS320AV110 driver. 34 * 35 * Currently, only minimum support for audio output. For audio/video 36 * synchronization, more is needed. 37 */ 38 39#include <sys/cdefs.h> 40__KERNEL_RCSID(0, "$NetBSD$"); 41 42#include <sys/param.h> 43#include <sys/systm.h> 44#include <sys/kernel.h> 45#include <sys/device.h> 46#include <sys/proc.h> 47 48#include <sys/audioio.h> 49#include <dev/audio_if.h> 50 51#include <dev/ic/tms320av110reg.h> 52#include <dev/ic/tms320av110var.h> 53 54#include <sys/bus.h> 55 56int tav_open(void *, int); 57void tav_close(void *); 58int tav_drain(void *); 59int tav_query_encoding(void *, struct audio_encoding *); 60int tav_set_params(void *, int, int, audio_params_t *, audio_params_t *, 61 stream_filter_list_t *, stream_filter_list_t *); 62int tav_round_blocksize(void *, int, int, const audio_params_t *); 63int tav_init_output(void *, void *, int); 64int tav_start_output(void *, void *, int, void (*)(void *), void *); 65int tav_start_input(void *, void *, int, void (*)(void *), void *); 66int tav_halt_output(void *); 67int tav_halt_input(void *); 68int tav_speaker_ctl(void *, int); 69int tav_getdev(void *, struct audio_device *); 70int tav_setfd(void *, int); 71int tav_set_port(void *, mixer_ctrl_t *); 72int tav_get_port(void *, mixer_ctrl_t *); 73int tav_query_devinfo(void *, mixer_devinfo_t *); 74int tav_get_props(void *); 75void tav_get_locks(void *, kmutex_t **, kmutex_t **); 76 77const struct audio_hw_if tav_audio_if = { 78 tav_open, 79 tav_close, 80 0 /* tav_drain*/, /* optional */ 81 tav_query_encoding, 82 tav_set_params, 83 tav_round_blocksize, 84 0 /* commit_settings */, /* optional */ 85 tav_init_output, /* optional */ 86 0 /* tav_init_input */, /* optional */ 87 tav_start_output, 88 tav_start_input, 89 tav_halt_output, 90 tav_halt_input, 91 tav_speaker_ctl, /* optional */ 92 tav_getdev, 93 0 /* setfd */, /* optional */ 94 tav_set_port, 95 tav_get_port, 96 tav_query_devinfo, 97 0 /* alloc */, /* optional */ 98 0 /* free */, /* optional */ 99 0 /* round_buffersize */, /* optional */ 100 0 /* mappage */, /* optional */ 101 tav_get_props, 102 0, /* trigger_output */ 103 0, /* trigger_input */ 104 0, /* dev_ioctl */ /* optional */ 105 tav_get_locks, 106}; 107 108void 109tms320av110_attach_mi(struct tav_softc *sc) 110{ 111 bus_space_tag_t iot; 112 bus_space_handle_t ioh; 113 114 iot = sc->sc_iot; 115 ioh = sc->sc_ioh; 116 tav_write_byte(iot, ioh, TAV_RESET, 1); 117 while (tav_read_byte(iot, ioh, TAV_RESET)) 118 delay(250); 119 120 tav_write_byte(iot, ioh, TAV_PCM_ORD, sc->sc_pcm_ord); 121 tav_write_byte(iot, ioh, TAV_PCM_18, sc->sc_pcm_18); 122 tav_write_byte(iot, ioh, TAV_DIF, sc->sc_dif); 123 tav_write_byte(iot, ioh, TAV_PCM_DIV, sc->sc_pcm_div); 124 125 printf(": chip rev. %d, %d bytes buffer\n", 126 tav_read_byte(iot, ioh, TAV_VERSION), 127 TAV_DRAM_SIZE(tav_read_byte(iot, ioh, TAV_DRAM_EXT))); 128 129 tav_write_byte(iot, ioh, TAV_AUD_ID_EN, 0); 130 tav_write_byte(iot, ioh, TAV_SKIP, 0); 131 tav_write_byte(iot, ioh, TAV_REPEAT, 0); 132 tav_write_byte(iot, ioh, TAV_MUTE, 0); 133 tav_write_byte(iot, ioh, TAV_PLAY, 1); 134 tav_write_byte(iot, ioh, TAV_SYNC_ECM, 0); 135 tav_write_byte(iot, ioh, TAV_CRC_ECM, 0); 136 tav_write_byte(iot, ioh, TAV_ATTEN_L, 0); 137 tav_write_byte(iot, ioh, TAV_ATTEN_R, 0); 138 tav_write_short(iot, ioh, TAV_FREE_FORM, 0); 139 tav_write_byte(iot, ioh, TAV_SIN_EN, 0); 140 tav_write_byte(iot, ioh, TAV_SYNC_ECM, TAV_ECM_REPEAT); 141 tav_write_byte(iot, ioh, TAV_CRC_ECM, TAV_ECM_REPEAT); 142 143 audio_attach_mi(&tav_audio_if, sc, &sc->sc_dev); 144} 145 146int 147tms320av110_intr(void *p) 148{ 149 struct tav_softc *sc; 150 uint16_t intlist; 151 152 sc = p; 153 154 mutex_spin_enter(&sc->sc_intr_lock); 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 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 cv_broadcast(&sc->sc_cv); 172 } 173 174 mutex_spin_exit(&sc->sc_intr_lock); 175 176 return 1; 177} 178 179struct audio_encoding tav_encodings[] = { 180 {0, AudioEmpeg_l2_stream, AUDIO_ENCODING_MPEG_L2_STREAM, 1, 0,}, 181 {1, AudioEmpeg_l2_packets, AUDIO_ENCODING_MPEG_L2_PACKETS, 1, 0,}, 182 {2, AudioEmpeg_l2_system, AUDIO_ENCODING_MPEG_L2_SYSTEM, 1, 0,}, 183 {3, AudioEslinear_be, AUDIO_ENCODING_SLINEAR_BE, 16, 0,}, 184}; 185 186int 187tav_open(void *hdl, int flags) 188{ 189 190 /* dummy */ 191 return 0; 192} 193 194void 195tav_close(void *hdl) 196{ 197 struct tav_softc *sc; 198 bus_space_tag_t iot; 199 bus_space_handle_t ioh; 200 201 sc = hdl; 202 iot = sc->sc_iot; 203 ioh = sc->sc_ioh; 204 205 /* re"start" chip, also clears interrupts and interrupt enable */ 206 tav_write_short(iot, ioh, TAV_INTR_EN, 0); 207 if (sc->sc_intack) 208 (*sc->sc_intack)(sc); 209} 210 211int 212tav_drain(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 mutex_spin_enter(&sc->sc_intr_lock); 224 225 /* 226 * wait for underflow interrupt. 227 */ 228 if (tav_read_short(iot, ioh, TAV_BUFF)) { 229 mask = tav_read_short(iot, ioh, TAV_INTR_EN); 230 tav_write_short(iot, ioh, TAV_INTR_EN, 231 mask|TAV_INTR_PCM_OUTPUT_UNDERFLOW); 232 233 /* still more than zero? */ 234 if (tav_read_short(iot, ioh, TAV_BUFF)) { 235 (void)cv_timedwait_sig(&sc->sc_cv, 236 &sc->sc_intr_lock, 32*hz); 237 } 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 mutex_spin_exit(&sc->sc_intr_lock); 247 248 return 0; 249} 250 251int 252tav_query_encoding(void *hdl, 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 265int 266tav_start_input(void *hdl, void *block, int bsize, 267 void (*intr)(void *), void *intrarg) 268{ 269 270 return ENOTTY; 271} 272 273int 274tav_halt_input(void *hdl) 275{ 276 277 return ENOTTY; 278} 279 280int 281tav_start_output(void *hdl, void *block, int bsize, 282 void (*intr)(void *), void *intrarg) 283{ 284 struct tav_softc *sc; 285 bus_space_tag_t iot; 286 bus_space_handle_t ioh; 287 uint8_t *ptr; 288 int count; 289 290 sc = hdl; 291 iot = sc->sc_iot; 292 ioh = sc->sc_ioh; 293 ptr = block; 294 count = bsize; 295 296 sc->sc_intr = intr; 297 sc->sc_intrarg = intrarg; 298 299 bus_space_write_multi_1(iot, ioh, TAV_DATAIN, ptr, count); 300 tav_write_short(iot, ioh, TAV_INTR_EN, TAV_INTR_LOWWATER); 301 302 return 0; 303} 304 305int 306tav_init_output(void *hdl, void *buffer, 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 322int 323tav_halt_output(void *hdl) 324{ 325 struct tav_softc *sc; 326 bus_space_tag_t iot; 327 bus_space_handle_t ioh; 328 329 sc = hdl; 330 iot = sc->sc_iot; 331 ioh = sc->sc_ioh; 332 333 tav_write_byte(iot, ioh, TAV_PLAY, 0); 334 335 return 0; 336} 337 338int 339tav_getdev(void *hdl, struct audio_device *ret) 340{ 341 struct tav_softc *sc; 342 bus_space_tag_t iot; 343 bus_space_handle_t ioh; 344 345 sc = hdl; 346 iot = sc->sc_iot; 347 ioh = sc->sc_ioh; 348 349 strlcpy(ret->name, "tms320av110", sizeof(ret->name)); 350 /* guaranteed to be <= 4 in length */ 351 snprintf(ret->version, sizeof(ret->version), "%u", 352 tav_read_byte(iot, ioh, TAV_VERSION)); 353 strlcpy(ret->config, device_xname(&sc->sc_dev), sizeof(ret->config)); 354 355 return 0; 356} 357 358int 359tav_round_blocksize(void *hdl, int size, int mode, const audio_params_t *param) 360{ 361 struct tav_softc *sc; 362 bus_space_tag_t iot; 363 bus_space_handle_t ioh; 364 int maxhalf; 365 366 sc = hdl; 367 iot = sc->sc_iot; 368 ioh = sc->sc_ioh; 369 370 maxhalf = TAV_DRAM_HSIZE(tav_read_byte(iot, ioh, TAV_DRAM_EXT)); 371 if (size > maxhalf) 372 size = maxhalf; 373 374 /* XXX should round to 128 bytes limits for audio bypass */ 375 size &= ~3; 376 377 tav_write_short(iot, ioh, TAV_BALE_LIM, size/8); 378 379 /* the buffer limits are in units of 4 bytes */ 380 return (size); 381} 382 383int 384tav_get_props(void *hdl) 385{ 386 return 0; 387} 388 389void 390tav_get_locks(void *hdl, kmutex_t **intr, kmutex_t **thread) 391{ 392 struct tav_softc *sc; 393 394 sc = hdl; 395 *intr = &sc->sc_intr_lock; 396 *thread = &sc->sc_lock; 397} 398 399int 400tav_set_params(void *hdl, int setmode, int usemode, audio_params_t *p, 401 audio_params_t *r, stream_filter_list_t *pfil, stream_filter_list_t *rfil) 402{ 403 struct tav_softc *sc; 404 bus_space_tag_t iot; 405 bus_space_handle_t ioh; 406 407 sc = hdl; 408 iot = sc->sc_iot; 409 ioh = sc->sc_ioh; 410 411 if (!(setmode & AUMODE_PLAY)) 412 return 0; 413 414 if (p->encoding == AUDIO_ENCODING_ULAW) 415 p->encoding = AUDIO_ENCODING_MPEG_L2_STREAM; 416 417 switch(p->encoding) { 418 default: 419 return EINVAL; 420 421 case AUDIO_ENCODING_SLINEAR_BE: 422 423 /* XXX: todo: add 8bit and mono using software */ 424 p->precision = 16; 425 p->channels = 2; 426 427 /* XXX: this might depend on the specific board. 428 should be handled by the backend */ 429 430 p->sample_rate = 44100; 431 432 bus_space_write_1(iot, ioh, TAV_STR_SEL, 433 TAV_STR_SEL_AUDIO_BYPASS); 434 break; 435 436 /* XXX: later: add ULINEAR, and LE using software encoding */ 437 438 case AUDIO_ENCODING_MPEG_L1_STREAM: 439 /* FALLTHROUGH */ 440 case AUDIO_ENCODING_MPEG_L2_STREAM: 441 bus_space_write_1(iot, ioh, TAV_STR_SEL, 442 TAV_STR_SEL_MPEG_AUDIO_STREAM); 443 p->sample_rate = 44100; 444 p->precision = 1; 445 break; 446 447 case AUDIO_ENCODING_MPEG_L1_PACKETS: 448 /* FALLTHROUGH */ 449 case AUDIO_ENCODING_MPEG_L2_PACKETS: 450 bus_space_write_1(iot, ioh, TAV_STR_SEL, 451 TAV_STR_SEL_MPEG_AUDIO_PACKETS); 452 p->sample_rate = 44100; 453 p->precision = 1; 454 break; 455 456 case AUDIO_ENCODING_MPEG_L1_SYSTEM: 457 /* FALLTHROUGH */ 458 case AUDIO_ENCODING_MPEG_L2_SYSTEM: 459 bus_space_write_1(iot, ioh, TAV_STR_SEL, 460 TAV_STR_SEL_MPEG_SYSTEM_STREAM); 461 p->sample_rate = 44100; 462 p->precision = 1; 463 break; 464 } 465 tav_write_byte(iot, ioh, TAV_RESTART, 1); 466 do { 467 delay(10); 468 } while (tav_read_byte(iot, ioh, TAV_RESTART)); 469 470 return 0; 471} 472 473int 474tav_set_port(void *hdl, mixer_ctrl_t *mc) 475{ 476 struct tav_softc *sc; 477 478 sc = hdl; 479 /* dummy */ 480 return 0; 481} 482 483int 484tav_get_port(void *hdl, mixer_ctrl_t *mc) 485{ 486 struct tav_softc *sc; 487 488 sc = hdl; 489 /* dummy */ 490 return 0; 491} 492 493int 494tav_query_devinfo(void *hdl, mixer_devinfo_t *di) 495{ 496 return ENXIO; 497} 498 499int 500tav_speaker_ctl(void *hdl, int value) 501{ 502 struct tav_softc *sc; 503 bus_space_tag_t iot; 504 bus_space_handle_t ioh; 505 506 sc = hdl; 507 iot = sc->sc_iot; 508 ioh = sc->sc_ioh; 509 510 tav_write_byte(iot, ioh, TAV_MUTE, !value); 511 512 return 0; 513} 514