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