xref: /netbsd-src/sys/dev/pci/gcscaudio.c (revision 4d12bfcd155352508213ace5ccc59ce930ea2974)
1 /*	$NetBSD: gcscaudio.c,v 1.12 2012/03/02 11:41:36 nonaka Exp $	*/
2 
3 /*-
4  * Copyright (c) 2008 SHIMIZU Ryo <ryo@nerv.org>
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  *
16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: gcscaudio.c,v 1.12 2012/03/02 11:41:36 nonaka Exp $");
31 
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/kmem.h>
35 #include <sys/device.h>
36 #include <sys/queue.h>
37 
38 #include <dev/pci/pcidevs.h>
39 #include <dev/pci/pcivar.h>
40 
41 #include <sys/audioio.h>
42 #include <dev/audio_if.h>
43 #include <dev/mulaw.h>
44 #include <dev/auconv.h>
45 #include <dev/ic/ac97reg.h>
46 #include <dev/ic/ac97var.h>
47 
48 #include <dev/pci/gcscaudioreg.h>
49 
50 
51 #define	GCSCAUDIO_NPRDTABLE	256	/* including a JMP-PRD for loop */
52 #define	GCSCAUDIO_PRD_SIZE_MAX	65532	/* limited by CS5536 Controller */
53 #define	GCSCAUDIO_BUFSIZE_MAX	(GCSCAUDIO_PRD_SIZE_MAX * (GCSCAUDIO_NPRDTABLE - 1))
54 
55 struct gcscaudio_prd {
56 	/* PRD table for play/rec */
57 	struct gcscaudio_prdtables {
58 #define	PRD_TABLE_FRONT		0
59 #define	PRD_TABLE_SURR		1
60 #define	PRD_TABLE_CENTER	2
61 #define	PRD_TABLE_LFE		3
62 #define	PRD_TABLE_REC		4
63 #define	PRD_TABLE_MAX		5
64 		struct acc_prd prdtbl[PRD_TABLE_MAX][GCSCAUDIO_NPRDTABLE];
65 	} *p_prdtables;
66 	bus_dmamap_t p_prdmap;
67 	bus_dma_segment_t p_prdsegs[1];
68 	int p_prdnseg;
69 };
70 
71 struct gcscaudio_dma {
72 	LIST_ENTRY(gcscaudio_dma) list;
73 	bus_dmamap_t map;
74 	void *addr;
75 	size_t size;
76 	bus_dma_segment_t segs[1];
77 	int nseg;
78 };
79 
80 struct gcscaudio_softc_ch {
81 	void (*ch_intr)(void *);
82 	void *ch_intr_arg;
83 	struct audio_params ch_params;
84 };
85 
86 struct gcscaudio_softc {
87 	device_t sc_dev;
88 	kmutex_t sc_lock;
89 	kmutex_t sc_intr_lock;
90 	pci_chipset_tag_t sc_pc;
91 	pcitag_t sc_pt;
92 	void *sc_ih;
93 	bus_space_tag_t sc_iot;
94 	bus_space_handle_t sc_ioh;
95 	bus_size_t sc_ios;
96 	bus_dma_tag_t sc_dmat;
97 
98 	/* allocated DMA buffer list */
99 	LIST_HEAD(, gcscaudio_dma) sc_dmalist;
100 
101 #define GCSCAUDIO_MAXFORMATS	4
102 	struct audio_format sc_formats[GCSCAUDIO_MAXFORMATS];
103 	int sc_nformats;
104 	struct audio_encoding_set *sc_encodings;
105 
106 	/* AC97 codec */
107 	struct ac97_host_if host_if;
108 	struct ac97_codec_if *codec_if;
109 
110 	/* input, output channels */
111 	struct gcscaudio_softc_ch sc_play;
112 	struct gcscaudio_softc_ch sc_rec;
113 	struct gcscaudio_prd sc_prd;
114 
115 	/* multi channel splitter work; {4,6}ch stream to {2,4} DMA buffers */
116 	void *sc_mch_split_buf;
117 	void *sc_mch_split_start;
118 	int sc_mch_split_off;
119 	int sc_mch_split_size;
120 	int sc_mch_split_blksize;
121 	void (*sc_mch_splitter)(void *, void *, int, int);
122 	bool sc_spdif;
123 };
124 
125 /* for cfattach */
126 static int gcscaudio_match(device_t, cfdata_t, void *);
127 static void gcscaudio_attach(device_t, device_t, void *);
128 
129 /* for audio_hw_if */
130 static int gcscaudio_open(void *, int);
131 static void gcscaudio_close(void *);
132 static int gcscaudio_query_encoding(void *, struct audio_encoding *);
133 static int gcscaudio_set_params(void *, int, int, audio_params_t *,
134                                 audio_params_t *, stream_filter_list_t *,
135                                 stream_filter_list_t *);
136 static int gcscaudio_round_blocksize(void *, int, int, const audio_params_t *);
137 static int gcscaudio_halt_output(void *);
138 static int gcscaudio_halt_input(void *);
139 static int gcscaudio_getdev(void *, struct audio_device *);
140 static int gcscaudio_set_port(void *, mixer_ctrl_t *);
141 static int gcscaudio_get_port(void *, mixer_ctrl_t *);
142 static int gcscaudio_query_devinfo(void *, mixer_devinfo_t *);
143 static void *gcscaudio_malloc(void *, int, size_t);
144 static void gcscaudio_free(void *, void *, size_t);
145 static size_t gcscaudio_round_buffersize(void *, int, size_t);
146 static paddr_t gcscaudio_mappage(void *, void *, off_t, int);
147 static int gcscaudio_get_props(void *);
148 static int gcscaudio_trigger_output(void *, void *, void *, int,
149                                     void (*)(void *), void *,
150                                     const audio_params_t *);
151 static int gcscaudio_trigger_input(void *, void *, void *, int,
152                                    void (*)(void *), void *,
153                                    const audio_params_t *);
154 static void gcscaudio_get_locks(void *, kmutex_t **, kmutex_t **);
155 static bool gcscaudio_resume(device_t, const pmf_qual_t *);
156 static int gcscaudio_intr(void *);
157 
158 /* for codec_if */
159 static int gcscaudio_attach_codec(void *, struct ac97_codec_if *);
160 static int gcscaudio_write_codec(void *, uint8_t, uint16_t);
161 static int gcscaudio_read_codec(void *, uint8_t, uint16_t *);
162 static int gcscaudio_reset_codec(void *);
163 static void gcscaudio_spdif_event_codec(void *, bool);
164 
165 /* misc */
166 static int gcscaudio_append_formats(struct gcscaudio_softc *,
167                                     const struct audio_format *);
168 static int gcscaudio_wait_ready_codec(struct gcscaudio_softc *sc, const char *);
169 static int gcscaudio_set_params_ch(struct gcscaudio_softc *,
170                                    struct gcscaudio_softc_ch *, int,
171                                    audio_params_t *, stream_filter_list_t *);
172 static int gcscaudio_allocate_dma(struct gcscaudio_softc *, size_t, void **,
173                                   bus_dma_segment_t *, int, int *,
174                                   bus_dmamap_t *);
175 
176 
177 CFATTACH_DECL_NEW(gcscaudio, sizeof (struct gcscaudio_softc),
178     gcscaudio_match, gcscaudio_attach, NULL, NULL);
179 
180 
181 static struct audio_device gcscaudio_device = {
182 	"AMD Geode CS5536",
183 	"",
184 	"gcscaudio"
185 };
186 
187 static const struct audio_hw_if gcscaudio_hw_if = {
188 	.open			= gcscaudio_open,
189 	.close			= gcscaudio_close,
190 	.drain			= NULL,
191 	.query_encoding		= gcscaudio_query_encoding,
192 	.set_params		= gcscaudio_set_params,
193 	.round_blocksize	= gcscaudio_round_blocksize,
194 	.commit_settings	= NULL,
195 	.init_output		= NULL,
196 	.init_input		= NULL,
197 	.start_output		= NULL,
198 	.start_input		= NULL,
199 	.halt_output		= gcscaudio_halt_output,
200 	.halt_input		= gcscaudio_halt_input,
201 	.speaker_ctl		= NULL,
202 	.getdev			= gcscaudio_getdev,
203 	.setfd			= NULL,
204 	.set_port		= gcscaudio_set_port,
205 	.get_port		= gcscaudio_get_port,
206 	.query_devinfo		= gcscaudio_query_devinfo,
207 	.allocm			= gcscaudio_malloc,
208 	.freem			= gcscaudio_free,
209 	.round_buffersize	= gcscaudio_round_buffersize,
210 	.mappage		= gcscaudio_mappage,
211 	.get_props		= gcscaudio_get_props,
212 	.trigger_output		= gcscaudio_trigger_output,
213 	.trigger_input		= gcscaudio_trigger_input,
214 	.dev_ioctl		= NULL,
215 	.get_locks		= gcscaudio_get_locks,
216 };
217 
218 static const struct audio_format gcscaudio_formats_2ch = {
219 	NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 16, 16,
220 	2, AUFMT_STEREO, 0, {8000, 48000}
221 };
222 
223 static const struct audio_format gcscaudio_formats_4ch = {
224 	NULL, AUMODE_PLAY, AUDIO_ENCODING_SLINEAR_LE, 16, 16,
225 	4, AUFMT_SURROUND4, 0, {8000, 48000}
226 };
227 
228 static const struct audio_format gcscaudio_formats_6ch = {
229 	NULL, AUMODE_PLAY, AUDIO_ENCODING_SLINEAR_LE, 16, 16,
230 	6, AUFMT_DOLBY_5_1, 0, {8000, 48000}
231 };
232 
233 static int
234 gcscaudio_match(device_t parent, cfdata_t match, void *aux)
235 {
236 	struct pci_attach_args *pa;
237 
238 	pa = (struct pci_attach_args *)aux;
239 	if ((PCI_VENDOR(pa->pa_id) == PCI_VENDOR_AMD) &&
240 	    (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AMD_CS5536_AUDIO))
241 		return 1;
242 
243 	return 0;
244 }
245 
246 static int
247 gcscaudio_append_formats(struct gcscaudio_softc *sc,
248                          const struct audio_format *format)
249 {
250 	if (sc->sc_nformats >= GCSCAUDIO_MAXFORMATS) {
251 		aprint_error_dev(sc->sc_dev, "too many formats\n");
252 		return EINVAL;
253 	}
254 	sc->sc_formats[sc->sc_nformats++] = *format;
255 	return 0;
256 }
257 
258 static void
259 gcscaudio_attach(device_t parent, device_t self, void *aux)
260 {
261 	struct gcscaudio_softc *sc;
262 	struct pci_attach_args *pa;
263 	const char *intrstr;
264 	pci_intr_handle_t ih;
265 	int rc, i;
266 
267 	sc = device_private(self);
268 
269 	sc->sc_dev = self;
270 
271 	aprint_naive(": Audio controller\n");
272 
273 	pa = aux;
274 	sc->sc_pc = pa->pa_pc;
275 	sc->sc_pt = pa->pa_tag;
276 	sc->sc_dmat = pa->pa_dmat;
277 	LIST_INIT(&sc->sc_dmalist);
278 	sc->sc_mch_split_buf = NULL;
279 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
280 	mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO);
281 
282 	aprint_normal(": AMD Geode CS5536 Audio\n");
283 
284 	if (pci_mapreg_map(pa, PCI_MAPREG_START, PCI_MAPREG_TYPE_IO, 0,
285 	    &sc->sc_iot, &sc->sc_ioh, NULL, &sc->sc_ios)) {
286 		aprint_error_dev(sc->sc_dev, "can't map i/o space\n");
287 		return;
288 	}
289 
290 	if (pci_intr_map(pa, &ih)) {
291 		aprint_error_dev(sc->sc_dev, "couldn't map interrupt\n");
292 		goto attach_failure_unmap;
293 	}
294 	intrstr = pci_intr_string(sc->sc_pc, ih);
295 
296 	sc->sc_ih = pci_intr_establish(sc->sc_pc, ih, IPL_AUDIO,
297 	    gcscaudio_intr, sc);
298 	if (sc->sc_ih == NULL) {
299 		aprint_error_dev(sc->sc_dev, "couldn't establish interrupt");
300 		if (intrstr != NULL)
301 			aprint_error(" at %s", intrstr);
302 		aprint_error("\n");
303 		goto attach_failure_unmap;
304 	}
305 
306 	aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr);
307 
308 
309 	if (gcscaudio_allocate_dma(sc, sizeof(*sc->sc_prd.p_prdtables),
310 	    (void **)&(sc->sc_prd.p_prdtables), sc->sc_prd.p_prdsegs, 1,
311 	    &(sc->sc_prd.p_prdnseg), &(sc->sc_prd.p_prdmap)) != 0)
312 		goto attach_failure_intr;
313 
314 	sc->host_if.arg = sc;
315 	sc->host_if.attach = gcscaudio_attach_codec;
316 	sc->host_if.read = gcscaudio_read_codec;
317 	sc->host_if.write = gcscaudio_write_codec;
318 	sc->host_if.reset = gcscaudio_reset_codec;
319 	sc->host_if.spdif_event = gcscaudio_spdif_event_codec;
320 
321 	if ((rc = ac97_attach(&sc->host_if, self, &sc->sc_lock)) != 0) {
322 		aprint_error_dev(sc->sc_dev,
323 		    "can't attach codec (error=%d)\n", rc);
324 		goto attach_failure_intr;
325 	}
326 
327 	if (!pmf_device_register(self, NULL, gcscaudio_resume))
328 		aprint_error_dev(self, "couldn't establish power handler\n");
329 
330 
331 	sc->sc_nformats = 0;
332 	gcscaudio_append_formats(sc, &gcscaudio_formats_2ch);
333 
334 	mutex_enter(&sc->sc_lock);
335 	if (AC97_IS_4CH(sc->codec_if))
336 		gcscaudio_append_formats(sc, &gcscaudio_formats_4ch);
337 	if (AC97_IS_6CH(sc->codec_if))
338 		gcscaudio_append_formats(sc, &gcscaudio_formats_6ch);
339 	if (AC97_IS_FIXED_RATE(sc->codec_if)) {
340 		for (i = 0; i < sc->sc_nformats; i++) {
341 			sc->sc_formats[i].frequency_type = 1;
342 			sc->sc_formats[i].frequency[0] = 48000;
343 		}
344 	}
345 	mutex_exit(&sc->sc_lock);
346 
347 	if ((rc = auconv_create_encodings(sc->sc_formats, sc->sc_nformats,
348 	    &sc->sc_encodings)) != 0) {
349 		aprint_error_dev(self,
350 		    "auconv_create_encoding: error=%d\n", rc);
351 		goto attach_failure_codec;
352 	}
353 
354 	audio_attach_mi(&gcscaudio_hw_if, sc, sc->sc_dev);
355 	return;
356 
357 attach_failure_codec:
358 	sc->codec_if->vtbl->detach(sc->codec_if);
359 attach_failure_intr:
360 	pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
361 attach_failure_unmap:
362 	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
363 	return;
364 }
365 
366 static int
367 gcscaudio_attach_codec(void *arg, struct ac97_codec_if *codec_if)
368 {
369 	struct gcscaudio_softc *sc;
370 
371 	sc = (struct gcscaudio_softc *)arg;
372 	sc->codec_if = codec_if;
373 	return 0;
374 }
375 
376 static int
377 gcscaudio_reset_codec(void *arg)
378 {
379 	struct gcscaudio_softc *sc;
380 	sc = (struct gcscaudio_softc *)arg;
381 
382 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_CODEC_CNTL,
383 	    ACC_CODEC_CNTL_LNK_WRM_RST |
384 	    ACC_CODEC_CNTL_CMD_NEW);
385 
386 	if (gcscaudio_wait_ready_codec(sc, "reset timeout\n"))
387 		return 1;
388 
389 	return 0;
390 }
391 
392 static void
393 gcscaudio_spdif_event_codec(void *arg, bool flag)
394 {
395 	struct gcscaudio_softc *sc;
396 
397 	sc = (struct gcscaudio_softc *)arg;
398 	sc->sc_spdif = flag;
399 }
400 
401 static int
402 gcscaudio_wait_ready_codec(struct gcscaudio_softc *sc, const char *timeout_msg)
403 {
404 	int i;
405 
406 #define GCSCAUDIO_WAIT_READY_CODEC_TIMEOUT	500
407 	for (i = GCSCAUDIO_WAIT_READY_CODEC_TIMEOUT; (i >= 0) &&
408 	    (bus_space_read_4(sc->sc_iot, sc->sc_ioh, ACC_CODEC_CNTL) &
409 	    ACC_CODEC_CNTL_CMD_NEW); i--)
410 		delay(1);
411 
412 	if (i < 0) {
413 		aprint_error_dev(sc->sc_dev, "%s", timeout_msg);
414 		return 1;
415 	}
416 
417 	return 0;
418 }
419 
420 static int
421 gcscaudio_write_codec(void *arg, uint8_t reg, uint16_t val)
422 {
423 	struct gcscaudio_softc *sc;
424 
425 	sc = (struct gcscaudio_softc *)arg;
426 
427 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_CODEC_CNTL,
428 	    ACC_CODEC_CNTL_WRITE_CMD |
429 	    ACC_CODEC_CNTL_CMD_NEW |
430 	    ACC_CODEC_REG2ADDR(reg) |
431 	    (val & ACC_CODEC_CNTL_CMD_DATA_MASK));
432 
433 	if (gcscaudio_wait_ready_codec(sc, "codec write timeout\n"))
434 		return 1;
435 
436 #ifdef GCSCAUDIO_CODEC_DEBUG
437 	aprint_error_dev(sc->sc_dev, "codec write: reg=0x%02x, val=0x%04x\n",
438 	    reg, val);
439 #endif
440 
441 	return 0;
442 }
443 
444 static int
445 gcscaudio_read_codec(void *arg, uint8_t reg, uint16_t *val)
446 {
447 	struct gcscaudio_softc *sc;
448 	uint32_t v;
449 	int i;
450 
451 	sc = (struct gcscaudio_softc *)arg;
452 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_CODEC_CNTL,
453 	    ACC_CODEC_CNTL_READ_CMD | ACC_CODEC_CNTL_CMD_NEW |
454 	    ACC_CODEC_REG2ADDR(reg));
455 
456 	if (gcscaudio_wait_ready_codec(sc, "codec write timeout for reading"))
457 		return 1;
458 
459 #define GCSCAUDIO_READ_CODEC_TIMEOUT	50
460 	for (i = GCSCAUDIO_READ_CODEC_TIMEOUT; i >= 0; i--) {
461 		v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, ACC_CODEC_STATUS);
462 		if ((v & ACC_CODEC_STATUS_STS_NEW) &&
463 		    (ACC_CODEC_ADDR2REG(v) == reg))
464 			break;
465 
466 		delay(10);
467 	}
468 
469 	if (i < 0) {
470 		aprint_error_dev(sc->sc_dev, "codec read timeout\n");
471 		return 1;
472 	}
473 
474 #ifdef GCSCAUDIO_CODEC_DEBUG
475 	aprint_error_dev(sc->sc_dev, "codec read: reg=0x%02x, val=0x%04x\n",
476 	    reg, v & ACC_CODEC_STATUS_STS_DATA_MASK);
477 #endif
478 
479 	*val = v;
480 	return 0;
481 }
482 
483 static int
484 gcscaudio_open(void *arg, int flags)
485 {
486 	struct gcscaudio_softc *sc;
487 
488 	sc = (struct gcscaudio_softc *)arg;
489 	sc->codec_if->vtbl->lock(sc->codec_if);
490 	return 0;
491 }
492 
493 static void
494 gcscaudio_close(void *arg)
495 {
496 	struct gcscaudio_softc *sc;
497 
498 	sc = (struct gcscaudio_softc *)arg;
499 	sc->codec_if->vtbl->unlock(sc->codec_if);
500 }
501 
502 static int
503 gcscaudio_query_encoding(void *arg, struct audio_encoding *fp)
504 {
505 	struct gcscaudio_softc *sc;
506 
507 	sc = (struct gcscaudio_softc *)arg;
508 	return auconv_query_encoding(sc->sc_encodings, fp);
509 }
510 
511 static int
512 gcscaudio_set_params_ch(struct gcscaudio_softc *sc,
513                         struct gcscaudio_softc_ch *ch, int mode,
514                         audio_params_t *p, stream_filter_list_t *fil)
515 {
516 	int error, idx;
517 
518 	if ((p->sample_rate < 8000) || (p->sample_rate > 48000))
519 		return EINVAL;
520 
521 	if (p->precision != 8 && p->precision != 16)
522 		return EINVAL;
523 
524 	if ((idx = auconv_set_converter(sc->sc_formats, sc->sc_nformats,
525 	    mode, p, TRUE, fil)) < 0)
526 		return EINVAL;
527 
528 	if (fil->req_size > 0)
529 		p = &fil->filters[0].param;
530 
531 	if (mode == AUMODE_PLAY) {
532 		if (!AC97_IS_FIXED_RATE(sc->codec_if)) {
533 			/* setup rate of DAC/ADC */
534 			if ((error = sc->codec_if->vtbl->set_rate(sc->codec_if,
535 			    AC97_REG_PCM_LR_ADC_RATE, &p->sample_rate)) != 0)
536 				return error;
537 
538 			/* additional rate of DAC for Surround */
539 			if ((p->channels >= 4) &&
540 			    (error = sc->codec_if->vtbl->set_rate(sc->codec_if,
541 			    AC97_REG_PCM_SURR_DAC_RATE, &p->sample_rate)) != 0)
542 				return error;
543 
544 			/* additional rate of DAC for LowFrequencyEffect */
545 			if ((p->channels == 6) &&
546 			    (error = sc->codec_if->vtbl->set_rate(sc->codec_if,
547 			    AC97_REG_PCM_LFE_DAC_RATE, &p->sample_rate)) != 0)
548 				return error;
549 		}
550 	}
551 
552 	if (mode == AUMODE_RECORD) {
553 		if (!AC97_IS_FIXED_RATE(sc->codec_if)) {
554 			/* setup rate of DAC/ADC */
555 			if ((error = sc->codec_if->vtbl->set_rate(sc->codec_if,
556 			    AC97_REG_PCM_FRONT_DAC_RATE, &p->sample_rate)) != 0)
557 				return error;
558 		}
559 	}
560 
561 	ch->ch_params = *p;
562 	return 0;
563 }
564 
565 static int
566 gcscaudio_set_params(void *arg, int setmode, int usemode,
567                      audio_params_t *play, audio_params_t *rec,
568                      stream_filter_list_t *pfil, stream_filter_list_t *rfil)
569 {
570 	struct gcscaudio_softc *sc;
571 	int error;
572 
573 	sc = (struct gcscaudio_softc *)arg;
574 
575 	if (setmode & AUMODE_PLAY) {
576 		if ((error = gcscaudio_set_params_ch(sc, &sc->sc_play,
577 		    AUMODE_PLAY, play, pfil)) != 0)
578 			return error;
579 	}
580 	if (setmode & AUMODE_RECORD) {
581 		if ((error = gcscaudio_set_params_ch(sc, &sc->sc_rec,
582 		    AUMODE_RECORD, rec, rfil)) != 0)
583 			return error;
584 	}
585 
586 	return 0;
587 }
588 
589 static int
590 gcscaudio_round_blocksize(void *arg, int blk, int mode,
591                           const audio_params_t *param)
592 {
593 	blk &= -4;
594 	if (blk > GCSCAUDIO_PRD_SIZE_MAX)
595 		blk = GCSCAUDIO_PRD_SIZE_MAX;
596 
597 	return blk;
598 }
599 
600 static int
601 gcscaudio_halt_output(void *arg)
602 {
603 	struct gcscaudio_softc *sc;
604 
605 	sc = (struct gcscaudio_softc *)arg;
606 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM0_CMD,
607 	    ACC_BMx_CMD_BM_CTL_DISABLE);
608 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM4_CMD,
609 	    ACC_BMx_CMD_BM_CTL_DISABLE);
610 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM6_CMD,
611 	    ACC_BMx_CMD_BM_CTL_DISABLE);
612 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM7_CMD,
613 	    ACC_BMx_CMD_BM_CTL_DISABLE);
614 	sc->sc_play.ch_intr = NULL;
615 
616 	/* channel splitter */
617 	sc->sc_mch_splitter = NULL;
618 	if (sc->sc_mch_split_buf)
619 		gcscaudio_free(sc, sc->sc_mch_split_buf, sc->sc_mch_split_size);
620 	sc->sc_mch_split_buf = NULL;
621 
622 	return 0;
623 }
624 
625 static int
626 gcscaudio_halt_input(void *arg)
627 {
628 	struct gcscaudio_softc *sc;
629 
630 	sc = (struct gcscaudio_softc *)arg;
631 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM1_CMD,
632 	    ACC_BMx_CMD_BM_CTL_DISABLE);
633 	sc->sc_rec.ch_intr = NULL;
634 	return 0;
635 }
636 
637 static int
638 gcscaudio_getdev(void *addr, struct audio_device *retp)
639 {
640 	*retp = gcscaudio_device;
641 	return 0;
642 }
643 
644 static int
645 gcscaudio_set_port(void *addr, mixer_ctrl_t *cp)
646 {
647 	struct gcscaudio_softc *sc;
648 
649 	sc = addr;
650 	return sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp);
651 }
652 
653 static int
654 gcscaudio_get_port(void *addr, mixer_ctrl_t *cp)
655 {
656 	struct gcscaudio_softc *sc;
657 
658 	sc = addr;
659 	return sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp);
660 }
661 
662 static int
663 gcscaudio_query_devinfo(void *addr, mixer_devinfo_t *dip)
664 {
665 	struct gcscaudio_softc *sc;
666 
667 	sc = addr;
668 	return sc->codec_if->vtbl->query_devinfo(sc->codec_if, dip);
669 }
670 
671 static void *
672 gcscaudio_malloc(void *arg, int direction, size_t size)
673 {
674 	struct gcscaudio_softc *sc;
675 	struct gcscaudio_dma *p;
676 	int error;
677 
678 	sc = (struct gcscaudio_softc *)arg;
679 
680 	p = kmem_alloc(sizeof(*p), KM_SLEEP);
681 	if (p == NULL)
682 		return NULL;
683 	p->size = size;
684 
685 	error = gcscaudio_allocate_dma(sc, size, &p->addr,
686 	    p->segs, sizeof(p->segs)/sizeof(p->segs[0]), &p->nseg, &p->map);
687 	if (error) {
688 		kmem_free(p, sizeof(*p));
689 		return NULL;
690 	}
691 
692 	LIST_INSERT_HEAD(&sc->sc_dmalist, p, list);
693 	return p->addr;
694 }
695 
696 static void
697 gcscaudio_free(void *arg, void *ptr, size_t size)
698 {
699 	struct gcscaudio_softc *sc;
700 	struct gcscaudio_dma *p;
701 
702 	sc = (struct gcscaudio_softc *)arg;
703 
704 	LIST_FOREACH(p, &sc->sc_dmalist, list) {
705 		if (p->addr == ptr) {
706 			bus_dmamap_unload(sc->sc_dmat, p->map);
707 			bus_dmamap_destroy(sc->sc_dmat, p->map);
708 			bus_dmamem_unmap(sc->sc_dmat, p->addr, p->size);
709 			bus_dmamem_free(sc->sc_dmat, p->segs, p->nseg);
710 
711 			LIST_REMOVE(p, list);
712 			kmem_free(p, sizeof(*p));
713 			break;
714 		}
715 	}
716 }
717 
718 static paddr_t
719 gcscaudio_mappage(void *arg, void *mem, off_t off, int prot)
720 {
721 	struct gcscaudio_softc *sc;
722 	struct gcscaudio_dma *p;
723 
724 	if (off < 0)
725 		return -1;
726 
727 	sc = (struct gcscaudio_softc *)arg;
728 	LIST_FOREACH(p, &sc->sc_dmalist, list) {
729 		if (p->addr == mem) {
730 			return bus_dmamem_mmap(sc->sc_dmat, p->segs, p->nseg,
731 			    off, prot, BUS_DMA_WAITOK);
732 		}
733 	}
734 
735 	return -1;
736 }
737 
738 static size_t
739 gcscaudio_round_buffersize(void *addr, int direction, size_t size)
740 {
741 	if (size > GCSCAUDIO_BUFSIZE_MAX)
742 		size = GCSCAUDIO_BUFSIZE_MAX;
743 
744 	return size;
745 }
746 
747 static int
748 gcscaudio_get_props(void *addr)
749 {
750 	struct gcscaudio_softc *sc;
751 	int props;
752 
753 	sc = (struct gcscaudio_softc *)addr;
754 	props = AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
755 	/*
756 	 * Even if the codec is fixed-rate, set_param() succeeds for any sample
757 	 * rate because of aurateconv.  Applications can't know what rate the
758 	 * device can process in the case of mmap().
759 	 */
760 	if (!AC97_IS_FIXED_RATE(sc->codec_if))
761 		props |= AUDIO_PROP_MMAP;
762 	return props;
763 }
764 
765 static int
766 build_prdtables(struct gcscaudio_softc *sc, int prdidx,
767                 void *addr, size_t size, int blksize, int blklen, int blkoff)
768 {
769 	struct gcscaudio_dma *p;
770 	struct acc_prd *prdp;
771 	bus_addr_t paddr;
772 	int i;
773 
774 	/* get physical address of start */
775 	paddr = (bus_addr_t)0;
776 	LIST_FOREACH(p, &sc->sc_dmalist, list) {
777 		if (p->addr == addr) {
778 			paddr = p->map->dm_segs[0].ds_addr;
779 			break;
780 		}
781 	}
782 	if (!paddr) {
783 		aprint_error_dev(sc->sc_dev, "bad addr %p\n", addr);
784 		return EINVAL;
785 	}
786 
787 #define PRDADDR(prdidx,idx) \
788 	(sc->sc_prd.p_prdmap->dm_segs[0].ds_addr) + sizeof(struct acc_prd) * \
789 	(((prdidx) * GCSCAUDIO_NPRDTABLE) + (idx))
790 
791 	/*
792 	 * build PRD table
793 	 *   prdtbl[] = <PRD0>, <PRD1>, <PRD2>, ..., <PRDn>, <jmp to PRD0>
794 	 */
795 	prdp = sc->sc_prd.p_prdtables->prdtbl[prdidx];
796 	for (i = 0; size > 0; size -= blksize, i++) {
797 		prdp[i].address = paddr + blksize * i + blkoff;
798 		prdp[i].ctrlsize =
799 		    (size < blklen ? size : blklen) | ACC_BMx_PRD_CTRL_EOP;
800 	}
801 	prdp[i].address = PRDADDR(prdidx, 0);
802 	prdp[i].ctrlsize = ACC_BMx_PRD_CTRL_JMP;
803 
804 	bus_dmamap_sync(sc->sc_dmat, sc->sc_prd.p_prdmap, 0,
805 	    sizeof(struct acc_prd) * i, BUS_DMASYNC_PREWRITE);
806 
807 	return 0;
808 }
809 
810 static void
811 split_buffer_4ch(void *dst, void *src, int size, int blksize)
812 {
813 	int left, i;
814 	uint16_t *s, *d;
815 
816 	/*
817 	 * src[blk0]: L,R,SL,SR,L,R,SL,SR,L,R,SL,SR,....
818 	 * src[blk1]: L,R,SL,SR,L,R,SL,SR,L,R,SL,SR,....
819 	 * src[blk2]: L,R,SL,SR,L,R,SL,SR,L,R,SL,SR,....
820 	 *     :
821 	 *
822 	 *   rearrange to
823 	 *
824 	 * src[blk0]: L,R,L,R,L,R,L,R,..
825 	 * src[blk1]: L,R,L,R,L,R,L,R,..
826 	 * src[blk2]: L,R,L,R,L,R,L,R,..
827 	 *     :
828 	 * dst[blk0]: SL,SR,SL,SR,SL,SR,SL,SR,..
829 	 * dst[blk1]: SL,SR,SL,SR,SL,SR,SL,SR,..
830 	 * dst[blk2]: SL,SR,SL,SR,SL,SR,SL,SR,..
831 	 *     :
832 	 */
833 	for (left = size; left > 0; left -= blksize) {
834 		s = (uint16_t *)src;
835 		d = (uint16_t *)dst;
836 		for (i = 0; i < blksize / sizeof(uint16_t) / 4; i++) {
837 			/* L,R,SL,SR -> SL,SR */
838 			s++;
839 			s++;
840 			*d++ = *s++;
841 			*d++ = *s++;
842 		}
843 
844 		s = (uint16_t *)src;
845 		d = (uint16_t *)src;
846 		for (i = 0; i < blksize / sizeof(uint16_t) / 2 / 2; i++) {
847 			/* L,R,SL,SR -> L,R */
848 			*d++ = *s++;
849 			*d++ = *s++;
850 			s++;
851 			s++;
852 		}
853 
854 		src = (char *)src + blksize;
855 		dst = (char *)dst + blksize;
856 	}
857 }
858 
859 static void
860 split_buffer_6ch(void *dst, void *src, int size, int blksize)
861 {
862 	int left, i;
863 	uint16_t *s, *d, *dc, *dl;
864 
865 	/*
866 	 * by default, treat as WAV style 5.1ch order
867 	 *   5.1ch(WAV): L R C LFE SL SR
868 	 *   5.1ch(AAC): C L R SL SR LFE
869 	 *        :
870 	 */
871 
872 	/*
873 	 * src[blk0]: L,R,C,LFE,SL,SR,L,R,C,LFE,SL,SR,...
874 	 * src[blk1]: L,R,C,LFE,SL,SR,L,R,C,LFE,SL,SR,...
875 	 * src[blk2]: L,R,C,LFE,SL,SR,L,R,C,LFE,SL,SR,...
876 	 *     :
877 	 * src[N-1] : L,R,C,LFE,SL,SR,L,R,C,LFE,SL,SR,...
878 	 *
879 	 *   rearrange to
880 	 *
881 	 * src[blk0]: L,R,L,R,..
882 	 * src[blk1]: L,R,L,R,..
883 	 * src[blk2]: L,R,L,R,..
884 	 *     :
885 	 *
886 	 * dst[blk0]: SL,SR,SL,SR,..
887 	 * dst[blk1]: SL,SR,SL,SR,..
888 	 * dst[blk2]: SL,SR,SL,SR,..
889 	 *     :
890 	 *
891 	 * dst[N/2+0]: C,C,C,..
892 	 * dst[N/2+1]: C,C,C,..
893 	 *     :
894 	 *
895 	 * dst[N/2+N/4+0]: LFE,LFE,LFE,..
896 	 * dst[N/2+N/4+1]: LFE,LFE,LFE,..
897 	 *     :
898 	 */
899 
900 	for (left = size; left > 0; left -= blksize) {
901 		s = (uint16_t *)src;
902 		d = (uint16_t *)dst;
903 		dc = (uint16_t *)((char *)dst + blksize / 2);
904 		dl = (uint16_t *)((char *)dst + blksize / 2 + blksize / 4);
905 		for (i = 0; i < blksize / sizeof(uint16_t) / 6; i++) {
906 #ifdef GCSCAUDIO_5_1CH_AAC_ORDER
907 			/*
908 			 * AAC: [C,L,R,SL,SR,LFE]
909 			 *  => [SL,SR]
910 			 *  => [C]
911 			 *  => [LFE]
912 			 */
913 			*dc++ = s[0];	/* C */
914 			*dl++ = s[5];	/* LFE */
915 			*d++ = s[3];	/* SL */
916 			*d++ = s[4];	/* SR */
917 #else
918 			/*
919 			 * WAV: [L,R,C,LFE,SL,SR]
920 			 *  => [SL,SR]
921 			 *  => [C]
922 			 *  => [LFE]
923 			 */
924 			*dc++ = s[2];	/* C */
925 			*dl++ = s[3];	/* LFE */
926 			*d++ = s[4];	/* SL */
927 			*d++ = s[5];	/* SR */
928 #endif
929 			s += 6;
930 		}
931 
932 		s = (uint16_t *)src;
933 		d = (uint16_t *)src;
934 		for (i = 0; i < blksize / sizeof(uint16_t) / 2 / 2; i++) {
935 #ifdef GCSCAUDIO_5_1CH_AAC_ORDER
936 			/* AAC: [C,L,R,SL,SR,LFE] => [L,R] */
937 			*d++ = s[1];
938 			*d++ = s[2];
939 #else
940 			/* WAV: [L,R,C,LFE,SL,SR] => [L,R] */
941 			*d++ = s[0];
942 			*d++ = s[1];
943 #endif
944 			s += 6;
945 		}
946 
947 		src = (char *)src + blksize;
948 		dst = (char *)dst + blksize;
949 	}
950 }
951 
952 static void
953 channel_splitter(struct gcscaudio_softc *sc)
954 {
955 	int splitsize, left;
956 	void *src, *dst;
957 
958 	if (sc->sc_mch_splitter == NULL)
959 		return;
960 
961 	left = sc->sc_mch_split_size - sc->sc_mch_split_off;
962 	splitsize = sc->sc_mch_split_blksize;
963 	if (left < splitsize)
964 		splitsize = left;
965 
966 	src = (char *)sc->sc_mch_split_start + sc->sc_mch_split_off;
967 	dst = (char *)sc->sc_mch_split_buf + sc->sc_mch_split_off;
968 
969 	sc->sc_mch_splitter(dst, src, splitsize, sc->sc_mch_split_blksize);
970 
971 	sc->sc_mch_split_off += sc->sc_mch_split_blksize;
972 	if (sc->sc_mch_split_off >= sc->sc_mch_split_size)
973 		sc->sc_mch_split_off = 0;
974 }
975 
976 static int
977 gcscaudio_trigger_output(void *addr, void *start, void *end, int blksize,
978                          void (*intr)(void *), void *arg,
979                          const audio_params_t *param)
980 {
981 	struct gcscaudio_softc *sc;
982 	size_t size;
983 
984 	sc = (struct gcscaudio_softc *)addr;
985 	sc->sc_play.ch_intr = intr;
986 	sc->sc_play.ch_intr_arg = arg;
987 	size = (char *)end - (char *)start;
988 
989 	switch (sc->sc_play.ch_params.channels) {
990 	case 2:
991 		if (build_prdtables(sc, PRD_TABLE_FRONT, start, size, blksize,
992 		    blksize, 0))
993 			return EINVAL;
994 
995 		if (!AC97_IS_4CH(sc->codec_if)) {
996 			/*
997 			 * output 2ch PCM to FRONT.LR(BM0)
998 			 *
999 			 * 2ch: L,R,L,R,L,R,L,R,... => BM0: L,R,L,R,L,R,L,R,...
1000 			 *
1001 			 */
1002 			bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM0_PRD,
1003 			    PRDADDR(PRD_TABLE_FRONT, 0));
1004 
1005 			/* start DMA transfer */
1006 			bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM0_CMD,
1007 			    ACC_BMx_CMD_WRITE |
1008 			    ACC_BMx_CMD_BYTE_ORD_EL |
1009 			    ACC_BMx_CMD_BM_CTL_ENABLE);
1010 		} else {
1011 			/*
1012 			 * output same PCM to FRONT.LR(BM0) and SURROUND.LR(BM6).
1013 			 * CENTER(BM4) and LFE(BM7) doesn't sound.
1014 			 *
1015 			 * 2ch: L,R,L,R,L,R,L,R,... => BM0: L,R,L,R,L,R,L,R,...
1016 			 *                             BM6: (same of BM0)
1017 			 *                             BM4: none
1018 			 *                             BM7: none
1019 			 */
1020 			bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM0_PRD,
1021 			    PRDADDR(PRD_TABLE_FRONT, 0));
1022 			bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM6_PRD,
1023 			    PRDADDR(PRD_TABLE_FRONT, 0));
1024 
1025 			/* start DMA transfer */
1026 			bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM0_CMD,
1027 			    ACC_BMx_CMD_WRITE |
1028 			    ACC_BMx_CMD_BYTE_ORD_EL |
1029 			    ACC_BMx_CMD_BM_CTL_ENABLE);
1030 			bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM6_CMD,
1031 			    ACC_BMx_CMD_WRITE |
1032 			    ACC_BMx_CMD_BYTE_ORD_EL |
1033 			    ACC_BMx_CMD_BM_CTL_ENABLE);
1034 		}
1035 		break;
1036 	case 4:
1037 		/*
1038 		 * output 4ch PCM split to FRONT.LR(BM0) and SURROUND.LR(BM6).
1039 		 * CENTER(BM4) and LFE(BM7) doesn't sound.
1040 		 *
1041 		 * rearrange ordered channel to continuous per channel
1042 		 *
1043 		 *   4ch: L,R,SL,SR,L,R,SL,SR,... => BM0: L,R,L,R,...
1044 		 *                                   BM6: SL,SR,SL,SR,...
1045 		 *                                   BM4: none
1046 		 *                                   BM7: none
1047 		 */
1048 		if (sc->sc_mch_split_buf)
1049 			gcscaudio_free(sc, sc->sc_mch_split_buf,
1050 			    sc->sc_mch_split_size);
1051 
1052 		if ((sc->sc_mch_split_buf = gcscaudio_malloc(sc, AUMODE_PLAY,
1053 		    size)) == NULL)
1054 			return ENOMEM;
1055 
1056 		/*
1057 		 * 1st and 2nd blocks are split immediately.
1058 		 * Other blocks will be split synchronous with intr.
1059 		 */
1060 		split_buffer_4ch(sc->sc_mch_split_buf, start, blksize * 2,
1061 		    blksize);
1062 
1063 		sc->sc_mch_split_start = start;
1064 		sc->sc_mch_split_size = size;
1065 		sc->sc_mch_split_blksize = blksize;
1066 		sc->sc_mch_split_off = (blksize * 2) % size;
1067 		sc->sc_mch_splitter = split_buffer_4ch;	/* split function */
1068 
1069 		if (build_prdtables(sc, PRD_TABLE_FRONT, start, size, blksize,
1070 		    blksize / 2, 0))
1071 			return EINVAL;
1072 		if (build_prdtables(sc, PRD_TABLE_SURR, sc->sc_mch_split_buf,
1073 		    size, blksize, blksize / 2, 0))
1074 			return EINVAL;
1075 
1076 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM0_PRD,
1077 		    PRDADDR(PRD_TABLE_FRONT, 0));
1078 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM6_PRD,
1079 		    PRDADDR(PRD_TABLE_SURR, 0));
1080 
1081 		/* start DMA transfer */
1082 		bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM0_CMD,
1083 		    ACC_BMx_CMD_WRITE |
1084 		    ACC_BMx_CMD_BYTE_ORD_EL |
1085 		    ACC_BMx_CMD_BM_CTL_ENABLE);
1086 		bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM6_CMD,
1087 		    ACC_BMx_CMD_WRITE |
1088 		    ACC_BMx_CMD_BYTE_ORD_EL |
1089 		    ACC_BMx_CMD_BM_CTL_ENABLE);
1090 		break;
1091 	case 6:
1092 		/*
1093 		 * output 6ch PCM split to
1094 		 * FRONT.LR(BM0), SURROUND.LR(BM6), CENTER(BM4) and LFE(BM7)
1095 		 *
1096 		 * rearrange ordered channel to continuous per channel
1097 		 *
1098 		 *   5.1ch: L,R,C,LFE,SL,SR,... => BM0: L,R,...
1099 		 *                                 BM4: C,...
1100 		 *                                 BM6: SL,SR,...
1101 		 *                                 BM7: LFE,...
1102 		 *
1103 		 */
1104 		if (sc->sc_mch_split_buf)
1105 			gcscaudio_free(sc, sc->sc_mch_split_buf,
1106 			    sc->sc_mch_split_size);
1107 
1108 		if ((sc->sc_mch_split_buf = gcscaudio_malloc(sc, AUMODE_PLAY,
1109 		    size)) == NULL)
1110 			return ENOMEM;
1111 
1112 		/*
1113 		 * 1st and 2nd blocks are split immediately.
1114 		 * Other block will be split synchronous with intr.
1115 		 */
1116 		split_buffer_6ch(sc->sc_mch_split_buf, start, blksize * 2,
1117 		    blksize);
1118 
1119 		sc->sc_mch_split_start = start;
1120 		sc->sc_mch_split_size = size;
1121 		sc->sc_mch_split_blksize = blksize;
1122 		sc->sc_mch_split_off = (blksize * 2) % size;
1123 		sc->sc_mch_splitter = split_buffer_6ch;	/* split function */
1124 
1125 		if (build_prdtables(sc, PRD_TABLE_FRONT, start, size, blksize,
1126 		    blksize / 3, 0))
1127 			return EINVAL;
1128 		if (build_prdtables(sc, PRD_TABLE_CENTER, sc->sc_mch_split_buf,
1129 		    size, blksize, blksize / 3, blksize / 2))
1130 			return EINVAL;
1131 		if (build_prdtables(sc, PRD_TABLE_SURR, sc->sc_mch_split_buf,
1132 		    size, blksize, blksize / 3, 0))
1133 			return EINVAL;
1134 		if (build_prdtables(sc, PRD_TABLE_LFE, sc->sc_mch_split_buf,
1135 		    size, blksize, blksize / 3, blksize / 2 + blksize / 4))
1136 			return EINVAL;
1137 
1138 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM0_PRD,
1139 		    PRDADDR(PRD_TABLE_FRONT, 0));
1140 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM4_PRD,
1141 		    PRDADDR(PRD_TABLE_CENTER, 0));
1142 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM6_PRD,
1143 		    PRDADDR(PRD_TABLE_SURR, 0));
1144 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM7_PRD,
1145 		    PRDADDR(PRD_TABLE_LFE, 0));
1146 
1147 		/* start DMA transfer */
1148 		bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM0_CMD,
1149 		    ACC_BMx_CMD_WRITE | ACC_BMx_CMD_BYTE_ORD_EL |
1150 		    ACC_BMx_CMD_BM_CTL_ENABLE);
1151 		bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM4_CMD,
1152 		    ACC_BMx_CMD_WRITE | ACC_BMx_CMD_BYTE_ORD_EL |
1153 		    ACC_BMx_CMD_BM_CTL_ENABLE);
1154 		bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM6_CMD,
1155 		    ACC_BMx_CMD_WRITE | ACC_BMx_CMD_BYTE_ORD_EL |
1156 		    ACC_BMx_CMD_BM_CTL_ENABLE);
1157 		bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM7_CMD,
1158 		    ACC_BMx_CMD_WRITE | ACC_BMx_CMD_BYTE_ORD_EL |
1159 		    ACC_BMx_CMD_BM_CTL_ENABLE);
1160 		break;
1161 	}
1162 
1163 	return 0;
1164 }
1165 
1166 static int
1167 gcscaudio_trigger_input(void *addr, void *start, void *end, int blksize,
1168                         void (*intr)(void *), void *arg,
1169                         const audio_params_t *param)
1170 {
1171 	struct gcscaudio_softc *sc;
1172 	size_t size;
1173 
1174 	sc = (struct gcscaudio_softc *)addr;
1175 	sc->sc_rec.ch_intr = intr;
1176 	sc->sc_rec.ch_intr_arg = arg;
1177 	size = (char *)end - (char *)start;
1178 
1179 	if (build_prdtables(sc, PRD_TABLE_REC, start, size, blksize, blksize, 0))
1180 		return EINVAL;
1181 
1182 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, ACC_BM1_PRD,
1183 	    PRDADDR(PRD_TABLE_REC, 0));
1184 
1185 	/* start transfer */
1186 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, ACC_BM1_CMD,
1187 	    ACC_BMx_CMD_READ |
1188 	    ACC_BMx_CMD_BYTE_ORD_EL |
1189 	    ACC_BMx_CMD_BM_CTL_ENABLE);
1190 
1191 	return 0;
1192 }
1193 
1194 static void
1195 gcscaudio_get_locks(void *arg, kmutex_t **intr, kmutex_t **thread)
1196 {
1197 	struct gcscaudio_softc *sc;
1198 
1199 	sc = (struct gcscaudio_softc *)arg;
1200 
1201 	*intr = &sc->sc_intr_lock;
1202 	*thread = &sc->sc_lock;
1203 }
1204 
1205 static int
1206 gcscaudio_intr(void *arg)
1207 {
1208 	struct gcscaudio_softc *sc;
1209 	uint16_t intr;
1210 	uint8_t bmstat;
1211 	int nintr;
1212 
1213 	nintr = 0;
1214 	sc = (struct gcscaudio_softc *)arg;
1215 
1216 	mutex_spin_enter(&sc->sc_intr_lock);
1217 
1218 	intr = bus_space_read_2(sc->sc_iot, sc->sc_ioh, ACC_IRQ_STATUS);
1219 	if (intr == 0)
1220 		goto done;
1221 
1222 	/* Front output */
1223 	if (intr & ACC_IRQ_STATUS_BM0_IRQ_STS) {
1224 		bmstat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, ACC_BM0_STATUS);
1225 		if (bmstat & ACC_BMx_STATUS_BM_EOP_ERR)
1226 			aprint_normal_dev(sc->sc_dev, "BM0: Bus Master Error\n");
1227 		if (!(bmstat & ACC_BMx_STATUS_EOP))
1228 			aprint_normal_dev(sc->sc_dev, "BM0: NO End of Page?\n");
1229 
1230 		if (sc->sc_play.ch_intr) {
1231 			sc->sc_play.ch_intr(sc->sc_play.ch_intr_arg);
1232 			channel_splitter(sc);
1233 		}
1234 		nintr++;
1235 	}
1236 
1237 	/* Center output */
1238 	if (intr & ACC_IRQ_STATUS_BM4_IRQ_STS) {
1239 		bmstat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, ACC_BM4_STATUS);
1240 		if (bmstat & ACC_BMx_STATUS_BM_EOP_ERR)
1241 			aprint_normal_dev(sc->sc_dev, "BM4: Bus Master Error\n");
1242 		if (!(bmstat & ACC_BMx_STATUS_EOP))
1243 			aprint_normal_dev(sc->sc_dev, "BM4: NO End of Page?\n");
1244 
1245 		nintr++;
1246 	}
1247 
1248 	/* Surround output */
1249 	if (intr & ACC_IRQ_STATUS_BM6_IRQ_STS) {
1250 		bmstat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, ACC_BM6_STATUS);
1251 		if (bmstat & ACC_BMx_STATUS_BM_EOP_ERR)
1252 			aprint_normal_dev(sc->sc_dev, "BM6: Bus Master Error\n");
1253 		if (!(bmstat & ACC_BMx_STATUS_EOP))
1254 			aprint_normal_dev(sc->sc_dev, "BM6: NO End of Page?\n");
1255 
1256 		nintr++;
1257 	}
1258 
1259 	/* LowFrequencyEffect output */
1260 	if (intr & ACC_IRQ_STATUS_BM7_IRQ_STS) {
1261 		bmstat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, ACC_BM7_STATUS);
1262 		if (bmstat & ACC_BMx_STATUS_BM_EOP_ERR)
1263 			aprint_normal_dev(sc->sc_dev, "BM7: Bus Master Error\n");
1264 		if (!(bmstat & ACC_BMx_STATUS_EOP))
1265 			aprint_normal_dev(sc->sc_dev, "BM7: NO End of Page?\n");
1266 
1267 		nintr++;
1268 	}
1269 
1270 	/* record */
1271 	if (intr & ACC_IRQ_STATUS_BM1_IRQ_STS) {
1272 		bmstat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, ACC_BM1_STATUS);
1273 		if (bmstat & ACC_BMx_STATUS_BM_EOP_ERR)
1274 			aprint_normal_dev(sc->sc_dev, "BM1: Bus Master Error\n");
1275 		if (!(bmstat & ACC_BMx_STATUS_EOP))
1276 			aprint_normal_dev(sc->sc_dev, "BM1: NO End of Page?\n");
1277 
1278 		if (sc->sc_rec.ch_intr) {
1279 			sc->sc_rec.ch_intr(sc->sc_rec.ch_intr_arg);
1280 		}
1281 		nintr++;
1282 	}
1283 
1284 #ifdef GCSCAUDIO_DEBUG
1285 	if (intr & ACC_IRQ_STATUS_IRQ_STS)
1286 		aprint_normal_dev(sc->sc_dev, "Codec GPIO IRQ Status\n");
1287 	if (intr & ACC_IRQ_STATUS_WU_IRQ_STS)
1288 		aprint_normal_dev(sc->sc_dev, "Codec GPIO Wakeup IRQ Status\n");
1289 	if (intr & ACC_IRQ_STATUS_BM2_IRQ_STS)
1290 		aprint_normal_dev(sc->sc_dev, "Audio Bus Master 2 IRQ Status\n");
1291 	if (intr & ACC_IRQ_STATUS_BM3_IRQ_STS)
1292 		aprint_normal_dev(sc->sc_dev, "Audio Bus Master 3 IRQ Status\n");
1293 	if (intr & ACC_IRQ_STATUS_BM5_IRQ_STS)
1294 		aprint_normal_dev(sc->sc_dev, "Audio Bus Master 5 IRQ Status\n");
1295 #endif
1296 
1297 done:
1298 	mutex_spin_exit(&sc->sc_intr_lock);
1299 
1300 	return nintr ? 1 : 0;
1301 }
1302 
1303 static bool
1304 gcscaudio_resume(device_t dv, const pmf_qual_t *qual)
1305 {
1306 	struct gcscaudio_softc *sc = device_private(dv);
1307 
1308 	gcscaudio_reset_codec(sc);
1309 	DELAY(1000);
1310 	(sc->codec_if->vtbl->restore_ports)(sc->codec_if);
1311 
1312 	return true;
1313 }
1314 
1315 static int
1316 gcscaudio_allocate_dma(struct gcscaudio_softc *sc, size_t size, void **addrp,
1317                        bus_dma_segment_t *seglist, int nseg, int *rsegp,
1318                        bus_dmamap_t *mapp)
1319 {
1320 	int error;
1321 
1322 	if ((error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, seglist,
1323 	    nseg, rsegp, BUS_DMA_WAITOK)) != 0) {
1324 		aprint_error_dev(sc->sc_dev,
1325 		    "unable to allocate DMA buffer, error=%d\n", error);
1326 		goto fail_alloc;
1327 	}
1328 
1329 	if ((error = bus_dmamem_map(sc->sc_dmat, seglist, nseg, size, addrp,
1330 	    BUS_DMA_WAITOK | BUS_DMA_COHERENT)) != 0) {
1331 		aprint_error_dev(sc->sc_dev,
1332 		    "unable to map DMA buffer, error=%d\n",
1333 		    error);
1334 		goto fail_map;
1335 	}
1336 
1337 	if ((error = bus_dmamap_create(sc->sc_dmat, size, nseg, size, 0,
1338 	    BUS_DMA_WAITOK, mapp)) != 0) {
1339 		aprint_error_dev(sc->sc_dev,
1340 		    "unable to create DMA map, error=%d\n", error);
1341 		goto fail_create;
1342 	}
1343 
1344 	if ((error = bus_dmamap_load(sc->sc_dmat, *mapp, *addrp, size, NULL,
1345 	    BUS_DMA_WAITOK)) != 0) {
1346 		aprint_error_dev(sc->sc_dev,
1347 		    "unable to load DMA map, error=%d\n", error);
1348 		goto fail_load;
1349 	}
1350 
1351 	return 0;
1352 
1353 fail_load:
1354 	bus_dmamap_destroy(sc->sc_dmat, *mapp);
1355 fail_create:
1356 	bus_dmamem_unmap(sc->sc_dmat, *addrp, size);
1357 fail_map:
1358 	bus_dmamem_free(sc->sc_dmat, seglist, nseg);
1359 fail_alloc:
1360 	return error;
1361 }
1362