xref: /dragonfly/sys/dev/sound/pci/via8233.c (revision 2020c8fe)
1 /*-
2  * Copyright (c) 2002 Orion Hodson <orion@freebsd.org>
3  * Portions of this code derived from via82c686.c:
4  * 	Copyright (c) 2000 David Jones <dej@ox.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 AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $FreeBSD: src/sys/dev/sound/pci/via8233.c,v 1.20.2.3 2007/04/26 08:21:44 ariff Exp $
29  */
30 
31 /*
32  * Credits due to:
33  *
34  * Grzybowski Rafal, Russell Davies, Mark Handley, Daniel O'Connor for
35  * comments, machine time, testing patches, and patience.  VIA for
36  * providing specs.  ALSA for helpful comments and some register poke
37  * ordering.
38  */
39 
40 #include <dev/sound/pcm/sound.h>
41 #include <dev/sound/pcm/ac97.h>
42 
43 #include <bus/pci/pcireg.h>
44 #include <bus/pci/pcivar.h>
45 #include <sys/sysctl.h>
46 
47 #include <dev/sound/pci/via8233.h>
48 
49 SND_DECLARE_FILE("$DragonFly: src/sys/dev/sound/pci/via8233.c,v 1.10 2007/06/16 20:07:19 dillon Exp $");
50 
51 #define VIA8233_PCI_ID 0x30591106
52 
53 #define VIA8233_REV_ID_8233PRE	0x10
54 #define VIA8233_REV_ID_8233C	0x20
55 #define VIA8233_REV_ID_8233	0x30
56 #define VIA8233_REV_ID_8233A	0x40
57 #define VIA8233_REV_ID_8235	0x50
58 #define VIA8233_REV_ID_8237	0x60
59 #define VIA8233_REV_ID_8251	0x70
60 
61 #define SEGS_PER_CHAN	2			/* Segments per channel */
62 #define NDXSCHANS	4			/* No of DXS channels */
63 #define NMSGDCHANS	1			/* No of multichannel SGD */
64 #define NWRCHANS	1			/* No of write channels */
65 #define NCHANS		(NWRCHANS + NDXSCHANS + NMSGDCHANS)
66 #define	NSEGS		NCHANS * SEGS_PER_CHAN	/* Segments in SGD table */
67 
68 #define	VIA_DEFAULT_BUFSZ	0x1000
69 
70 /* we rely on this struct being packed to 64 bits */
71 struct via_dma_op {
72         volatile u_int32_t ptr;
73         volatile u_int32_t flags;
74 #define VIA_DMAOP_EOL         0x80000000
75 #define VIA_DMAOP_FLAG        0x40000000
76 #define VIA_DMAOP_STOP        0x20000000
77 #define VIA_DMAOP_COUNT(x)    ((x)&0x00FFFFFF)
78 };
79 
80 struct via_info;
81 
82 struct via_chinfo {
83 	struct via_info *parent;
84 	struct pcm_channel *channel;
85 	struct snd_dbuf *buffer;
86 	struct via_dma_op *sgd_table;
87 	bus_addr_t sgd_addr;
88 	int dir, blksz;
89 	int rbase;
90 };
91 
92 struct via_info {
93 	bus_space_tag_t st;
94 	bus_space_handle_t sh;
95 	bus_dma_tag_t parent_dmat;
96 	bus_dma_tag_t sgd_dmat;
97 	bus_dmamap_t sgd_dmamap;
98 	bus_addr_t sgd_addr;
99 
100 	struct resource *reg, *irq;
101 	int regid, irqid;
102 	void *ih;
103 	struct ac97_info *codec;
104 
105 	unsigned int bufsz;
106 	int dxs_src, dma_eol_wake;
107 
108 	struct via_chinfo pch[NDXSCHANS + NMSGDCHANS];
109 	struct via_chinfo rch[NWRCHANS];
110 	struct via_dma_op *sgd_table;
111 	u_int16_t codec_caps;
112 	u_int16_t n_dxs_registered;
113 	sndlock_t	lock;
114 };
115 
116 static u_int32_t via_fmt[] = {
117 	AFMT_U8,
118 	AFMT_STEREO | AFMT_U8,
119 	AFMT_S16_LE,
120 	AFMT_STEREO | AFMT_S16_LE,
121 	0
122 };
123 
124 static struct pcmchan_caps via_vracaps = { 4000, 48000, via_fmt, 0 };
125 static struct pcmchan_caps via_caps = { 48000, 48000, via_fmt, 0 };
126 
127 #ifdef SND_DYNSYSCTL
128 static int
129 sysctl_via8233_spdif_enable(SYSCTL_HANDLER_ARGS)
130 {
131 	struct via_info *via;
132 	device_t dev;
133 	uint32_t r;
134 	int err, new_en;
135 
136 	dev = oidp->oid_arg1;
137 	via = pcm_getdevinfo(dev);
138 	snd_mtxlock(via->lock);
139 	r = pci_read_config(dev, VIA_PCI_SPDIF, 1);
140 	snd_mtxunlock(via->lock);
141 	new_en = (r & VIA_SPDIF_EN) ? 1 : 0;
142 	err = sysctl_handle_int(oidp, &new_en, sizeof(new_en), req);
143 
144 	if (err || req->newptr == NULL)
145 		return err;
146 	if (new_en < 0 || new_en > 1)
147 		return EINVAL;
148 
149 	if (new_en)
150 		r |= VIA_SPDIF_EN;
151 	else
152 		r &= ~VIA_SPDIF_EN;
153 	snd_mtxlock(via->lock);
154 	pci_write_config(dev, VIA_PCI_SPDIF, r, 1);
155 	snd_mtxunlock(via->lock);
156 
157 	return 0;
158 }
159 
160 #if 0
161 static int
162 sysctl_via8233_dxs_src(SYSCTL_HANDLER_ARGS)
163 {
164 	struct via_info *via;
165 	device_t dev;
166 	int err, val;
167 
168 	dev = oidp->oid_arg1;
169 	via = pcm_getdevinfo(dev);
170 	snd_mtxlock(via->lock);
171 	val = via->dxs_src;
172 	snd_mtxunlock(via->lock);
173 	err = sysctl_handle_int(oidp, &val, sizeof(val), req);
174 
175 	if (err || req->newptr == NULL)
176 		return err;
177 	if (val < 0 || val > 1)
178 		return EINVAL;
179 
180 	snd_mtxlock(via->lock);
181 	via->dxs_src = val;
182 	snd_mtxunlock(via->lock);
183 
184 	return 0;
185 }
186 #endif
187 #endif /* SND_DYNSYSCTL */
188 
189 static void
190 via_init_sysctls(device_t dev)
191 {
192 #ifdef SND_DYNSYSCTL
193 	SYSCTL_ADD_PROC(snd_sysctl_tree(dev),
194 			SYSCTL_CHILDREN(snd_sysctl_tree_top(dev)),
195 			OID_AUTO, "spdif_enabled",
196 			CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev),
197 			sysctl_via8233_spdif_enable, "I",
198 			"Enable S/PDIF output on primary playback channel");
199 #if 0
200 	SYSCTL_ADD_PROC(snd_sysctl_tree(dev),
201 			SYSCTL_CHILDREN(snd_sysctl_tree_top(dev)),
202 			OID_AUTO, "via_dxs_src",
203 			CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev),
204 			sysctl_via8233_dxs_src, "I",
205 			"Enable VIA DXS Sample Rate Converter");
206 #endif
207 #endif
208 }
209 
210 static __inline u_int32_t
211 via_rd(struct via_info *via, int regno, int size)
212 {
213 	switch (size) {
214 	case 1:
215 		return bus_space_read_1(via->st, via->sh, regno);
216 	case 2:
217 		return bus_space_read_2(via->st, via->sh, regno);
218 	case 4:
219 		return bus_space_read_4(via->st, via->sh, regno);
220 	default:
221 		return 0xFFFFFFFF;
222 	}
223 }
224 
225 static __inline void
226 via_wr(struct via_info *via, int regno, u_int32_t data, int size)
227 {
228 
229 	switch (size) {
230 	case 1:
231 		bus_space_write_1(via->st, via->sh, regno, data);
232 		break;
233 	case 2:
234 		bus_space_write_2(via->st, via->sh, regno, data);
235 		break;
236 	case 4:
237 		bus_space_write_4(via->st, via->sh, regno, data);
238 		break;
239 	}
240 }
241 
242 /* -------------------------------------------------------------------- */
243 /* Codec interface */
244 
245 static int
246 via_waitready_codec(struct via_info *via)
247 {
248 	int i;
249 
250 	/* poll until codec not busy */
251 	for (i = 0; i < 1000; i++) {
252 		if ((via_rd(via, VIA_AC97_CONTROL, 4) & VIA_AC97_BUSY) == 0)
253 			return 0;
254 		DELAY(1);
255 	}
256 	kprintf("via: codec busy\n");
257 	return 1;
258 }
259 
260 static int
261 via_waitvalid_codec(struct via_info *via)
262 {
263 	int i;
264 
265 	/* poll until codec valid */
266 	for (i = 0; i < 1000; i++) {
267 		if (via_rd(via, VIA_AC97_CONTROL, 4) & VIA_AC97_CODEC00_VALID)
268 			return 0;
269 		DELAY(1);
270 	}
271 	kprintf("via: codec invalid\n");
272 	return 1;
273 }
274 
275 static int
276 via_write_codec(kobj_t obj, void *addr, int reg, u_int32_t val)
277 {
278 	struct via_info *via = addr;
279 
280 	if (via_waitready_codec(via)) return -1;
281 
282 	via_wr(via, VIA_AC97_CONTROL,
283 	       VIA_AC97_CODEC00_VALID | VIA_AC97_INDEX(reg) |
284 	       VIA_AC97_DATA(val), 4);
285 
286 	return 0;
287 }
288 
289 static int
290 via_read_codec(kobj_t obj, void *addr, int reg)
291 {
292 	struct via_info *via = addr;
293 
294 	if (via_waitready_codec(via))
295 		return -1;
296 
297 	via_wr(via, VIA_AC97_CONTROL, VIA_AC97_CODEC00_VALID |
298 	       VIA_AC97_READ | VIA_AC97_INDEX(reg), 4);
299 
300 	if (via_waitready_codec(via))
301 		return -1;
302 
303 	if (via_waitvalid_codec(via))
304 		return -1;
305 
306 	return via_rd(via, VIA_AC97_CONTROL, 2);
307 }
308 
309 static kobj_method_t via_ac97_methods[] = {
310     	KOBJMETHOD(ac97_read,		via_read_codec),
311     	KOBJMETHOD(ac97_write,		via_write_codec),
312 	{ 0, 0 }
313 };
314 AC97_DECLARE(via_ac97);
315 
316 /* -------------------------------------------------------------------- */
317 
318 static int
319 via_buildsgdt(struct via_chinfo *ch)
320 {
321 	u_int32_t phys_addr, flag;
322 	int i, seg_size;
323 
324 	seg_size = sndbuf_getsize(ch->buffer) / SEGS_PER_CHAN;
325 	phys_addr = sndbuf_getbufaddr(ch->buffer);
326 
327 	for (i = 0; i < SEGS_PER_CHAN; i++) {
328 		flag = (i == SEGS_PER_CHAN - 1) ? VIA_DMAOP_EOL : VIA_DMAOP_FLAG;
329 		ch->sgd_table[i].ptr = phys_addr + (i * seg_size);
330 		ch->sgd_table[i].flags = flag | seg_size;
331 	}
332 
333 	return 0;
334 }
335 
336 /* -------------------------------------------------------------------- */
337 /* Format setting functions */
338 
339 static int
340 via8233wr_setformat(kobj_t obj, void *data, u_int32_t format)
341 {
342 	struct via_chinfo *ch = data;
343 	struct via_info *via = ch->parent;
344 
345 	u_int32_t f = WR_FORMAT_STOP_INDEX;
346 
347 	if (format & AFMT_STEREO)
348 		f |= WR_FORMAT_STEREO;
349 	if (format & AFMT_S16_LE)
350 		f |= WR_FORMAT_16BIT;
351 	snd_mtxlock(via->lock);
352 	via_wr(via, VIA_WR0_FORMAT, f, 4);
353 	snd_mtxunlock(via->lock);
354 
355 	return 0;
356 }
357 
358 static int
359 via8233dxs_setformat(kobj_t obj, void *data, u_int32_t format)
360 {
361 	struct via_chinfo *ch = data;
362 	struct via_info *via = ch->parent;
363 	u_int32_t r, v;
364 
365 	r = ch->rbase + VIA8233_RP_DXS_RATEFMT;
366 	snd_mtxlock(via->lock);
367 	v = via_rd(via, r, 4);
368 
369 	v &= ~(VIA8233_DXS_RATEFMT_STEREO | VIA8233_DXS_RATEFMT_16BIT);
370 	if (format & AFMT_STEREO)
371 		v |= VIA8233_DXS_RATEFMT_STEREO;
372 	if (format & AFMT_16BIT)
373 		v |= VIA8233_DXS_RATEFMT_16BIT;
374 	via_wr(via, r, v, 4);
375 	snd_mtxunlock(via->lock);
376 
377 	return 0;
378 }
379 
380 static int
381 via8233msgd_setformat(kobj_t obj, void *data, u_int32_t format)
382 {
383 	struct via_chinfo *ch = data;
384 	struct via_info *via = ch->parent;
385 
386 	u_int32_t s = 0xff000000;
387 	u_int8_t  v = (format & AFMT_S16_LE) ? MC_SGD_16BIT : MC_SGD_8BIT;
388 
389 	if (format & AFMT_STEREO) {
390 		v |= MC_SGD_CHANNELS(2);
391 		s |= SLOT3(1) | SLOT4(2);
392 	} else {
393 		v |= MC_SGD_CHANNELS(1);
394 		s |= SLOT3(1) | SLOT4(1);
395 	}
396 
397 	snd_mtxlock(via->lock);
398 	via_wr(via, VIA_MC_SLOT_SELECT, s, 4);
399 	via_wr(via, VIA_MC_SGD_FORMAT, v, 1);
400 	snd_mtxunlock(via->lock);
401 
402 	return 0;
403 }
404 
405 /* -------------------------------------------------------------------- */
406 /* Speed setting functions */
407 
408 static int
409 via8233wr_setspeed(kobj_t obj, void *data, u_int32_t speed)
410 {
411 	struct via_chinfo *ch = data;
412 	struct via_info *via = ch->parent;
413 
414 	if (via->codec_caps & AC97_EXTCAP_VRA)
415 		return ac97_setrate(via->codec, AC97_REGEXT_LADCRATE, speed);
416 
417 	return 48000;
418 }
419 
420 static int
421 via8233dxs_setspeed(kobj_t obj, void *data, u_int32_t speed)
422 {
423 	struct via_chinfo *ch = data;
424 	struct via_info *via = ch->parent;
425 	u_int32_t r, v;
426 
427 	r = ch->rbase + VIA8233_RP_DXS_RATEFMT;
428 	snd_mtxlock(via->lock);
429 	v = via_rd(via, r, 4) & ~VIA8233_DXS_RATEFMT_48K;
430 
431 	/* Careful to avoid overflow (divide by 48 per vt8233c docs) */
432 
433 	v |= VIA8233_DXS_RATEFMT_48K * (speed / 48) / (48000 / 48);
434 	via_wr(via, r, v, 4);
435 	snd_mtxunlock(via->lock);
436 
437 	return speed;
438 }
439 
440 static int
441 via8233msgd_setspeed(kobj_t obj, void *data, u_int32_t speed)
442 {
443 	struct via_chinfo *ch = data;
444 	struct via_info *via = ch->parent;
445 
446 	if (via->codec_caps & AC97_EXTCAP_VRA)
447 		return ac97_setrate(via->codec, AC97_REGEXT_FDACRATE, speed);
448 
449 	return 48000;
450 }
451 
452 /* -------------------------------------------------------------------- */
453 /* Format probing functions */
454 
455 static struct pcmchan_caps *
456 via8233wr_getcaps(kobj_t obj, void *data)
457 {
458 	struct via_chinfo *ch = data;
459 	struct via_info *via = ch->parent;
460 
461 	/* Controlled by ac97 registers */
462 	if (via->codec_caps & AC97_EXTCAP_VRA)
463 		return &via_vracaps;
464 	return &via_caps;
465 }
466 
467 static struct pcmchan_caps *
468 via8233dxs_getcaps(kobj_t obj, void *data)
469 {
470 	struct via_chinfo *ch = data;
471 	struct via_info *via = ch->parent;
472 
473 	/*
474 	 * Controlled by onboard registers
475 	 *
476 	 * Apparently, few boards can do DXS sample rate
477 	 * conversion.
478 	 */
479 	if (via->dxs_src)
480 		return &via_vracaps;
481 	return &via_caps;
482 }
483 
484 static struct pcmchan_caps *
485 via8233msgd_getcaps(kobj_t obj, void *data)
486 {
487 	struct via_chinfo *ch = data;
488 	struct via_info *via = ch->parent;
489 
490 	/* Controlled by ac97 registers */
491 	if (via->codec_caps & AC97_EXTCAP_VRA)
492 		return &via_vracaps;
493 	return &via_caps;
494 }
495 
496 /* -------------------------------------------------------------------- */
497 /* Common functions */
498 
499 static int
500 via8233chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
501 {
502 	struct via_chinfo *ch = data;
503 
504 	sndbuf_resize(ch->buffer, SEGS_PER_CHAN, blocksize);
505 	ch->blksz = sndbuf_getblksz(ch->buffer);
506 	return ch->blksz;
507 }
508 
509 static int
510 via8233chan_getptr(kobj_t obj, void *data)
511 {
512 	struct via_chinfo *ch = data;
513 	struct via_info *via = ch->parent;
514 	u_int32_t v, index, count;
515 	int ptr;
516 
517 	snd_mtxlock(via->lock);
518 	v = via_rd(via, ch->rbase + VIA_RP_CURRENT_COUNT, 4);
519 	snd_mtxunlock(via->lock);
520 	index = v >> 24;		/* Last completed buffer */
521 	count = v & 0x00ffffff;	/* Bytes remaining */
522 	ptr = (index + 1) * ch->blksz - count;
523 	ptr %= SEGS_PER_CHAN * ch->blksz;	/* Wrap to available space */
524 
525 	return ptr;
526 }
527 
528 static void
529 via8233chan_reset(struct via_info *via, struct via_chinfo *ch)
530 {
531 	via_wr(via, ch->rbase + VIA_RP_CONTROL, SGD_CONTROL_STOP, 1);
532 	via_wr(via, ch->rbase + VIA_RP_CONTROL, 0x00, 1);
533 	via_wr(via, ch->rbase + VIA_RP_STATUS,
534 	       SGD_STATUS_EOL | SGD_STATUS_FLAG, 1);
535 }
536 
537 /* -------------------------------------------------------------------- */
538 /* Channel initialization functions */
539 
540 static void
541 via8233chan_sgdinit(struct via_info *via, struct via_chinfo *ch, int chnum)
542 {
543 	ch->sgd_table = &via->sgd_table[chnum * SEGS_PER_CHAN];
544 	ch->sgd_addr = via->sgd_addr + chnum * SEGS_PER_CHAN * sizeof(struct via_dma_op);
545 }
546 
547 static void*
548 via8233wr_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
549 	       struct pcm_channel *c, int dir)
550 {
551 	struct via_info *via = devinfo;
552 	struct via_chinfo *ch = &via->rch[c->num];
553 
554 	ch->parent = via;
555 	ch->channel = c;
556 	ch->buffer = b;
557 	ch->dir = dir;
558 
559 	ch->rbase = VIA_WR_BASE(c->num);
560 	snd_mtxlock(via->lock);
561 	via_wr(via, ch->rbase + VIA_WR_RP_SGD_FORMAT, WR_FIFO_ENABLE, 1);
562 	snd_mtxunlock(via->lock);
563 
564 	if (sndbuf_alloc(ch->buffer, via->parent_dmat, via->bufsz) != 0)
565 		return NULL;
566 
567 	snd_mtxlock(via->lock);
568 	via8233chan_sgdinit(via, ch, c->num);
569 	via8233chan_reset(via, ch);
570 	snd_mtxunlock(via->lock);
571 
572 	return ch;
573 }
574 
575 static void*
576 via8233dxs_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
577 		struct pcm_channel *c, int dir)
578 {
579 	struct via_info *via = devinfo;
580 	struct via_chinfo *ch = &via->pch[c->num];
581 
582 	ch->parent = via;
583 	ch->channel = c;
584 	ch->buffer = b;
585 	ch->dir = dir;
586 
587 	/*
588 	 * All cards apparently support DXS3, but not other DXS
589 	 * channels.  We therefore want to align first DXS channel to
590 	 * DXS3.
591 	 */
592 	snd_mtxlock(via->lock);
593 	ch->rbase = VIA_DXS_BASE(NDXSCHANS - 1 - via->n_dxs_registered);
594 	via->n_dxs_registered++;
595 	snd_mtxunlock(via->lock);
596 
597 	if (sndbuf_alloc(ch->buffer, via->parent_dmat, via->bufsz) != 0)
598 		return NULL;
599 
600 	snd_mtxlock(via->lock);
601 	via8233chan_sgdinit(via, ch, NWRCHANS + c->num);
602 	via8233chan_reset(via, ch);
603 	snd_mtxunlock(via->lock);
604 
605 	return ch;
606 }
607 
608 static void*
609 via8233msgd_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
610 		 struct pcm_channel *c, int dir)
611 {
612 	struct via_info *via = devinfo;
613 	struct via_chinfo *ch = &via->pch[c->num];
614 
615 	ch->parent = via;
616 	ch->channel = c;
617 	ch->buffer = b;
618 	ch->dir = dir;
619 	ch->rbase = VIA_MC_SGD_STATUS;
620 
621 	if (sndbuf_alloc(ch->buffer, via->parent_dmat, via->bufsz) != 0)
622 		return NULL;
623 
624 	snd_mtxlock(via->lock);
625 	via8233chan_sgdinit(via, ch, NWRCHANS + c->num);
626 	via8233chan_reset(via, ch);
627 	snd_mtxunlock(via->lock);
628 
629 	return ch;
630 }
631 
632 static void
633 via8233chan_mute(struct via_info *via, struct via_chinfo *ch, int muted)
634 {
635 	if (BASE_IS_VIA_DXS_REG(ch->rbase)) {
636 		int r;
637 		muted = (muted) ? VIA8233_DXS_MUTE : 0;
638 		via_wr(via, ch->rbase + VIA8233_RP_DXS_LVOL, muted, 1);
639 		via_wr(via, ch->rbase + VIA8233_RP_DXS_RVOL, muted, 1);
640 		r = via_rd(via, ch->rbase + VIA8233_RP_DXS_LVOL, 1) & VIA8233_DXS_MUTE;
641 		if (r != muted) {
642 			kprintf("via: failed to set dxs volume "
643 			       "(dxs base 0x%02x).\n", ch->rbase);
644 		}
645 	}
646 }
647 
648 static int
649 via8233chan_trigger(kobj_t obj, void* data, int go)
650 {
651 	struct via_chinfo *ch = data;
652 	struct via_info *via = ch->parent;
653 
654 	snd_mtxlock(via->lock);
655 	switch(go) {
656 	case PCMTRIG_START:
657 		via_buildsgdt(ch);
658 		via8233chan_mute(via, ch, 0);
659 		via_wr(via, ch->rbase + VIA_RP_TABLE_PTR, ch->sgd_addr, 4);
660 		via_wr(via, ch->rbase + VIA_RP_CONTROL,
661 		       SGD_CONTROL_START | SGD_CONTROL_AUTOSTART |
662 		       SGD_CONTROL_I_EOL | SGD_CONTROL_I_FLAG, 1);
663 		break;
664 	case PCMTRIG_STOP:
665 	case PCMTRIG_ABORT:
666 		via_wr(via, ch->rbase + VIA_RP_CONTROL, SGD_CONTROL_STOP, 1);
667 		via8233chan_mute(via, ch, 1);
668 		via8233chan_reset(via, ch);
669 		break;
670 	}
671 	snd_mtxunlock(via->lock);
672 	return 0;
673 }
674 
675 static kobj_method_t via8233wr_methods[] = {
676     	KOBJMETHOD(channel_init,		via8233wr_init),
677     	KOBJMETHOD(channel_setformat,		via8233wr_setformat),
678     	KOBJMETHOD(channel_setspeed,		via8233wr_setspeed),
679     	KOBJMETHOD(channel_getcaps,		via8233wr_getcaps),
680     	KOBJMETHOD(channel_setblocksize,	via8233chan_setblocksize),
681     	KOBJMETHOD(channel_trigger,		via8233chan_trigger),
682     	KOBJMETHOD(channel_getptr,		via8233chan_getptr),
683 	{ 0, 0 }
684 };
685 CHANNEL_DECLARE(via8233wr);
686 
687 static kobj_method_t via8233dxs_methods[] = {
688     	KOBJMETHOD(channel_init,		via8233dxs_init),
689     	KOBJMETHOD(channel_setformat,		via8233dxs_setformat),
690     	KOBJMETHOD(channel_setspeed,		via8233dxs_setspeed),
691     	KOBJMETHOD(channel_getcaps,		via8233dxs_getcaps),
692     	KOBJMETHOD(channel_setblocksize,	via8233chan_setblocksize),
693     	KOBJMETHOD(channel_trigger,		via8233chan_trigger),
694     	KOBJMETHOD(channel_getptr,		via8233chan_getptr),
695 	{ 0, 0 }
696 };
697 CHANNEL_DECLARE(via8233dxs);
698 
699 static kobj_method_t via8233msgd_methods[] = {
700     	KOBJMETHOD(channel_init,		via8233msgd_init),
701     	KOBJMETHOD(channel_setformat,		via8233msgd_setformat),
702     	KOBJMETHOD(channel_setspeed,		via8233msgd_setspeed),
703     	KOBJMETHOD(channel_getcaps,		via8233msgd_getcaps),
704     	KOBJMETHOD(channel_setblocksize,	via8233chan_setblocksize),
705     	KOBJMETHOD(channel_trigger,		via8233chan_trigger),
706     	KOBJMETHOD(channel_getptr,		via8233chan_getptr),
707 	{ 0, 0 }
708 };
709 CHANNEL_DECLARE(via8233msgd);
710 
711 /* -------------------------------------------------------------------- */
712 
713 static void
714 via_intr(void *p)
715 {
716 	struct via_info *via = p;
717 	int i, reg, stat;
718 
719 	/* Poll playback channels */
720 	snd_mtxlock(via->lock);
721 	for (i = 0; i < NDXSCHANS + NMSGDCHANS; i++) {
722 		if (via->pch[i].channel == NULL)
723 			continue;
724 		reg = via->pch[i].rbase + VIA_RP_STATUS;
725 		stat = via_rd(via, reg, 1);
726 		if (stat & SGD_STATUS_INTR) {
727 			if (via->dma_eol_wake && ((stat & SGD_STATUS_EOL) ||
728 					!(stat & SGD_STATUS_ACTIVE))) {
729 				via_wr(via,
730 					via->pch[i].rbase + VIA_RP_CONTROL,
731 					SGD_CONTROL_START |
732 					SGD_CONTROL_AUTOSTART |
733 					SGD_CONTROL_I_EOL |
734 					SGD_CONTROL_I_FLAG, 1);
735 			}
736 			via_wr(via, reg, stat, 1);
737 			snd_mtxunlock(via->lock);
738 			chn_intr(via->pch[i].channel);
739 			snd_mtxlock(via->lock);
740 		}
741 	}
742 
743 	/* Poll record channels */
744 	for (i = 0; i < NWRCHANS; i++) {
745 		if (via->rch[i].channel == NULL)
746 			continue;
747 		reg = via->rch[i].rbase + VIA_RP_STATUS;
748 		stat = via_rd(via, reg, 1);
749 		if (stat & SGD_STATUS_INTR) {
750 			if (via->dma_eol_wake && ((stat & SGD_STATUS_EOL) ||
751 					!(stat & SGD_STATUS_ACTIVE))) {
752 				via_wr(via,
753 					via->rch[i].rbase + VIA_RP_CONTROL,
754 					SGD_CONTROL_START |
755 					SGD_CONTROL_AUTOSTART |
756 					SGD_CONTROL_I_EOL |
757 					SGD_CONTROL_I_FLAG, 1);
758 			}
759 			via_wr(via, reg, stat, 1);
760 			snd_mtxunlock(via->lock);
761 			chn_intr(via->rch[i].channel);
762 			snd_mtxlock(via->lock);
763 		}
764 	}
765 	snd_mtxunlock(via->lock);
766 }
767 
768 /*
769  *  Probe and attach the card
770  */
771 static int
772 via_probe(device_t dev)
773 {
774 	switch(pci_get_devid(dev)) {
775 	case VIA8233_PCI_ID:
776 		switch(pci_get_revid(dev)) {
777 		case VIA8233_REV_ID_8233PRE:
778 			device_set_desc(dev, "VIA VT8233 (pre)");
779 			return BUS_PROBE_DEFAULT;
780 		case VIA8233_REV_ID_8233C:
781 			device_set_desc(dev, "VIA VT8233C");
782 			return BUS_PROBE_DEFAULT;
783 		case VIA8233_REV_ID_8233:
784 			device_set_desc(dev, "VIA VT8233");
785 			return BUS_PROBE_DEFAULT;
786 		case VIA8233_REV_ID_8233A:
787 			device_set_desc(dev, "VIA VT8233A");
788 			return BUS_PROBE_DEFAULT;
789 		case VIA8233_REV_ID_8235:
790 			device_set_desc(dev, "VIA VT8235");
791 			return BUS_PROBE_DEFAULT;
792 		case VIA8233_REV_ID_8237:
793 			device_set_desc(dev, "VIA VT8237");
794 			return BUS_PROBE_DEFAULT;
795 		case VIA8233_REV_ID_8251:
796 			device_set_desc(dev, "VIA VT8251");
797 			return BUS_PROBE_DEFAULT;
798 		default:
799 			device_set_desc(dev, "VIA VT8233X");	/* Unknown */
800 			return BUS_PROBE_DEFAULT;
801 		}
802 	}
803 	return ENXIO;
804 }
805 
806 static void
807 dma_cb(void *p, bus_dma_segment_t *bds, int a, int b)
808 {
809 	struct via_info *via = (struct via_info *)p;
810 	via->sgd_addr = bds->ds_addr;
811 }
812 
813 static int
814 via_chip_init(device_t dev)
815 {
816 	u_int32_t data, cnt;
817 
818 	/* Wake up and reset AC97 if necessary */
819 	data = pci_read_config(dev, VIA_PCI_ACLINK_STAT, 1);
820 
821 	if ((data & VIA_PCI_ACLINK_C00_READY) == 0) {
822 		/* Cold reset per ac97r2.3 spec (page 95) */
823 		/* Assert low */
824 		pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
825 				 VIA_PCI_ACLINK_EN, 1);
826 		/* Wait T_rst_low */
827 		DELAY(100);
828 		/* Assert high */
829 		pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
830 				 VIA_PCI_ACLINK_EN | VIA_PCI_ACLINK_NRST, 1);
831 		/* Wait T_rst2clk */
832 		DELAY(5);
833 		/* Assert low */
834 		pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
835 				 VIA_PCI_ACLINK_EN, 1);
836 	} else {
837 		/* Warm reset */
838 		/* Force no sync */
839 		pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
840 				 VIA_PCI_ACLINK_EN, 1);
841 		DELAY(100);
842 		/* Sync */
843 		pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
844 				 VIA_PCI_ACLINK_EN | VIA_PCI_ACLINK_SYNC, 1);
845 		/* Wait T_sync_high */
846 		DELAY(5);
847 		/* Force no sync */
848 		pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
849 				 VIA_PCI_ACLINK_EN, 1);
850 		/* Wait T_sync2clk */
851 		DELAY(5);
852 	}
853 
854 	/* Power everything up */
855 	pci_write_config(dev, VIA_PCI_ACLINK_CTRL, VIA_PCI_ACLINK_DESIRED, 1);
856 
857 	/* Wait for codec to become ready (largest reported delay 310ms) */
858 	for (cnt = 0; cnt < 2000; cnt++) {
859 		data = pci_read_config(dev, VIA_PCI_ACLINK_STAT, 1);
860 		if (data & VIA_PCI_ACLINK_C00_READY) {
861 			return 0;
862 		}
863 		DELAY(5000);
864 	}
865 	device_printf(dev, "primary codec not ready (cnt = 0x%02x)\n", cnt);
866 	return ENXIO;
867 }
868 
869 static int
870 via_attach(device_t dev)
871 {
872 	struct via_info *via = NULL;
873 	char status[SND_STATUSLEN];
874 	int i, via_dxs_disabled, via_dxs_src, via_dxs_chnum, via_sgd_chnum;
875 	uint32_t revid;
876 
877 	via = kmalloc(sizeof *via, M_DEVBUF, M_WAITOK | M_ZERO);
878 	via->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc");
879 
880 	pci_set_powerstate(dev, PCI_POWERSTATE_D0);
881 	pci_enable_busmaster(dev);
882 
883 	via->regid = PCIR_BAR(0);
884 	via->reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &via->regid,
885 					  RF_ACTIVE);
886 	if (!via->reg) {
887 		device_printf(dev, "cannot allocate bus resource.");
888 		goto bad;
889 	}
890 	via->st = rman_get_bustag(via->reg);
891 	via->sh = rman_get_bushandle(via->reg);
892 
893 	via->bufsz = pcm_getbuffersize(dev, 4096, VIA_DEFAULT_BUFSZ, 65536);
894 
895 	via->irqid = 0;
896 	via->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &via->irqid,
897 					  RF_ACTIVE | RF_SHAREABLE);
898 	if (!via->irq ||
899 	    snd_setup_intr(dev, via->irq, INTR_MPSAFE, via_intr, via, &via->ih)) {
900 		device_printf(dev, "unable to map interrupt\n");
901 		goto bad;
902 	}
903 
904 	/* DMA tag for buffers */
905 	if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
906 		/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
907 		/*highaddr*/BUS_SPACE_MAXADDR,
908 		/*filter*/NULL, /*filterarg*/NULL,
909 		/*maxsize*/via->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
910 		/*flags*/0,
911 		&via->parent_dmat) != 0) {
912 		device_printf(dev, "unable to create dma tag\n");
913 		goto bad;
914 	}
915 
916 	/*
917 	 *  DMA tag for SGD table.  The 686 uses scatter/gather DMA and
918 	 *  requires a list in memory of work to do.  We need only 16 bytes
919 	 *  for this list, and it is wasteful to allocate 16K.
920 	 */
921 	if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
922 		/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
923 		/*highaddr*/BUS_SPACE_MAXADDR,
924 		/*filter*/NULL, /*filterarg*/NULL,
925 		/*maxsize*/NSEGS * sizeof(struct via_dma_op),
926 		/*nsegments*/1, /*maxsegz*/0x3ffff,
927 		/*flags*/0,
928 		&via->sgd_dmat) != 0) {
929 		device_printf(dev, "unable to create dma tag\n");
930 		goto bad;
931 	}
932 
933 	if (bus_dmamem_alloc(via->sgd_dmat, (void **)&via->sgd_table,
934 			     BUS_DMA_NOWAIT, &via->sgd_dmamap) == -1)
935 		goto bad;
936 	if (bus_dmamap_load(via->sgd_dmat, via->sgd_dmamap, via->sgd_table,
937 			    NSEGS * sizeof(struct via_dma_op), dma_cb, via, 0))
938 		goto bad;
939 
940 	if (via_chip_init(dev))
941 		goto bad;
942 
943 	via->codec = AC97_CREATE(dev, via, via_ac97);
944 	if (!via->codec)
945 		goto bad;
946 
947 	mixer_init(dev, ac97_getmixerclass(), via->codec);
948 
949 	via->codec_caps = ac97_getextcaps(via->codec);
950 
951 	/* Try to set VRA without generating an error, VRM not reqrd yet */
952 	if (via->codec_caps &
953 	    (AC97_EXTCAP_VRA | AC97_EXTCAP_VRM | AC97_EXTCAP_DRA)) {
954 		u_int16_t ext = ac97_getextmode(via->codec);
955 		ext |= (via->codec_caps &
956 			(AC97_EXTCAP_VRA | AC97_EXTCAP_VRM));
957 		ext &= ~AC97_EXTCAP_DRA;
958 		ac97_setextmode(via->codec, ext);
959 	}
960 
961 	ksnprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld %s",
962 		 rman_get_start(via->reg), rman_get_start(via->irq),PCM_KLDSTRING(snd_via8233));
963 
964 	revid = pci_get_revid(dev);
965 
966 	/*
967 	 * VIA8251 lost its interrupt after DMA EOL, and need
968 	 * a gentle spank on its face within interrupt handler.
969 	 */
970 	if (revid == VIA8233_REV_ID_8251)
971 		via->dma_eol_wake = 1;
972 	else
973 		via->dma_eol_wake = 0;
974 
975 	/*
976 	 * Decide whether DXS had to be disabled or not
977 	 */
978 	if (revid == VIA8233_REV_ID_8233A) {
979 		/*
980 		 * DXS channel is disabled.  Reports from multiple users
981 		 * that it plays at half-speed.  Do not see this behaviour
982 		 * on available 8233C or when emulating 8233A register set
983 		 * on 8233C (either with or without ac97 VRA).
984 		 */
985 		via_dxs_disabled = 1;
986 	} else if (resource_int_value(device_get_name(dev),
987 			device_get_unit(dev), "via_dxs_disabled",
988 			&via_dxs_disabled) == 0)
989 		via_dxs_disabled = (via_dxs_disabled > 0) ? 1 : 0;
990 	else
991 		via_dxs_disabled = 0;
992 
993 	if (via_dxs_disabled) {
994 		via_dxs_chnum = 0;
995 		via_sgd_chnum = 1;
996 	} else {
997 		if (resource_int_value(device_get_name(dev),
998 				device_get_unit(dev), "via_dxs_channels",
999 				&via_dxs_chnum) != 0)
1000 			via_dxs_chnum = NDXSCHANS;
1001 		if (resource_int_value(device_get_name(dev),
1002 				device_get_unit(dev), "via_sgd_channels",
1003 				&via_sgd_chnum) != 0)
1004 			via_sgd_chnum = NMSGDCHANS;
1005 	}
1006 	if (via_dxs_chnum > NDXSCHANS)
1007 		via_dxs_chnum = NDXSCHANS;
1008 	else if (via_dxs_chnum < 0)
1009 		via_dxs_chnum = 0;
1010 	if (via_sgd_chnum > NMSGDCHANS)
1011 		via_sgd_chnum = NMSGDCHANS;
1012 	else if (via_sgd_chnum < 0)
1013 		via_sgd_chnum = 0;
1014 	if (via_dxs_chnum + via_sgd_chnum < 1) {
1015 		/* Minimalist ? */
1016 		via_dxs_chnum = 1;
1017 		via_sgd_chnum = 0;
1018 	}
1019 	if (via_dxs_chnum > 0 && resource_int_value(device_get_name(dev),
1020 			device_get_unit(dev), "via_dxs_src",
1021 			&via_dxs_src) == 0)
1022 		via->dxs_src = (via_dxs_src > 0) ? 1 : 0;
1023 	else
1024 		via->dxs_src = 0;
1025 	/* Register */
1026 	if (pcm_register(dev, via, via_dxs_chnum + via_sgd_chnum, NWRCHANS))
1027 	      goto bad;
1028 	for (i = 0; i < via_dxs_chnum; i++)
1029 	      pcm_addchan(dev, PCMDIR_PLAY, &via8233dxs_class, via);
1030 	for (i = 0; i < via_sgd_chnum; i++)
1031 	      pcm_addchan(dev, PCMDIR_PLAY, &via8233msgd_class, via);
1032 	for (i = 0; i < NWRCHANS; i++)
1033 	      pcm_addchan(dev, PCMDIR_REC, &via8233wr_class, via);
1034 	if (via_dxs_chnum > 0)
1035 		via_init_sysctls(dev);
1036 	device_printf(dev, "<VIA DXS %sabled: DXS%s %d / SGD %d / REC %d>\n",
1037 		(via_dxs_chnum > 0) ? "En" : "Dis",
1038 		(via->dxs_src) ? "(SRC)" : "",
1039 		via_dxs_chnum, via_sgd_chnum, NWRCHANS);
1040 
1041 	pcm_setstatus(dev, status);
1042 
1043 	return 0;
1044 bad:
1045 	if (via->codec) ac97_destroy(via->codec);
1046 	if (via->reg) bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg);
1047 	if (via->ih) bus_teardown_intr(dev, via->irq, via->ih);
1048 	if (via->irq) bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq);
1049 	if (via->parent_dmat) bus_dma_tag_destroy(via->parent_dmat);
1050 	if (via->sgd_dmamap) bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap);
1051 	if (via->sgd_table) bus_dmamem_free(via->sgd_dmat, via->sgd_table, via->sgd_dmamap);
1052 	if (via->sgd_dmat) bus_dma_tag_destroy(via->sgd_dmat);
1053 	if (via->lock) snd_mtxfree(via->lock);
1054 	if (via) kfree(via, M_DEVBUF);
1055 	return ENXIO;
1056 }
1057 
1058 static int
1059 via_detach(device_t dev)
1060 {
1061 	int r;
1062 	struct via_info *via = NULL;
1063 
1064 	r = pcm_unregister(dev);
1065 	if (r) return r;
1066 
1067 	via = pcm_getdevinfo(dev);
1068 	bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg);
1069 	bus_teardown_intr(dev, via->irq, via->ih);
1070 	bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq);
1071 	bus_dma_tag_destroy(via->parent_dmat);
1072 	bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap);
1073 	bus_dmamem_free(via->sgd_dmat, via->sgd_table, via->sgd_dmamap);
1074 	bus_dma_tag_destroy(via->sgd_dmat);
1075 	snd_mtxfree(via->lock);
1076 	kfree(via, M_DEVBUF);
1077 	return 0;
1078 }
1079 
1080 
1081 static device_method_t via_methods[] = {
1082 	DEVMETHOD(device_probe,		via_probe),
1083 	DEVMETHOD(device_attach,	via_attach),
1084 	DEVMETHOD(device_detach,	via_detach),
1085 	{ 0, 0}
1086 };
1087 
1088 static driver_t via_driver = {
1089 	"pcm",
1090 	via_methods,
1091 	PCM_SOFTC_SIZE,
1092 };
1093 
1094 DRIVER_MODULE(snd_via8233, pci, via_driver, pcm_devclass, NULL, NULL);
1095 MODULE_DEPEND(snd_via8233, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
1096 MODULE_VERSION(snd_via8233, 1);
1097