1 1.27 isaki /* $NetBSD: tms320av110.c,v 1.27 2019/06/08 08:02:38 isaki Exp $ */ 2 1.1 is 3 1.1 is /*- 4 1.8 is * Copyright (c) 1997 The NetBSD Foundation, Inc. 5 1.7 is * All rights reserved. 6 1.7 is * 7 1.7 is * This code is derived from software contributed to The NetBSD Foundation 8 1.7 is * by Ignatios Souvatzis. 9 1.1 is * 10 1.1 is * Redistribution and use in source and binary forms, with or without 11 1.1 is * modification, are permitted provided that the following conditions 12 1.1 is * are met: 13 1.1 is * 1. Redistributions of source code must retain the above copyright 14 1.1 is * notice, this list of conditions and the following disclaimer. 15 1.1 is * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 is * notice, this list of conditions and the following disclaimer in the 17 1.1 is * documentation and/or other materials provided with the distribution. 18 1.1 is * 19 1.7 is * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.7 is * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.7 is * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.7 is * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.7 is * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.7 is * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.7 is * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.7 is * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.7 is * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.7 is * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.7 is * POSSIBILITY OF SUCH DAMAGE. 30 1.1 is */ 31 1.1 is 32 1.1 is /* 33 1.1 is * Machine independent part of TMS320AV110 driver. 34 1.1 is * 35 1.1 is * Currently, only minimum support for audio output. For audio/video 36 1.1 is * synchronization, more is needed. 37 1.1 is */ 38 1.10 lukem 39 1.10 lukem #include <sys/cdefs.h> 40 1.27 isaki __KERNEL_RCSID(0, "$NetBSD: tms320av110.c,v 1.27 2019/06/08 08:02:38 isaki Exp $"); 41 1.1 is 42 1.1 is #include <sys/param.h> 43 1.1 is #include <sys/systm.h> 44 1.1 is #include <sys/kernel.h> 45 1.1 is #include <sys/device.h> 46 1.1 is #include <sys/proc.h> 47 1.1 is 48 1.1 is #include <sys/audioio.h> 49 1.26 isaki #include <dev/audio/audio_if.h> 50 1.1 is 51 1.1 is #include <dev/ic/tms320av110reg.h> 52 1.1 is #include <dev/ic/tms320av110var.h> 53 1.1 is 54 1.19 ad #include <sys/bus.h> 55 1.1 is 56 1.17 kent void tav_close(void *); 57 1.26 isaki int tav_query_format(void *, audio_format_query_t *); 58 1.26 isaki int tav_set_format(void *, int, 59 1.26 isaki const audio_params_t *, const audio_params_t *, 60 1.26 isaki audio_filter_reg_t *, audio_filter_reg_t *); 61 1.17 kent int tav_round_blocksize(void *, int, int, const audio_params_t *); 62 1.17 kent int tav_start_output(void *, void *, int, void (*)(void *), void *); 63 1.17 kent int tav_start_input(void *, void *, int, void (*)(void *), void *); 64 1.17 kent int tav_halt_output(void *); 65 1.17 kent int tav_halt_input(void *); 66 1.17 kent int tav_speaker_ctl(void *, int); 67 1.17 kent int tav_getdev(void *, struct audio_device *); 68 1.17 kent int tav_set_port(void *, mixer_ctrl_t *); 69 1.17 kent int tav_get_port(void *, mixer_ctrl_t *); 70 1.17 kent int tav_query_devinfo(void *, mixer_devinfo_t *); 71 1.17 kent int tav_get_props(void *); 72 1.22 jmcneill void tav_get_locks(void *, kmutex_t **, kmutex_t **); 73 1.1 is 74 1.15 yamt const struct audio_hw_if tav_audio_if = { 75 1.25 isaki .close = tav_close, 76 1.26 isaki .query_format = tav_query_format, 77 1.26 isaki .set_format = tav_set_format, 78 1.25 isaki .round_blocksize = tav_round_blocksize, 79 1.25 isaki .start_output = tav_start_output, 80 1.25 isaki .start_input = tav_start_input, 81 1.25 isaki .halt_output = tav_halt_output, 82 1.25 isaki .halt_input = tav_halt_input, 83 1.25 isaki .speaker_ctl = tav_speaker_ctl, /* optional */ 84 1.25 isaki .getdev = tav_getdev, 85 1.25 isaki .set_port = tav_set_port, 86 1.25 isaki .get_port = tav_get_port, 87 1.25 isaki .query_devinfo = tav_query_devinfo, 88 1.25 isaki .get_props = tav_get_props, 89 1.25 isaki .get_locks = tav_get_locks, 90 1.1 is }; 91 1.1 is 92 1.26 isaki /* 93 1.26 isaki * XXX: The frequency might depend on the specific board. 94 1.26 isaki * should be handled by the backend. 95 1.26 isaki */ 96 1.26 isaki #define TAV_FORMAT(prio, enc, prec) \ 97 1.26 isaki { \ 98 1.26 isaki .priority = (prio), \ 99 1.26 isaki .mode = AUMODE_PLAY, \ 100 1.26 isaki .encoding = (enc), \ 101 1.26 isaki .validbits = (prec), \ 102 1.26 isaki .precision = (prec), \ 103 1.26 isaki .channels = 2, \ 104 1.26 isaki .channel_mask = AUFMT_STEREO, \ 105 1.26 isaki .frequency_type = 1, \ 106 1.26 isaki .frequency = { 44100 }, \ 107 1.26 isaki } 108 1.26 isaki const struct audio_format tav_formats[] = { 109 1.26 isaki TAV_FORMAT(-1, AUDIO_ENCODING_MPEG_L2_STREAM, 1), 110 1.26 isaki TAV_FORMAT(-1, AUDIO_ENCODING_MPEG_L2_PACKETS, 1), 111 1.26 isaki TAV_FORMAT(-1, AUDIO_ENCODING_MPEG_L2_SYSTEM, 1), 112 1.26 isaki TAV_FORMAT( 0, AUDIO_ENCODING_SLINEAR_BE, 16), 113 1.26 isaki }; 114 1.26 isaki #define TAV_NFORMATS __arraycount(tav_formats) 115 1.26 isaki 116 1.1 is void 117 1.17 kent tms320av110_attach_mi(struct tav_softc *sc) 118 1.1 is { 119 1.17 kent bus_space_tag_t iot; 120 1.17 kent bus_space_handle_t ioh; 121 1.1 is 122 1.17 kent iot = sc->sc_iot; 123 1.17 kent ioh = sc->sc_ioh; 124 1.1 is tav_write_byte(iot, ioh, TAV_RESET, 1); 125 1.1 is while (tav_read_byte(iot, ioh, TAV_RESET)) 126 1.1 is delay(250); 127 1.1 is 128 1.1 is tav_write_byte(iot, ioh, TAV_PCM_ORD, sc->sc_pcm_ord); 129 1.1 is tav_write_byte(iot, ioh, TAV_PCM_18, sc->sc_pcm_18); 130 1.1 is tav_write_byte(iot, ioh, TAV_DIF, sc->sc_dif); 131 1.1 is tav_write_byte(iot, ioh, TAV_PCM_DIV, sc->sc_pcm_div); 132 1.1 is 133 1.1 is printf(": chip rev. %d, %d bytes buffer\n", 134 1.1 is tav_read_byte(iot, ioh, TAV_VERSION), 135 1.1 is TAV_DRAM_SIZE(tav_read_byte(iot, ioh, TAV_DRAM_EXT))); 136 1.1 is 137 1.1 is tav_write_byte(iot, ioh, TAV_AUD_ID_EN, 0); 138 1.1 is tav_write_byte(iot, ioh, TAV_SKIP, 0); 139 1.1 is tav_write_byte(iot, ioh, TAV_REPEAT, 0); 140 1.1 is tav_write_byte(iot, ioh, TAV_MUTE, 0); 141 1.1 is tav_write_byte(iot, ioh, TAV_PLAY, 1); 142 1.1 is tav_write_byte(iot, ioh, TAV_SYNC_ECM, 0); 143 1.1 is tav_write_byte(iot, ioh, TAV_CRC_ECM, 0); 144 1.1 is tav_write_byte(iot, ioh, TAV_ATTEN_L, 0); 145 1.1 is tav_write_byte(iot, ioh, TAV_ATTEN_R, 0); 146 1.3 is tav_write_short(iot, ioh, TAV_FREE_FORM, 0); 147 1.1 is tav_write_byte(iot, ioh, TAV_SIN_EN, 0); 148 1.1 is tav_write_byte(iot, ioh, TAV_SYNC_ECM, TAV_ECM_REPEAT); 149 1.1 is tav_write_byte(iot, ioh, TAV_CRC_ECM, TAV_ECM_REPEAT); 150 1.1 is 151 1.26 isaki sc->sc_active = 0; 152 1.26 isaki 153 1.23 chs audio_attach_mi(&tav_audio_if, sc, sc->sc_dev); 154 1.1 is } 155 1.1 is 156 1.1 is int 157 1.17 kent tms320av110_intr(void *p) 158 1.1 is { 159 1.17 kent struct tav_softc *sc; 160 1.17 kent uint16_t intlist; 161 1.1 is 162 1.17 kent sc = p; 163 1.22 jmcneill 164 1.22 jmcneill mutex_spin_enter(&sc->sc_intr_lock); 165 1.22 jmcneill 166 1.1 is intlist = tav_read_short(sc->sc_iot, sc->sc_ioh, TAV_INTR) 167 1.1 is /* & tav_read_short(sc->sc_iot, sc->sc_ioh, TAV_INTR_EN)*/; 168 1.1 is 169 1.26 isaki if (!intlist) { 170 1.26 isaki mutex_spin_exit(&sc->sc_intr_lock); 171 1.1 is return 0; 172 1.26 isaki } 173 1.1 is 174 1.12 wiz /* ack now, so that we don't miss later interrupts */ 175 1.1 is if (sc->sc_intack) 176 1.1 is (sc->sc_intack)(sc); 177 1.1 is 178 1.1 is if (intlist & TAV_INTR_LOWWATER) { 179 1.1 is (*sc->sc_intr)(sc->sc_intrarg); 180 1.1 is } 181 1.1 is 182 1.22 jmcneill mutex_spin_exit(&sc->sc_intr_lock); 183 1.22 jmcneill 184 1.1 is return 1; 185 1.1 is } 186 1.1 is 187 1.1 is void 188 1.17 kent tav_close(void *hdl) 189 1.1 is { 190 1.17 kent struct tav_softc *sc; 191 1.1 is bus_space_tag_t iot; 192 1.1 is bus_space_handle_t ioh; 193 1.1 is 194 1.1 is sc = hdl; 195 1.1 is iot = sc->sc_iot; 196 1.1 is ioh = sc->sc_ioh; 197 1.1 is 198 1.12 wiz /* re"start" chip, also clears interrupts and interrupt enable */ 199 1.1 is tav_write_short(iot, ioh, TAV_INTR_EN, 0); 200 1.1 is if (sc->sc_intack) 201 1.1 is (*sc->sc_intack)(sc); 202 1.1 is } 203 1.1 is 204 1.1 is int 205 1.26 isaki tav_query_format(void *hdl, audio_format_query_t *afp) 206 1.1 is { 207 1.1 is 208 1.26 isaki return audio_query_format(tav_formats, TAV_NFORMATS, afp); 209 1.1 is } 210 1.1 is 211 1.1 is int 212 1.17 kent tav_start_input(void *hdl, void *block, int bsize, 213 1.17 kent void (*intr)(void *), void *intrarg) 214 1.1 is { 215 1.17 kent 216 1.1 is return ENOTTY; 217 1.1 is } 218 1.1 is 219 1.1 is int 220 1.17 kent tav_halt_input(void *hdl) 221 1.1 is { 222 1.17 kent 223 1.1 is return ENOTTY; 224 1.1 is } 225 1.1 is 226 1.1 is int 227 1.17 kent tav_start_output(void *hdl, void *block, int bsize, 228 1.17 kent void (*intr)(void *), void *intrarg) 229 1.1 is { 230 1.17 kent struct tav_softc *sc; 231 1.1 is bus_space_tag_t iot; 232 1.1 is bus_space_handle_t ioh; 233 1.17 kent uint8_t *ptr; 234 1.1 is int count; 235 1.1 is 236 1.17 kent sc = hdl; 237 1.1 is iot = sc->sc_iot; 238 1.1 is ioh = sc->sc_ioh; 239 1.1 is ptr = block; 240 1.1 is count = bsize; 241 1.17 kent 242 1.1 is sc->sc_intr = intr; 243 1.1 is sc->sc_intrarg = intrarg; 244 1.1 is 245 1.26 isaki if (sc->sc_active == 0) { 246 1.26 isaki tav_write_byte(iot, ioh, TAV_PLAY, 1); 247 1.26 isaki tav_write_byte(iot, ioh, TAV_MUTE, 0); 248 1.26 isaki sc->sc_active = 1; 249 1.26 isaki } 250 1.26 isaki 251 1.5 is bus_space_write_multi_1(iot, ioh, TAV_DATAIN, ptr, count); 252 1.1 is tav_write_short(iot, ioh, TAV_INTR_EN, TAV_INTR_LOWWATER); 253 1.1 is 254 1.1 is return 0; 255 1.1 is } 256 1.1 is 257 1.1 is int 258 1.17 kent tav_halt_output(void *hdl) 259 1.1 is { 260 1.17 kent struct tav_softc *sc; 261 1.1 is bus_space_tag_t iot; 262 1.1 is bus_space_handle_t ioh; 263 1.1 is 264 1.17 kent sc = hdl; 265 1.1 is iot = sc->sc_iot; 266 1.1 is ioh = sc->sc_ioh; 267 1.1 is 268 1.1 is tav_write_byte(iot, ioh, TAV_PLAY, 0); 269 1.26 isaki sc->sc_active = 0; 270 1.1 is 271 1.1 is return 0; 272 1.1 is } 273 1.1 is 274 1.1 is int 275 1.17 kent tav_getdev(void *hdl, struct audio_device *ret) 276 1.1 is { 277 1.17 kent struct tav_softc *sc; 278 1.1 is bus_space_tag_t iot; 279 1.1 is bus_space_handle_t ioh; 280 1.1 is 281 1.17 kent sc = hdl; 282 1.1 is iot = sc->sc_iot; 283 1.1 is ioh = sc->sc_ioh; 284 1.1 is 285 1.13 itojun strlcpy(ret->name, "tms320av110", sizeof(ret->name)); 286 1.13 itojun /* guaranteed to be <= 4 in length */ 287 1.13 itojun snprintf(ret->version, sizeof(ret->version), "%u", 288 1.1 is tav_read_byte(iot, ioh, TAV_VERSION)); 289 1.23 chs strlcpy(ret->config, device_xname(sc->sc_dev), sizeof(ret->config)); 290 1.1 is 291 1.1 is return 0; 292 1.1 is } 293 1.1 is 294 1.1 is int 295 1.17 kent tav_round_blocksize(void *hdl, int size, int mode, const audio_params_t *param) 296 1.1 is { 297 1.17 kent struct tav_softc *sc; 298 1.1 is bus_space_tag_t iot; 299 1.1 is bus_space_handle_t ioh; 300 1.1 is int maxhalf; 301 1.1 is 302 1.17 kent sc = hdl; 303 1.1 is iot = sc->sc_iot; 304 1.1 is ioh = sc->sc_ioh; 305 1.1 is 306 1.1 is maxhalf = TAV_DRAM_HSIZE(tav_read_byte(iot, ioh, TAV_DRAM_EXT)); 307 1.1 is if (size > maxhalf) 308 1.1 is size = maxhalf; 309 1.1 is 310 1.1 is /* XXX should round to 128 bytes limits for audio bypass */ 311 1.1 is size &= ~3; 312 1.1 is 313 1.1 is tav_write_short(iot, ioh, TAV_BALE_LIM, size/8); 314 1.1 is 315 1.1 is /* the buffer limits are in units of 4 bytes */ 316 1.1 is return (size); 317 1.1 is } 318 1.1 is 319 1.1 is int 320 1.17 kent tav_get_props(void *hdl) 321 1.1 is { 322 1.27 isaki 323 1.27 isaki return AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE; 324 1.1 is } 325 1.1 is 326 1.22 jmcneill void 327 1.22 jmcneill tav_get_locks(void *hdl, kmutex_t **intr, kmutex_t **thread) 328 1.22 jmcneill { 329 1.22 jmcneill struct tav_softc *sc; 330 1.22 jmcneill 331 1.22 jmcneill sc = hdl; 332 1.22 jmcneill *intr = &sc->sc_intr_lock; 333 1.22 jmcneill *thread = &sc->sc_lock; 334 1.22 jmcneill } 335 1.22 jmcneill 336 1.1 is int 337 1.26 isaki tav_set_format(void *hdl, int setmode, 338 1.26 isaki const audio_params_t *p, const audio_params_t *r, 339 1.26 isaki audio_filter_reg_t *pfil, audio_filter_reg_t *rfil) 340 1.1 is { 341 1.16 kent struct tav_softc *sc; 342 1.1 is bus_space_tag_t iot; 343 1.1 is bus_space_handle_t ioh; 344 1.1 is 345 1.16 kent sc = hdl; 346 1.1 is iot = sc->sc_iot; 347 1.1 is ioh = sc->sc_ioh; 348 1.1 is 349 1.26 isaki KASSERT((setmode & AUMODE_PLAY)); 350 1.26 isaki KASSERT(p->encoding == AUDIO_ENCODING_SLINEAR_BE); 351 1.1 is 352 1.26 isaki bus_space_write_1(iot, ioh, TAV_STR_SEL, TAV_STR_SEL_AUDIO_BYPASS); 353 1.1 is 354 1.1 is tav_write_byte(iot, ioh, TAV_RESTART, 1); 355 1.1 is do { 356 1.1 is delay(10); 357 1.1 is } while (tav_read_byte(iot, ioh, TAV_RESTART)); 358 1.1 is 359 1.1 is return 0; 360 1.1 is } 361 1.1 is 362 1.1 is int 363 1.17 kent tav_set_port(void *hdl, mixer_ctrl_t *mc) 364 1.1 is { 365 1.1 is 366 1.1 is /* dummy */ 367 1.1 is return 0; 368 1.1 is } 369 1.1 is 370 1.1 is int 371 1.17 kent tav_get_port(void *hdl, mixer_ctrl_t *mc) 372 1.1 is { 373 1.1 is 374 1.1 is /* dummy */ 375 1.1 is return 0; 376 1.1 is } 377 1.1 is 378 1.1 is int 379 1.17 kent tav_query_devinfo(void *hdl, mixer_devinfo_t *di) 380 1.1 is { 381 1.2 augustss return ENXIO; 382 1.1 is } 383 1.1 is 384 1.1 is int 385 1.17 kent tav_speaker_ctl(void *hdl, int value) 386 1.1 is { 387 1.17 kent struct tav_softc *sc; 388 1.1 is bus_space_tag_t iot; 389 1.1 is bus_space_handle_t ioh; 390 1.1 is 391 1.1 is sc = hdl; 392 1.1 is iot = sc->sc_iot; 393 1.1 is ioh = sc->sc_ioh; 394 1.1 is 395 1.1 is tav_write_byte(iot, ioh, TAV_MUTE, !value); 396 1.1 is 397 1.1 is return 0; 398 1.1 is } 399