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