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