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