auacer.c revision 1.36 1 /* $NetBSD: auacer.c,v 1.36 2019/03/16 12:09:58 isaki Exp $ */
2
3 /*-
4 * Copyright (c) 2004, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Lennart Augustsson.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * Acer Labs M5455 audio driver
34 *
35 * Acer provides data sheets after signing an NDA, so this is guess work.
36 * The chip behaves somewhat like the Intel i8x0, so this driver
37 * is loosely based on the auich driver. Additional information taken from
38 * the ALSA intel8x0.c driver (which handles M5455 as well).
39 *
40 * As an historical note one can observe that the auich driver borrows
41 * lot from the first NetBSD PCI audio driver, the eap driver. But this
42 * is not attributed anywhere.
43 */
44
45
46 #include <sys/cdefs.h>
47 __KERNEL_RCSID(0, "$NetBSD: auacer.c,v 1.36 2019/03/16 12:09:58 isaki Exp $");
48
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/kernel.h>
52 #include <sys/kmem.h>
53 #include <sys/device.h>
54 #include <sys/fcntl.h>
55 #include <sys/proc.h>
56
57 #include <dev/pci/pcidevs.h>
58 #include <dev/pci/pcivar.h>
59 #include <dev/pci/auacerreg.h>
60
61 #include <sys/audioio.h>
62 #include <dev/audio_if.h>
63 #include <dev/mulaw.h>
64 #include <dev/auconv.h>
65
66 #include <sys/bus.h>
67
68 #include <dev/ic/ac97reg.h>
69 #include <dev/ic/ac97var.h>
70
71 struct auacer_dma {
72 bus_dmamap_t map;
73 void *addr;
74 bus_dma_segment_t segs[1];
75 int nsegs;
76 size_t size;
77 struct auacer_dma *next;
78 };
79
80 #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr)
81 #define KERNADDR(p) ((void *)((p)->addr))
82
83 struct auacer_cdata {
84 struct auacer_dmalist ic_dmalist_pcmo[ALI_DMALIST_MAX];
85 };
86
87 struct auacer_chan {
88 uint32_t ptr;
89 uint32_t start, p, end;
90 uint32_t blksize, fifoe;
91 uint32_t ack;
92 uint32_t port;
93 struct auacer_dmalist *dmalist;
94 void (*intr)(void *);
95 void *arg;
96 };
97
98 struct auacer_softc {
99 device_t sc_dev;
100 void *sc_ih;
101 kmutex_t sc_lock;
102 kmutex_t sc_intr_lock;
103
104 audio_device_t sc_audev;
105
106 bus_space_tag_t iot;
107 bus_space_handle_t mix_ioh;
108 bus_space_handle_t aud_ioh;
109 bus_dma_tag_t dmat;
110
111 struct ac97_codec_if *codec_if;
112 struct ac97_host_if host_if;
113
114 /* DMA scatter-gather lists. */
115 bus_dmamap_t sc_cddmamap;
116 #define sc_cddma sc_cddmamap->dm_segs[0].ds_addr
117
118 struct auacer_cdata *sc_cdata;
119
120 struct auacer_chan sc_pcmo;
121
122 struct auacer_dma *sc_dmas;
123
124 pci_chipset_tag_t sc_pc;
125 pcitag_t sc_pt;
126
127 int sc_dmamap_flags;
128
129 #define AUACER_NFORMATS 3
130 struct audio_format sc_formats[AUACER_NFORMATS];
131 struct audio_encoding_set *sc_encodings;
132 };
133
134 #define READ1(sc, a) bus_space_read_1(sc->iot, sc->aud_ioh, a)
135 #define READ2(sc, a) bus_space_read_2(sc->iot, sc->aud_ioh, a)
136 #define READ4(sc, a) bus_space_read_4(sc->iot, sc->aud_ioh, a)
137 #define WRITE1(sc, a, v) bus_space_write_1(sc->iot, sc->aud_ioh, a, v)
138 #define WRITE2(sc, a, v) bus_space_write_2(sc->iot, sc->aud_ioh, a, v)
139 #define WRITE4(sc, a, v) bus_space_write_4(sc->iot, sc->aud_ioh, a, v)
140
141 /* Debug */
142 #ifdef AUACER_DEBUG
143 #define DPRINTF(l,x) do { if (auacer_debug & (l)) printf x; } while(0)
144 int auacer_debug = 0;
145 #define ALI_DEBUG_CODECIO 0x0001
146 #define ALI_DEBUG_DMA 0x0002
147 #define ALI_DEBUG_INTR 0x0004
148 #define ALI_DEBUG_API 0x0008
149 #define ALI_DEBUG_MIXERAPI 0x0010
150 #else
151 #define DPRINTF(x,y) /* nothing */
152 #endif
153
154 static int auacer_intr(void *);
155
156 static int auacer_query_encoding(void *, struct audio_encoding *);
157 static int auacer_set_params(void *, int, int, audio_params_t *,
158 audio_params_t *, stream_filter_list_t *,
159 stream_filter_list_t *);
160 static int auacer_round_blocksize(void *, int, int,
161 const audio_params_t *);
162 static int auacer_halt_output(void *);
163 static int auacer_halt_input(void *);
164 static int auacer_getdev(void *, struct audio_device *);
165 static int auacer_set_port(void *, mixer_ctrl_t *);
166 static int auacer_get_port(void *, mixer_ctrl_t *);
167 static int auacer_query_devinfo(void *, mixer_devinfo_t *);
168 static void *auacer_allocm(void *, int, size_t);
169 static void auacer_freem(void *, void *, size_t);
170 static size_t auacer_round_buffersize(void *, int, size_t);
171 static paddr_t auacer_mappage(void *, void *, off_t, int);
172 static int auacer_get_props(void *);
173 static int auacer_trigger_output(void *, void *, void *, int,
174 void (*)(void *), void *,
175 const audio_params_t *);
176 static int auacer_trigger_input(void *, void *, void *, int,
177 void (*)(void *), void *,
178 const audio_params_t *);
179
180 static int auacer_alloc_cdata(struct auacer_softc *);
181
182 static int auacer_allocmem(struct auacer_softc *, size_t, size_t,
183 struct auacer_dma *);
184 static int auacer_freemem(struct auacer_softc *, struct auacer_dma *);
185 static void auacer_get_locks(void *, kmutex_t **, kmutex_t **);
186
187 static bool auacer_resume(device_t, const pmf_qual_t *);
188 static int auacer_set_rate(struct auacer_softc *, int, u_int);
189
190 static void auacer_reset(struct auacer_softc *sc);
191
192 static const struct audio_hw_if auacer_hw_if = {
193 .query_encoding = auacer_query_encoding,
194 .set_params = auacer_set_params,
195 .round_blocksize = auacer_round_blocksize,
196 .halt_output = auacer_halt_output,
197 .halt_input = auacer_halt_input,
198 .getdev = auacer_getdev,
199 .set_port = auacer_set_port,
200 .get_port = auacer_get_port,
201 .query_devinfo = auacer_query_devinfo,
202 .allocm = auacer_allocm,
203 .freem = auacer_freem,
204 .round_buffersize = auacer_round_buffersize,
205 .mappage = auacer_mappage,
206 .get_props = auacer_get_props,
207 .trigger_output = auacer_trigger_output,
208 .trigger_input = auacer_trigger_input,
209 .get_locks = auacer_get_locks,
210 };
211
212 #define AUACER_FORMATS_4CH 1
213 #define AUACER_FORMATS_6CH 2
214 static const struct audio_format auacer_formats[AUACER_NFORMATS] = {
215 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 16, 16,
216 2, AUFMT_STEREO, 0, {8000, 48000}},
217 {NULL, AUMODE_PLAY, AUDIO_ENCODING_SLINEAR_LE, 16, 16,
218 4, AUFMT_SURROUND4, 0, {8000, 48000}},
219 {NULL, AUMODE_PLAY, AUDIO_ENCODING_SLINEAR_LE, 16, 16,
220 6, AUFMT_DOLBY_5_1, 0, {8000, 48000}},
221 };
222
223 static int auacer_attach_codec(void *, struct ac97_codec_if *);
224 static int auacer_read_codec(void *, uint8_t, uint16_t *);
225 static int auacer_write_codec(void *, uint8_t, uint16_t);
226 static int auacer_reset_codec(void *);
227
228 static int
229 auacer_match(device_t parent, cfdata_t match, void *aux)
230 {
231 struct pci_attach_args *pa;
232
233 pa = (struct pci_attach_args *)aux;
234 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ALI &&
235 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ALI_M5455)
236 return 1;
237 return 0;
238 }
239
240 static void
241 auacer_attach(device_t parent, device_t self, void *aux)
242 {
243 struct auacer_softc *sc;
244 struct pci_attach_args *pa;
245 pci_intr_handle_t ih;
246 bus_size_t aud_size;
247 pcireg_t v;
248 const char *intrstr;
249 int i;
250 char intrbuf[PCI_INTRSTR_LEN];
251
252 sc = device_private(self);
253 sc->sc_dev = self;
254 pa = aux;
255 aprint_normal(": Acer Labs M5455 Audio controller\n");
256
257 if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0, &sc->iot,
258 &sc->aud_ioh, NULL, &aud_size)) {
259 aprint_error(": can't map i/o space\n");
260 return;
261 }
262
263 sc->sc_pc = pa->pa_pc;
264 sc->sc_pt = pa->pa_tag;
265 sc->dmat = pa->pa_dmat;
266
267 sc->sc_dmamap_flags = BUS_DMA_COHERENT; /* XXX remove */
268
269 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
270 mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO);
271
272 /* enable bus mastering */
273 v = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
274 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
275 v | PCI_COMMAND_MASTER_ENABLE);
276
277 /* Map and establish the interrupt. */
278 if (pci_intr_map(pa, &ih)) {
279 aprint_error_dev(sc->sc_dev, "can't map interrupt\n");
280 mutex_destroy(&sc->sc_lock);
281 mutex_destroy(&sc->sc_intr_lock);
282 return;
283 }
284 intrstr = pci_intr_string(pa->pa_pc, ih, intrbuf, sizeof(intrbuf));
285 sc->sc_ih = pci_intr_establish_xname(pa->pa_pc, ih, IPL_AUDIO,
286 auacer_intr, sc, device_xname(self));
287 if (sc->sc_ih == NULL) {
288 aprint_error_dev(sc->sc_dev, "can't establish interrupt");
289 if (intrstr != NULL)
290 aprint_error(" at %s", intrstr);
291 aprint_error("\n");
292 mutex_destroy(&sc->sc_lock);
293 mutex_destroy(&sc->sc_intr_lock);
294 return;
295 }
296 aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr);
297
298 strlcpy(sc->sc_audev.name, "M5455 AC97", MAX_AUDIO_DEV_LEN);
299 snprintf(sc->sc_audev.version, MAX_AUDIO_DEV_LEN,
300 "0x%02x", PCI_REVISION(pa->pa_class));
301 strlcpy(sc->sc_audev.config, device_xname(sc->sc_dev), MAX_AUDIO_DEV_LEN);
302
303 /* Set up DMA lists. */
304 auacer_alloc_cdata(sc);
305 sc->sc_pcmo.dmalist = sc->sc_cdata->ic_dmalist_pcmo;
306 sc->sc_pcmo.ptr = 0;
307 sc->sc_pcmo.port = ALI_BASE_PO;
308
309 DPRINTF(ALI_DEBUG_DMA, ("auacer_attach: lists %p\n",
310 sc->sc_pcmo.dmalist));
311
312 sc->host_if.arg = sc;
313 sc->host_if.attach = auacer_attach_codec;
314 sc->host_if.read = auacer_read_codec;
315 sc->host_if.write = auacer_write_codec;
316 sc->host_if.reset = auacer_reset_codec;
317
318 if (ac97_attach(&sc->host_if, self, &sc->sc_lock) != 0) {
319 mutex_destroy(&sc->sc_lock);
320 mutex_destroy(&sc->sc_intr_lock);
321 return;
322 }
323
324 /* setup audio_format */
325 memcpy(sc->sc_formats, auacer_formats, sizeof(auacer_formats));
326 mutex_enter(&sc->sc_lock);
327 if (!AC97_IS_4CH(sc->codec_if))
328 AUFMT_INVALIDATE(&sc->sc_formats[AUACER_FORMATS_4CH]);
329 if (!AC97_IS_6CH(sc->codec_if))
330 AUFMT_INVALIDATE(&sc->sc_formats[AUACER_FORMATS_6CH]);
331 if (AC97_IS_FIXED_RATE(sc->codec_if)) {
332 for (i = 0; i < AUACER_NFORMATS; i++) {
333 sc->sc_formats[i].frequency_type = 1;
334 sc->sc_formats[i].frequency[0] = 48000;
335 }
336 }
337 mutex_exit(&sc->sc_lock);
338
339 if (0 != auconv_create_encodings(sc->sc_formats, AUACER_NFORMATS,
340 &sc->sc_encodings)) {
341 mutex_destroy(&sc->sc_lock);
342 mutex_destroy(&sc->sc_intr_lock);
343 return;
344 }
345
346 mutex_enter(&sc->sc_lock);
347 mutex_spin_enter(&sc->sc_intr_lock);
348 auacer_reset(sc);
349 mutex_spin_exit(&sc->sc_intr_lock);
350 mutex_exit(&sc->sc_lock);
351
352 audio_attach_mi(&auacer_hw_if, sc, sc->sc_dev);
353
354 if (!pmf_device_register(self, NULL, auacer_resume))
355 aprint_error_dev(self, "couldn't establish power handler\n");
356 }
357
358 CFATTACH_DECL_NEW(auacer, sizeof(struct auacer_softc),
359 auacer_match, auacer_attach, NULL, NULL);
360
361 static int
362 auacer_ready_codec(struct auacer_softc *sc, int mask)
363 {
364 int count;
365
366 for (count = 0; count < 0x7f; count++) {
367 int val = READ1(sc, ALI_CSPSR);
368 if (val & mask)
369 return 0;
370 }
371
372 aprint_normal("auacer_ready_codec: AC97 codec ready timeout.\n");
373 return EBUSY;
374 }
375
376 static int
377 auacer_sema_codec(struct auacer_softc *sc)
378 {
379 int ttime;
380
381 ttime = 100;
382 while (ttime-- && (READ4(sc, ALI_CAS) & ALI_CAS_SEM_BUSY))
383 delay(1);
384 if (!ttime)
385 aprint_normal("auacer_sema_codec: timeout\n");
386 return auacer_ready_codec(sc, ALI_CSPSR_CODEC_READY);
387 }
388
389 static int
390 auacer_read_codec(void *v, uint8_t reg, uint16_t *val)
391 {
392 struct auacer_softc *sc;
393
394 sc = v;
395 if (auacer_sema_codec(sc))
396 return EIO;
397
398 reg |= ALI_CPR_ADDR_READ;
399 #if 0
400 if (ac97->num)
401 reg |= ALI_CPR_ADDR_SECONDARY;
402 #endif
403 WRITE2(sc, ALI_CPR_ADDR, reg);
404 if (auacer_ready_codec(sc, ALI_CSPSR_READ_OK))
405 return EIO;
406 *val = READ2(sc, ALI_SPR);
407
408 DPRINTF(ALI_DEBUG_CODECIO, ("auacer_read_codec: reg=0x%x val=0x%x\n",
409 reg, *val));
410
411 return 0;
412 }
413
414 int
415 auacer_write_codec(void *v, uint8_t reg, uint16_t val)
416 {
417 struct auacer_softc *sc;
418
419 DPRINTF(ALI_DEBUG_CODECIO, ("auacer_write_codec: reg=0x%x val=0x%x\n",
420 reg, val));
421 sc = v;
422 if (auacer_sema_codec(sc))
423 return EIO;
424 WRITE2(sc, ALI_CPR, val);
425 #if 0
426 if (ac97->num)
427 reg |= ALI_CPR_ADDR_SECONDARY;
428 #endif
429 WRITE2(sc, ALI_CPR_ADDR, reg);
430 auacer_ready_codec(sc, ALI_CSPSR_WRITE_OK);
431 return 0;
432 }
433
434 static int
435 auacer_attach_codec(void *v, struct ac97_codec_if *cif)
436 {
437 struct auacer_softc *sc;
438
439 sc = v;
440 sc->codec_if = cif;
441 return 0;
442 }
443
444 static int
445 auacer_reset_codec(void *v)
446 {
447 struct auacer_softc *sc;
448 uint32_t reg;
449 int i;
450
451 sc = v;
452 i = 0;
453 reg = READ4(sc, ALI_SCR);
454 if ((reg & 2) == 0) /* Cold required */
455 reg |= 2;
456 else
457 reg |= 1; /* Warm */
458 reg &= ~0x80000000; /* ACLink on */
459 WRITE4(sc, ALI_SCR, reg);
460
461 while (i < 10) {
462 if ((READ4(sc, ALI_INTERRUPTSR) & ALI_INT_GPIO) == 0)
463 break;
464 delay(50000); /* XXX */
465 i++;
466 }
467 if (i == 10) {
468 return EIO;
469 }
470
471 for (i = 0; i < 10; i++) {
472 reg = READ4(sc, ALI_RTSR);
473 if (reg & 0x80) /* primary codec */
474 break;
475 WRITE4(sc, ALI_RTSR, reg | 0x80);
476 delay(50000); /* XXX */
477 }
478
479 return 0;
480 }
481
482 static void
483 auacer_reset(struct auacer_softc *sc)
484 {
485 WRITE4(sc, ALI_SCR, ALI_SCR_RESET);
486 WRITE4(sc, ALI_FIFOCR1, 0x83838383);
487 WRITE4(sc, ALI_FIFOCR2, 0x83838383);
488 WRITE4(sc, ALI_FIFOCR3, 0x83838383);
489 WRITE4(sc, ALI_INTERFACECR, ALI_IF_PO); /* XXX pcm out only */
490 WRITE4(sc, ALI_INTERRUPTCR, 0x00000000);
491 WRITE4(sc, ALI_INTERRUPTSR, 0x00000000);
492 }
493
494 static int
495 auacer_query_encoding(void *v, struct audio_encoding *aep)
496 {
497 struct auacer_softc *sc;
498
499 DPRINTF(ALI_DEBUG_API, ("auacer_query_encoding\n"));
500 sc = v;
501 return auconv_query_encoding(sc->sc_encodings, aep);
502 }
503
504 static int
505 auacer_set_rate(struct auacer_softc *sc, int mode, u_int srate)
506 {
507 int ret;
508 u_int ratetmp;
509
510 DPRINTF(ALI_DEBUG_API, ("auacer_set_rate: srate=%u\n", srate));
511
512 ratetmp = srate;
513 if (mode == AUMODE_RECORD)
514 return sc->codec_if->vtbl->set_rate(sc->codec_if,
515 AC97_REG_PCM_LR_ADC_RATE, &ratetmp);
516 ret = sc->codec_if->vtbl->set_rate(sc->codec_if,
517 AC97_REG_PCM_FRONT_DAC_RATE, &ratetmp);
518 if (ret)
519 return ret;
520 ratetmp = srate;
521 ret = sc->codec_if->vtbl->set_rate(sc->codec_if,
522 AC97_REG_PCM_SURR_DAC_RATE, &ratetmp);
523 if (ret)
524 return ret;
525 ratetmp = srate;
526 ret = sc->codec_if->vtbl->set_rate(sc->codec_if,
527 AC97_REG_PCM_LFE_DAC_RATE, &ratetmp);
528 return ret;
529 }
530
531 static int
532 auacer_set_params(void *v, int setmode, int usemode,
533 audio_params_t *play, audio_params_t *rec, stream_filter_list_t *pfil,
534 stream_filter_list_t *rfil)
535 {
536 struct auacer_softc *sc;
537 struct audio_params *p;
538 stream_filter_list_t *fil;
539 uint32_t control;
540 int mode, index;
541
542 DPRINTF(ALI_DEBUG_API, ("auacer_set_params\n"));
543 sc = v;
544 for (mode = AUMODE_RECORD; mode != -1;
545 mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
546 if ((setmode & mode) == 0)
547 continue;
548
549 p = mode == AUMODE_PLAY ? play : rec;
550 if (p == NULL)
551 continue;
552
553 if ((p->sample_rate != 8000) &&
554 (p->sample_rate != 11025) &&
555 (p->sample_rate != 12000) &&
556 (p->sample_rate != 16000) &&
557 (p->sample_rate != 22050) &&
558 (p->sample_rate != 24000) &&
559 (p->sample_rate != 32000) &&
560 (p->sample_rate != 44100) &&
561 (p->sample_rate != 48000))
562 return (EINVAL);
563
564 fil = mode == AUMODE_PLAY ? pfil : rfil;
565 index = auconv_set_converter(sc->sc_formats, AUACER_NFORMATS,
566 mode, p, TRUE, fil);
567 if (index < 0)
568 return EINVAL;
569 if (fil->req_size > 0)
570 p = &fil->filters[0].param;
571 /* p points HW encoding */
572 if (sc->sc_formats[index].frequency_type != 1
573 && auacer_set_rate(sc, mode, p->sample_rate))
574 return EINVAL;
575 if (mode == AUMODE_PLAY) {
576 control = READ4(sc, ALI_SCR);
577 control &= ~ALI_SCR_PCM_246_MASK;
578 if (p->channels == 4)
579 control |= ALI_SCR_PCM_4;
580 else if (p->channels == 6)
581 control |= ALI_SCR_PCM_6;
582 WRITE4(sc, ALI_SCR, control);
583 }
584 }
585
586 return (0);
587 }
588
589 static int
590 auacer_round_blocksize(void *v, int blk, int mode,
591 const audio_params_t *param)
592 {
593
594 return blk & ~0x3f; /* keep good alignment */
595 }
596
597 static void
598 auacer_halt(struct auacer_softc *sc, struct auacer_chan *chan)
599 {
600 uint32_t val;
601 uint8_t port;
602 uint32_t slot;
603
604 port = chan->port;
605 DPRINTF(ALI_DEBUG_API, ("auacer_halt: port=0x%x\n", port));
606 chan->intr = 0;
607
608 slot = ALI_PORT2SLOT(port);
609
610 val = READ4(sc, ALI_DMACR);
611 val |= 1 << (slot+16); /* pause */
612 val &= ~(1 << slot); /* no start */
613 WRITE4(sc, ALI_DMACR, val);
614 WRITE1(sc, port + ALI_OFF_CR, 0);
615 while (READ1(sc, port + ALI_OFF_CR))
616 ;
617 /* reset whole DMA things */
618 WRITE1(sc, port + ALI_OFF_CR, ALI_CR_RR);
619 /* clear interrupts */
620 WRITE1(sc, port + ALI_OFF_SR, READ1(sc, port+ALI_OFF_SR) | ALI_SR_W1TC);
621 WRITE4(sc, ALI_INTERRUPTSR, ALI_PORT2INTR(port));
622 }
623
624 static int
625 auacer_halt_output(void *v)
626 {
627 struct auacer_softc *sc;
628
629 DPRINTF(ALI_DEBUG_DMA, ("auacer_halt_output\n"));
630 sc = v;
631 auacer_halt(sc, &sc->sc_pcmo);
632
633 return 0;
634 }
635
636 static int
637 auacer_halt_input(void *v)
638 {
639 DPRINTF(ALI_DEBUG_DMA, ("auacer_halt_input\n"));
640
641 return 0;
642 }
643
644 static int
645 auacer_getdev(void *v, struct audio_device *adp)
646 {
647 struct auacer_softc *sc;
648
649 DPRINTF(ALI_DEBUG_API, ("auacer_getdev\n"));
650 sc = v;
651 *adp = sc->sc_audev;
652 return 0;
653 }
654
655 static int
656 auacer_set_port(void *v, mixer_ctrl_t *cp)
657 {
658 struct auacer_softc *sc;
659
660 DPRINTF(ALI_DEBUG_MIXERAPI, ("auacer_set_port\n"));
661 sc = v;
662 return sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp);
663 }
664
665 static int
666 auacer_get_port(void *v, mixer_ctrl_t *cp)
667 {
668 struct auacer_softc *sc;
669
670 DPRINTF(ALI_DEBUG_MIXERAPI, ("auacer_get_port\n"));
671 sc = v;
672 return sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp);
673 }
674
675 static int
676 auacer_query_devinfo(void *v, mixer_devinfo_t *dp)
677 {
678 struct auacer_softc *sc;
679
680 DPRINTF(ALI_DEBUG_MIXERAPI, ("auacer_query_devinfo\n"));
681 sc = v;
682 return sc->codec_if->vtbl->query_devinfo(sc->codec_if, dp);
683 }
684
685 static void *
686 auacer_allocm(void *v, int direction, size_t size)
687 {
688 struct auacer_softc *sc;
689 struct auacer_dma *p;
690 int error;
691
692 if (size > (ALI_DMALIST_MAX * ALI_DMASEG_MAX))
693 return NULL;
694
695 p = kmem_zalloc(sizeof(*p), KM_SLEEP);
696 sc = v;
697 error = auacer_allocmem(sc, size, 0, p);
698 if (error) {
699 kmem_free(p, sizeof(*p));
700 return NULL;
701 }
702
703 p->next = sc->sc_dmas;
704 sc->sc_dmas = p;
705
706 return KERNADDR(p);
707 }
708
709 static void
710 auacer_freem(void *v, void *ptr, size_t size)
711 {
712 struct auacer_softc *sc;
713 struct auacer_dma *p, **pp;
714
715 sc = v;
716 for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) {
717 if (KERNADDR(p) == ptr) {
718 auacer_freemem(sc, p);
719 *pp = p->next;
720 kmem_free(p, sizeof(*p));
721 return;
722 }
723 }
724 }
725
726 static size_t
727 auacer_round_buffersize(void *v, int direction, size_t size)
728 {
729
730 if (size > (ALI_DMALIST_MAX * ALI_DMASEG_MAX))
731 size = ALI_DMALIST_MAX * ALI_DMASEG_MAX;
732
733 return size;
734 }
735
736 static paddr_t
737 auacer_mappage(void *v, void *mem, off_t off, int prot)
738 {
739 struct auacer_softc *sc;
740 struct auacer_dma *p;
741
742 if (off < 0)
743 return -1;
744 sc = v;
745 for (p = sc->sc_dmas; p && KERNADDR(p) != mem; p = p->next)
746 continue;
747 if (p == NULL)
748 return -1;
749 return bus_dmamem_mmap(sc->dmat, p->segs, p->nsegs,
750 off, prot, BUS_DMA_WAITOK);
751 }
752
753 static int
754 auacer_get_props(void *v)
755 {
756 struct auacer_softc *sc;
757 int props;
758
759 sc = v;
760 props = AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
761 /*
762 * Even if the codec is fixed-rate, set_param() succeeds for any sample
763 * rate because of aurateconv. Applications can't know what rate the
764 * device can process in the case of mmap().
765 */
766 if (!AC97_IS_FIXED_RATE(sc->codec_if))
767 props |= AUDIO_PROP_MMAP;
768 return props;
769 }
770
771 static void
772 auacer_get_locks(void *v, kmutex_t **intr, kmutex_t **proc)
773 {
774 struct auacer_softc *sc;
775
776 sc = v;
777 *intr = &sc->sc_intr_lock;
778 *proc = &sc->sc_lock;
779 }
780
781 static void
782 auacer_add_entry(struct auacer_chan *chan)
783 {
784 struct auacer_dmalist *q;
785
786 q = &chan->dmalist[chan->ptr];
787
788 DPRINTF(ALI_DEBUG_INTR,
789 ("auacer_add_entry: %p = %x @ 0x%x\n",
790 q, chan->blksize / 2, chan->p));
791
792 q->base = htole32(chan->p);
793 q->len = htole32((chan->blksize / ALI_SAMPLE_SIZE) | ALI_DMAF_IOC);
794 chan->p += chan->blksize;
795 if (chan->p >= chan->end)
796 chan->p = chan->start;
797
798 if (++chan->ptr >= ALI_DMALIST_MAX)
799 chan->ptr = 0;
800 }
801
802 static void
803 auacer_upd_chan(struct auacer_softc *sc, struct auacer_chan *chan)
804 {
805 uint32_t sts;
806 uint32_t civ;
807
808 sts = READ2(sc, chan->port + ALI_OFF_SR);
809 /* intr ack */
810 WRITE2(sc, chan->port + ALI_OFF_SR, sts & ALI_SR_W1TC);
811 WRITE4(sc, ALI_INTERRUPTSR, ALI_PORT2INTR(chan->port));
812
813 DPRINTF(ALI_DEBUG_INTR, ("auacer_upd_chan: sts=0x%x\n", sts));
814
815 if (sts & ALI_SR_DMA_INT_FIFO) {
816 printf("%s: fifo underrun # %u\n",
817 device_xname(sc->sc_dev), ++chan->fifoe);
818 }
819
820 civ = READ1(sc, chan->port + ALI_OFF_CIV);
821
822 DPRINTF(ALI_DEBUG_INTR,("auacer_intr: civ=%u ptr=%u\n",civ,chan->ptr));
823
824 /* XXX */
825 while (chan->ptr != civ) {
826 auacer_add_entry(chan);
827 }
828
829 WRITE1(sc, chan->port + ALI_OFF_LVI, (chan->ptr - 1) & ALI_LVI_MASK);
830
831 while (chan->ack != civ) {
832 if (chan->intr) {
833 DPRINTF(ALI_DEBUG_INTR,("auacer_upd_chan: callback\n"));
834 chan->intr(chan->arg);
835 }
836 chan->ack++;
837 if (chan->ack >= ALI_DMALIST_MAX)
838 chan->ack = 0;
839 }
840 }
841
842 static int
843 auacer_intr(void *v)
844 {
845 struct auacer_softc *sc;
846 int ret, intrs;
847
848 sc = v;
849
850 DPRINTF(ALI_DEBUG_INTR, ("auacer_intr: intrs=0x%x\n",
851 READ4(sc, ALI_INTERRUPTSR)));
852
853 mutex_spin_enter(&sc->sc_intr_lock);
854 intrs = READ4(sc, ALI_INTERRUPTSR);
855 ret = 0;
856 if (intrs & ALI_INT_PCMOUT) {
857 auacer_upd_chan(sc, &sc->sc_pcmo);
858 ret++;
859 }
860 mutex_spin_exit(&sc->sc_intr_lock);
861
862 return ret != 0;
863 }
864
865 static void
866 auacer_setup_chan(struct auacer_softc *sc, struct auacer_chan *chan,
867 uint32_t start, uint32_t size, uint32_t blksize,
868 void (*intr)(void *), void *arg)
869 {
870 uint32_t port, slot;
871 uint32_t offs, val;
872
873 chan->start = start;
874 chan->ptr = 0;
875 chan->p = chan->start;
876 chan->end = chan->start + size;
877 chan->blksize = blksize;
878 chan->ack = 0;
879 chan->intr = intr;
880 chan->arg = arg;
881
882 auacer_add_entry(chan);
883 auacer_add_entry(chan);
884
885 port = chan->port;
886 slot = ALI_PORT2SLOT(port);
887
888 WRITE1(sc, port + ALI_OFF_CIV, 0);
889 WRITE1(sc, port + ALI_OFF_LVI, (chan->ptr - 1) & ALI_LVI_MASK);
890 offs = (char *)chan->dmalist - (char *)sc->sc_cdata;
891 WRITE4(sc, port + ALI_OFF_BDBAR, sc->sc_cddma + offs);
892 WRITE1(sc, port + ALI_OFF_CR,
893 ALI_CR_IOCE | ALI_CR_FEIE | ALI_CR_LVBIE | ALI_CR_RPBM);
894 val = READ4(sc, ALI_DMACR);
895 val &= ~(1 << (slot+16)); /* no pause */
896 val |= 1 << slot; /* start */
897 WRITE4(sc, ALI_DMACR, val);
898 }
899
900 static int
901 auacer_trigger_output(void *v, void *start, void *end, int blksize,
902 void (*intr)(void *), void *arg, const audio_params_t *param)
903 {
904 struct auacer_softc *sc;
905 struct auacer_dma *p;
906 uint32_t size;
907
908 DPRINTF(ALI_DEBUG_DMA,
909 ("auacer_trigger_output(%p, %p, %d, %p, %p, %p)\n",
910 start, end, blksize, intr, arg, param));
911 sc = v;
912 for (p = sc->sc_dmas; p && KERNADDR(p) != start; p = p->next)
913 continue;
914 if (!p) {
915 printf("auacer_trigger_output: bad addr %p\n", start);
916 return (EINVAL);
917 }
918
919 size = (char *)end - (char *)start;
920 auacer_setup_chan(sc, &sc->sc_pcmo, DMAADDR(p), size, blksize,
921 intr, arg);
922
923 return 0;
924 }
925
926 static int
927 auacer_trigger_input(void *v, void *start, void *end,
928 int blksize, void (*intr)(void *), void *arg,
929 const audio_params_t *param)
930 {
931 return EINVAL;
932 }
933
934 static int
935 auacer_allocmem(struct auacer_softc *sc, size_t size, size_t align,
936 struct auacer_dma *p)
937 {
938 int error;
939
940 p->size = size;
941 error = bus_dmamem_alloc(sc->dmat, p->size, align, 0,
942 p->segs, sizeof(p->segs)/sizeof(p->segs[0]),
943 &p->nsegs, BUS_DMA_WAITOK);
944 if (error)
945 return error;
946
947 error = bus_dmamem_map(sc->dmat, p->segs, p->nsegs, p->size,
948 &p->addr, BUS_DMA_WAITOK|sc->sc_dmamap_flags);
949 if (error)
950 goto free;
951
952 error = bus_dmamap_create(sc->dmat, p->size, 1, p->size,
953 0, BUS_DMA_WAITOK, &p->map);
954 if (error)
955 goto unmap;
956
957 error = bus_dmamap_load(sc->dmat, p->map, p->addr, p->size, NULL,
958 BUS_DMA_WAITOK);
959 if (error)
960 goto destroy;
961 return (0);
962
963 destroy:
964 bus_dmamap_destroy(sc->dmat, p->map);
965 unmap:
966 bus_dmamem_unmap(sc->dmat, p->addr, p->size);
967 free:
968 bus_dmamem_free(sc->dmat, p->segs, p->nsegs);
969 return error;
970 }
971
972 static int
973 auacer_freemem(struct auacer_softc *sc, struct auacer_dma *p)
974 {
975
976 bus_dmamap_unload(sc->dmat, p->map);
977 bus_dmamap_destroy(sc->dmat, p->map);
978 bus_dmamem_unmap(sc->dmat, p->addr, p->size);
979 bus_dmamem_free(sc->dmat, p->segs, p->nsegs);
980 return 0;
981 }
982
983 static int
984 auacer_alloc_cdata(struct auacer_softc *sc)
985 {
986 bus_dma_segment_t seg;
987 int error, rseg;
988
989 /*
990 * Allocate the control data structure, and create and load the
991 * DMA map for it.
992 */
993 if ((error = bus_dmamem_alloc(sc->dmat,
994 sizeof(struct auacer_cdata),
995 PAGE_SIZE, 0, &seg, 1, &rseg, 0)) != 0) {
996 aprint_error_dev(sc->sc_dev, "unable to allocate control data, error = %d\n",
997 error);
998 goto fail_0;
999 }
1000
1001 if ((error = bus_dmamem_map(sc->dmat, &seg, rseg,
1002 sizeof(struct auacer_cdata),
1003 (void **) &sc->sc_cdata,
1004 sc->sc_dmamap_flags)) != 0) {
1005 aprint_error_dev(sc->sc_dev, "unable to map control data, error = %d\n",
1006 error);
1007 goto fail_1;
1008 }
1009
1010 if ((error = bus_dmamap_create(sc->dmat, sizeof(struct auacer_cdata), 1,
1011 sizeof(struct auacer_cdata), 0, 0,
1012 &sc->sc_cddmamap)) != 0) {
1013 aprint_error_dev(sc->sc_dev, "unable to create control data DMA map, "
1014 "error = %d\n", error);
1015 goto fail_2;
1016 }
1017
1018 if ((error = bus_dmamap_load(sc->dmat, sc->sc_cddmamap,
1019 sc->sc_cdata, sizeof(struct auacer_cdata),
1020 NULL, 0)) != 0) {
1021 aprint_error_dev(sc->sc_dev, "unable to load control data DMA map, "
1022 "error = %d\n", error);
1023 goto fail_3;
1024 }
1025
1026 return 0;
1027
1028 fail_3:
1029 bus_dmamap_destroy(sc->dmat, sc->sc_cddmamap);
1030 fail_2:
1031 bus_dmamem_unmap(sc->dmat, (void *) sc->sc_cdata,
1032 sizeof(struct auacer_cdata));
1033 fail_1:
1034 bus_dmamem_free(sc->dmat, &seg, rseg);
1035 fail_0:
1036 return error;
1037 }
1038
1039 static bool
1040 auacer_resume(device_t dv, const pmf_qual_t *qual)
1041 {
1042 struct auacer_softc *sc = device_private(dv);
1043
1044 mutex_enter(&sc->sc_lock);
1045 mutex_spin_enter(&sc->sc_intr_lock);
1046 auacer_reset_codec(sc);
1047 mutex_spin_exit(&sc->sc_intr_lock);
1048 delay(1000);
1049 sc->codec_if->vtbl->restore_ports(sc->codec_if);
1050 mutex_exit(&sc->sc_lock);
1051
1052 return true;
1053 }
1054