1 /* $NetBSD: tms320av110.c,v 1.27 2019/06/08 08:02:38 isaki 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.27 2019/06/08 08:02:38 isaki 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/audio_if.h> 50 51 #include <dev/ic/tms320av110reg.h> 52 #include <dev/ic/tms320av110var.h> 53 54 #include <sys/bus.h> 55 56 void tav_close(void *); 57 int tav_query_format(void *, audio_format_query_t *); 58 int tav_set_format(void *, int, 59 const audio_params_t *, const audio_params_t *, 60 audio_filter_reg_t *, audio_filter_reg_t *); 61 int tav_round_blocksize(void *, int, int, const audio_params_t *); 62 int tav_start_output(void *, void *, int, void (*)(void *), void *); 63 int tav_start_input(void *, void *, int, void (*)(void *), void *); 64 int tav_halt_output(void *); 65 int tav_halt_input(void *); 66 int tav_speaker_ctl(void *, int); 67 int tav_getdev(void *, struct audio_device *); 68 int tav_set_port(void *, mixer_ctrl_t *); 69 int tav_get_port(void *, mixer_ctrl_t *); 70 int tav_query_devinfo(void *, mixer_devinfo_t *); 71 int tav_get_props(void *); 72 void tav_get_locks(void *, kmutex_t **, kmutex_t **); 73 74 const struct audio_hw_if tav_audio_if = { 75 .close = tav_close, 76 .query_format = tav_query_format, 77 .set_format = tav_set_format, 78 .round_blocksize = tav_round_blocksize, 79 .start_output = tav_start_output, 80 .start_input = tav_start_input, 81 .halt_output = tav_halt_output, 82 .halt_input = tav_halt_input, 83 .speaker_ctl = tav_speaker_ctl, /* optional */ 84 .getdev = tav_getdev, 85 .set_port = tav_set_port, 86 .get_port = tav_get_port, 87 .query_devinfo = tav_query_devinfo, 88 .get_props = tav_get_props, 89 .get_locks = tav_get_locks, 90 }; 91 92 /* 93 * XXX: The frequency might depend on the specific board. 94 * should be handled by the backend. 95 */ 96 #define TAV_FORMAT(prio, enc, prec) \ 97 { \ 98 .priority = (prio), \ 99 .mode = AUMODE_PLAY, \ 100 .encoding = (enc), \ 101 .validbits = (prec), \ 102 .precision = (prec), \ 103 .channels = 2, \ 104 .channel_mask = AUFMT_STEREO, \ 105 .frequency_type = 1, \ 106 .frequency = { 44100 }, \ 107 } 108 const struct audio_format tav_formats[] = { 109 TAV_FORMAT(-1, AUDIO_ENCODING_MPEG_L2_STREAM, 1), 110 TAV_FORMAT(-1, AUDIO_ENCODING_MPEG_L2_PACKETS, 1), 111 TAV_FORMAT(-1, AUDIO_ENCODING_MPEG_L2_SYSTEM, 1), 112 TAV_FORMAT( 0, AUDIO_ENCODING_SLINEAR_BE, 16), 113 }; 114 #define TAV_NFORMATS __arraycount(tav_formats) 115 116 void 117 tms320av110_attach_mi(struct tav_softc *sc) 118 { 119 bus_space_tag_t iot; 120 bus_space_handle_t ioh; 121 122 iot = sc->sc_iot; 123 ioh = sc->sc_ioh; 124 tav_write_byte(iot, ioh, TAV_RESET, 1); 125 while (tav_read_byte(iot, ioh, TAV_RESET)) 126 delay(250); 127 128 tav_write_byte(iot, ioh, TAV_PCM_ORD, sc->sc_pcm_ord); 129 tav_write_byte(iot, ioh, TAV_PCM_18, sc->sc_pcm_18); 130 tav_write_byte(iot, ioh, TAV_DIF, sc->sc_dif); 131 tav_write_byte(iot, ioh, TAV_PCM_DIV, sc->sc_pcm_div); 132 133 printf(": chip rev. %d, %d bytes buffer\n", 134 tav_read_byte(iot, ioh, TAV_VERSION), 135 TAV_DRAM_SIZE(tav_read_byte(iot, ioh, TAV_DRAM_EXT))); 136 137 tav_write_byte(iot, ioh, TAV_AUD_ID_EN, 0); 138 tav_write_byte(iot, ioh, TAV_SKIP, 0); 139 tav_write_byte(iot, ioh, TAV_REPEAT, 0); 140 tav_write_byte(iot, ioh, TAV_MUTE, 0); 141 tav_write_byte(iot, ioh, TAV_PLAY, 1); 142 tav_write_byte(iot, ioh, TAV_SYNC_ECM, 0); 143 tav_write_byte(iot, ioh, TAV_CRC_ECM, 0); 144 tav_write_byte(iot, ioh, TAV_ATTEN_L, 0); 145 tav_write_byte(iot, ioh, TAV_ATTEN_R, 0); 146 tav_write_short(iot, ioh, TAV_FREE_FORM, 0); 147 tav_write_byte(iot, ioh, TAV_SIN_EN, 0); 148 tav_write_byte(iot, ioh, TAV_SYNC_ECM, TAV_ECM_REPEAT); 149 tav_write_byte(iot, ioh, TAV_CRC_ECM, TAV_ECM_REPEAT); 150 151 sc->sc_active = 0; 152 153 audio_attach_mi(&tav_audio_if, sc, sc->sc_dev); 154 } 155 156 int 157 tms320av110_intr(void *p) 158 { 159 struct tav_softc *sc; 160 uint16_t intlist; 161 162 sc = p; 163 164 mutex_spin_enter(&sc->sc_intr_lock); 165 166 intlist = tav_read_short(sc->sc_iot, sc->sc_ioh, TAV_INTR) 167 /* & tav_read_short(sc->sc_iot, sc->sc_ioh, TAV_INTR_EN)*/; 168 169 if (!intlist) { 170 mutex_spin_exit(&sc->sc_intr_lock); 171 return 0; 172 } 173 174 /* ack now, so that we don't miss later interrupts */ 175 if (sc->sc_intack) 176 (sc->sc_intack)(sc); 177 178 if (intlist & TAV_INTR_LOWWATER) { 179 (*sc->sc_intr)(sc->sc_intrarg); 180 } 181 182 mutex_spin_exit(&sc->sc_intr_lock); 183 184 return 1; 185 } 186 187 void 188 tav_close(void *hdl) 189 { 190 struct tav_softc *sc; 191 bus_space_tag_t iot; 192 bus_space_handle_t ioh; 193 194 sc = hdl; 195 iot = sc->sc_iot; 196 ioh = sc->sc_ioh; 197 198 /* re"start" chip, also clears interrupts and interrupt enable */ 199 tav_write_short(iot, ioh, TAV_INTR_EN, 0); 200 if (sc->sc_intack) 201 (*sc->sc_intack)(sc); 202 } 203 204 int 205 tav_query_format(void *hdl, audio_format_query_t *afp) 206 { 207 208 return audio_query_format(tav_formats, TAV_NFORMATS, afp); 209 } 210 211 int 212 tav_start_input(void *hdl, void *block, int bsize, 213 void (*intr)(void *), void *intrarg) 214 { 215 216 return ENOTTY; 217 } 218 219 int 220 tav_halt_input(void *hdl) 221 { 222 223 return ENOTTY; 224 } 225 226 int 227 tav_start_output(void *hdl, void *block, int bsize, 228 void (*intr)(void *), void *intrarg) 229 { 230 struct tav_softc *sc; 231 bus_space_tag_t iot; 232 bus_space_handle_t ioh; 233 uint8_t *ptr; 234 int count; 235 236 sc = hdl; 237 iot = sc->sc_iot; 238 ioh = sc->sc_ioh; 239 ptr = block; 240 count = bsize; 241 242 sc->sc_intr = intr; 243 sc->sc_intrarg = intrarg; 244 245 if (sc->sc_active == 0) { 246 tav_write_byte(iot, ioh, TAV_PLAY, 1); 247 tav_write_byte(iot, ioh, TAV_MUTE, 0); 248 sc->sc_active = 1; 249 } 250 251 bus_space_write_multi_1(iot, ioh, TAV_DATAIN, ptr, count); 252 tav_write_short(iot, ioh, TAV_INTR_EN, TAV_INTR_LOWWATER); 253 254 return 0; 255 } 256 257 int 258 tav_halt_output(void *hdl) 259 { 260 struct tav_softc *sc; 261 bus_space_tag_t iot; 262 bus_space_handle_t ioh; 263 264 sc = hdl; 265 iot = sc->sc_iot; 266 ioh = sc->sc_ioh; 267 268 tav_write_byte(iot, ioh, TAV_PLAY, 0); 269 sc->sc_active = 0; 270 271 return 0; 272 } 273 274 int 275 tav_getdev(void *hdl, struct audio_device *ret) 276 { 277 struct tav_softc *sc; 278 bus_space_tag_t iot; 279 bus_space_handle_t ioh; 280 281 sc = hdl; 282 iot = sc->sc_iot; 283 ioh = sc->sc_ioh; 284 285 strlcpy(ret->name, "tms320av110", sizeof(ret->name)); 286 /* guaranteed to be <= 4 in length */ 287 snprintf(ret->version, sizeof(ret->version), "%u", 288 tav_read_byte(iot, ioh, TAV_VERSION)); 289 strlcpy(ret->config, device_xname(sc->sc_dev), sizeof(ret->config)); 290 291 return 0; 292 } 293 294 int 295 tav_round_blocksize(void *hdl, int size, int mode, const audio_params_t *param) 296 { 297 struct tav_softc *sc; 298 bus_space_tag_t iot; 299 bus_space_handle_t ioh; 300 int maxhalf; 301 302 sc = hdl; 303 iot = sc->sc_iot; 304 ioh = sc->sc_ioh; 305 306 maxhalf = TAV_DRAM_HSIZE(tav_read_byte(iot, ioh, TAV_DRAM_EXT)); 307 if (size > maxhalf) 308 size = maxhalf; 309 310 /* XXX should round to 128 bytes limits for audio bypass */ 311 size &= ~3; 312 313 tav_write_short(iot, ioh, TAV_BALE_LIM, size/8); 314 315 /* the buffer limits are in units of 4 bytes */ 316 return (size); 317 } 318 319 int 320 tav_get_props(void *hdl) 321 { 322 323 return AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE; 324 } 325 326 void 327 tav_get_locks(void *hdl, kmutex_t **intr, kmutex_t **thread) 328 { 329 struct tav_softc *sc; 330 331 sc = hdl; 332 *intr = &sc->sc_intr_lock; 333 *thread = &sc->sc_lock; 334 } 335 336 int 337 tav_set_format(void *hdl, int setmode, 338 const audio_params_t *p, const audio_params_t *r, 339 audio_filter_reg_t *pfil, audio_filter_reg_t *rfil) 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 KASSERT((setmode & AUMODE_PLAY)); 350 KASSERT(p->encoding == AUDIO_ENCODING_SLINEAR_BE); 351 352 bus_space_write_1(iot, ioh, TAV_STR_SEL, TAV_STR_SEL_AUDIO_BYPASS); 353 354 tav_write_byte(iot, ioh, TAV_RESTART, 1); 355 do { 356 delay(10); 357 } while (tav_read_byte(iot, ioh, TAV_RESTART)); 358 359 return 0; 360 } 361 362 int 363 tav_set_port(void *hdl, mixer_ctrl_t *mc) 364 { 365 366 /* dummy */ 367 return 0; 368 } 369 370 int 371 tav_get_port(void *hdl, mixer_ctrl_t *mc) 372 { 373 374 /* dummy */ 375 return 0; 376 } 377 378 int 379 tav_query_devinfo(void *hdl, mixer_devinfo_t *di) 380 { 381 return ENXIO; 382 } 383 384 int 385 tav_speaker_ctl(void *hdl, int value) 386 { 387 struct tav_softc *sc; 388 bus_space_tag_t iot; 389 bus_space_handle_t ioh; 390 391 sc = hdl; 392 iot = sc->sc_iot; 393 ioh = sc->sc_ioh; 394 395 tav_write_byte(iot, ioh, TAV_MUTE, !value); 396 397 return 0; 398 } 399