1 1.26 isaki /* $NetBSD: haltwo.c,v 1.26 2019/05/25 04:41:53 isaki Exp $ */ 2 1.1 lonewolf 3 1.1 lonewolf /* 4 1.1 lonewolf * Copyright (c) 2003 Ilpo Ruotsalainen 5 1.1 lonewolf * All rights reserved. 6 1.1 lonewolf * 7 1.1 lonewolf * Redistribution and use in source and binary forms, with or without 8 1.1 lonewolf * modification, are permitted provided that the following conditions 9 1.1 lonewolf * are met: 10 1.1 lonewolf * 1. Redistributions of source code must retain the above copyright 11 1.1 lonewolf * notice, this list of conditions and the following disclaimer. 12 1.1 lonewolf * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 lonewolf * notice, this list of conditions and the following disclaimer in the 14 1.1 lonewolf * documentation and/or other materials provided with the distribution. 15 1.1 lonewolf * 3. The name of the author may not be used to endorse or promote products 16 1.1 lonewolf * derived from this software without specific prior written permission. 17 1.1 lonewolf * 18 1.1 lonewolf * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 1.1 lonewolf * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 1.1 lonewolf * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 1.1 lonewolf * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 1.1 lonewolf * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 1.1 lonewolf * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 1.1 lonewolf * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 1.1 lonewolf * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 1.1 lonewolf * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 1.1 lonewolf * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 1.1 lonewolf * 29 1.1 lonewolf * <<Id: LICENSE_GC,v 1.1 2001/10/01 23:24:05 cgd Exp>> 30 1.1 lonewolf */ 31 1.1 lonewolf 32 1.1 lonewolf #include <sys/cdefs.h> 33 1.26 isaki __KERNEL_RCSID(0, "$NetBSD: haltwo.c,v 1.26 2019/05/25 04:41:53 isaki Exp $"); 34 1.1 lonewolf 35 1.1 lonewolf #include <sys/param.h> 36 1.1 lonewolf #include <sys/systm.h> 37 1.1 lonewolf #include <sys/device.h> 38 1.1 lonewolf #include <sys/audioio.h> 39 1.21 jmcneill #include <sys/kmem.h> 40 1.20 dyoung #include <sys/bus.h> 41 1.11 rumble #include <machine/sysconf.h> 42 1.1 lonewolf 43 1.25 isaki #include <dev/audio/audio_if.h> 44 1.25 isaki 45 1.1 lonewolf #include <sgimips/hpc/hpcvar.h> 46 1.1 lonewolf #include <sgimips/hpc/hpcreg.h> 47 1.1 lonewolf 48 1.1 lonewolf #include <sgimips/hpc/haltworeg.h> 49 1.1 lonewolf #include <sgimips/hpc/haltwovar.h> 50 1.1 lonewolf 51 1.1 lonewolf #ifdef AUDIO_DEBUG 52 1.1 lonewolf #define DPRINTF(x) printf x 53 1.1 lonewolf #else 54 1.1 lonewolf #define DPRINTF(x) 55 1.1 lonewolf #endif 56 1.1 lonewolf 57 1.25 isaki static int haltwo_query_format(void *, audio_format_query_t *); 58 1.25 isaki static int haltwo_set_format(void *, int, 59 1.25 isaki const audio_params_t *, const audio_params_t *, 60 1.25 isaki audio_filter_reg_t *, audio_filter_reg_t *); 61 1.6 kent static int haltwo_round_blocksize(void *, int, int, const audio_params_t *); 62 1.1 lonewolf static int haltwo_halt_output(void *); 63 1.1 lonewolf static int haltwo_halt_input(void *); 64 1.1 lonewolf static int haltwo_getdev(void *, struct audio_device *); 65 1.1 lonewolf static int haltwo_set_port(void *, mixer_ctrl_t *); 66 1.1 lonewolf static int haltwo_get_port(void *, mixer_ctrl_t *); 67 1.1 lonewolf static int haltwo_query_devinfo(void *, mixer_devinfo_t *); 68 1.21 jmcneill static void *haltwo_malloc(void *, int, size_t); 69 1.21 jmcneill static void haltwo_free(void *, void *, size_t); 70 1.1 lonewolf static int haltwo_get_props(void *); 71 1.1 lonewolf static int haltwo_trigger_output(void *, void *, void *, int, void (*)(void *), 72 1.6 kent void *, const audio_params_t *); 73 1.1 lonewolf static int haltwo_trigger_input(void *, void *, void *, int, void (*)(void *), 74 1.6 kent void *, const audio_params_t *); 75 1.21 jmcneill static void haltwo_get_locks(void *, kmutex_t **, kmutex_t **); 76 1.17 tsutsui static bool haltwo_shutdown(device_t, int); 77 1.1 lonewolf 78 1.4 yamt static const struct audio_hw_if haltwo_hw_if = { 79 1.25 isaki .query_format = haltwo_query_format, 80 1.25 isaki .set_format = haltwo_set_format, 81 1.24 isaki .round_blocksize = haltwo_round_blocksize, 82 1.24 isaki .halt_output = haltwo_halt_output, 83 1.24 isaki .halt_input = haltwo_halt_input, 84 1.24 isaki .getdev = haltwo_getdev, 85 1.24 isaki .set_port = haltwo_set_port, 86 1.24 isaki .get_port = haltwo_get_port, 87 1.24 isaki .query_devinfo = haltwo_query_devinfo, 88 1.24 isaki .allocm = haltwo_malloc, 89 1.24 isaki .freem = haltwo_free, 90 1.24 isaki .get_props = haltwo_get_props, 91 1.24 isaki .trigger_output = haltwo_trigger_output, 92 1.24 isaki .trigger_input = haltwo_trigger_input, 93 1.24 isaki .get_locks = haltwo_get_locks, 94 1.1 lonewolf }; 95 1.1 lonewolf 96 1.1 lonewolf static const struct audio_device haltwo_device = { 97 1.2 tsutsui "HAL2", 98 1.2 tsutsui "", 99 1.2 tsutsui "haltwo" 100 1.1 lonewolf }; 101 1.1 lonewolf 102 1.25 isaki static const struct audio_format haltwo_formats = { 103 1.25 isaki .mode = AUMODE_PLAY, 104 1.25 isaki .encoding = AUDIO_ENCODING_SLINEAR_NE, 105 1.25 isaki .validbits = 16, 106 1.25 isaki .precision = 16, 107 1.25 isaki .channels = 2, 108 1.25 isaki .channel_mask = AUFMT_STEREO, 109 1.25 isaki .frequency_type = 2, 110 1.25 isaki .frequency = { 44100, 48000 }, 111 1.25 isaki }; 112 1.25 isaki #define HALTWO_NFORMATS __arraycount(haltwo_formats) 113 1.25 isaki 114 1.19 tsutsui static int haltwo_match(device_t, cfdata_t, void *); 115 1.19 tsutsui static void haltwo_attach(device_t, device_t, void *); 116 1.1 lonewolf static int haltwo_intr(void *); 117 1.1 lonewolf 118 1.19 tsutsui CFATTACH_DECL_NEW(haltwo, sizeof(struct haltwo_softc), 119 1.1 lonewolf haltwo_match, haltwo_attach, NULL, NULL); 120 1.1 lonewolf 121 1.1 lonewolf #define haltwo_write(sc,type,off,val) \ 122 1.1 lonewolf bus_space_write_4(sc->sc_st, sc->sc_##type##_sh, off, val) 123 1.1 lonewolf 124 1.1 lonewolf #define haltwo_read(sc,type,off) \ 125 1.1 lonewolf bus_space_read_4(sc->sc_st, sc->sc_##type##_sh, off) 126 1.1 lonewolf 127 1.1 lonewolf static void 128 1.1 lonewolf haltwo_write_indirect(struct haltwo_softc *sc, uint32_t ireg, uint16_t low, 129 1.1 lonewolf uint16_t high) 130 1.1 lonewolf { 131 1.2 tsutsui 132 1.1 lonewolf haltwo_write(sc, ctl, HAL2_REG_CTL_IDR0, low); 133 1.1 lonewolf haltwo_write(sc, ctl, HAL2_REG_CTL_IDR1, high); 134 1.1 lonewolf haltwo_write(sc, ctl, HAL2_REG_CTL_IDR2, 0); 135 1.1 lonewolf haltwo_write(sc, ctl, HAL2_REG_CTL_IDR3, 0); 136 1.1 lonewolf haltwo_write(sc, ctl, HAL2_REG_CTL_IAR, ireg); 137 1.1 lonewolf 138 1.1 lonewolf while (haltwo_read(sc, ctl, HAL2_REG_CTL_ISR) & HAL2_ISR_TSTATUS) 139 1.7 kent continue; 140 1.1 lonewolf } 141 1.1 lonewolf 142 1.1 lonewolf static void 143 1.1 lonewolf haltwo_read_indirect(struct haltwo_softc *sc, uint32_t ireg, uint16_t *low, 144 1.1 lonewolf uint16_t *high) 145 1.1 lonewolf { 146 1.2 tsutsui 147 1.1 lonewolf haltwo_write(sc, ctl, HAL2_REG_CTL_IAR, 148 1.1 lonewolf ireg | HAL2_IAR_READ); 149 1.1 lonewolf 150 1.1 lonewolf while (haltwo_read(sc, ctl, HAL2_REG_CTL_ISR) & HAL2_ISR_TSTATUS) 151 1.7 kent continue; 152 1.1 lonewolf 153 1.1 lonewolf if (low) 154 1.1 lonewolf *low = haltwo_read(sc, ctl, HAL2_REG_CTL_IDR0); 155 1.2 tsutsui 156 1.1 lonewolf if (high) 157 1.1 lonewolf *high = haltwo_read(sc, ctl, HAL2_REG_CTL_IDR1); 158 1.1 lonewolf } 159 1.1 lonewolf 160 1.1 lonewolf static int 161 1.1 lonewolf haltwo_init_codec(struct haltwo_softc *sc, struct haltwo_codec *codec) 162 1.1 lonewolf { 163 1.1 lonewolf int err; 164 1.1 lonewolf int rseg; 165 1.7 kent size_t allocsz; 166 1.1 lonewolf 167 1.7 kent allocsz = sizeof(struct hpc_dma_desc) * HALTWO_MAX_DMASEGS; 168 1.1 lonewolf KASSERT(allocsz <= PAGE_SIZE); 169 1.1 lonewolf 170 1.1 lonewolf err = bus_dmamem_alloc(sc->sc_dma_tag, allocsz, 0, 0, &codec->dma_seg, 171 1.1 lonewolf 1, &rseg, BUS_DMA_NOWAIT); 172 1.1 lonewolf if (err) 173 1.1 lonewolf goto out; 174 1.1 lonewolf 175 1.1 lonewolf err = bus_dmamem_map(sc->sc_dma_tag, &codec->dma_seg, rseg, allocsz, 176 1.12 christos (void **)&codec->dma_descs, BUS_DMA_NOWAIT); 177 1.1 lonewolf if (err) 178 1.1 lonewolf goto out_free; 179 1.1 lonewolf 180 1.1 lonewolf err = bus_dmamap_create(sc->sc_dma_tag, allocsz, 1, PAGE_SIZE, 0, 181 1.1 lonewolf BUS_DMA_NOWAIT, &codec->dma_map); 182 1.1 lonewolf if (err) 183 1.1 lonewolf goto out_free; 184 1.1 lonewolf 185 1.1 lonewolf err = bus_dmamap_load(sc->sc_dma_tag, codec->dma_map, codec->dma_descs, 186 1.1 lonewolf allocsz, NULL, BUS_DMA_NOWAIT); 187 1.1 lonewolf if (err) 188 1.1 lonewolf goto out_destroy; 189 1.1 lonewolf 190 1.1 lonewolf DPRINTF(("haltwo_init_codec: allocated %d descriptors (%d bytes)" 191 1.1 lonewolf " at %p\n", HALTWO_MAX_DMASEGS, allocsz, codec->dma_descs)); 192 1.1 lonewolf 193 1.1 lonewolf memset(codec->dma_descs, 0, allocsz); 194 1.1 lonewolf 195 1.7 kent return 0; 196 1.1 lonewolf 197 1.1 lonewolf out_destroy: 198 1.1 lonewolf bus_dmamap_destroy(sc->sc_dma_tag, codec->dma_map); 199 1.1 lonewolf out_free: 200 1.1 lonewolf bus_dmamem_free(sc->sc_dma_tag, &codec->dma_seg, rseg); 201 1.1 lonewolf out: 202 1.1 lonewolf DPRINTF(("haltwo_init_codec failed: %d\n",err)); 203 1.1 lonewolf 204 1.7 kent return err; 205 1.1 lonewolf } 206 1.1 lonewolf 207 1.1 lonewolf static void 208 1.1 lonewolf haltwo_setup_dma(struct haltwo_softc *sc, struct haltwo_codec *codec, 209 1.1 lonewolf struct haltwo_dmabuf *dmabuf, size_t len, int blksize, 210 1.1 lonewolf void (*intr)(void *), void *intrarg) 211 1.1 lonewolf { 212 1.1 lonewolf int i; 213 1.1 lonewolf bus_dma_segment_t *segp; 214 1.1 lonewolf struct hpc_dma_desc *descp; 215 1.7 kent int next_intr; 216 1.2 tsutsui 217 1.1 lonewolf KASSERT(len % blksize == 0); 218 1.1 lonewolf 219 1.7 kent next_intr = blksize; 220 1.1 lonewolf codec->intr = intr; 221 1.1 lonewolf codec->intr_arg = intrarg; 222 1.1 lonewolf 223 1.1 lonewolf segp = dmabuf->dma_map->dm_segs; 224 1.1 lonewolf descp = codec->dma_descs; 225 1.1 lonewolf 226 1.1 lonewolf /* Build descriptor chain for looping DMA, triggering interrupt every 227 1.1 lonewolf * blksize bytes */ 228 1.1 lonewolf for (i = 0; i < dmabuf->dma_map->dm_nsegs; i++) { 229 1.3 sekiya descp->hpc3_hdd_bufptr = segp->ds_addr; 230 1.3 sekiya descp->hpc3_hdd_ctl = segp->ds_len; 231 1.1 lonewolf 232 1.1 lonewolf KASSERT(next_intr >= segp->ds_len); 233 1.1 lonewolf 234 1.1 lonewolf if (next_intr == segp->ds_len) { 235 1.1 lonewolf /* Generate intr after this DMA buffer */ 236 1.5 rumble descp->hpc3_hdd_ctl |= HPC3_HDD_CTL_INTR; 237 1.1 lonewolf next_intr = blksize; 238 1.2 tsutsui } else 239 1.1 lonewolf next_intr -= segp->ds_len; 240 1.1 lonewolf 241 1.1 lonewolf if (i < dmabuf->dma_map->dm_nsegs - 1) 242 1.1 lonewolf descp->hdd_descptr = codec->dma_seg.ds_addr + 243 1.1 lonewolf sizeof(struct hpc_dma_desc) * (i + 1); 244 1.1 lonewolf else 245 1.1 lonewolf descp->hdd_descptr = codec->dma_seg.ds_addr; 246 1.1 lonewolf 247 1.1 lonewolf DPRINTF(("haltwo_setup_dma: hdd_bufptr = %x hdd_ctl = %x" 248 1.3 sekiya " hdd_descptr = %x\n", descp->hpc3_hdd_bufptr, 249 1.3 sekiya descp->hpc3_hdd_ctl, descp->hdd_descptr)); 250 1.1 lonewolf 251 1.1 lonewolf segp++; 252 1.1 lonewolf descp++; 253 1.1 lonewolf } 254 1.1 lonewolf 255 1.1 lonewolf bus_dmamap_sync(sc->sc_dma_tag, codec->dma_map, 0, 256 1.1 lonewolf codec->dma_map->dm_mapsize, BUS_DMASYNC_PREWRITE); 257 1.1 lonewolf } 258 1.1 lonewolf 259 1.1 lonewolf static int 260 1.19 tsutsui haltwo_match(device_t parent, cfdata_t cf, void *aux) 261 1.1 lonewolf { 262 1.7 kent struct hpc_attach_args *haa; 263 1.10 rumble uint32_t rev; 264 1.1 lonewolf 265 1.7 kent haa = aux; 266 1.8 sekiya if (strcmp(haa->ha_name, cf->cf_name)) 267 1.8 sekiya return 0; 268 1.10 rumble 269 1.13 he if ( platform.badaddr((void *)(vaddr_t)(haa->ha_sh + haa->ha_devoff), 270 1.18 tsutsui sizeof(uint32_t)) ) 271 1.8 sekiya return 0; 272 1.1 lonewolf 273 1.11 rumble if ( platform.badaddr( 274 1.13 he (void *)(vaddr_t)(haa->ha_sh + haa->ha_devoff + HAL2_REG_CTL_REV), 275 1.18 tsutsui sizeof(uint32_t)) ) 276 1.10 rumble return 0; 277 1.10 rumble 278 1.10 rumble rev = *(uint32_t *)MIPS_PHYS_TO_KSEG1(haa->ha_sh + haa->ha_devoff + 279 1.10 rumble HAL2_REG_CTL_REV); 280 1.10 rumble 281 1.10 rumble /* This bit is inverted, the test is correct */ 282 1.10 rumble if (rev & HAL2_REV_AUDIO_PRESENT_N) 283 1.10 rumble return 0; 284 1.10 rumble 285 1.8 sekiya return 1; 286 1.1 lonewolf } 287 1.1 lonewolf 288 1.1 lonewolf static void 289 1.19 tsutsui haltwo_attach(device_t parent, device_t self, void *aux) 290 1.1 lonewolf { 291 1.7 kent struct haltwo_softc *sc; 292 1.7 kent struct hpc_attach_args *haa; 293 1.1 lonewolf uint32_t rev; 294 1.2 tsutsui 295 1.19 tsutsui sc = device_private(self); 296 1.7 kent haa = aux; 297 1.19 tsutsui sc->sc_dev = self; 298 1.1 lonewolf sc->sc_st = haa->ha_st; 299 1.1 lonewolf sc->sc_dma_tag = haa->ha_dmat; 300 1.1 lonewolf 301 1.21 jmcneill mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); 302 1.22 mrg mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO); 303 1.21 jmcneill 304 1.1 lonewolf if (bus_space_subregion(haa->ha_st, haa->ha_sh, haa->ha_devoff, 305 1.5 rumble HPC3_PBUS_CH0_DEVREGS_SIZE, &sc->sc_ctl_sh)) { 306 1.1 lonewolf aprint_error(": unable to map control registers\n"); 307 1.1 lonewolf return; 308 1.1 lonewolf } 309 1.1 lonewolf 310 1.5 rumble if (bus_space_subregion(haa->ha_st, haa->ha_sh, HPC3_PBUS_CH2_DEVREGS, 311 1.5 rumble HPC3_PBUS_CH2_DEVREGS_SIZE, &sc->sc_vol_sh)) { 312 1.1 lonewolf aprint_error(": unable to map volume registers\n"); 313 1.1 lonewolf return; 314 1.1 lonewolf } 315 1.1 lonewolf 316 1.1 lonewolf if (bus_space_subregion(haa->ha_st, haa->ha_sh, haa->ha_dmaoff, 317 1.5 rumble HPC3_PBUS_DMAREGS_SIZE, &sc->sc_dma_sh)) { 318 1.1 lonewolf aprint_error(": unable to map DMA registers\n"); 319 1.1 lonewolf return; 320 1.1 lonewolf } 321 1.1 lonewolf 322 1.1 lonewolf haltwo_write(sc, ctl, HAL2_REG_CTL_ISR, 0); 323 1.1 lonewolf haltwo_write(sc, ctl, HAL2_REG_CTL_ISR, 324 1.1 lonewolf HAL2_ISR_GLOBAL_RESET_N | HAL2_ISR_CODEC_RESET_N); 325 1.1 lonewolf haltwo_write_indirect(sc, HAL2_IREG_RELAY_C, HAL2_RELAY_C_STATE, 0); 326 1.1 lonewolf 327 1.1 lonewolf rev = haltwo_read(sc, ctl, HAL2_REG_CTL_REV); 328 1.1 lonewolf 329 1.22 mrg if (cpu_intr_establish(haa->ha_irq, IPL_AUDIO, haltwo_intr, sc) 330 1.1 lonewolf == NULL) { 331 1.1 lonewolf aprint_error(": unable to establish interrupt\n"); 332 1.1 lonewolf return; 333 1.1 lonewolf } 334 1.1 lonewolf 335 1.1 lonewolf aprint_naive(": Audio controller\n"); 336 1.1 lonewolf 337 1.1 lonewolf aprint_normal(": HAL2 revision %d.%d.%d\n", (rev & 0x7000) >> 12, 338 1.1 lonewolf (rev & 0x00F0) >> 4, rev & 0x000F); 339 1.1 lonewolf 340 1.1 lonewolf if (haltwo_init_codec(sc, &sc->sc_dac)) { 341 1.1 lonewolf aprint_error( 342 1.1 lonewolf "haltwo_attach: unable to create DMA descriptor list\n"); 343 1.1 lonewolf return; 344 1.1 lonewolf } 345 1.1 lonewolf 346 1.1 lonewolf /* XXX Magic PBUS CFGDMA values from Linux HAL2 driver XXX */ 347 1.5 rumble bus_space_write_4(haa->ha_st, haa->ha_sh, HPC3_PBUS_CH0_CFGDMA, 348 1.1 lonewolf 0x8208844); 349 1.5 rumble bus_space_write_4(haa->ha_st, haa->ha_sh, HPC3_PBUS_CH1_CFGDMA, 350 1.1 lonewolf 0x8208844); 351 1.1 lonewolf 352 1.1 lonewolf /* Unmute output */ 353 1.1 lonewolf /* XXX Add mute/unmute support to mixer ops? XXX */ 354 1.1 lonewolf haltwo_write_indirect(sc, HAL2_IREG_DAC_C2, 0, 0); 355 1.1 lonewolf 356 1.1 lonewolf /* Set master volume to zero */ 357 1.1 lonewolf sc->sc_vol_left = sc->sc_vol_right = 0; 358 1.1 lonewolf haltwo_write(sc, vol, HAL2_REG_VOL_LEFT, sc->sc_vol_left); 359 1.1 lonewolf haltwo_write(sc, vol, HAL2_REG_VOL_RIGHT, sc->sc_vol_right); 360 1.1 lonewolf 361 1.19 tsutsui audio_attach_mi(&haltwo_hw_if, sc, self); 362 1.15 tsutsui 363 1.17 tsutsui if (!pmf_device_register1(self, NULL, NULL, haltwo_shutdown)) 364 1.15 tsutsui aprint_error_dev(self, 365 1.17 tsutsui "couldn't establish power handler\n"); 366 1.1 lonewolf } 367 1.1 lonewolf 368 1.1 lonewolf static int 369 1.1 lonewolf haltwo_intr(void *v) 370 1.1 lonewolf { 371 1.7 kent struct haltwo_softc *sc; 372 1.7 kent int ret; 373 1.1 lonewolf 374 1.7 kent sc = v; 375 1.7 kent ret = 0; 376 1.21 jmcneill 377 1.21 jmcneill mutex_spin_enter(&sc->sc_intr_lock); 378 1.21 jmcneill 379 1.5 rumble if (bus_space_read_4(sc->sc_st, sc->sc_dma_sh, HPC3_PBUS_CH0_CTL) 380 1.5 rumble & HPC3_PBUS_DMACTL_IRQ) { 381 1.2 tsutsui sc->sc_dac.intr(sc->sc_dac.intr_arg); 382 1.1 lonewolf 383 1.2 tsutsui ret = 1; 384 1.2 tsutsui } else 385 1.2 tsutsui DPRINTF(("haltwo_intr: Huh?\n")); 386 1.1 lonewolf 387 1.21 jmcneill mutex_spin_exit(&sc->sc_intr_lock); 388 1.21 jmcneill 389 1.7 kent return ret; 390 1.1 lonewolf } 391 1.1 lonewolf 392 1.1 lonewolf static int 393 1.25 isaki haltwo_query_format(void *v, audio_format_query_t *afp) 394 1.1 lonewolf { 395 1.2 tsutsui 396 1.25 isaki return audio_query_format(&haltwo_formats, 1, afp); 397 1.1 lonewolf } 398 1.1 lonewolf 399 1.1 lonewolf static int 400 1.25 isaki haltwo_set_format(void *v, int setmode, 401 1.25 isaki const audio_params_t *play, const audio_params_t *rec, 402 1.25 isaki audio_filter_reg_t *pfil, audio_filter_reg_t *rfil) 403 1.1 lonewolf { 404 1.7 kent struct haltwo_softc *sc; 405 1.25 isaki int inc; 406 1.1 lonewolf uint16_t tmp; 407 1.1 lonewolf 408 1.7 kent sc = v; 409 1.6 kent inc = 4; 410 1.1 lonewolf 411 1.1 lonewolf /* Setup samplerate to HW */ 412 1.1 lonewolf haltwo_write_indirect(sc, HAL2_IREG_BRES1_C1, 413 1.25 isaki play->sample_rate == 44100 ? 1 : 0, 0); 414 1.1 lonewolf /* XXX Documentation disagrees but this seems to work XXX */ 415 1.25 isaki haltwo_write_indirect(sc, HAL2_IREG_BRES1_C2, inc, 0xFFFF); 416 1.1 lonewolf 417 1.1 lonewolf /* Setup endianness to HW */ 418 1.1 lonewolf haltwo_read_indirect(sc, HAL2_IREG_DMA_END, &tmp, NULL); 419 1.6 kent if (play->encoding == AUDIO_ENCODING_SLINEAR_LE) 420 1.1 lonewolf tmp |= HAL2_DMA_END_CODECTX; 421 1.1 lonewolf else 422 1.1 lonewolf tmp &= ~HAL2_DMA_END_CODECTX; 423 1.1 lonewolf haltwo_write_indirect(sc, HAL2_IREG_DMA_END, tmp, 0); 424 1.1 lonewolf 425 1.1 lonewolf /* Set PBUS channel, Bresenham clock source, number of channels to HW */ 426 1.1 lonewolf haltwo_write_indirect(sc, HAL2_IREG_DAC_C1, 427 1.1 lonewolf (0 << HAL2_C1_DMA_SHIFT) | 428 1.1 lonewolf (1 << HAL2_C1_CLKID_SHIFT) | 429 1.6 kent (play->channels << HAL2_C1_DATAT_SHIFT), 0); 430 1.1 lonewolf 431 1.25 isaki DPRINTF(("%s: hw_encoding = %d hw_channels = %d\n", __func__, 432 1.6 kent play->encoding, play->channels)); 433 1.1 lonewolf 434 1.7 kent return 0; 435 1.1 lonewolf } 436 1.1 lonewolf 437 1.1 lonewolf static int 438 1.6 kent haltwo_round_blocksize(void *v, int blocksize, 439 1.6 kent int mode, const audio_params_t *param) 440 1.1 lonewolf { 441 1.2 tsutsui 442 1.1 lonewolf /* XXX Make this smarter and support DMA descriptor chaining XXX */ 443 1.1 lonewolf /* XXX Rounding to nearest PAGE_SIZE might work? XXX */ 444 1.1 lonewolf return PAGE_SIZE; 445 1.1 lonewolf } 446 1.1 lonewolf 447 1.1 lonewolf static int 448 1.1 lonewolf haltwo_halt_output(void *v) 449 1.1 lonewolf { 450 1.7 kent struct haltwo_softc *sc; 451 1.1 lonewolf 452 1.7 kent sc = v; 453 1.1 lonewolf /* Disable PBUS DMA */ 454 1.5 rumble bus_space_write_4(sc->sc_st, sc->sc_dma_sh, HPC3_PBUS_CH0_CTL, 455 1.5 rumble HPC3_PBUS_DMACTL_ACT_LD); 456 1.1 lonewolf 457 1.7 kent return 0; 458 1.1 lonewolf } 459 1.1 lonewolf 460 1.1 lonewolf static int 461 1.1 lonewolf haltwo_halt_input(void *v) 462 1.1 lonewolf { 463 1.2 tsutsui 464 1.7 kent return ENXIO; 465 1.1 lonewolf } 466 1.1 lonewolf 467 1.1 lonewolf static int 468 1.1 lonewolf haltwo_getdev(void *v, struct audio_device *dev) 469 1.1 lonewolf { 470 1.2 tsutsui 471 1.1 lonewolf *dev = haltwo_device; 472 1.7 kent return 0; 473 1.1 lonewolf } 474 1.1 lonewolf 475 1.1 lonewolf static int 476 1.1 lonewolf haltwo_set_port(void *v, mixer_ctrl_t *mc) 477 1.1 lonewolf { 478 1.7 kent struct haltwo_softc *sc; 479 1.1 lonewolf int lval, rval; 480 1.2 tsutsui 481 1.1 lonewolf if (mc->type != AUDIO_MIXER_VALUE) 482 1.7 kent return EINVAL; 483 1.1 lonewolf 484 1.1 lonewolf if (mc->un.value.num_channels == 1) 485 1.1 lonewolf lval = rval = mc->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 486 1.1 lonewolf else if (mc->un.value.num_channels == 2) { 487 1.1 lonewolf lval = mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 488 1.1 lonewolf rval = mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 489 1.1 lonewolf } else 490 1.7 kent return EINVAL; 491 1.1 lonewolf 492 1.7 kent sc = v; 493 1.1 lonewolf switch (mc->dev) { 494 1.1 lonewolf case HALTWO_MASTER_VOL: 495 1.1 lonewolf sc->sc_vol_left = lval; 496 1.1 lonewolf sc->sc_vol_right = rval; 497 1.1 lonewolf 498 1.1 lonewolf haltwo_write(sc, vol, HAL2_REG_VOL_LEFT, 499 1.1 lonewolf sc->sc_vol_left); 500 1.1 lonewolf haltwo_write(sc, vol, HAL2_REG_VOL_RIGHT, 501 1.1 lonewolf sc->sc_vol_right); 502 1.1 lonewolf break; 503 1.1 lonewolf 504 1.1 lonewolf default: 505 1.7 kent return EINVAL; 506 1.1 lonewolf } 507 1.1 lonewolf 508 1.7 kent return 0; 509 1.1 lonewolf } 510 1.1 lonewolf 511 1.1 lonewolf static int 512 1.1 lonewolf haltwo_get_port(void *v, mixer_ctrl_t *mc) 513 1.1 lonewolf { 514 1.7 kent struct haltwo_softc *sc; 515 1.1 lonewolf int l, r; 516 1.2 tsutsui 517 1.1 lonewolf switch (mc->dev) { 518 1.1 lonewolf case HALTWO_MASTER_VOL: 519 1.7 kent sc = v; 520 1.1 lonewolf l = sc->sc_vol_left; 521 1.1 lonewolf r = sc->sc_vol_right; 522 1.1 lonewolf break; 523 1.1 lonewolf 524 1.1 lonewolf default: 525 1.7 kent return EINVAL; 526 1.1 lonewolf } 527 1.1 lonewolf 528 1.1 lonewolf if (mc->un.value.num_channels == 1) 529 1.1 lonewolf mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] = (l+r) / 2; 530 1.1 lonewolf else if (mc->un.value.num_channels == 2) { 531 1.1 lonewolf mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l; 532 1.1 lonewolf mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r; 533 1.1 lonewolf } else 534 1.7 kent return EINVAL; 535 1.1 lonewolf 536 1.7 kent return 0; 537 1.1 lonewolf } 538 1.1 lonewolf 539 1.1 lonewolf static int 540 1.1 lonewolf haltwo_query_devinfo(void *v, mixer_devinfo_t *dev) 541 1.1 lonewolf { 542 1.2 tsutsui 543 1.1 lonewolf switch (dev->index) { 544 1.1 lonewolf /* Mixer values */ 545 1.1 lonewolf case HALTWO_MASTER_VOL: 546 1.1 lonewolf dev->type = AUDIO_MIXER_VALUE; 547 1.1 lonewolf dev->mixer_class = HALTWO_OUTPUT_CLASS; 548 1.1 lonewolf dev->prev = dev->next = AUDIO_MIXER_LAST; 549 1.1 lonewolf strcpy(dev->label.name, AudioNmaster); 550 1.1 lonewolf dev->un.v.num_channels = 2; 551 1.16 macallan dev->un.v.delta = 16; 552 1.1 lonewolf strcpy(dev->un.v.units.name, AudioNvolume); 553 1.1 lonewolf break; 554 1.1 lonewolf 555 1.1 lonewolf /* Mixer classes */ 556 1.1 lonewolf case HALTWO_OUTPUT_CLASS: 557 1.1 lonewolf dev->type = AUDIO_MIXER_CLASS; 558 1.1 lonewolf dev->mixer_class = HALTWO_OUTPUT_CLASS; 559 1.1 lonewolf dev->next = dev->prev = AUDIO_MIXER_LAST; 560 1.1 lonewolf strcpy(dev->label.name, AudioCoutputs); 561 1.1 lonewolf break; 562 1.1 lonewolf 563 1.1 lonewolf default: 564 1.7 kent return EINVAL; 565 1.1 lonewolf } 566 1.1 lonewolf 567 1.7 kent return 0; 568 1.1 lonewolf } 569 1.1 lonewolf 570 1.1 lonewolf static int 571 1.1 lonewolf haltwo_alloc_dmamem(struct haltwo_softc *sc, size_t size, 572 1.1 lonewolf struct haltwo_dmabuf *p) 573 1.1 lonewolf { 574 1.1 lonewolf int err; 575 1.1 lonewolf 576 1.1 lonewolf p->size = size; 577 1.1 lonewolf 578 1.1 lonewolf /* XXX Check align/boundary XXX */ 579 1.1 lonewolf err = bus_dmamem_alloc(sc->sc_dma_tag, p->size, 0, 0, p->dma_segs, 580 1.21 jmcneill HALTWO_MAX_DMASEGS, &p->dma_segcount, BUS_DMA_WAITOK); 581 1.1 lonewolf if (err) 582 1.1 lonewolf goto out; 583 1.1 lonewolf 584 1.1 lonewolf /* XXX BUS_DMA_COHERENT? XXX */ 585 1.1 lonewolf err = bus_dmamem_map(sc->sc_dma_tag, p->dma_segs, p->dma_segcount, 586 1.21 jmcneill p->size, &p->kern_addr, BUS_DMA_WAITOK | BUS_DMA_COHERENT); 587 1.1 lonewolf if (err) 588 1.1 lonewolf goto out_free; 589 1.1 lonewolf 590 1.1 lonewolf /* XXX Just guessing ... XXX */ 591 1.1 lonewolf err = bus_dmamap_create(sc->sc_dma_tag, p->size, HALTWO_MAX_DMASEGS, 592 1.21 jmcneill PAGE_SIZE, 0, BUS_DMA_WAITOK, &p->dma_map); 593 1.1 lonewolf if (err) 594 1.1 lonewolf goto out_free; 595 1.1 lonewolf 596 1.1 lonewolf err = bus_dmamap_load(sc->sc_dma_tag, p->dma_map, p->kern_addr, 597 1.21 jmcneill p->size, NULL, BUS_DMA_WAITOK); 598 1.1 lonewolf if (err) 599 1.1 lonewolf goto out_destroy; 600 1.1 lonewolf 601 1.1 lonewolf return 0; 602 1.1 lonewolf 603 1.1 lonewolf out_destroy: 604 1.1 lonewolf bus_dmamap_destroy(sc->sc_dma_tag, p->dma_map); 605 1.1 lonewolf out_free: 606 1.1 lonewolf bus_dmamem_free(sc->sc_dma_tag, p->dma_segs, p->dma_segcount); 607 1.1 lonewolf out: 608 1.1 lonewolf DPRINTF(("haltwo_alloc_dmamem failed: %d\n",err)); 609 1.1 lonewolf 610 1.1 lonewolf return err; 611 1.1 lonewolf } 612 1.1 lonewolf 613 1.1 lonewolf static void * 614 1.21 jmcneill haltwo_malloc(void *v, int direction, size_t size) 615 1.1 lonewolf { 616 1.7 kent struct haltwo_softc *sc; 617 1.1 lonewolf struct haltwo_dmabuf *p; 618 1.1 lonewolf 619 1.1 lonewolf DPRINTF(("haltwo_malloc size = %d\n", size)); 620 1.7 kent sc = v; 621 1.21 jmcneill p = kmem_alloc(sizeof(*p), KM_SLEEP); 622 1.1 lonewolf if (haltwo_alloc_dmamem(sc, size, p)) { 623 1.21 jmcneill kmem_free(p, sizeof(*p)); 624 1.21 jmcneill return NULL; 625 1.1 lonewolf } 626 1.1 lonewolf 627 1.1 lonewolf p->next = sc->sc_dma_bufs; 628 1.1 lonewolf sc->sc_dma_bufs = p; 629 1.1 lonewolf 630 1.1 lonewolf return p->kern_addr; 631 1.1 lonewolf } 632 1.1 lonewolf 633 1.1 lonewolf static void 634 1.21 jmcneill haltwo_free(void *v, void *addr, size_t size) 635 1.1 lonewolf { 636 1.7 kent struct haltwo_softc *sc; 637 1.7 kent struct haltwo_dmabuf *p, **pp; 638 1.1 lonewolf 639 1.7 kent sc = v; 640 1.1 lonewolf for (pp = &sc->sc_dma_bufs; (p = *pp) != NULL; pp = &p->next) { 641 1.1 lonewolf if (p->kern_addr == addr) { 642 1.1 lonewolf *pp = p->next; 643 1.21 jmcneill kmem_free(p, sizeof(*p)); 644 1.1 lonewolf return; 645 1.1 lonewolf } 646 1.1 lonewolf } 647 1.1 lonewolf 648 1.1 lonewolf panic("haltwo_free: buffer not in list"); 649 1.1 lonewolf } 650 1.1 lonewolf 651 1.1 lonewolf static int 652 1.1 lonewolf haltwo_get_props(void *v) 653 1.1 lonewolf { 654 1.2 tsutsui 655 1.25 isaki return AUDIO_PROP_PLAYBACK; 656 1.1 lonewolf } 657 1.1 lonewolf 658 1.1 lonewolf static int 659 1.1 lonewolf haltwo_trigger_output(void *v, void *start, void *end, int blksize, 660 1.6 kent void (*intr)(void *), void *intrarg, const audio_params_t *param) 661 1.1 lonewolf { 662 1.7 kent struct haltwo_softc *sc; 663 1.1 lonewolf struct haltwo_dmabuf *p; 664 1.1 lonewolf uint16_t tmp; 665 1.1 lonewolf uint32_t ctrl; 666 1.1 lonewolf unsigned int fifobeg, fifoend, highwater; 667 1.1 lonewolf 668 1.1 lonewolf DPRINTF(("haltwo_trigger_output start = %p end = %p blksize = %d" 669 1.2 tsutsui " param = %p\n", start, end, blksize, param)); 670 1.7 kent sc = v; 671 1.1 lonewolf for (p = sc->sc_dma_bufs; p != NULL; p = p->next) 672 1.1 lonewolf if (p->kern_addr == start) 673 1.1 lonewolf break; 674 1.1 lonewolf 675 1.1 lonewolf if (p == NULL) { 676 1.1 lonewolf printf("haltwo_trigger_output: buffer not in list\n"); 677 1.2 tsutsui 678 1.7 kent return EINVAL; 679 1.1 lonewolf } 680 1.1 lonewolf 681 1.1 lonewolf /* Disable PBUS DMA */ 682 1.5 rumble bus_space_write_4(sc->sc_st, sc->sc_dma_sh, HPC3_PBUS_CH0_CTL, 683 1.5 rumble HPC3_PBUS_DMACTL_ACT_LD); 684 1.1 lonewolf 685 1.1 lonewolf /* Disable HAL2 codec DMA */ 686 1.1 lonewolf haltwo_read_indirect(sc, HAL2_IREG_DMA_PORT_EN, &tmp, NULL); 687 1.1 lonewolf haltwo_write_indirect(sc, HAL2_IREG_DMA_PORT_EN, 688 1.1 lonewolf tmp & ~HAL2_DMA_PORT_EN_CODECTX, 0); 689 1.1 lonewolf 690 1.1 lonewolf haltwo_setup_dma(sc, &sc->sc_dac, p, (char *)end - (char *)start, 691 1.1 lonewolf blksize, intr, intrarg); 692 1.1 lonewolf 693 1.6 kent highwater = (param->channels * 4) >> 1; 694 1.1 lonewolf fifobeg = 0; 695 1.6 kent fifoend = (param->channels * 8) >> 3; 696 1.1 lonewolf 697 1.1 lonewolf DPRINTF(("haltwo_trigger_output: hw_channels = %d highwater = %d" 698 1.26 isaki " fifobeg = %d fifoend = %d\n", param->channels, highwater, 699 1.2 tsutsui fifobeg, fifoend)); 700 1.1 lonewolf 701 1.5 rumble ctrl = HPC3_PBUS_DMACTL_RT 702 1.5 rumble | HPC3_PBUS_DMACTL_ACT_LD 703 1.5 rumble | (highwater << HPC3_PBUS_DMACTL_HIGHWATER_SHIFT) 704 1.5 rumble | (fifobeg << HPC3_PBUS_DMACTL_FIFOBEG_SHIFT) 705 1.5 rumble | (fifoend << HPC3_PBUS_DMACTL_FIFOEND_SHIFT); 706 1.1 lonewolf 707 1.1 lonewolf /* Using PBUS CH0 for DAC DMA */ 708 1.1 lonewolf haltwo_write_indirect(sc, HAL2_IREG_DMA_DRV, 1, 0); 709 1.1 lonewolf 710 1.1 lonewolf /* HAL2 is ready for action, now setup PBUS for DMA transfer */ 711 1.5 rumble bus_space_write_4(sc->sc_st, sc->sc_dma_sh, HPC3_PBUS_CH0_DP, 712 1.1 lonewolf sc->sc_dac.dma_seg.ds_addr); 713 1.5 rumble bus_space_write_4(sc->sc_st, sc->sc_dma_sh, HPC3_PBUS_CH0_CTL, 714 1.5 rumble ctrl | HPC3_PBUS_DMACTL_ACT); 715 1.1 lonewolf 716 1.1 lonewolf /* Both HAL2 and PBUS have been setup, now start it up */ 717 1.1 lonewolf haltwo_read_indirect(sc, HAL2_IREG_DMA_PORT_EN, &tmp, NULL); 718 1.1 lonewolf haltwo_write_indirect(sc, HAL2_IREG_DMA_PORT_EN, 719 1.1 lonewolf tmp | HAL2_DMA_PORT_EN_CODECTX, 0); 720 1.2 tsutsui 721 1.7 kent return 0; 722 1.1 lonewolf } 723 1.1 lonewolf 724 1.1 lonewolf static int 725 1.1 lonewolf haltwo_trigger_input(void *v, void *start, void *end, int blksize, 726 1.6 kent void (*intr)(void *), void *intrarg, const audio_params_t *param) 727 1.1 lonewolf { 728 1.7 kent struct haltwo_softc *sc; 729 1.1 lonewolf struct haltwo_dmabuf *p; 730 1.2 tsutsui 731 1.1 lonewolf DPRINTF(("haltwo_trigger_input start = %p end = %p blksize = %d\n", 732 1.2 tsutsui start, end, blksize)); 733 1.7 kent sc = v; 734 1.1 lonewolf for (p = sc->sc_dma_bufs; p != NULL; p = p->next) 735 1.1 lonewolf if (p->kern_addr == start) 736 1.1 lonewolf break; 737 1.1 lonewolf 738 1.1 lonewolf if (p == NULL) { 739 1.1 lonewolf printf("haltwo_trigger_input: buffer not in list\n"); 740 1.2 tsutsui 741 1.7 kent return EINVAL; 742 1.1 lonewolf } 743 1.1 lonewolf 744 1.1 lonewolf #if 0 745 1.1 lonewolf haltwo_setup_dma(sc, &sc->sc_adc, p, (char *)end - (char *)start, 746 1.1 lonewolf blksize, intr, intrarg); 747 1.1 lonewolf #endif 748 1.2 tsutsui 749 1.7 kent return ENXIO; 750 1.1 lonewolf } 751 1.15 tsutsui 752 1.21 jmcneill static void 753 1.21 jmcneill haltwo_get_locks(void *v, kmutex_t **intr, kmutex_t **thread) 754 1.21 jmcneill { 755 1.21 jmcneill struct haltwo_softc *sc; 756 1.21 jmcneill 757 1.21 jmcneill DPRINTF(("haltwo_get_locks\n")); 758 1.21 jmcneill sc = v; 759 1.21 jmcneill 760 1.21 jmcneill *intr = &sc->sc_intr_lock; 761 1.21 jmcneill *thread = &sc->sc_lock; 762 1.21 jmcneill } 763 1.21 jmcneill 764 1.17 tsutsui bool 765 1.17 tsutsui haltwo_shutdown(device_t self, int howto) 766 1.15 tsutsui { 767 1.17 tsutsui struct haltwo_softc *sc; 768 1.15 tsutsui 769 1.17 tsutsui sc = device_private(self); 770 1.15 tsutsui haltwo_write(sc, ctl, HAL2_REG_CTL_ISR, 0); 771 1.15 tsutsui haltwo_write(sc, ctl, HAL2_REG_CTL_ISR, 772 1.15 tsutsui HAL2_ISR_GLOBAL_RESET_N | HAL2_ISR_CODEC_RESET_N); 773 1.17 tsutsui 774 1.17 tsutsui return true; 775 1.15 tsutsui } 776