1 1.20 skrll /* $NetBSD: vraiu.c,v 1.20 2021/01/13 06:39:46 skrll Exp $ */ 2 1.1 hamajima 3 1.1 hamajima /* 4 1.1 hamajima * Copyright (c) 2001 HAMAJIMA Katsuomi. All rights reserved. 5 1.1 hamajima * 6 1.1 hamajima * Redistribution and use in source and binary forms, with or without 7 1.1 hamajima * modification, are permitted provided that the following conditions 8 1.1 hamajima * are met: 9 1.1 hamajima * 1. Redistributions of source code must retain the above copyright 10 1.1 hamajima * notice, this list of conditions and the following disclaimer. 11 1.1 hamajima * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 hamajima * notice, this list of conditions and the following disclaimer in the 13 1.1 hamajima * documentation and/or other materials provided with the distribution. 14 1.1 hamajima * 15 1.1 hamajima * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 1.1 hamajima * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 1.1 hamajima * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 1.1 hamajima * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 1.1 hamajima * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 1.1 hamajima * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 1.1 hamajima * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 1.1 hamajima * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 1.1 hamajima * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 1.1 hamajima * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 1.1 hamajima * SUCH DAMAGE. 26 1.1 hamajima */ 27 1.6 lukem 28 1.6 lukem #include <sys/cdefs.h> 29 1.20 skrll __KERNEL_RCSID(0, "$NetBSD: vraiu.c,v 1.20 2021/01/13 06:39:46 skrll Exp $"); 30 1.1 hamajima 31 1.1 hamajima #include <sys/param.h> 32 1.1 hamajima #include <sys/systm.h> 33 1.1 hamajima #include <sys/device.h> 34 1.1 hamajima #include <sys/bswap.h> 35 1.1 hamajima 36 1.1 hamajima #include <machine/cpu.h> 37 1.1 hamajima #include <machine/intr.h> 38 1.1 hamajima #include <machine/bus.h> 39 1.1 hamajima #include <machine/platid.h> 40 1.1 hamajima #include <machine/platid_mask.h> 41 1.1 hamajima #include <machine/config_hook.h> 42 1.1 hamajima 43 1.1 hamajima #include <sys/audioio.h> 44 1.17 isaki #include <dev/audio/audio_if.h> 45 1.1 hamajima 46 1.1 hamajima #include <hpcmips/vr/vr.h> 47 1.1 hamajima #include <hpcmips/vr/vripif.h> 48 1.1 hamajima #include <hpcmips/vr/icureg.h> 49 1.1 hamajima #include <hpcmips/vr/cmureg.h> 50 1.1 hamajima #include <hpcmips/vr/vraiureg.h> 51 1.1 hamajima 52 1.1 hamajima #ifdef VRAIU_DEBUG 53 1.1 hamajima int vraiu_debug = VRAIU_DEBUG; 54 1.1 hamajima #define DPRINTFN(n,x) if (vraiu_debug>(n)) printf x; 55 1.1 hamajima #else 56 1.1 hamajima #define DPRINTFN(n,x) 57 1.1 hamajima #endif 58 1.1 hamajima 59 1.1 hamajima #define AUDIO_BUF_SIZE 2048 60 1.1 hamajima 61 1.1 hamajima struct vraiu_softc { 62 1.15 chs device_t sc_dev; 63 1.13 jmcneill kmutex_t sc_lock; 64 1.13 jmcneill kmutex_t sc_intr_lock; 65 1.1 hamajima bus_space_tag_t sc_iot; 66 1.1 hamajima bus_space_handle_t sc_ioh; 67 1.1 hamajima bus_dma_tag_t sc_dmat; 68 1.1 hamajima bus_dmamap_t sc_dmap; 69 1.1 hamajima vrip_chipset_tag_t sc_vrip; 70 1.1 hamajima vrdcu_chipset_tag_t sc_dc; 71 1.1 hamajima vrdmaau_chipset_tag_t sc_ac; 72 1.1 hamajima vrcmu_chipset_tag_t sc_cc; 73 1.1 hamajima void *sc_handler; 74 1.5 wiz u_short *sc_buf; /* DMA buffer pointer */ 75 1.1 hamajima u_int sc_rate; /* sampling rate */ 76 1.7 jmcneill u_char sc_volume; /* volume */ 77 1.1 hamajima void (*sc_intr)(void *); /* interrupt routine */ 78 1.1 hamajima void *sc_intrdata; /* interrupt data */ 79 1.1 hamajima }; 80 1.1 hamajima 81 1.15 chs int vraiu_match(device_t, cfdata_t, void *); 82 1.15 chs void vraiu_attach(device_t, device_t, void *); 83 1.1 hamajima int vraiu_intr(void *); 84 1.1 hamajima 85 1.15 chs CFATTACH_DECL_NEW(vraiu, sizeof(struct vraiu_softc), 86 1.3 thorpej vraiu_match, vraiu_attach, NULL, NULL); 87 1.1 hamajima 88 1.1 hamajima struct audio_device aiu_device = { 89 1.1 hamajima "VR4121 AIU", 90 1.1 hamajima "0.1", 91 1.1 hamajima "aiu" 92 1.1 hamajima }; 93 1.1 hamajima 94 1.17 isaki const struct audio_format vraiu_formats = { 95 1.17 isaki .mode = AUMODE_PLAY, 96 1.17 isaki .encoding = AUDIO_ENCODING_SLINEAR_NE, 97 1.17 isaki .validbits = 10, 98 1.17 isaki .precision = 16, 99 1.17 isaki .channels = 1, 100 1.17 isaki .channel_mask = AUFMT_MONAURAL, 101 1.17 isaki .frequency_type = 4, 102 1.17 isaki .frequency = { 8000, 11025, 22050, 44100 }, 103 1.17 isaki }; 104 1.17 isaki 105 1.1 hamajima /* 106 1.1 hamajima * Define our interface to the higher level audio driver. 107 1.1 hamajima */ 108 1.17 isaki int vraiu_query_format(void *, audio_format_query_t *); 109 1.9 kent int vraiu_round_blocksize(void *, int, int, const audio_params_t *); 110 1.1 hamajima int vraiu_commit_settings(void *); 111 1.1 hamajima int vraiu_init_output(void *, void*, int); 112 1.1 hamajima int vraiu_start_output(void *, void *, int, void (*)(void *), void *); 113 1.1 hamajima int vraiu_halt_output(void *); 114 1.1 hamajima int vraiu_getdev(void *, struct audio_device *); 115 1.1 hamajima int vraiu_set_port(void *, mixer_ctrl_t *); 116 1.1 hamajima int vraiu_get_port(void *, mixer_ctrl_t *); 117 1.1 hamajima int vraiu_query_devinfo(void *, mixer_devinfo_t *); 118 1.17 isaki int vraiu_set_format(void *, int, 119 1.17 isaki const audio_params_t *, const audio_params_t *, 120 1.17 isaki audio_filter_reg_t *, audio_filter_reg_t *); 121 1.1 hamajima int vraiu_get_props(void *); 122 1.13 jmcneill void vraiu_get_locks(void *, kmutex_t **, kmutex_t **); 123 1.1 hamajima 124 1.8 yamt const struct audio_hw_if vraiu_hw_if = { 125 1.17 isaki .query_format = vraiu_query_format, 126 1.17 isaki .set_format = vraiu_set_format, 127 1.16 isaki .round_blocksize = vraiu_round_blocksize, 128 1.16 isaki .commit_settings = vraiu_commit_settings, 129 1.16 isaki .init_output = vraiu_init_output, 130 1.16 isaki .start_output = vraiu_start_output, 131 1.16 isaki .halt_output = vraiu_halt_output, 132 1.16 isaki .getdev = vraiu_getdev, 133 1.16 isaki .set_port = vraiu_set_port, 134 1.16 isaki .get_port = vraiu_get_port, 135 1.16 isaki .query_devinfo = vraiu_query_devinfo, 136 1.16 isaki .get_props = vraiu_get_props, 137 1.16 isaki .get_locks = vraiu_get_locks, 138 1.1 hamajima }; 139 1.1 hamajima 140 1.1 hamajima /* 141 1.1 hamajima * convert to 1ch 10bit unsigned PCM data. 142 1.1 hamajima */ 143 1.1 hamajima static void vraiu_slinear16_1(struct vraiu_softc *, u_short *, void *, int); 144 1.1 hamajima 145 1.1 hamajima int 146 1.15 chs vraiu_match(device_t parent, cfdata_t cf, void *aux) 147 1.1 hamajima { 148 1.1 hamajima return 1; 149 1.1 hamajima } 150 1.1 hamajima 151 1.1 hamajima void 152 1.15 chs vraiu_attach(device_t parent, device_t self, void *aux) 153 1.1 hamajima { 154 1.10 kent struct vrip_attach_args *va; 155 1.10 kent struct vraiu_softc *sc; 156 1.1 hamajima bus_dma_segment_t segs; 157 1.1 hamajima int rsegs; 158 1.1 hamajima 159 1.10 kent va = aux; 160 1.15 chs sc = device_private(self); 161 1.15 chs sc->sc_dev = self; 162 1.1 hamajima sc->sc_intr = NULL; 163 1.1 hamajima sc->sc_iot = va->va_iot; 164 1.1 hamajima sc->sc_vrip = va->va_vc; 165 1.1 hamajima sc->sc_cc = va->va_cc; 166 1.1 hamajima sc->sc_dc = va->va_dc; 167 1.1 hamajima sc->sc_ac = va->va_ac; 168 1.1 hamajima sc->sc_dmat = &vrdcu_bus_dma_tag; 169 1.7 jmcneill sc->sc_volume = 127; 170 1.13 jmcneill mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); 171 1.14 mrg mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO); 172 1.1 hamajima 173 1.1 hamajima if (!sc->sc_cc) { 174 1.1 hamajima printf(" not configured: cmu not found\n"); 175 1.1 hamajima return; 176 1.1 hamajima } 177 1.1 hamajima if (!sc->sc_dc) { 178 1.1 hamajima printf(" not configured: dcu not found\n"); 179 1.1 hamajima return; 180 1.1 hamajima } 181 1.1 hamajima if (!sc->sc_ac) { 182 1.1 hamajima printf(" not configured: dmaau not found\n"); 183 1.1 hamajima return; 184 1.1 hamajima } 185 1.1 hamajima if (bus_space_map(sc->sc_iot, va->va_addr, va->va_size, 186 1.1 hamajima 0 /* no flags */, &sc->sc_ioh)) { 187 1.1 hamajima printf(": can't map i/o space\n"); 188 1.1 hamajima return; 189 1.1 hamajima } 190 1.1 hamajima 191 1.1 hamajima /* install interrupt handler and enable interrupt */ 192 1.1 hamajima if (!(sc->sc_handler = vrip_intr_establish(va->va_vc, va->va_unit, 193 1.14 mrg 0, IPL_AUDIO, vraiu_intr, sc))) { 194 1.1 hamajima printf(": can't map interrupt line.\n"); 195 1.1 hamajima return; 196 1.1 hamajima } 197 1.1 hamajima vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, (AIUINT_INTMEND | \ 198 1.1 hamajima AIUINT_INTM | \ 199 1.1 hamajima AIUINT_INTMIDLE | \ 200 1.1 hamajima AIUINT_INTMST | \ 201 1.1 hamajima AIUINT_INTSEND | \ 202 1.1 hamajima AIUINT_INTS | \ 203 1.1 hamajima AIUINT_INTSIDLE), 0); 204 1.1 hamajima 205 1.1 hamajima if (bus_dmamem_alloc(sc->sc_dmat, AUDIO_BUF_SIZE, 0, 0, &segs, 1, 206 1.13 jmcneill &rsegs, BUS_DMA_WAITOK)) { 207 1.1 hamajima printf(": can't allocate memory.\n"); 208 1.1 hamajima return; 209 1.1 hamajima } 210 1.1 hamajima if (bus_dmamem_map(sc->sc_dmat, &segs, rsegs, AUDIO_BUF_SIZE, 211 1.12 christos (void **)&sc->sc_buf, 212 1.13 jmcneill BUS_DMA_WAITOK | BUS_DMA_COHERENT)) { 213 1.1 hamajima printf(": can't map memory.\n"); 214 1.1 hamajima bus_dmamem_free(sc->sc_dmat, &segs, rsegs); 215 1.1 hamajima return; 216 1.1 hamajima } 217 1.1 hamajima if (bus_dmamap_create(sc->sc_dmat, AUDIO_BUF_SIZE, 1, AUDIO_BUF_SIZE, 218 1.13 jmcneill 0, BUS_DMA_WAITOK, &sc->sc_dmap)) { 219 1.1 hamajima printf(": can't create DMA map.\n"); 220 1.12 christos bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_buf, 221 1.1 hamajima AUDIO_BUF_SIZE); 222 1.1 hamajima bus_dmamem_free(sc->sc_dmat, &segs, rsegs); 223 1.1 hamajima return; 224 1.1 hamajima } 225 1.1 hamajima if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmap, sc->sc_buf, 226 1.13 jmcneill AUDIO_BUF_SIZE, NULL, BUS_DMA_WAITOK)) { 227 1.1 hamajima printf(": can't load DMA map.\n"); 228 1.1 hamajima bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmap); 229 1.12 christos bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_buf, 230 1.1 hamajima AUDIO_BUF_SIZE); 231 1.1 hamajima bus_dmamem_free(sc->sc_dmat, &segs, rsegs); 232 1.1 hamajima return; 233 1.1 hamajima } 234 1.1 hamajima if (sc->sc_ac->ac_set_aiuout(sc->sc_ac, sc->sc_buf)) { 235 1.1 hamajima printf(": can't set DMA address.\n"); 236 1.1 hamajima bus_dmamap_unload(sc->sc_dmat, sc->sc_dmap); 237 1.1 hamajima bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmap); 238 1.12 christos bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_buf, 239 1.1 hamajima AUDIO_BUF_SIZE); 240 1.1 hamajima bus_dmamem_free(sc->sc_dmat, &segs, rsegs); 241 1.1 hamajima return; 242 1.1 hamajima } 243 1.1 hamajima printf("\n"); 244 1.1 hamajima 245 1.1 hamajima sc->sc_rate = SPS8000; 246 1.1 hamajima DPRINTFN(1, ("vraiu_attach: reset AIU\n")) 247 1.1 hamajima bus_space_write_2(sc->sc_iot, sc->sc_ioh, SEQ_REG_W, AIURST); 248 1.1 hamajima /* attach audio subsystem */ 249 1.15 chs audio_attach_mi(&vraiu_hw_if, sc, self); 250 1.1 hamajima } 251 1.1 hamajima 252 1.1 hamajima int 253 1.17 isaki vraiu_query_format(void *self, audio_format_query_t *afp) 254 1.1 hamajima { 255 1.1 hamajima 256 1.17 isaki return audio_query_format(&vraiu_formats, 1, afp); 257 1.1 hamajima } 258 1.1 hamajima 259 1.1 hamajima int 260 1.17 isaki vraiu_set_format(void *self, int setmode, 261 1.17 isaki const audio_params_t *play, const audio_params_t *rec, 262 1.17 isaki audio_filter_reg_t *pfil, audio_filter_reg_t *rfil) 263 1.1 hamajima { 264 1.10 kent struct vraiu_softc *sc; 265 1.1 hamajima 266 1.17 isaki DPRINTFN(1, ("%s: %ubit, %uch, %uHz, encoding %u\n", __func__, 267 1.1 hamajima play->precision, play->channels, play->sample_rate, 268 1.1 hamajima play->encoding)); 269 1.10 kent sc = self; 270 1.17 isaki 271 1.1 hamajima switch (play->sample_rate) { 272 1.1 hamajima case 8000: 273 1.1 hamajima sc->sc_rate = SPS8000; 274 1.1 hamajima break; 275 1.1 hamajima case 11025: 276 1.1 hamajima sc->sc_rate = SPS11025; 277 1.1 hamajima break; 278 1.1 hamajima case 22050: 279 1.1 hamajima sc->sc_rate = SPS22050; 280 1.1 hamajima break; 281 1.1 hamajima case 44100: 282 1.1 hamajima sc->sc_rate = SPS44100; 283 1.1 hamajima break; 284 1.1 hamajima default: 285 1.17 isaki /* NOTREACHED */ 286 1.17 isaki panic("%s: rate error (%d)\n", __func__, play->sample_rate); 287 1.1 hamajima } 288 1.1 hamajima 289 1.1 hamajima return 0; 290 1.1 hamajima } 291 1.1 hamajima 292 1.1 hamajima int 293 1.9 kent vraiu_round_blocksize(void *self, int bs, int mode, const audio_params_t *param) 294 1.1 hamajima { 295 1.17 isaki return AUDIO_BUF_SIZE; 296 1.1 hamajima } 297 1.1 hamajima 298 1.1 hamajima int 299 1.1 hamajima vraiu_commit_settings(void *self) 300 1.1 hamajima { 301 1.10 kent struct vraiu_softc *sc; 302 1.1 hamajima int err; 303 1.1 hamajima 304 1.1 hamajima DPRINTFN(1, ("vraiu_commit_settings\n")); 305 1.10 kent sc = self; 306 1.1 hamajima 307 1.1 hamajima DPRINTFN(1, ("vraiu_commit_settings: set conversion rate %d\n", 308 1.1 hamajima sc->sc_rate)) 309 1.1 hamajima bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCNVR_REG_W, sc->sc_rate); 310 1.1 hamajima DPRINTFN(1, ("vraiu_commit_settings: clock supply start\n")) 311 1.1 hamajima if ((err = sc->sc_cc->cc_clock(sc->sc_cc, VR4102_CMUMSKAIU, 1))) { 312 1.1 hamajima DPRINTFN(0, ("vraiu_commit_settings: clock supply error\n")); 313 1.1 hamajima return err; 314 1.1 hamajima } 315 1.1 hamajima DPRINTFN(1, ("vraiu_commit_settings: enable DMA\n")) 316 1.1 hamajima if ((err = sc->sc_dc->dc_enable_aiuout(sc->sc_dc))) { 317 1.1 hamajima sc->sc_cc->cc_clock(sc->sc_cc, VR4102_CMUMSKAIU, 0); 318 1.5 wiz DPRINTFN(0, ("vraiu_commit_settings: enable DMA error\n")); 319 1.1 hamajima return err; 320 1.1 hamajima } 321 1.1 hamajima DPRINTFN(1, ("vraiu_commit_settings: Vref on\n")) 322 1.1 hamajima bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCNT_REG_W, DAENAIU); 323 1.1 hamajima return 0; 324 1.1 hamajima } 325 1.1 hamajima 326 1.1 hamajima int 327 1.1 hamajima vraiu_init_output(void *self, void *buffer, int size) 328 1.1 hamajima { 329 1.10 kent struct vraiu_softc *sc; 330 1.1 hamajima 331 1.1 hamajima DPRINTFN(1, ("vraiu_init_output: buffer %p, size %d\n", buffer, size)); 332 1.10 kent sc = self; 333 1.1 hamajima sc->sc_intr = NULL; 334 1.1 hamajima DPRINTFN(1, ("vraiu_init_output: speaker power on\n")) 335 1.1 hamajima config_hook_call(CONFIG_HOOK_POWERCONTROL, 336 1.1 hamajima CONFIG_HOOK_POWERCONTROL_SPEAKER, (void*)1); 337 1.1 hamajima DPRINTFN(1, ("vraiu_init_output: start output\n")) 338 1.1 hamajima bus_space_write_2(sc->sc_iot, sc->sc_ioh, SEQ_REG_W, AIUSEN); 339 1.1 hamajima return 0; 340 1.1 hamajima } 341 1.1 hamajima 342 1.1 hamajima int 343 1.1 hamajima vraiu_start_output(void *self, void *block, int bsize, 344 1.1 hamajima void (*intr)(void *), void *intrarg) 345 1.1 hamajima { 346 1.10 kent struct vraiu_softc *sc; 347 1.1 hamajima 348 1.1 hamajima DPRINTFN(2, ("vraiu_start_output: block %p, bsize %d\n", 349 1.1 hamajima block, bsize)); 350 1.10 kent sc = self; 351 1.17 isaki vraiu_slinear16_1(sc, sc->sc_buf, block, bsize); 352 1.1 hamajima bus_dmamap_sync(sc->sc_dmat, sc->sc_dmap, 0, AUDIO_BUF_SIZE, 353 1.1 hamajima BUS_DMASYNC_PREWRITE); 354 1.1 hamajima sc->sc_intr = intr; 355 1.1 hamajima sc->sc_intrdata = intrarg; 356 1.1 hamajima /* clear interrupt status */ 357 1.1 hamajima bus_space_write_2(sc->sc_iot, sc->sc_ioh, INT_REG_W, 358 1.1 hamajima SENDINTR | SINTR | SIDLEINTR); 359 1.1 hamajima /* enable interrupt */ 360 1.1 hamajima vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AIUINT_INTSEND, 1); 361 1.1 hamajima return 0; 362 1.1 hamajima } 363 1.1 hamajima 364 1.1 hamajima int 365 1.1 hamajima vraiu_intr(void* self) 366 1.1 hamajima { 367 1.10 kent struct vraiu_softc *sc; 368 1.10 kent uint32_t reg; 369 1.1 hamajima 370 1.1 hamajima DPRINTFN(2, ("vraiu_intr")); 371 1.10 kent sc = self; 372 1.13 jmcneill 373 1.13 jmcneill mutex_spin_enter(&sc->sc_intr_lock); 374 1.13 jmcneill 375 1.1 hamajima vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AIUINT_INTSEND, 0); 376 1.1 hamajima vrip_intr_getstatus2(sc->sc_vrip, sc->sc_handler, ®); 377 1.1 hamajima if (reg & AIUINT_INTSEND) { 378 1.1 hamajima DPRINTFN(2, (": AIUINT_INTSEND")); 379 1.1 hamajima if (sc->sc_intr) { 380 1.10 kent void (*intr)(void *); 381 1.10 kent intr = sc->sc_intr; 382 1.1 hamajima sc->sc_intr = NULL; 383 1.1 hamajima (*(intr))(sc->sc_intrdata); 384 1.1 hamajima } 385 1.1 hamajima bus_space_write_2(sc->sc_iot, sc->sc_ioh, INT_REG_W, SENDINTR); 386 1.1 hamajima } 387 1.1 hamajima DPRINTFN(2, ("\n")); 388 1.13 jmcneill 389 1.13 jmcneill mutex_spin_exit(&sc->sc_intr_lock); 390 1.13 jmcneill 391 1.1 hamajima return 0; 392 1.1 hamajima } 393 1.1 hamajima 394 1.1 hamajima int 395 1.1 hamajima vraiu_halt_output(void *self) 396 1.1 hamajima { 397 1.10 kent struct vraiu_softc *sc; 398 1.1 hamajima 399 1.1 hamajima DPRINTFN(1, ("vraiu_halt_output\n")); 400 1.10 kent sc =self; 401 1.1 hamajima DPRINTFN(1, ("vraiu_halt_output: disable interrupt\n")) 402 1.1 hamajima vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AIUINT_INTSEND, 0); 403 1.1 hamajima DPRINTFN(1, ("vraiu_halt_output: stop output\n")) 404 1.1 hamajima bus_space_write_2(sc->sc_iot, sc->sc_ioh, SEQ_REG_W, 0); 405 1.1 hamajima DPRINTFN(1, ("vraiu_halt_output: speaker power off\n")) 406 1.1 hamajima config_hook_call(CONFIG_HOOK_POWERCONTROL, 407 1.1 hamajima CONFIG_HOOK_POWERCONTROL_SPEAKER, (void*)0); 408 1.1 hamajima DPRINTFN(1, ("vraiu_halt_output: Vref off\n")) 409 1.1 hamajima bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCNT_REG_W, 0); 410 1.1 hamajima DPRINTFN(1, ("vraiu_halt_output: disable DMA\n")) 411 1.1 hamajima sc->sc_dc->dc_disable(sc->sc_dc); 412 1.1 hamajima DPRINTFN(1, ("vraiu_halt_output: clock supply stop\n")) 413 1.1 hamajima sc->sc_cc->cc_clock(sc->sc_cc, VR4102_CMUMSKAIU, 0); 414 1.1 hamajima sc->sc_intr = NULL; 415 1.1 hamajima return 0; 416 1.1 hamajima } 417 1.1 hamajima 418 1.1 hamajima int 419 1.1 hamajima vraiu_getdev(void *self, struct audio_device *ret) 420 1.1 hamajima { 421 1.10 kent 422 1.1 hamajima DPRINTFN(3, ("vraiu_getdev\n")); 423 1.1 hamajima *ret = aiu_device; 424 1.1 hamajima return 0; 425 1.1 hamajima } 426 1.1 hamajima 427 1.1 hamajima int 428 1.1 hamajima vraiu_set_port(void *self, mixer_ctrl_t *mc) 429 1.1 hamajima { 430 1.10 kent struct vraiu_softc *sc; 431 1.10 kent 432 1.1 hamajima DPRINTFN(3, ("vraiu_set_port\n")); 433 1.10 kent sc = self; 434 1.7 jmcneill /* software mixer, 1ch */ 435 1.7 jmcneill if (mc->dev == 0) { 436 1.7 jmcneill if (mc->type != AUDIO_MIXER_VALUE) 437 1.7 jmcneill return EINVAL; 438 1.7 jmcneill if (mc->un.value.num_channels != 1) 439 1.7 jmcneill return EINVAL; 440 1.7 jmcneill sc->sc_volume = mc->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 441 1.7 jmcneill return 0; 442 1.7 jmcneill } 443 1.7 jmcneill 444 1.1 hamajima return EINVAL; 445 1.1 hamajima } 446 1.1 hamajima 447 1.1 hamajima int 448 1.1 hamajima vraiu_get_port(void *self, mixer_ctrl_t *mc) 449 1.1 hamajima { 450 1.10 kent struct vraiu_softc *sc; 451 1.10 kent 452 1.1 hamajima DPRINTFN(3, ("vraiu_get_port\n")); 453 1.10 kent sc = self; 454 1.7 jmcneill /* software mixer, 1ch */ 455 1.7 jmcneill if (mc->dev == 0) { 456 1.7 jmcneill if (mc->un.value.num_channels != 1) 457 1.7 jmcneill return EINVAL; 458 1.7 jmcneill mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_volume; 459 1.7 jmcneill return 0; 460 1.7 jmcneill } 461 1.10 kent 462 1.1 hamajima return EINVAL; 463 1.1 hamajima } 464 1.1 hamajima 465 1.1 hamajima int 466 1.1 hamajima vraiu_query_devinfo(void *self, mixer_devinfo_t *di) 467 1.1 hamajima { 468 1.10 kent 469 1.1 hamajima DPRINTFN(3, ("vraiu_query_devinfo\n")); 470 1.7 jmcneill /* software mixer, 1ch */ 471 1.7 jmcneill switch (di->index) { 472 1.7 jmcneill case 0: /* inputs.dac mixer value */ 473 1.7 jmcneill di->mixer_class = 1; 474 1.7 jmcneill di->next = di->prev = AUDIO_MIXER_LAST; 475 1.7 jmcneill strcpy(di->label.name, AudioNdac); 476 1.7 jmcneill di->type = AUDIO_MIXER_VALUE; 477 1.7 jmcneill di->un.v.num_channels = 1; 478 1.7 jmcneill strcpy(di->un.v.units.name, AudioNvolume); 479 1.7 jmcneill return 0; 480 1.7 jmcneill case 1: /* outputs class */ 481 1.7 jmcneill di->mixer_class = 1; 482 1.7 jmcneill di->next = di->prev = AUDIO_MIXER_LAST; 483 1.7 jmcneill strcpy(di->label.name, AudioCinputs); 484 1.7 jmcneill di->type = AUDIO_MIXER_CLASS; 485 1.7 jmcneill return 0; 486 1.7 jmcneill } 487 1.7 jmcneill 488 1.1 hamajima return ENXIO; 489 1.1 hamajima } 490 1.1 hamajima 491 1.1 hamajima int 492 1.1 hamajima vraiu_get_props(void *self) 493 1.1 hamajima { 494 1.1 hamajima DPRINTFN(3, ("vraiu_get_props\n")); 495 1.1 hamajima 496 1.20 skrll return AUDIO_PROP_PLAYBACK; 497 1.1 hamajima } 498 1.1 hamajima 499 1.13 jmcneill void 500 1.13 jmcneill vraiu_get_locks(void *self, kmutex_t **intr, kmutex_t **thread) 501 1.13 jmcneill { 502 1.13 jmcneill struct vraiu_softc *sc; 503 1.13 jmcneill 504 1.13 jmcneill DPRINTFN(3, ("vraiu_get_locks\n")); 505 1.13 jmcneill sc = self; 506 1.13 jmcneill 507 1.13 jmcneill *intr = &sc->sc_intr_lock; 508 1.13 jmcneill *thread = &sc->sc_lock; 509 1.13 jmcneill } 510 1.13 jmcneill 511 1.17 isaki /* slinear16/mono -> ulinear10/mono with volume */ 512 1.1 hamajima static void 513 1.1 hamajima vraiu_slinear16_1(struct vraiu_softc *sc, u_short *dmap, void *p, int n) 514 1.1 hamajima { 515 1.10 kent short *q; 516 1.1 hamajima 517 1.1 hamajima DPRINTFN(3, ("vraiu_slinear16_1\n")); 518 1.10 kent q = p; 519 1.1 hamajima #ifdef DIAGNOSTIC 520 1.1 hamajima if (n > AUDIO_BUF_SIZE) { 521 1.1 hamajima printf("%s: output data too large (%d > %d)\n", 522 1.15 chs device_xname(sc->sc_dev), n, AUDIO_BUF_SIZE); 523 1.1 hamajima n = AUDIO_BUF_SIZE; 524 1.1 hamajima } 525 1.1 hamajima #endif 526 1.1 hamajima n /= 2; 527 1.1 hamajima while (n--) { 528 1.17 isaki int i = *q++; 529 1.17 isaki i = i * sc->sc_volume / 255; 530 1.1 hamajima *dmap++ = (i >> 6) + 0x200; 531 1.1 hamajima } 532 1.1 hamajima } 533