1 1.26 thorpej /* $NetBSD: ucbsnd.c,v 1.26 2020/11/21 21:23:48 thorpej Exp $ */ 2 1.1 uch 3 1.6 uch /*- 4 1.6 uch * Copyright (c) 2000 The NetBSD Foundation, Inc. 5 1.1 uch * All rights reserved. 6 1.1 uch * 7 1.6 uch * This code is derived from software contributed to The NetBSD Foundation 8 1.6 uch * by UCHIYAMA Yasushi. 9 1.6 uch * 10 1.1 uch * Redistribution and use in source and binary forms, with or without 11 1.1 uch * modification, are permitted provided that the following conditions 12 1.1 uch * are met: 13 1.1 uch * 1. Redistributions of source code must retain the above copyright 14 1.1 uch * notice, this list of conditions and the following disclaimer. 15 1.6 uch * 2. Redistributions in binary form must reproduce the above copyright 16 1.6 uch * notice, this list of conditions and the following disclaimer in the 17 1.6 uch * documentation and/or other materials provided with the distribution. 18 1.1 uch * 19 1.6 uch * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.6 uch * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.6 uch * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.6 uch * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.6 uch * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.6 uch * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.6 uch * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.6 uch * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.6 uch * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.6 uch * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.6 uch * POSSIBILITY OF SUCH DAMAGE. 30 1.1 uch */ 31 1.1 uch 32 1.1 uch /* 33 1.1 uch * Device driver for PHILIPS UCB1200 Advanced modem/audio analog front-end 34 1.1 uch * Audio codec part. 35 1.3 uch * 36 1.3 uch * /dev/ucbsnd0 : sampling rate 22.154kHz monoral 16bit straight PCM device. 37 1.1 uch */ 38 1.15 lukem 39 1.15 lukem #include <sys/cdefs.h> 40 1.26 thorpej __KERNEL_RCSID(0, "$NetBSD: ucbsnd.c,v 1.26 2020/11/21 21:23:48 thorpej Exp $"); 41 1.1 uch 42 1.1 uch #include "opt_use_poll.h" 43 1.1 uch 44 1.1 uch #include <sys/param.h> 45 1.1 uch #include <sys/systm.h> 46 1.3 uch #include <sys/conf.h> 47 1.26 thorpej #include <sys/kmem.h> 48 1.1 uch #include <sys/device.h> 49 1.3 uch #include <sys/proc.h> 50 1.3 uch #include <sys/endian.h> 51 1.24 matt #include <sys/bus.h> 52 1.24 matt #include <sys/intr.h> 53 1.1 uch 54 1.24 matt #include <mips/locore.h> 55 1.7 thorpej #include <mips/cache.h> 56 1.7 thorpej 57 1.1 uch #include <hpcmips/tx/tx39var.h> 58 1.1 uch #include <hpcmips/tx/tx39sibvar.h> 59 1.1 uch #include <hpcmips/tx/tx39sibreg.h> 60 1.1 uch #include <hpcmips/tx/tx39icureg.h> 61 1.1 uch #include <hpcmips/tx/txsnd.h> 62 1.1 uch 63 1.1 uch #include <hpcmips/dev/ucb1200var.h> 64 1.1 uch #include <hpcmips/dev/ucb1200reg.h> 65 1.1 uch 66 1.3 uch #define AUDIOUNIT(x) (minor(x)&0x0f) 67 1.3 uch #define AUDIODEV(x) (minor(x)&0xf0) 68 1.3 uch 69 1.1 uch #ifdef UCBSNDDEBUG 70 1.1 uch int ucbsnd_debug = 1; 71 1.1 uch #define DPRINTF(arg) if (ucbsnd_debug) printf arg; 72 1.1 uch #define DPRINTFN(n, arg) if (ucbsnd_debug > (n)) printf arg; 73 1.1 uch #else 74 1.1 uch #define DPRINTF(arg) 75 1.1 uch #define DPRINTFN(n, arg) 76 1.1 uch #endif 77 1.1 uch 78 1.3 uch #define UCBSND_BUFBLOCK 5 79 1.3 uch /* 80 1.3 uch * XXX temporary DMA buffer 81 1.3 uch */ 82 1.3 uch static u_int8_t dmabuf_static[TX39_SIBDMA_SIZE * UCBSND_BUFBLOCK] __attribute__((__aligned__(16))); /* XXX */ 83 1.3 uch static size_t dmabufcnt_static[UCBSND_BUFBLOCK]; /* XXX */ 84 1.3 uch 85 1.1 uch enum ucbsnd_state { 86 1.1 uch /* 0 */ UCBSND_IDLE, 87 1.1 uch /* 1 */ UCBSND_INIT, 88 1.1 uch /* 2 */ UCBSND_ENABLE_SAMPLERATE, 89 1.1 uch /* 3 */ UCBSND_ENABLE_OUTPUTPATH, 90 1.3 uch /* 4 */ UCBSND_ENABLE_SETVOLUME, 91 1.1 uch /* 5 */ UCBSND_ENABLE_SPEAKER0, 92 1.1 uch /* 6 */ UCBSND_ENABLE_SPEAKER1, 93 1.1 uch /* 7 */ UCBSND_TRANSITION_PIO, 94 1.1 uch /* 8 */ UCBSND_PIO, 95 1.1 uch /* 9 */ UCBSND_TRANSITION_DISABLE, 96 1.1 uch /*10 */ UCBSND_DISABLE_OUTPUTPATH, 97 1.1 uch /*11 */ UCBSND_DISABLE_SPEAKER0, 98 1.1 uch /*12 */ UCBSND_DISABLE_SPEAKER1, 99 1.3 uch /*13 */ UCBSND_DISABLE_SIB, 100 1.3 uch /*14 */ UCBSND_DMASTART, 101 1.3 uch /*15 */ UCBSND_DMAEND, 102 1.3 uch }; 103 1.3 uch 104 1.3 uch struct ring_buf { 105 1.3 uch u_int32_t rb_buf; /* buffer start address */ 106 1.3 uch size_t *rb_bufcnt; /* effective data count (max rb_blksize)*/ 107 1.3 uch 108 1.3 uch size_t rb_bufsize; /* total amount of buffer */ 109 1.3 uch int rb_blksize; /* DMA block size */ 110 1.3 uch int rb_maxblks; /* # of blocks in ring */ 111 1.3 uch 112 1.3 uch int rb_inp; /* start of input (to buffer) */ 113 1.3 uch int rb_outp; /* output pointer */ 114 1.1 uch }; 115 1.1 uch 116 1.1 uch struct ucbsnd_softc { 117 1.21 chs device_t sc_dev; 118 1.21 chs device_t sc_sib; /* parent (TX39 SIB module) */ 119 1.21 chs device_t sc_ucb; /* parent (UCB1200 module) */ 120 1.1 uch tx_chipset_tag_t sc_tc; 121 1.1 uch 122 1.3 uch struct tx_sound_tag sc_tag; 123 1.3 uch int sc_mute; 124 1.1 uch 125 1.1 uch /* 126 1.1 uch * audio codec state machine 127 1.1 uch */ 128 1.3 uch int sa_transfer_mode; 129 1.3 uch #define UCBSND_TRANSFERMODE_DMA 0 130 1.3 uch #define UCBSND_TRANSFERMODE_PIO 1 131 1.1 uch enum ucbsnd_state sa_state; 132 1.3 uch int sa_snd_attenuation; 133 1.3 uch #define UCBSND_DEFAULT_ATTENUATION 0 /* Full volume */ 134 1.1 uch int sa_snd_rate; /* passed down from SIB module */ 135 1.1 uch int sa_tel_rate; 136 1.1 uch void* sa_sf0ih; 137 1.1 uch void* sa_sndih; 138 1.1 uch int sa_retry; 139 1.1 uch int sa_cnt; /* misc counter */ 140 1.3 uch 141 1.3 uch /* 142 1.3 uch * input buffer 143 1.3 uch */ 144 1.3 uch size_t sa_dmacnt; 145 1.3 uch struct ring_buf sc_rb; 146 1.1 uch }; 147 1.1 uch 148 1.21 chs int ucbsnd_match(device_t, cfdata_t, void *); 149 1.21 chs void ucbsnd_attach(device_t, device_t, void *); 150 1.1 uch 151 1.21 chs int ucbsnd_exec_output(void *); 152 1.21 chs int ucbsnd_busy(void *); 153 1.1 uch 154 1.21 chs void ucbsnd_sound_init(struct ucbsnd_softc *); 155 1.6 uch void __ucbsnd_sound_click(tx_sound_tag_t); 156 1.6 uch void __ucbsnd_sound_mute(tx_sound_tag_t, int); 157 1.6 uch 158 1.6 uch int ucbsndwrite_subr(struct ucbsnd_softc *, u_int32_t *, size_t, 159 1.6 uch struct uio *); 160 1.6 uch 161 1.21 chs int ringbuf_allocate(struct ring_buf *, size_t, int); 162 1.21 chs void ringbuf_deallocate(struct ring_buf *); 163 1.21 chs void ringbuf_reset(struct ring_buf *); 164 1.21 chs int ringbuf_full(struct ring_buf *); 165 1.21 chs void *ringbuf_producer_get(struct ring_buf *); 166 1.21 chs void ringbuf_producer_return(struct ring_buf *, size_t); 167 1.21 chs void *ringbuf_consumer_get(struct ring_buf *, size_t *); 168 1.21 chs void ringbuf_consumer_return(struct ring_buf *); 169 1.3 uch 170 1.21 chs CFATTACH_DECL_NEW(ucbsnd, sizeof(struct ucbsnd_softc), 171 1.11 thorpej ucbsnd_match, ucbsnd_attach, NULL, NULL); 172 1.9 gehenna 173 1.9 gehenna dev_type_open(ucbsndopen); 174 1.9 gehenna dev_type_close(ucbsndclose); 175 1.9 gehenna dev_type_read(ucbsndread); 176 1.9 gehenna dev_type_write(ucbsndwrite); 177 1.9 gehenna 178 1.9 gehenna const struct cdevsw ucbsnd_cdevsw = { 179 1.22 dholland .d_open = ucbsndopen, 180 1.22 dholland .d_close = ucbsndclose, 181 1.22 dholland .d_read = ucbsndread, 182 1.22 dholland .d_write = ucbsndwrite, 183 1.22 dholland .d_ioctl = nullioctl, 184 1.22 dholland .d_stop = nostop, 185 1.22 dholland .d_tty = notty, 186 1.22 dholland .d_poll = nopoll, 187 1.25 riastrad .d_mmap = nommap, 188 1.22 dholland .d_kqfilter = nokqfilter, 189 1.23 dholland .d_discard = nodiscard, 190 1.22 dholland .d_flag = 0 191 1.1 uch }; 192 1.1 uch 193 1.1 uch int 194 1.21 chs ucbsnd_match(device_t parent, cfdata_t cf, void *aux) 195 1.1 uch { 196 1.6 uch 197 1.6 uch return (1); 198 1.1 uch } 199 1.1 uch 200 1.1 uch void 201 1.21 chs ucbsnd_attach(device_t parent, device_t self, void *aux) 202 1.1 uch { 203 1.1 uch struct ucb1200_attach_args *ucba = aux; 204 1.21 chs struct ucbsnd_softc *sc = device_private(self); 205 1.1 uch tx_chipset_tag_t tc; 206 1.1 uch 207 1.21 chs sc->sc_dev = self; 208 1.1 uch tc = sc->sc_tc = ucba->ucba_tc; 209 1.1 uch sc->sc_sib = ucba->ucba_sib; 210 1.1 uch sc->sc_ucb = ucba->ucba_ucb; 211 1.2 uch 212 1.2 uch /* register sound functions */ 213 1.1 uch ucbsnd_sound_init(sc); 214 1.2 uch 215 1.1 uch sc->sa_snd_rate = ucba->ucba_snd_rate; 216 1.1 uch sc->sa_tel_rate = ucba->ucba_tel_rate; 217 1.1 uch 218 1.3 uch sc->sa_snd_attenuation = UCBSND_DEFAULT_ATTENUATION; 219 1.1 uch #define KHZ(a) ((a) / 1000), (((a) % 1000)) 220 1.1 uch printf(": audio %d.%03d kHz telecom %d.%03d kHz", 221 1.6 uch KHZ((tx39sib_clock(sc->sc_sib) * 2) / 222 1.6 uch (sc->sa_snd_rate * 64)), 223 1.6 uch KHZ((tx39sib_clock(sc->sc_sib) * 2) / 224 1.6 uch (sc->sa_tel_rate * 64))); 225 1.1 uch 226 1.1 uch ucb1200_state_install(parent, ucbsnd_busy, self, 227 1.6 uch UCB1200_SND_MODULE); 228 1.1 uch 229 1.3 uch ringbuf_allocate(&sc->sc_rb, TX39_SIBDMA_SIZE, UCBSND_BUFBLOCK); 230 1.3 uch 231 1.1 uch printf("\n"); 232 1.1 uch } 233 1.1 uch 234 1.1 uch int 235 1.6 uch ucbsnd_busy(void *arg) 236 1.1 uch { 237 1.1 uch struct ucbsnd_softc *sc = arg; 238 1.1 uch 239 1.6 uch return (sc->sa_state != UCBSND_IDLE); 240 1.1 uch } 241 1.1 uch 242 1.1 uch int 243 1.6 uch ucbsnd_exec_output(void *arg) 244 1.1 uch { 245 1.1 uch struct ucbsnd_softc *sc = arg; 246 1.1 uch tx_chipset_tag_t tc = sc->sc_tc; 247 1.1 uch txreg_t reg; 248 1.3 uch u_int32_t *buf; 249 1.3 uch size_t bufcnt; 250 1.1 uch 251 1.1 uch switch (sc->sa_state) { 252 1.1 uch default: 253 1.1 uch panic("ucbsnd_exec_output: invalid state %d", sc->sa_state); 254 1.1 uch /* NOTREACHED */ 255 1.1 uch break; 256 1.1 uch 257 1.1 uch case UCBSND_IDLE: 258 1.1 uch /* nothing to do */ 259 1.6 uch return (0); 260 1.1 uch 261 1.1 uch case UCBSND_INIT: 262 1.1 uch sc->sa_sf0ih = tx_intr_establish( 263 1.1 uch tc, MAKEINTR(1, TX39_INTRSTATUS1_SIBSF0INT), 264 1.1 uch IST_EDGE, IPL_TTY, ucbsnd_exec_output, sc); 265 1.1 uch 266 1.1 uch sc->sa_state = UCBSND_ENABLE_SAMPLERATE; 267 1.6 uch return (0); 268 1.1 uch 269 1.1 uch case UCBSND_ENABLE_SAMPLERATE: 270 1.1 uch /* Enable UCB1200 side sample rate */ 271 1.1 uch reg = TX39_SIBSF0_WRITE; 272 1.1 uch reg = TX39_SIBSF0_REGADDR_SET(reg, UCB1200_AUDIOCTRLA_REG); 273 1.1 uch reg = TX39_SIBSF0_REGDATA_SET(reg, sc->sa_snd_rate); 274 1.1 uch tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); 275 1.3 uch 276 1.1 uch sc->sa_state = UCBSND_ENABLE_OUTPUTPATH; 277 1.6 uch return (0); 278 1.3 uch 279 1.1 uch case UCBSND_ENABLE_OUTPUTPATH: 280 1.1 uch /* Enable UCB1200 side */ 281 1.1 uch reg = TX39_SIBSF0_WRITE; 282 1.1 uch reg = TX39_SIBSF0_REGADDR_SET(reg, UCB1200_AUDIOCTRLB_REG); 283 1.3 uch reg = TX39_SIBSF0_REGDATA_SET(reg, sc->sa_snd_attenuation | 284 1.6 uch UCB1200_AUDIOCTRLB_OUTEN); 285 1.1 uch tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); 286 1.1 uch 287 1.1 uch /* Enable SIB side */ 288 1.1 uch reg = tx_conf_read(tc, TX39_SIBCTRL_REG); 289 1.1 uch tx_conf_write(tc, TX39_SIBCTRL_REG, 290 1.6 uch reg | TX39_SIBCTRL_ENSND); 291 1.1 uch 292 1.1 uch sc->sa_state = UCBSND_ENABLE_SPEAKER0; 293 1.1 uch sc->sa_retry = 10; 294 1.6 uch return (0); 295 1.1 uch case UCBSND_ENABLE_SPEAKER0: 296 1.1 uch /* Speaker on */ 297 1.1 uch 298 1.1 uch reg = TX39_SIBSF0_REGADDR_SET(0, UCB1200_IO_DATA_REG); 299 1.1 uch tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); 300 1.1 uch 301 1.1 uch sc->sa_state = UCBSND_ENABLE_SPEAKER1; 302 1.6 uch return (0); 303 1.1 uch 304 1.1 uch case UCBSND_ENABLE_SPEAKER1: 305 1.1 uch reg = tx_conf_read(tc, TX39_SIBSF0STAT_REG); 306 1.1 uch if ((TX39_SIBSF0_REGADDR(reg) != UCB1200_IO_DATA_REG) && 307 1.1 uch --sc->sa_retry > 0) { 308 1.1 uch 309 1.1 uch sc->sa_state = UCBSND_ENABLE_SPEAKER0; 310 1.6 uch return (0); 311 1.1 uch } 312 1.1 uch 313 1.1 uch if (sc->sa_retry <= 0) { 314 1.1 uch printf("ucbsnd_exec_output: subframe0 busy\n"); 315 1.1 uch 316 1.1 uch sc->sa_state = UCBSND_IDLE; 317 1.6 uch return (0); 318 1.1 uch } 319 1.1 uch 320 1.1 uch reg |= TX39_SIBSF0_WRITE; 321 1.1 uch reg |= UCB1200_IO_DATA_SPEAKER; 322 1.1 uch tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); 323 1.1 uch 324 1.3 uch /* 325 1.3 uch * Begin to transfer. 326 1.3 uch */ 327 1.3 uch switch (sc->sa_transfer_mode) { 328 1.3 uch case UCBSND_TRANSFERMODE_DMA: 329 1.3 uch sc->sa_state = UCBSND_DMASTART; 330 1.3 uch sc->sa_dmacnt = 0; 331 1.3 uch break; 332 1.3 uch case UCBSND_TRANSFERMODE_PIO: 333 1.3 uch sc->sa_state = UCBSND_TRANSITION_PIO; 334 1.3 uch break; 335 1.3 uch } 336 1.3 uch 337 1.6 uch return (0); 338 1.3 uch case UCBSND_DMASTART: 339 1.3 uch /* get data */ 340 1.3 uch if (sc->sa_dmacnt) /* return previous buffer */ 341 1.3 uch ringbuf_consumer_return(&sc->sc_rb); 342 1.3 uch buf = ringbuf_consumer_get(&sc->sc_rb, &bufcnt); 343 1.3 uch if (buf == 0) { 344 1.3 uch sc->sa_state = UCBSND_DMAEND; 345 1.6 uch return (0); 346 1.3 uch } 347 1.3 uch 348 1.3 uch if (sc->sa_dmacnt == 0) { 349 1.3 uch /* change interrupt source */ 350 1.3 uch if (sc->sa_sf0ih) { 351 1.3 uch tx_intr_disestablish(tc, sc->sa_sf0ih); 352 1.3 uch sc->sa_sf0ih = 0; 353 1.3 uch } 354 1.3 uch sc->sa_sndih = tx_intr_establish( 355 1.3 uch tc, MAKEINTR(1, TX39_INTRSTATUS1_SND1_0INT), 356 1.3 uch IST_EDGE, IPL_TTY, ucbsnd_exec_output, sc); 357 1.3 uch } else { 358 1.3 uch wakeup(&sc->sc_rb); 359 1.3 uch } 360 1.3 uch 361 1.3 uch /* set DMA buffer address */ 362 1.3 uch tx_conf_write(tc, TX39_SIBSNDTXSTART_REG, 363 1.6 uch MIPS_KSEG0_TO_PHYS(buf)); 364 1.3 uch 365 1.3 uch /* set DMA buffer size */ 366 1.3 uch tx_conf_write(tc, TX39_SIBSIZE_REG, 367 1.6 uch TX39_SIBSIZE_SNDSIZE_SET(0, bufcnt)); 368 1.3 uch 369 1.3 uch tx_conf_write(tc, TX39_SIBSF0CTRL_REG, TX39_SIBSF0_SNDVALID); 370 1.3 uch 371 1.3 uch /* kick DMA */ 372 1.3 uch reg = tx_conf_read(tc, TX39_SIBDMACTRL_REG); 373 1.3 uch reg |= TX39_SIBDMACTRL_ENDMATXSND; 374 1.3 uch tx_conf_write(tc, TX39_SIBDMACTRL_REG, reg); 375 1.3 uch 376 1.3 uch /* set next */ 377 1.3 uch sc->sa_dmacnt += bufcnt; 378 1.3 uch 379 1.3 uch break; 380 1.1 uch 381 1.3 uch case UCBSND_DMAEND: 382 1.3 uch sc->sa_state = UCBSND_TRANSITION_DISABLE; 383 1.3 uch break; 384 1.1 uch case UCBSND_TRANSITION_PIO: 385 1.1 uch /* change interrupt source */ 386 1.3 uch if (sc->sa_sf0ih) { 387 1.3 uch tx_intr_disestablish(tc, sc->sa_sf0ih); 388 1.3 uch sc->sa_sf0ih = 0; 389 1.3 uch } 390 1.1 uch sc->sa_sndih = tx_intr_establish( 391 1.1 uch tc, MAKEINTR(1, TX39_INTRSTATUS1_SNDININT), 392 1.1 uch IST_EDGE, IPL_TTY, ucbsnd_exec_output, sc); 393 1.1 uch 394 1.1 uch sc->sa_state = UCBSND_PIO; 395 1.2 uch sc->sa_cnt = 0; 396 1.6 uch return (0); 397 1.1 uch 398 1.1 uch case UCBSND_PIO: 399 1.3 uch { 400 1.3 uch /* PIO test routine */ 401 1.3 uch int dummy_data = sc->sa_cnt * 3; 402 1.3 uch tx_conf_write(tc, TX39_SIBSNDHOLD_REG, 403 1.6 uch dummy_data << 16 | dummy_data); 404 1.1 uch tx_conf_write(tc, TX39_SIBSF0CTRL_REG, TX39_SIBSF0_SNDVALID); 405 1.3 uch if (sc->sa_cnt++ > 50) { 406 1.1 uch sc->sa_state = UCBSND_TRANSITION_DISABLE; 407 1.3 uch } 408 1.6 uch return (0); 409 1.3 uch } 410 1.1 uch case UCBSND_TRANSITION_DISABLE: 411 1.1 uch /* change interrupt source */ 412 1.3 uch if (sc->sa_sndih) { 413 1.3 uch tx_intr_disestablish(tc, sc->sa_sndih); 414 1.3 uch sc->sa_sndih = 0; 415 1.3 uch } 416 1.1 uch sc->sa_sf0ih = tx_intr_establish( 417 1.1 uch tc, MAKEINTR(1, TX39_INTRSTATUS1_SIBSF0INT), 418 1.1 uch IST_EDGE, IPL_TTY, ucbsnd_exec_output, sc); 419 1.1 uch 420 1.1 uch sc->sa_state = UCBSND_DISABLE_OUTPUTPATH; 421 1.6 uch return (0); 422 1.1 uch 423 1.1 uch case UCBSND_DISABLE_OUTPUTPATH: 424 1.1 uch /* disable codec output path and mute */ 425 1.1 uch reg = TX39_SIBSF0_WRITE; 426 1.1 uch reg = TX39_SIBSF0_REGADDR_SET(reg, UCB1200_AUDIOCTRLB_REG); 427 1.1 uch reg = TX39_SIBSF0_REGDATA_SET(reg, UCB1200_AUDIOCTRLB_MUTE); 428 1.1 uch tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); 429 1.1 uch 430 1.1 uch sc->sa_state = UCBSND_DISABLE_SPEAKER0; 431 1.1 uch sc->sa_retry = 10; 432 1.6 uch return (0); 433 1.1 uch 434 1.1 uch case UCBSND_DISABLE_SPEAKER0: 435 1.1 uch /* Speaker off */ 436 1.1 uch reg = TX39_SIBSF0_REGADDR_SET(0, UCB1200_IO_DATA_REG); 437 1.1 uch tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); 438 1.1 uch 439 1.1 uch sc->sa_state = UCBSND_DISABLE_SPEAKER1; 440 1.6 uch return (0); 441 1.1 uch 442 1.1 uch case UCBSND_DISABLE_SPEAKER1: 443 1.1 uch reg = tx_conf_read(tc, TX39_SIBSF0STAT_REG); 444 1.1 uch if ((TX39_SIBSF0_REGADDR(reg) != UCB1200_IO_DATA_REG) && 445 1.1 uch --sc->sa_retry > 0) { 446 1.1 uch 447 1.1 uch sc->sa_state = UCBSND_DISABLE_SPEAKER0; 448 1.6 uch return (0); 449 1.1 uch } 450 1.1 uch 451 1.1 uch if (sc->sa_retry <= 0) { 452 1.1 uch printf("ucbsnd_exec_output: subframe0 busy\n"); 453 1.1 uch 454 1.1 uch sc->sa_state = UCBSND_IDLE; 455 1.6 uch return (0); 456 1.1 uch } 457 1.1 uch 458 1.1 uch reg |= TX39_SIBSF0_WRITE; 459 1.1 uch reg &= ~UCB1200_IO_DATA_SPEAKER; 460 1.1 uch tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); 461 1.1 uch 462 1.1 uch sc->sa_state = UCBSND_DISABLE_SIB; 463 1.6 uch return (0); 464 1.1 uch 465 1.1 uch case UCBSND_DISABLE_SIB: 466 1.1 uch /* Disable SIB side */ 467 1.1 uch reg = tx_conf_read(tc, TX39_SIBCTRL_REG); 468 1.1 uch reg &= ~TX39_SIBCTRL_ENSND; 469 1.1 uch tx_conf_write(tc, TX39_SIBCTRL_REG, reg); 470 1.1 uch 471 1.1 uch /* end audio disable sequence */ 472 1.3 uch if (sc->sa_sf0ih) { 473 1.3 uch tx_intr_disestablish(tc, sc->sa_sf0ih); 474 1.3 uch sc->sa_sf0ih = 0; 475 1.3 uch } 476 1.1 uch sc->sa_state = UCBSND_IDLE; 477 1.1 uch 478 1.6 uch return (0); 479 1.1 uch } 480 1.1 uch 481 1.6 uch return (0); 482 1.1 uch } 483 1.1 uch 484 1.1 uch /* 485 1.1 uch * global sound interface. 486 1.1 uch */ 487 1.1 uch void 488 1.6 uch ucbsnd_sound_init(struct ucbsnd_softc *sc) 489 1.1 uch { 490 1.1 uch tx_sound_tag_t ts = &sc->sc_tag; 491 1.1 uch tx_chipset_tag_t tc = sc->sc_tc; 492 1.1 uch 493 1.1 uch ts->ts_v = sc; 494 1.2 uch ts->ts_click = __ucbsnd_sound_click; 495 1.2 uch ts->ts_mute = __ucbsnd_sound_mute; 496 1.1 uch 497 1.1 uch tx_conf_register_sound(tc, ts); 498 1.1 uch } 499 1.1 uch 500 1.1 uch void 501 1.6 uch __ucbsnd_sound_click(tx_sound_tag_t arg) 502 1.1 uch { 503 1.1 uch struct ucbsnd_softc *sc = (void*)arg; 504 1.1 uch 505 1.2 uch if (!sc->sc_mute && sc->sa_state == UCBSND_IDLE) { 506 1.3 uch sc->sa_transfer_mode = UCBSND_TRANSFERMODE_PIO; 507 1.1 uch sc->sa_state = UCBSND_INIT; 508 1.1 uch ucbsnd_exec_output((void*)sc); 509 1.1 uch } 510 1.1 uch } 511 1.1 uch 512 1.2 uch void 513 1.6 uch __ucbsnd_sound_mute(tx_sound_tag_t arg, int onoff) 514 1.2 uch { 515 1.2 uch struct ucbsnd_softc *sc = (void*)arg; 516 1.6 uch 517 1.2 uch sc->sc_mute = onoff; 518 1.3 uch } 519 1.3 uch 520 1.3 uch /* 521 1.3 uch * device access 522 1.3 uch */ 523 1.3 uch extern struct cfdriver ucbsnd_cd; 524 1.3 uch 525 1.3 uch int 526 1.16 christos ucbsndopen(dev_t dev, int flags, int ifmt, struct lwp *l) 527 1.3 uch { 528 1.3 uch int unit = AUDIOUNIT(dev); 529 1.3 uch struct ucbsnd_softc *sc; 530 1.4 uch int s; 531 1.3 uch 532 1.19 tsutsui sc = device_lookup_private(&ucbsnd_cd, unit); 533 1.19 tsutsui if (sc == NULL) 534 1.3 uch return (ENXIO); 535 1.4 uch 536 1.20 jmcneill s = splvm(); 537 1.4 uch ringbuf_reset(&sc->sc_rb); 538 1.4 uch splx(s); 539 1.3 uch 540 1.3 uch return (0); 541 1.3 uch } 542 1.3 uch 543 1.3 uch int 544 1.16 christos ucbsndclose(dev_t dev, int flags, int ifmt, struct lwp *l) 545 1.3 uch { 546 1.3 uch int unit = AUDIOUNIT(dev); 547 1.3 uch struct ucbsnd_softc *sc; 548 1.3 uch 549 1.19 tsutsui sc = device_lookup_private(&ucbsnd_cd, unit); 550 1.19 tsutsui if (sc == NULL) 551 1.3 uch return (ENXIO); 552 1.3 uch 553 1.3 uch return (0); 554 1.3 uch } 555 1.3 uch 556 1.3 uch int 557 1.6 uch ucbsndread(dev_t dev, struct uio *uio, int ioflag) 558 1.3 uch { 559 1.3 uch int unit = AUDIOUNIT(dev); 560 1.3 uch struct ucbsnd_softc *sc; 561 1.3 uch int error = 0; 562 1.3 uch 563 1.19 tsutsui sc = device_lookup_private(&ucbsnd_cd, unit); 564 1.19 tsutsui if (sc == NULL) 565 1.3 uch return (ENXIO); 566 1.3 uch /* not supported yet */ 567 1.3 uch 568 1.3 uch return (error); 569 1.3 uch } 570 1.3 uch 571 1.3 uch int 572 1.6 uch ucbsndwrite_subr(struct ucbsnd_softc *sc, u_int32_t *buf, size_t bufsize, 573 1.6 uch struct uio *uio) 574 1.3 uch { 575 1.3 uch int i, s, error; 576 1.3 uch 577 1.3 uch error = uiomove(buf, bufsize, uio); 578 1.3 uch /* 579 1.3 uch * inverse endian for UCB1200 580 1.3 uch */ 581 1.3 uch for (i = 0; i < bufsize / sizeof(int); i++) 582 1.3 uch buf[i] = htobe32(buf[i]); 583 1.7 thorpej mips_dcache_wbinv_range((vaddr_t)buf, bufsize); 584 1.3 uch 585 1.3 uch ringbuf_producer_return(&sc->sc_rb, bufsize); 586 1.3 uch 587 1.20 jmcneill s = splvm(); 588 1.3 uch if (sc->sa_state == UCBSND_IDLE && ringbuf_full(&sc->sc_rb)) { 589 1.3 uch sc->sa_transfer_mode = UCBSND_TRANSFERMODE_DMA; 590 1.3 uch sc->sa_state = UCBSND_INIT; 591 1.3 uch ucbsnd_exec_output((void*)sc); 592 1.3 uch } 593 1.3 uch splx(s); 594 1.3 uch 595 1.6 uch return (error); 596 1.3 uch } 597 1.3 uch 598 1.3 uch int 599 1.6 uch ucbsndwrite(dev_t dev, struct uio *uio, int ioflag) 600 1.3 uch { 601 1.3 uch int unit = AUDIOUNIT(dev); 602 1.3 uch struct ucbsnd_softc *sc; 603 1.3 uch int len, error = 0; 604 1.4 uch int i, n, s, rest; 605 1.3 uch void *buf; 606 1.3 uch 607 1.19 tsutsui sc = device_lookup_private(&ucbsnd_cd, unit); 608 1.19 tsutsui if (sc == NULL) 609 1.3 uch return (ENXIO); 610 1.3 uch 611 1.3 uch len = uio->uio_resid; 612 1.3 uch n = (len + TX39_SIBDMA_SIZE - 1) / TX39_SIBDMA_SIZE; 613 1.3 uch rest = len % TX39_SIBDMA_SIZE; 614 1.3 uch 615 1.3 uch if (rest) 616 1.3 uch --n; 617 1.3 uch 618 1.3 uch for (i = 0; i < n; i++) { 619 1.4 uch while (!(buf = ringbuf_producer_get(&sc->sc_rb))) { 620 1.4 uch error = tsleep(&sc->sc_rb, PRIBIO, "ucbsnd", 1000); 621 1.4 uch if (error) 622 1.4 uch goto errout; 623 1.4 uch } 624 1.4 uch 625 1.3 uch error = ucbsndwrite_subr(sc, buf, TX39_SIBDMA_SIZE, uio); 626 1.3 uch if (error) 627 1.3 uch goto out; 628 1.3 uch } 629 1.3 uch 630 1.3 uch if (rest) { 631 1.4 uch while (!(buf = ringbuf_producer_get(&sc->sc_rb))) { 632 1.4 uch error = tsleep(&sc->sc_rb, PRIBIO, "ucbsnd", 1000); 633 1.4 uch if (error) 634 1.4 uch goto errout; 635 1.4 uch } 636 1.3 uch 637 1.3 uch error = ucbsndwrite_subr(sc, buf, rest, uio); 638 1.3 uch } 639 1.3 uch 640 1.3 uch out: 641 1.4 uch return (error); 642 1.4 uch errout: 643 1.21 chs printf("%s: timeout. reset ring-buffer.\n", device_xname(sc->sc_dev)); 644 1.20 jmcneill s = splvm(); 645 1.4 uch ringbuf_reset(&sc->sc_rb); 646 1.4 uch splx(s); 647 1.3 uch 648 1.3 uch return (error); 649 1.3 uch } 650 1.3 uch 651 1.3 uch /* 652 1.3 uch * Ring buffer. 653 1.3 uch */ 654 1.3 uch int 655 1.6 uch ringbuf_allocate(struct ring_buf *rb, size_t blksize, int maxblk) 656 1.3 uch { 657 1.3 uch rb->rb_bufsize = blksize * maxblk; 658 1.3 uch rb->rb_blksize = blksize; 659 1.3 uch rb->rb_maxblks = maxblk; 660 1.3 uch #if notyet 661 1.26 thorpej rb->rb_buf = (u_int32_t)kmem_alloc(rb->rb_bufsize, KM_SLEEP); 662 1.3 uch #else 663 1.3 uch rb->rb_buf = (u_int32_t)dmabuf_static; 664 1.3 uch #endif 665 1.3 uch if (rb->rb_buf == 0) { 666 1.3 uch printf("ringbuf_allocate: can't allocate buffer\n"); 667 1.6 uch return (1); 668 1.3 uch } 669 1.3 uch memset((char*)rb->rb_buf, 0, rb->rb_bufsize); 670 1.3 uch #if notyet 671 1.26 thorpej rb->rb_bufcnt = kmem_alloc(rb->rb_maxblks * sizeof(size_t), KM_SLEEP); 672 1.3 uch #else 673 1.3 uch rb->rb_bufcnt = dmabufcnt_static; 674 1.3 uch #endif 675 1.3 uch if (rb->rb_bufcnt == 0) { 676 1.3 uch printf("ringbuf_allocate: can't allocate buffer\n"); 677 1.6 uch return (1); 678 1.3 uch } 679 1.3 uch memset((char*)rb->rb_bufcnt, 0, rb->rb_maxblks * sizeof(size_t)); 680 1.3 uch 681 1.3 uch ringbuf_reset(rb); 682 1.3 uch 683 1.6 uch return (0); 684 1.3 uch } 685 1.3 uch 686 1.3 uch void 687 1.6 uch ringbuf_deallocate(struct ring_buf *rb) 688 1.3 uch { 689 1.3 uch #if notyet 690 1.26 thorpej kmem_free((void*)rb->rb_buf, rb->rb_bufsize); 691 1.26 thorpej kmem_free(rb->rb_bufcnt, rb->rb_maxblks * sizeof(size_t)); 692 1.3 uch #endif 693 1.3 uch } 694 1.3 uch 695 1.3 uch void 696 1.6 uch ringbuf_reset(struct ring_buf *rb) 697 1.3 uch { 698 1.3 uch rb->rb_outp = 0; 699 1.3 uch rb->rb_inp = 0; 700 1.3 uch } 701 1.3 uch 702 1.3 uch int 703 1.6 uch ringbuf_full(struct ring_buf *rb) 704 1.3 uch { 705 1.3 uch int ret; 706 1.3 uch 707 1.3 uch ret = rb->rb_outp == rb->rb_maxblks; 708 1.3 uch 709 1.6 uch return (ret); 710 1.3 uch } 711 1.3 uch 712 1.3 uch void* 713 1.6 uch ringbuf_producer_get(struct ring_buf *rb) 714 1.3 uch { 715 1.3 uch u_int32_t ret; 716 1.3 uch int s; 717 1.3 uch 718 1.20 jmcneill s = splvm(); 719 1.3 uch ret = ringbuf_full(rb) ? 0 : 720 1.6 uch rb->rb_buf + rb->rb_inp * rb->rb_blksize; 721 1.3 uch splx(s); 722 1.3 uch 723 1.6 uch return (void *)ret; 724 1.3 uch } 725 1.3 uch 726 1.3 uch void 727 1.6 uch ringbuf_producer_return(struct ring_buf *rb, size_t cnt) 728 1.3 uch { 729 1.3 uch int s; 730 1.3 uch 731 1.3 uch assert(cnt <= rb->rb_blksize); 732 1.3 uch 733 1.20 jmcneill s = splvm(); 734 1.3 uch rb->rb_outp++; 735 1.3 uch 736 1.3 uch rb->rb_bufcnt[rb->rb_inp] = cnt; 737 1.3 uch rb->rb_inp = (rb->rb_inp + 1) % rb->rb_maxblks; 738 1.3 uch splx(s); 739 1.3 uch } 740 1.3 uch 741 1.3 uch void* 742 1.6 uch ringbuf_consumer_get(struct ring_buf *rb, size_t *cntp) 743 1.3 uch { 744 1.3 uch u_int32_t p; 745 1.3 uch int idx; 746 1.3 uch 747 1.3 uch if (rb->rb_outp == 0) 748 1.6 uch return (0); 749 1.3 uch 750 1.3 uch idx = (rb->rb_inp - rb->rb_outp + rb->rb_maxblks) % rb->rb_maxblks; 751 1.3 uch 752 1.3 uch p = rb->rb_buf + idx * rb->rb_blksize; 753 1.3 uch *cntp = rb->rb_bufcnt[idx]; 754 1.3 uch 755 1.6 uch return (void *)p; 756 1.3 uch } 757 1.3 uch 758 1.3 uch void 759 1.6 uch ringbuf_consumer_return(struct ring_buf *rb) 760 1.3 uch { 761 1.3 uch 762 1.3 uch if (rb->rb_outp > 0) 763 1.3 uch rb->rb_outp--; 764 1.2 uch } 765