via8233.c revision 170521
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
29/*
30 * Credits due to:
31 *
32 * Grzybowski Rafal, Russell Davies, Mark Handley, Daniel O'Connor for
33 * comments, machine time, testing patches, and patience.  VIA for
34 * providing specs.  ALSA for helpful comments and some register poke
35 * ordering.
36 */
37
38#include <dev/sound/pcm/sound.h>
39#include <dev/sound/pcm/ac97.h>
40
41#include <dev/pci/pcireg.h>
42#include <dev/pci/pcivar.h>
43#include <sys/sysctl.h>
44
45#include <dev/sound/pci/via8233.h>
46
47SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/via8233.c 170521 2007-06-11 00:49:46Z ariff $");
48
49#define VIA8233_PCI_ID 0x30591106
50
51#define VIA8233_REV_ID_8233PRE	0x10
52#define VIA8233_REV_ID_8233C	0x20
53#define VIA8233_REV_ID_8233	0x30
54#define VIA8233_REV_ID_8233A	0x40
55#define VIA8233_REV_ID_8235	0x50
56#define VIA8233_REV_ID_8237	0x60
57#define VIA8233_REV_ID_8251	0x70
58
59#define SEGS_PER_CHAN	2			/* Segments per channel */
60#define NDXSCHANS	4			/* No of DXS channels */
61#define NMSGDCHANS	1			/* No of multichannel SGD */
62#define NWRCHANS	1			/* No of write channels */
63#define NCHANS		(NWRCHANS + NDXSCHANS + NMSGDCHANS)
64#define	NSEGS		NCHANS * SEGS_PER_CHAN	/* Segments in SGD table */
65#define VIA_SEGS_MIN		2
66#define VIA_SEGS_MAX		64
67#define VIA_SEGS_DEFAULT	2
68#define VIA_BLK_MIN		32
69#define VIA_BLK_ALIGN		(~(VIA_BLK_MIN - 1))
70
71#define	VIA_DEFAULT_BUFSZ	0x1000
72
73/* we rely on this struct being packed to 64 bits */
74struct via_dma_op {
75	volatile uint32_t ptr;
76	volatile uint32_t flags;
77#define VIA_DMAOP_EOL         0x80000000
78#define VIA_DMAOP_FLAG        0x40000000
79#define VIA_DMAOP_STOP        0x20000000
80#define VIA_DMAOP_COUNT(x)    ((x)&0x00FFFFFF)
81};
82
83struct via_info;
84
85struct via_chinfo {
86	struct via_info *parent;
87	struct pcm_channel *channel;
88	struct snd_dbuf *buffer;
89	struct via_dma_op *sgd_table;
90	bus_addr_t sgd_addr;
91	int dir, rbase, active;
92	unsigned int blksz, blkcnt;
93	unsigned int ptr, prevptr;
94};
95
96struct via_info {
97	device_t dev;
98
99	bus_space_tag_t st;
100	bus_space_handle_t sh;
101	bus_dma_tag_t parent_dmat;
102	bus_dma_tag_t sgd_dmat;
103	bus_dmamap_t sgd_dmamap;
104	bus_addr_t sgd_addr;
105
106	struct resource *reg, *irq;
107	int regid, irqid;
108	void *ih;
109	struct ac97_info *codec;
110
111	unsigned int bufsz, blkcnt;
112	int dxs_src, dma_eol_wake;
113
114	struct via_chinfo pch[NDXSCHANS + NMSGDCHANS];
115	struct via_chinfo rch[NWRCHANS];
116	struct via_dma_op *sgd_table;
117	uint16_t codec_caps;
118	uint16_t n_dxs_registered;
119	int play_num, rec_num;
120	struct mtx *lock;
121	struct callout poll_timer;
122	int poll_ticks, polling;
123};
124
125static uint32_t via_fmt[] = {
126	AFMT_U8,
127	AFMT_STEREO | AFMT_U8,
128	AFMT_S16_LE,
129	AFMT_STEREO | AFMT_S16_LE,
130	0
131};
132
133static struct pcmchan_caps via_vracaps = { 4000, 48000, via_fmt, 0 };
134static struct pcmchan_caps via_caps = { 48000, 48000, via_fmt, 0 };
135
136static __inline int
137via_chan_active(struct via_info *via)
138{
139	int i, ret = 0;
140
141	if (via == NULL)
142		return (0);
143
144	for (i = 0; i < NDXSCHANS + NMSGDCHANS; i++)
145		ret += via->pch[i].active;
146
147	for (i = 0; i < NWRCHANS; i++)
148		ret += via->rch[i].active;
149
150	return (ret);
151}
152
153#ifdef SND_DYNSYSCTL
154static int
155sysctl_via8233_spdif_enable(SYSCTL_HANDLER_ARGS)
156{
157	struct via_info *via;
158	device_t dev;
159	uint32_t r;
160	int err, new_en;
161
162	dev = oidp->oid_arg1;
163	via = pcm_getdevinfo(dev);
164	snd_mtxlock(via->lock);
165	r = pci_read_config(dev, VIA_PCI_SPDIF, 1);
166	snd_mtxunlock(via->lock);
167	new_en = (r & VIA_SPDIF_EN) ? 1 : 0;
168	err = sysctl_handle_int(oidp, &new_en, 0, req);
169
170	if (err || req->newptr == NULL)
171		return (err);
172	if (new_en < 0 || new_en > 1)
173		return (EINVAL);
174
175	if (new_en)
176		r |= VIA_SPDIF_EN;
177	else
178		r &= ~VIA_SPDIF_EN;
179	snd_mtxlock(via->lock);
180	pci_write_config(dev, VIA_PCI_SPDIF, r, 1);
181	snd_mtxunlock(via->lock);
182
183	return (0);
184}
185
186static int
187sysctl_via8233_dxs_src(SYSCTL_HANDLER_ARGS)
188{
189	struct via_info *via;
190	device_t dev;
191	int err, val;
192
193	dev = oidp->oid_arg1;
194	via = pcm_getdevinfo(dev);
195	snd_mtxlock(via->lock);
196	val = via->dxs_src;
197	snd_mtxunlock(via->lock);
198	err = sysctl_handle_int(oidp, &val, 0, req);
199
200	if (err || req->newptr == NULL)
201		return (err);
202	if (val < 0 || val > 1)
203		return (EINVAL);
204
205	snd_mtxlock(via->lock);
206	via->dxs_src = val;
207	snd_mtxunlock(via->lock);
208
209	return (0);
210}
211
212static int
213sysctl_via_polling(SYSCTL_HANDLER_ARGS)
214{
215	struct via_info *via;
216	device_t dev;
217	int err, val;
218
219	dev = oidp->oid_arg1;
220	via = pcm_getdevinfo(dev);
221	if (via == NULL)
222		return (EINVAL);
223	snd_mtxlock(via->lock);
224	val = via->polling;
225	snd_mtxunlock(via->lock);
226	err = sysctl_handle_int(oidp, &val, 0, req);
227
228	if (err || req->newptr == NULL)
229		return (err);
230	if (val < 0 || val > 1)
231		return (EINVAL);
232
233	snd_mtxlock(via->lock);
234	if (val != via->polling) {
235		if (via_chan_active(via) != 0)
236			err = EBUSY;
237		else if (val == 0)
238			via->polling = 0;
239		else
240			via->polling = 1;
241	}
242	snd_mtxunlock(via->lock);
243
244	return (err);
245}
246#endif /* SND_DYNSYSCTL */
247
248static void
249via_init_sysctls(device_t dev)
250{
251#ifdef SND_DYNSYSCTL
252	/* XXX: an user should be able to set this with a control tool,
253	   if not done before 7.0-RELEASE, this needs to be converted to
254	   a device specific sysctl "dev.pcm.X.yyy" via device_get_sysctl_*()
255	   as discussed on multimedia@ in msg-id <861wujij2q.fsf@xps.des.no> */
256	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
257	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
258	    "spdif_enabled",  CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev),
259	    sysctl_via8233_spdif_enable, "I",
260	    "Enable S/PDIF output on primary playback channel");
261	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
262	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
263	    "dxs_src", CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev),
264	    sysctl_via8233_dxs_src, "I",
265	    "Enable VIA DXS Sample Rate Converter");
266	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
267	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
268	    "polling", CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev),
269	    sysctl_via_polling, "I",
270	    "Enable polling mode");
271#endif
272}
273
274static __inline uint32_t
275via_rd(struct via_info *via, int regno, int size)
276{
277	switch (size) {
278	case 1:
279		return (bus_space_read_1(via->st, via->sh, regno));
280	case 2:
281		return (bus_space_read_2(via->st, via->sh, regno));
282	case 4:
283		return (bus_space_read_4(via->st, via->sh, regno));
284	default:
285		return (0xFFFFFFFF);
286	}
287}
288
289static __inline void
290via_wr(struct via_info *via, int regno, uint32_t data, int size)
291{
292
293	switch (size) {
294	case 1:
295		bus_space_write_1(via->st, via->sh, regno, data);
296		break;
297	case 2:
298		bus_space_write_2(via->st, via->sh, regno, data);
299		break;
300	case 4:
301		bus_space_write_4(via->st, via->sh, regno, data);
302		break;
303	}
304}
305
306/* -------------------------------------------------------------------- */
307/* Codec interface */
308
309static int
310via_waitready_codec(struct via_info *via)
311{
312	int i;
313
314	/* poll until codec not busy */
315	for (i = 0; i < 1000; i++) {
316		if ((via_rd(via, VIA_AC97_CONTROL, 4) & VIA_AC97_BUSY) == 0)
317			return (0);
318		DELAY(1);
319	}
320	device_printf(via->dev, "%s: codec busy\n", __func__);
321	return (1);
322}
323
324static int
325via_waitvalid_codec(struct via_info *via)
326{
327	int i;
328
329	/* poll until codec valid */
330	for (i = 0; i < 1000; i++) {
331		if (via_rd(via, VIA_AC97_CONTROL, 4) & VIA_AC97_CODEC00_VALID)
332			return (0);
333		DELAY(1);
334	}
335	device_printf(via->dev, "%s: codec invalid\n", __func__);
336	return (1);
337}
338
339static int
340via_write_codec(kobj_t obj, void *addr, int reg, uint32_t val)
341{
342	struct via_info *via = addr;
343
344	if (via_waitready_codec(via))
345		return (-1);
346
347	via_wr(via, VIA_AC97_CONTROL,
348	       VIA_AC97_CODEC00_VALID | VIA_AC97_INDEX(reg) |
349	       VIA_AC97_DATA(val), 4);
350
351	return (0);
352}
353
354static int
355via_read_codec(kobj_t obj, void *addr, int reg)
356{
357	struct via_info *via = addr;
358
359	if (via_waitready_codec(via))
360		return (-1);
361
362	via_wr(via, VIA_AC97_CONTROL, VIA_AC97_CODEC00_VALID |
363	    VIA_AC97_READ | VIA_AC97_INDEX(reg), 4);
364
365	if (via_waitready_codec(via))
366		return (-1);
367
368	if (via_waitvalid_codec(via))
369		return (-1);
370
371	return (via_rd(via, VIA_AC97_CONTROL, 2));
372}
373
374static kobj_method_t via_ac97_methods[] = {
375	KOBJMETHOD(ac97_read,		via_read_codec),
376	KOBJMETHOD(ac97_write,		via_write_codec),
377	{ 0, 0 }
378};
379AC97_DECLARE(via_ac97);
380
381/* -------------------------------------------------------------------- */
382
383static int
384via_buildsgdt(struct via_chinfo *ch)
385{
386	uint32_t phys_addr, flag;
387	int i;
388
389	phys_addr = sndbuf_getbufaddr(ch->buffer);
390
391	for (i = 0; i < ch->blkcnt; i++) {
392		flag = (i == ch->blkcnt - 1) ? VIA_DMAOP_EOL : VIA_DMAOP_FLAG;
393		ch->sgd_table[i].ptr = phys_addr + (i * ch->blksz);
394		ch->sgd_table[i].flags = flag | ch->blksz;
395	}
396
397	return (0);
398}
399
400/* -------------------------------------------------------------------- */
401/* Format setting functions */
402
403static int
404via8233wr_setformat(kobj_t obj, void *data, uint32_t format)
405{
406	struct via_chinfo *ch = data;
407	struct via_info *via = ch->parent;
408
409	uint32_t f = WR_FORMAT_STOP_INDEX;
410
411	if (format & AFMT_STEREO)
412		f |= WR_FORMAT_STEREO;
413	if (format & AFMT_S16_LE)
414		f |= WR_FORMAT_16BIT;
415	snd_mtxlock(via->lock);
416	via_wr(via, VIA_WR0_FORMAT, f, 4);
417	snd_mtxunlock(via->lock);
418
419	return (0);
420}
421
422static int
423via8233dxs_setformat(kobj_t obj, void *data, uint32_t format)
424{
425	struct via_chinfo *ch = data;
426	struct via_info *via = ch->parent;
427	uint32_t r, v;
428
429	r = ch->rbase + VIA8233_RP_DXS_RATEFMT;
430	snd_mtxlock(via->lock);
431	v = via_rd(via, r, 4);
432
433	v &= ~(VIA8233_DXS_RATEFMT_STEREO | VIA8233_DXS_RATEFMT_16BIT);
434	if (format & AFMT_STEREO)
435		v |= VIA8233_DXS_RATEFMT_STEREO;
436	if (format & AFMT_16BIT)
437		v |= VIA8233_DXS_RATEFMT_16BIT;
438	via_wr(via, r, v, 4);
439	snd_mtxunlock(via->lock);
440
441	return (0);
442}
443
444static int
445via8233msgd_setformat(kobj_t obj, void *data, uint32_t format)
446{
447	struct via_chinfo *ch = data;
448	struct via_info *via = ch->parent;
449
450	uint32_t s = 0xff000000;
451	uint8_t  v = (format & AFMT_S16_LE) ? MC_SGD_16BIT : MC_SGD_8BIT;
452
453	if (format & AFMT_STEREO) {
454		v |= MC_SGD_CHANNELS(2);
455		s |= SLOT3(1) | SLOT4(2);
456	} else {
457		v |= MC_SGD_CHANNELS(1);
458		s |= SLOT3(1) | SLOT4(1);
459	}
460
461	snd_mtxlock(via->lock);
462	via_wr(via, VIA_MC_SLOT_SELECT, s, 4);
463	via_wr(via, VIA_MC_SGD_FORMAT, v, 1);
464	snd_mtxunlock(via->lock);
465
466	return (0);
467}
468
469/* -------------------------------------------------------------------- */
470/* Speed setting functions */
471
472static int
473via8233wr_setspeed(kobj_t obj, void *data, uint32_t speed)
474{
475	struct via_chinfo *ch = data;
476	struct via_info *via = ch->parent;
477
478	if (via->codec_caps & AC97_EXTCAP_VRA)
479		return (ac97_setrate(via->codec, AC97_REGEXT_LADCRATE, speed));
480
481	return (48000);
482}
483
484static int
485via8233dxs_setspeed(kobj_t obj, void *data, uint32_t speed)
486{
487	struct via_chinfo *ch = data;
488	struct via_info *via = ch->parent;
489	uint32_t r, v;
490
491	r = ch->rbase + VIA8233_RP_DXS_RATEFMT;
492	snd_mtxlock(via->lock);
493	v = via_rd(via, r, 4) & ~VIA8233_DXS_RATEFMT_48K;
494
495	/* Careful to avoid overflow (divide by 48 per vt8233c docs) */
496
497	v |= VIA8233_DXS_RATEFMT_48K * (speed / 48) / (48000 / 48);
498	via_wr(via, r, v, 4);
499	snd_mtxunlock(via->lock);
500
501	return (speed);
502}
503
504static int
505via8233msgd_setspeed(kobj_t obj, void *data, uint32_t speed)
506{
507	struct via_chinfo *ch = data;
508	struct via_info *via = ch->parent;
509
510	if (via->codec_caps & AC97_EXTCAP_VRA)
511		return (ac97_setrate(via->codec, AC97_REGEXT_FDACRATE, speed));
512
513	return (48000);
514}
515
516/* -------------------------------------------------------------------- */
517/* Format probing functions */
518
519static struct pcmchan_caps *
520via8233wr_getcaps(kobj_t obj, void *data)
521{
522	struct via_chinfo *ch = data;
523	struct via_info *via = ch->parent;
524
525	/* Controlled by ac97 registers */
526	if (via->codec_caps & AC97_EXTCAP_VRA)
527		return (&via_vracaps);
528	return (&via_caps);
529}
530
531static struct pcmchan_caps *
532via8233dxs_getcaps(kobj_t obj, void *data)
533{
534	struct via_chinfo *ch = data;
535	struct via_info *via = ch->parent;
536
537	/*
538	 * Controlled by onboard registers
539	 *
540	 * Apparently, few boards can do DXS sample rate
541	 * conversion.
542	 */
543	if (via->dxs_src)
544		return (&via_vracaps);
545	return (&via_caps);
546}
547
548static struct pcmchan_caps *
549via8233msgd_getcaps(kobj_t obj, void *data)
550{
551	struct via_chinfo *ch = data;
552	struct via_info *via = ch->parent;
553
554	/* Controlled by ac97 registers */
555	if (via->codec_caps & AC97_EXTCAP_VRA)
556		return (&via_vracaps);
557	return (&via_caps);
558}
559
560/* -------------------------------------------------------------------- */
561/* Common functions */
562
563static int
564via8233chan_setfragments(kobj_t obj, void *data,
565					uint32_t blksz, uint32_t blkcnt)
566{
567	struct via_chinfo *ch = data;
568	struct via_info *via = ch->parent;
569
570	blksz &= VIA_BLK_ALIGN;
571
572	if (blksz > (sndbuf_getmaxsize(ch->buffer) / VIA_SEGS_MIN))
573		blksz = sndbuf_getmaxsize(ch->buffer) / VIA_SEGS_MIN;
574	if (blksz < VIA_BLK_MIN)
575		blksz = VIA_BLK_MIN;
576	if (blkcnt > VIA_SEGS_MAX)
577		blkcnt = VIA_SEGS_MAX;
578	if (blkcnt < VIA_SEGS_MIN)
579		blkcnt = VIA_SEGS_MIN;
580
581	while ((blksz * blkcnt) > sndbuf_getmaxsize(ch->buffer)) {
582		if ((blkcnt >> 1) >= VIA_SEGS_MIN)
583			blkcnt >>= 1;
584		else if ((blksz >> 1) >= VIA_BLK_MIN)
585			blksz >>= 1;
586		else
587			break;
588	}
589
590	if ((sndbuf_getblksz(ch->buffer) != blksz ||
591	    sndbuf_getblkcnt(ch->buffer) != blkcnt) &&
592	    sndbuf_resize(ch->buffer, blkcnt, blksz) != 0)
593		device_printf(via->dev, "%s: failed blksz=%u blkcnt=%u\n",
594		    __func__, blksz, blkcnt);
595
596	ch->blksz = sndbuf_getblksz(ch->buffer);
597	ch->blkcnt = sndbuf_getblkcnt(ch->buffer);
598
599	return (1);
600}
601
602static int
603via8233chan_setblocksize(kobj_t obj, void *data, uint32_t blksz)
604{
605	struct via_chinfo *ch = data;
606	struct via_info *via = ch->parent;
607
608	via8233chan_setfragments(obj, data, blksz, via->blkcnt);
609
610	return (ch->blksz);
611}
612
613static int
614via8233chan_getptr(kobj_t obj, void *data)
615{
616	struct via_chinfo *ch = data;
617	struct via_info *via = ch->parent;
618	uint32_t v, index, count;
619	int ptr;
620
621	snd_mtxlock(via->lock);
622	if (via->polling != 0) {
623		ptr = ch->ptr;
624		snd_mtxunlock(via->lock);
625	} else {
626		v = via_rd(via, ch->rbase + VIA_RP_CURRENT_COUNT, 4);
627		snd_mtxunlock(via->lock);
628		index = v >> 24;		/* Last completed buffer */
629		count = v & 0x00ffffff;	/* Bytes remaining */
630		ptr = (index + 1) * ch->blksz - count;
631		ptr %= ch->blkcnt * ch->blksz;	/* Wrap to available space */
632	}
633
634	return (ptr);
635}
636
637static void
638via8233chan_reset(struct via_info *via, struct via_chinfo *ch)
639{
640	via_wr(via, ch->rbase + VIA_RP_CONTROL, SGD_CONTROL_STOP, 1);
641	via_wr(via, ch->rbase + VIA_RP_CONTROL, 0x00, 1);
642	via_wr(via, ch->rbase + VIA_RP_STATUS,
643	    SGD_STATUS_EOL | SGD_STATUS_FLAG, 1);
644}
645
646/* -------------------------------------------------------------------- */
647/* Channel initialization functions */
648
649static void
650via8233chan_sgdinit(struct via_info *via, struct via_chinfo *ch, int chnum)
651{
652	ch->sgd_table = &via->sgd_table[chnum * VIA_SEGS_MAX];
653	ch->sgd_addr = via->sgd_addr + chnum * VIA_SEGS_MAX *
654	    sizeof(struct via_dma_op);
655}
656
657static void*
658via8233wr_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
659						struct pcm_channel *c, int dir)
660{
661	struct via_info *via = devinfo;
662	struct via_chinfo *ch;
663	int num;
664
665	snd_mtxlock(via->lock);
666	num = via->rec_num++;
667	ch = &via->rch[num];
668	ch->parent = via;
669	ch->channel = c;
670	ch->buffer = b;
671	ch->dir = dir;
672	ch->blkcnt = via->blkcnt;
673	ch->rbase = VIA_WR_BASE(num);
674	via_wr(via, ch->rbase + VIA_WR_RP_SGD_FORMAT, WR_FIFO_ENABLE, 1);
675	snd_mtxunlock(via->lock);
676
677	if (sndbuf_alloc(ch->buffer, via->parent_dmat, 0, via->bufsz) != 0)
678		return (NULL);
679
680	snd_mtxlock(via->lock);
681	via8233chan_sgdinit(via, ch, num);
682	via8233chan_reset(via, ch);
683	snd_mtxunlock(via->lock);
684
685	return (ch);
686}
687
688static void*
689via8233dxs_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
690						struct pcm_channel *c, int dir)
691{
692	struct via_info *via = devinfo;
693	struct via_chinfo *ch;
694	int num;
695
696	snd_mtxlock(via->lock);
697	num = via->play_num++;
698	ch = &via->pch[num];
699	ch->parent = via;
700	ch->channel = c;
701	ch->buffer = b;
702	ch->dir = dir;
703	ch->blkcnt = via->blkcnt;
704
705	/*
706	 * All cards apparently support DXS3, but not other DXS
707	 * channels.  We therefore want to align first DXS channel to
708	 * DXS3.
709	 */
710	ch->rbase = VIA_DXS_BASE(NDXSCHANS - 1 - via->n_dxs_registered);
711	via->n_dxs_registered++;
712	snd_mtxunlock(via->lock);
713
714	if (sndbuf_alloc(ch->buffer, via->parent_dmat, 0, via->bufsz) != 0)
715		return (NULL);
716
717	snd_mtxlock(via->lock);
718	via8233chan_sgdinit(via, ch, NWRCHANS + num);
719	via8233chan_reset(via, ch);
720	snd_mtxunlock(via->lock);
721
722	return (ch);
723}
724
725static void*
726via8233msgd_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
727						struct pcm_channel *c, int dir)
728{
729	struct via_info *via = devinfo;
730	struct via_chinfo *ch;
731	int num;
732
733	snd_mtxlock(via->lock);
734	num = via->play_num++;
735	ch = &via->pch[num];
736	ch->parent = via;
737	ch->channel = c;
738	ch->buffer = b;
739	ch->dir = dir;
740	ch->rbase = VIA_MC_SGD_STATUS;
741	ch->blkcnt = via->blkcnt;
742	snd_mtxunlock(via->lock);
743
744	if (sndbuf_alloc(ch->buffer, via->parent_dmat, 0, via->bufsz) != 0)
745		return (NULL);
746
747	snd_mtxlock(via->lock);
748	via8233chan_sgdinit(via, ch, NWRCHANS + num);
749	via8233chan_reset(via, ch);
750	snd_mtxunlock(via->lock);
751
752	return (ch);
753}
754
755static void
756via8233chan_mute(struct via_info *via, struct via_chinfo *ch, int muted)
757{
758	if (BASE_IS_VIA_DXS_REG(ch->rbase)) {
759		int r;
760		muted = (muted) ? VIA8233_DXS_MUTE : 0;
761		via_wr(via, ch->rbase + VIA8233_RP_DXS_LVOL, muted, 1);
762		via_wr(via, ch->rbase + VIA8233_RP_DXS_RVOL, muted, 1);
763		r = via_rd(via, ch->rbase + VIA8233_RP_DXS_LVOL, 1) &
764		    VIA8233_DXS_MUTE;
765		if (r != muted)
766			device_printf(via->dev,
767			    "%s: failed to set dxs volume "
768			    "(dxs base 0x%02x).\n", __func__, ch->rbase);
769	}
770}
771
772static __inline int
773via_poll_channel(struct via_chinfo *ch)
774{
775	struct via_info *via;
776	uint32_t sz, delta;
777	uint32_t v, index, count;
778	int ptr;
779
780	if (ch == NULL || ch->channel == NULL || ch->active == 0)
781		return (0);
782
783	via = ch->parent;
784	sz = ch->blksz * ch->blkcnt;
785	v = via_rd(via, ch->rbase + VIA_RP_CURRENT_COUNT, 4);
786	index = v >> 24;
787	count = v & 0x00ffffff;
788	ptr = ((index + 1) * ch->blksz) - count;
789	ptr %= sz;
790	ptr &= ~(ch->blksz - 1);
791	ch->ptr = ptr;
792	delta = (sz + ptr - ch->prevptr) % sz;
793
794	if (delta < ch->blksz)
795		return (0);
796
797	ch->prevptr = ptr;
798
799	return (1);
800}
801
802static void
803via_poll_callback(void *arg)
804{
805	struct via_info *via = arg;
806	uint32_t ptrigger = 0, rtrigger = 0;
807	int i;
808
809	if (via == NULL)
810		return;
811
812	snd_mtxlock(via->lock);
813	if (via->polling == 0 || via_chan_active(via) == 0) {
814		snd_mtxunlock(via->lock);
815		return;
816	}
817
818	for (i = 0; i < NDXSCHANS + NMSGDCHANS; i++)
819		ptrigger |= (via_poll_channel(&via->pch[i]) != 0) ?
820		    (1 << i) : 0;
821
822	for (i = 0; i < NWRCHANS; i++)
823		rtrigger |= (via_poll_channel(&via->rch[i]) != 0) ?
824		    (1 << i) : 0;
825
826	/* XXX */
827	callout_reset(&via->poll_timer, 1/*via->poll_ticks*/,
828	    via_poll_callback, via);
829
830	snd_mtxunlock(via->lock);
831
832	for (i = 0; i < NDXSCHANS + NMSGDCHANS; i++) {
833		if (ptrigger & (1 << i))
834			chn_intr(via->pch[i].channel);
835	}
836	for (i = 0; i < NWRCHANS; i++) {
837		if (rtrigger & (1 << i))
838			chn_intr(via->rch[i].channel);
839	}
840}
841
842static int
843via_poll_ticks(struct via_info *via)
844{
845	struct via_chinfo *ch;
846	int i;
847	int ret = hz;
848	int pollticks;
849
850	for (i = 0; i < NDXSCHANS + NMSGDCHANS; i++) {
851		ch = &via->pch[i];
852		if (ch->channel == NULL || ch->active == 0)
853			continue;
854		pollticks = ((uint64_t)hz * ch->blksz) /
855		    ((uint64_t)sndbuf_getbps(ch->buffer) *
856		    sndbuf_getspd(ch->buffer));
857		pollticks >>= 2;
858		if (pollticks > hz)
859			pollticks = hz;
860		if (pollticks < 1)
861			pollticks = 1;
862		if (pollticks < ret)
863			ret = pollticks;
864	}
865
866	for (i = 0; i < NWRCHANS; i++) {
867		ch = &via->rch[i];
868		if (ch->channel == NULL || ch->active == 0)
869			continue;
870		pollticks = ((uint64_t)hz * ch->blksz) /
871		    ((uint64_t)sndbuf_getbps(ch->buffer) *
872		    sndbuf_getspd(ch->buffer));
873		pollticks >>= 2;
874		if (pollticks > hz)
875			pollticks = hz;
876		if (pollticks < 1)
877			pollticks = 1;
878		if (pollticks < ret)
879			ret = pollticks;
880	}
881
882	return (ret);
883}
884
885static int
886via8233chan_trigger(kobj_t obj, void* data, int go)
887{
888	struct via_chinfo *ch = data;
889	struct via_info *via = ch->parent;
890	int pollticks;
891
892	if (!PCMTRIG_COMMON(go))
893		return (0);
894
895	snd_mtxlock(via->lock);
896	switch(go) {
897	case PCMTRIG_START:
898		via_buildsgdt(ch);
899		via8233chan_mute(via, ch, 0);
900		via_wr(via, ch->rbase + VIA_RP_TABLE_PTR, ch->sgd_addr, 4);
901		if (via->polling != 0) {
902			ch->ptr = 0;
903			ch->prevptr = 0;
904			pollticks = ((uint64_t)hz * ch->blksz) /
905			    ((uint64_t)sndbuf_getbps(ch->buffer) *
906			    sndbuf_getspd(ch->buffer));
907			pollticks >>= 2;
908			if (pollticks > hz)
909				pollticks = hz;
910			if (pollticks < 1)
911				pollticks = 1;
912			if (via_chan_active(via) == 0 ||
913			    pollticks < via->poll_ticks) {
914			    	if (bootverbose) {
915					if (via_chan_active(via) == 0)
916						printf("%s: pollticks=%d\n",
917						    __func__, pollticks);
918					else
919						printf("%s: "
920						    "pollticks %d -> %d\n",
921						    __func__, via->poll_ticks,
922						    pollticks);
923				}
924				via->poll_ticks = pollticks;
925				callout_reset(&via->poll_timer, 1,
926				    via_poll_callback, via);
927			}
928		}
929		via_wr(via, ch->rbase + VIA_RP_CONTROL,
930		    SGD_CONTROL_START | SGD_CONTROL_AUTOSTART |
931		    ((via->polling == 0) ?
932		    (SGD_CONTROL_I_EOL | SGD_CONTROL_I_FLAG) : 0), 1);
933		ch->active = 1;
934		break;
935	case PCMTRIG_STOP:
936	case PCMTRIG_ABORT:
937		via_wr(via, ch->rbase + VIA_RP_CONTROL, SGD_CONTROL_STOP, 1);
938		via8233chan_mute(via, ch, 1);
939		via8233chan_reset(via, ch);
940		ch->active = 0;
941		if (via->polling != 0) {
942			if (via_chan_active(via) == 0) {
943				callout_stop(&via->poll_timer);
944				via->poll_ticks = 1;
945			} else {
946				pollticks = via_poll_ticks(via);
947				if (pollticks > via->poll_ticks) {
948					if (bootverbose)
949						printf("%s: pollticks "
950						    "%d -> %d\n",
951						    __func__, via->poll_ticks,
952						    pollticks);
953					via->poll_ticks = pollticks;
954					callout_reset(&via->poll_timer,
955					    1, via_poll_callback,
956					    via);
957				}
958			}
959		}
960		break;
961	default:
962		break;
963	}
964	snd_mtxunlock(via->lock);
965	return (0);
966}
967
968static kobj_method_t via8233wr_methods[] = {
969	KOBJMETHOD(channel_init,		via8233wr_init),
970	KOBJMETHOD(channel_setformat,		via8233wr_setformat),
971	KOBJMETHOD(channel_setspeed,		via8233wr_setspeed),
972	KOBJMETHOD(channel_getcaps,		via8233wr_getcaps),
973	KOBJMETHOD(channel_setblocksize,	via8233chan_setblocksize),
974	KOBJMETHOD(channel_setfragments,	via8233chan_setfragments),
975	KOBJMETHOD(channel_trigger,		via8233chan_trigger),
976	KOBJMETHOD(channel_getptr,		via8233chan_getptr),
977	{ 0, 0 }
978};
979CHANNEL_DECLARE(via8233wr);
980
981static kobj_method_t via8233dxs_methods[] = {
982	KOBJMETHOD(channel_init,		via8233dxs_init),
983	KOBJMETHOD(channel_setformat,		via8233dxs_setformat),
984	KOBJMETHOD(channel_setspeed,		via8233dxs_setspeed),
985	KOBJMETHOD(channel_getcaps,		via8233dxs_getcaps),
986	KOBJMETHOD(channel_setblocksize,	via8233chan_setblocksize),
987	KOBJMETHOD(channel_setfragments,	via8233chan_setfragments),
988	KOBJMETHOD(channel_trigger,		via8233chan_trigger),
989	KOBJMETHOD(channel_getptr,		via8233chan_getptr),
990	{ 0, 0 }
991};
992CHANNEL_DECLARE(via8233dxs);
993
994static kobj_method_t via8233msgd_methods[] = {
995	KOBJMETHOD(channel_init,		via8233msgd_init),
996	KOBJMETHOD(channel_setformat,		via8233msgd_setformat),
997	KOBJMETHOD(channel_setspeed,		via8233msgd_setspeed),
998	KOBJMETHOD(channel_getcaps,		via8233msgd_getcaps),
999	KOBJMETHOD(channel_setblocksize,	via8233chan_setblocksize),
1000	KOBJMETHOD(channel_setfragments,	via8233chan_setfragments),
1001	KOBJMETHOD(channel_trigger,		via8233chan_trigger),
1002	KOBJMETHOD(channel_getptr,		via8233chan_getptr),
1003	{ 0, 0 }
1004};
1005CHANNEL_DECLARE(via8233msgd);
1006
1007/* -------------------------------------------------------------------- */
1008
1009static void
1010via_intr(void *p)
1011{
1012	struct via_info *via = p;
1013	uint32_t ptrigger = 0, rtrigger = 0;
1014	int i, reg, stat;
1015
1016	snd_mtxlock(via->lock);
1017	if (via->polling != 0) {
1018		snd_mtxunlock(via->lock);
1019		return;
1020	}
1021	/* Poll playback channels */
1022	for (i = 0; i < NDXSCHANS + NMSGDCHANS; i++) {
1023		if (via->pch[i].channel == NULL || via->pch[i].active == 0)
1024			continue;
1025		reg = via->pch[i].rbase + VIA_RP_STATUS;
1026		stat = via_rd(via, reg, 1);
1027		if (stat & SGD_STATUS_INTR) {
1028			if (via->dma_eol_wake && ((stat & SGD_STATUS_EOL) ||
1029			    !(stat & SGD_STATUS_ACTIVE)))
1030				via_wr(via, via->pch[i].rbase + VIA_RP_CONTROL,
1031				    SGD_CONTROL_START | SGD_CONTROL_AUTOSTART |
1032				    SGD_CONTROL_I_EOL | SGD_CONTROL_I_FLAG, 1);
1033			via_wr(via, reg, stat, 1);
1034			ptrigger |= 1 << i;
1035		}
1036	}
1037	/* Poll record channels */
1038	for (i = 0; i < NWRCHANS; i++) {
1039		if (via->rch[i].channel == NULL || via->rch[i].active == 0)
1040			continue;
1041		reg = via->rch[i].rbase + VIA_RP_STATUS;
1042		stat = via_rd(via, reg, 1);
1043		if (stat & SGD_STATUS_INTR) {
1044			if (via->dma_eol_wake && ((stat & SGD_STATUS_EOL) ||
1045			    !(stat & SGD_STATUS_ACTIVE)))
1046				via_wr(via, via->rch[i].rbase + VIA_RP_CONTROL,
1047				    SGD_CONTROL_START | SGD_CONTROL_AUTOSTART |
1048				    SGD_CONTROL_I_EOL | SGD_CONTROL_I_FLAG, 1);
1049			via_wr(via, reg, stat, 1);
1050			rtrigger |= 1 << i;
1051		}
1052	}
1053	snd_mtxunlock(via->lock);
1054
1055	for (i = 0; i < NDXSCHANS + NMSGDCHANS; i++) {
1056		if (ptrigger & (1 << i))
1057			chn_intr(via->pch[i].channel);
1058	}
1059	for (i = 0; i < NWRCHANS; i++) {
1060		if (rtrigger & (1 << i))
1061			chn_intr(via->rch[i].channel);
1062	}
1063}
1064
1065/*
1066 *  Probe and attach the card
1067 */
1068static int
1069via_probe(device_t dev)
1070{
1071	switch(pci_get_devid(dev)) {
1072	case VIA8233_PCI_ID:
1073		switch(pci_get_revid(dev)) {
1074		case VIA8233_REV_ID_8233PRE:
1075			device_set_desc(dev, "VIA VT8233 (pre)");
1076			return (BUS_PROBE_DEFAULT);
1077		case VIA8233_REV_ID_8233C:
1078			device_set_desc(dev, "VIA VT8233C");
1079			return (BUS_PROBE_DEFAULT);
1080		case VIA8233_REV_ID_8233:
1081			device_set_desc(dev, "VIA VT8233");
1082			return (BUS_PROBE_DEFAULT);
1083		case VIA8233_REV_ID_8233A:
1084			device_set_desc(dev, "VIA VT8233A");
1085			return (BUS_PROBE_DEFAULT);
1086		case VIA8233_REV_ID_8235:
1087			device_set_desc(dev, "VIA VT8235");
1088			return (BUS_PROBE_DEFAULT);
1089		case VIA8233_REV_ID_8237:
1090			device_set_desc(dev, "VIA VT8237");
1091			return (BUS_PROBE_DEFAULT);
1092		case VIA8233_REV_ID_8251:
1093			device_set_desc(dev, "VIA VT8251");
1094			return (BUS_PROBE_DEFAULT);
1095		default:
1096			device_set_desc(dev, "VIA VT8233X");	/* Unknown */
1097			return (BUS_PROBE_DEFAULT);
1098		}
1099	}
1100	return (ENXIO);
1101}
1102
1103static void
1104dma_cb(void *p, bus_dma_segment_t *bds, int a, int b)
1105{
1106	struct via_info *via = (struct via_info *)p;
1107	via->sgd_addr = bds->ds_addr;
1108}
1109
1110static int
1111via_chip_init(device_t dev)
1112{
1113	uint32_t data, cnt;
1114
1115	/* Wake up and reset AC97 if necessary */
1116	data = pci_read_config(dev, VIA_PCI_ACLINK_STAT, 1);
1117
1118	if ((data & VIA_PCI_ACLINK_C00_READY) == 0) {
1119		/* Cold reset per ac97r2.3 spec (page 95) */
1120		/* Assert low */
1121		pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
1122		    VIA_PCI_ACLINK_EN, 1);
1123		/* Wait T_rst_low */
1124		DELAY(100);
1125		/* Assert high */
1126		pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
1127		    VIA_PCI_ACLINK_EN | VIA_PCI_ACLINK_NRST, 1);
1128		/* Wait T_rst2clk */
1129		DELAY(5);
1130		/* Assert low */
1131		pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
1132		    VIA_PCI_ACLINK_EN, 1);
1133	} else {
1134		/* Warm reset */
1135		/* Force no sync */
1136		pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
1137		    VIA_PCI_ACLINK_EN, 1);
1138		DELAY(100);
1139		/* Sync */
1140		pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
1141		    VIA_PCI_ACLINK_EN | VIA_PCI_ACLINK_SYNC, 1);
1142		/* Wait T_sync_high */
1143		DELAY(5);
1144		/* Force no sync */
1145		pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
1146		    VIA_PCI_ACLINK_EN, 1);
1147		/* Wait T_sync2clk */
1148		DELAY(5);
1149	}
1150
1151	/* Power everything up */
1152	pci_write_config(dev, VIA_PCI_ACLINK_CTRL, VIA_PCI_ACLINK_DESIRED, 1);
1153
1154	/* Wait for codec to become ready (largest reported delay 310ms) */
1155	for (cnt = 0; cnt < 2000; cnt++) {
1156		data = pci_read_config(dev, VIA_PCI_ACLINK_STAT, 1);
1157		if (data & VIA_PCI_ACLINK_C00_READY)
1158			return (0);
1159		DELAY(5000);
1160	}
1161	device_printf(dev, "primary codec not ready (cnt = 0x%02x)\n", cnt);
1162	return (ENXIO);
1163}
1164
1165static int
1166via_attach(device_t dev)
1167{
1168	struct via_info *via = 0;
1169	char status[SND_STATUSLEN];
1170	int i, via_dxs_disabled, via_dxs_src, via_dxs_chnum, via_sgd_chnum;
1171	int nsegs;
1172	uint32_t revid;
1173
1174	if ((via = malloc(sizeof *via, M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
1175		device_printf(dev, "cannot allocate softc\n");
1176		return (ENXIO);
1177	}
1178	via->lock = snd_mtxcreate(device_get_nameunit(dev),
1179	    "snd_via8233 softc");
1180	via->dev = dev;
1181
1182	callout_init(&via->poll_timer, CALLOUT_MPSAFE);
1183	via->poll_ticks = 1;
1184
1185	if (resource_int_value(device_get_name(dev),
1186	    device_get_unit(dev), "polling", &i) == 0 && i != 0)
1187		via->polling = 1;
1188	else
1189		via->polling = 0;
1190
1191	pci_set_powerstate(dev, PCI_POWERSTATE_D0);
1192	pci_enable_busmaster(dev);
1193
1194	via->regid = PCIR_BAR(0);
1195	via->reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &via->regid,
1196					  RF_ACTIVE);
1197	if (!via->reg) {
1198		device_printf(dev, "cannot allocate bus resource.");
1199		goto bad;
1200	}
1201	via->st = rman_get_bustag(via->reg);
1202	via->sh = rman_get_bushandle(via->reg);
1203
1204	via->irqid = 0;
1205	via->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &via->irqid,
1206	    RF_ACTIVE | RF_SHAREABLE);
1207	if (!via->irq ||
1208	    snd_setup_intr(dev, via->irq, INTR_MPSAFE,
1209	    via_intr, via, &via->ih)) {
1210		device_printf(dev, "unable to map interrupt\n");
1211		goto bad;
1212	}
1213
1214	via->bufsz = pcm_getbuffersize(dev, 4096, VIA_DEFAULT_BUFSZ, 65536);
1215	if (resource_int_value(device_get_name(dev),
1216	    device_get_unit(dev), "blocksize", &i) == 0 && i > 0) {
1217		i &= VIA_BLK_ALIGN;
1218		if (i < VIA_BLK_MIN)
1219			i = VIA_BLK_MIN;
1220		via->blkcnt = via->bufsz / i;
1221		i = 0;
1222		while (via->blkcnt >> i)
1223			i++;
1224		via->blkcnt = 1 << (i - 1);
1225		if (via->blkcnt < VIA_SEGS_MIN)
1226			via->blkcnt = VIA_SEGS_MIN;
1227		else if (via->blkcnt > VIA_SEGS_MAX)
1228			via->blkcnt = VIA_SEGS_MAX;
1229
1230	} else
1231		via->blkcnt = VIA_SEGS_DEFAULT;
1232
1233	revid = pci_get_revid(dev);
1234
1235	/*
1236	 * VIA8251 lost its interrupt after DMA EOL, and need
1237	 * a gentle spank on its face within interrupt handler.
1238	 */
1239	if (revid == VIA8233_REV_ID_8251)
1240		via->dma_eol_wake = 1;
1241	else
1242		via->dma_eol_wake = 0;
1243
1244	/*
1245	 * Decide whether DXS had to be disabled or not
1246	 */
1247	if (revid == VIA8233_REV_ID_8233A) {
1248		/*
1249		 * DXS channel is disabled.  Reports from multiple users
1250		 * that it plays at half-speed.  Do not see this behaviour
1251		 * on available 8233C or when emulating 8233A register set
1252		 * on 8233C (either with or without ac97 VRA).
1253		 */
1254		via_dxs_disabled = 1;
1255	} else if (resource_int_value(device_get_name(dev),
1256	    device_get_unit(dev), "via_dxs_disabled",
1257	    &via_dxs_disabled) == 0)
1258		via_dxs_disabled = (via_dxs_disabled > 0) ? 1 : 0;
1259	else
1260		via_dxs_disabled = 0;
1261
1262	if (via_dxs_disabled) {
1263		via_dxs_chnum = 0;
1264		via_sgd_chnum = 1;
1265	} else {
1266		if (resource_int_value(device_get_name(dev),
1267		    device_get_unit(dev), "via_dxs_channels",
1268		    &via_dxs_chnum) != 0)
1269			via_dxs_chnum = NDXSCHANS;
1270		if (resource_int_value(device_get_name(dev),
1271		    device_get_unit(dev), "via_sgd_channels",
1272		    &via_sgd_chnum) != 0)
1273			via_sgd_chnum = NMSGDCHANS;
1274	}
1275	if (via_dxs_chnum > NDXSCHANS)
1276		via_dxs_chnum = NDXSCHANS;
1277	else if (via_dxs_chnum < 0)
1278		via_dxs_chnum = 0;
1279	if (via_sgd_chnum > NMSGDCHANS)
1280		via_sgd_chnum = NMSGDCHANS;
1281	else if (via_sgd_chnum < 0)
1282		via_sgd_chnum = 0;
1283	if (via_dxs_chnum + via_sgd_chnum < 1) {
1284		/* Minimalist ? */
1285		via_dxs_chnum = 1;
1286		via_sgd_chnum = 0;
1287	}
1288	if (via_dxs_chnum > 0 && resource_int_value(device_get_name(dev),
1289	    device_get_unit(dev), "via_dxs_src", &via_dxs_src) == 0)
1290		via->dxs_src = (via_dxs_src > 0) ? 1 : 0;
1291	else
1292		via->dxs_src = 0;
1293
1294	nsegs = (via_dxs_chnum + via_sgd_chnum + NWRCHANS) * VIA_SEGS_MAX;
1295
1296	/* DMA tag for buffers */
1297	if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
1298		/*boundary*/0,
1299		/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
1300		/*highaddr*/BUS_SPACE_MAXADDR,
1301		/*filter*/NULL, /*filterarg*/NULL,
1302		/*maxsize*/via->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
1303		/*flags*/0, /*lockfunc*/NULL,
1304		/*lockarg*/NULL, &via->parent_dmat) != 0) {
1305		device_printf(dev, "unable to create dma tag\n");
1306		goto bad;
1307	}
1308
1309	/*
1310	 *  DMA tag for SGD table.  The 686 uses scatter/gather DMA and
1311	 *  requires a list in memory of work to do.  We need only 16 bytes
1312	 *  for this list, and it is wasteful to allocate 16K.
1313	 */
1314	if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
1315		/*boundary*/0,
1316		/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
1317		/*highaddr*/BUS_SPACE_MAXADDR,
1318		/*filter*/NULL, /*filterarg*/NULL,
1319		/*maxsize*/nsegs * sizeof(struct via_dma_op),
1320		/*nsegments*/1, /*maxsegz*/0x3ffff,
1321		/*flags*/0, /*lockfunc*/NULL,
1322		/*lockarg*/NULL, &via->sgd_dmat) != 0) {
1323		device_printf(dev, "unable to create dma tag\n");
1324		goto bad;
1325	}
1326
1327	if (bus_dmamem_alloc(via->sgd_dmat, (void **)&via->sgd_table,
1328	    BUS_DMA_NOWAIT, &via->sgd_dmamap) == -1)
1329		goto bad;
1330	if (bus_dmamap_load(via->sgd_dmat, via->sgd_dmamap, via->sgd_table,
1331	    nsegs * sizeof(struct via_dma_op), dma_cb, via, 0))
1332		goto bad;
1333
1334	if (via_chip_init(dev))
1335		goto bad;
1336
1337	via->codec = AC97_CREATE(dev, via, via_ac97);
1338	if (!via->codec)
1339		goto bad;
1340
1341	mixer_init(dev, ac97_getmixerclass(), via->codec);
1342
1343	via->codec_caps = ac97_getextcaps(via->codec);
1344
1345	/* Try to set VRA without generating an error, VRM not reqrd yet */
1346	if (via->codec_caps &
1347	    (AC97_EXTCAP_VRA | AC97_EXTCAP_VRM | AC97_EXTCAP_DRA)) {
1348		uint16_t ext = ac97_getextmode(via->codec);
1349		ext |= (via->codec_caps &
1350		    (AC97_EXTCAP_VRA | AC97_EXTCAP_VRM));
1351		ext &= ~AC97_EXTCAP_DRA;
1352		ac97_setextmode(via->codec, ext);
1353	}
1354
1355	snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld %s",
1356	    rman_get_start(via->reg), rman_get_start(via->irq),
1357	    PCM_KLDSTRING(snd_via8233));
1358
1359	/* Register */
1360	if (pcm_register(dev, via, via_dxs_chnum + via_sgd_chnum, NWRCHANS))
1361	      goto bad;
1362	for (i = 0; i < via_dxs_chnum; i++)
1363	      pcm_addchan(dev, PCMDIR_PLAY, &via8233dxs_class, via);
1364	for (i = 0; i < via_sgd_chnum; i++)
1365	      pcm_addchan(dev, PCMDIR_PLAY, &via8233msgd_class, via);
1366	for (i = 0; i < NWRCHANS; i++)
1367	      pcm_addchan(dev, PCMDIR_REC, &via8233wr_class, via);
1368	if (via_dxs_chnum > 0)
1369		via_init_sysctls(dev);
1370	device_printf(dev, "<VIA DXS %sabled: DXS%s %d / SGD %d / REC %d>\n",
1371	    (via_dxs_chnum > 0) ? "En" : "Dis", (via->dxs_src) ? "(SRC)" : "",
1372	    via_dxs_chnum, via_sgd_chnum, NWRCHANS);
1373
1374	pcm_setstatus(dev, status);
1375
1376	return (0);
1377bad:
1378	if (via->codec)
1379		ac97_destroy(via->codec);
1380	if (via->reg)
1381		bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg);
1382	if (via->ih)
1383		bus_teardown_intr(dev, via->irq, via->ih);
1384	if (via->irq)
1385		bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq);
1386	if (via->parent_dmat)
1387		bus_dma_tag_destroy(via->parent_dmat);
1388	if (via->sgd_dmamap)
1389		bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap);
1390	if (via->sgd_table)
1391		bus_dmamem_free(via->sgd_dmat, via->sgd_table, via->sgd_dmamap);
1392	if (via->sgd_dmat)
1393		bus_dma_tag_destroy(via->sgd_dmat);
1394	if (via->lock)
1395		snd_mtxfree(via->lock);
1396	if (via)
1397		free(via, M_DEVBUF);
1398	return (ENXIO);
1399}
1400
1401static int
1402via_detach(device_t dev)
1403{
1404	int r;
1405	struct via_info *via = 0;
1406
1407	r = pcm_unregister(dev);
1408	if (r)
1409		return (r);
1410
1411	via = pcm_getdevinfo(dev);
1412	bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg);
1413	bus_teardown_intr(dev, via->irq, via->ih);
1414	bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq);
1415	bus_dma_tag_destroy(via->parent_dmat);
1416	bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap);
1417	bus_dmamem_free(via->sgd_dmat, via->sgd_table, via->sgd_dmamap);
1418	bus_dma_tag_destroy(via->sgd_dmat);
1419	snd_mtxfree(via->lock);
1420	free(via, M_DEVBUF);
1421	return (0);
1422}
1423
1424
1425static device_method_t via_methods[] = {
1426	DEVMETHOD(device_probe,		via_probe),
1427	DEVMETHOD(device_attach,	via_attach),
1428	DEVMETHOD(device_detach,	via_detach),
1429	{ 0, 0}
1430};
1431
1432static driver_t via_driver = {
1433	"pcm",
1434	via_methods,
1435	PCM_SOFTC_SIZE,
1436};
1437
1438DRIVER_MODULE(snd_via8233, pci, via_driver, pcm_devclass, 0, 0);
1439MODULE_DEPEND(snd_via8233, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
1440MODULE_VERSION(snd_via8233, 1);
1441