2 * Copyright (c) 2000 David Jones <dej@ox.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * $FreeBSD: src/sys/dev/sound/pci/via82c686.c,v 1.4.2.10 2003/05/11 01:45:53 orion Exp $
27 * $DragonFly: src/sys/dev/sound/pci/via82c686.c,v 1.6 2006/12/20 18:14:40 dillon Exp $
30 #include <dev/sound/pcm/sound.h>
31 #include <dev/sound/pcm/ac97.h>
33 #include <bus/pci/pcireg.h>
34 #include <bus/pci/pcivar.h>
35 #include <sys/sysctl.h>
37 #include <dev/sound/pci/via82c686.h>
39 SND_DECLARE_FILE("$DragonFly: src/sys/dev/sound/pci/via82c686.c,v 1.6 2006/12/20 18:14:40 dillon Exp $");
41 #define VIA_PCI_ID 0x30581106
42 #define NSEGS 4 /* Number of segments in SGD table */
44 #define SEGS_PER_CHAN (NSEGS/2)
47 #define VIA_DEFAULT_BUFSZ 0x1000
52 /* we rely on this struct being packed to 64 bits */
56 #define VIA_DMAOP_EOL 0x80000000
57 #define VIA_DMAOP_FLAG 0x40000000
58 #define VIA_DMAOP_STOP 0x20000000
59 #define VIA_DMAOP_COUNT(x) ((x)&0x00FFFFFF)
65 struct via_info
*parent
;
66 struct pcm_channel
*channel
;
67 struct snd_dbuf
*buffer
;
68 struct via_dma_op
*sgd_table
;
70 int base
, count
, mode
, ctrl
;
75 bus_space_handle_t sh
;
76 bus_dma_tag_t parent_dmat
;
77 bus_dma_tag_t sgd_dmat
;
78 bus_dmamap_t sgd_dmamap
;
80 struct resource
*reg
, *irq
;
83 struct ac97_info
*codec
;
87 struct via_chinfo pch
, rch
;
88 struct via_dma_op
*sgd_table
;
92 static u_int32_t via_fmt
[] = {
94 AFMT_STEREO
| AFMT_U8
,
96 AFMT_STEREO
| AFMT_S16_LE
,
99 static struct pcmchan_caps via_vracaps
= {4000, 48000, via_fmt
, 0};
100 static struct pcmchan_caps via_caps
= {48000, 48000, via_fmt
, 0};
103 via_rd(struct via_info
*via
, int regno
, int size
)
108 return bus_space_read_1(via
->st
, via
->sh
, regno
);
110 return bus_space_read_2(via
->st
, via
->sh
, regno
);
112 return bus_space_read_4(via
->st
, via
->sh
, regno
);
120 via_wr(struct via_info
*via
, int regno
, u_int32_t data
, int size
)
125 bus_space_write_1(via
->st
, via
->sh
, regno
, data
);
128 bus_space_write_2(via
->st
, via
->sh
, regno
, data
);
131 bus_space_write_4(via
->st
, via
->sh
, regno
, data
);
136 /* -------------------------------------------------------------------- */
137 /* Codec interface */
140 via_waitready_codec(struct via_info
*via
)
144 /* poll until codec not busy */
145 for (i
= 0; (i
< TIMEOUT
) &&
146 (via_rd(via
, VIA_CODEC_CTL
, 4) & VIA_CODEC_BUSY
); i
++)
149 printf("via: codec busy\n");
158 via_waitvalid_codec(struct via_info
*via
)
162 /* poll until codec valid */
163 for (i
= 0; (i
< TIMEOUT
) &&
164 !(via_rd(via
, VIA_CODEC_CTL
, 4) & VIA_CODEC_PRIVALID
); i
++)
167 printf("via: codec invalid\n");
176 via_write_codec(kobj_t obj
, void *addr
, int reg
, u_int32_t val
)
178 struct via_info
*via
= addr
;
180 if (via_waitready_codec(via
)) return -1;
182 via_wr(via
, VIA_CODEC_CTL
, VIA_CODEC_PRIVALID
| VIA_CODEC_INDEX(reg
) | val
, 4);
189 via_read_codec(kobj_t obj
, void *addr
, int reg
)
191 struct via_info
*via
= addr
;
193 if (via_waitready_codec(via
))
196 via_wr(via
, VIA_CODEC_CTL
, VIA_CODEC_PRIVALID
| VIA_CODEC_READ
| VIA_CODEC_INDEX(reg
),4);
198 if (via_waitready_codec(via
))
201 if (via_waitvalid_codec(via
))
204 return via_rd(via
, VIA_CODEC_CTL
, 2);
207 static kobj_method_t via_ac97_methods
[] = {
208 KOBJMETHOD(ac97_read
, via_read_codec
),
209 KOBJMETHOD(ac97_write
, via_write_codec
),
212 AC97_DECLARE(via_ac97
);
214 /* -------------------------------------------------------------------- */
217 via_buildsgdt(struct via_chinfo
*ch
)
219 u_int32_t phys_addr
, flag
;
220 int i
, segs
, seg_size
;
223 * Build the scatter/gather DMA (SGD) table.
224 * There are four slots in the table: two for play, two for record.
225 * This creates two half-buffers, one of which is playing; the other
228 seg_size
= ch
->blksz
;
229 segs
= sndbuf_getsize(ch
->buffer
) / seg_size
;
230 phys_addr
= vtophys(sndbuf_getbuf(ch
->buffer
));
232 for (i
= 0; i
< segs
; i
++) {
233 flag
= (i
== segs
- 1)? VIA_DMAOP_EOL
: VIA_DMAOP_FLAG
;
234 ch
->sgd_table
[i
].ptr
= phys_addr
+ (i
* seg_size
);
235 ch
->sgd_table
[i
].flags
= flag
| seg_size
;
241 /* channel interface */
243 viachan_init(kobj_t obj
, void *devinfo
, struct snd_dbuf
*b
, struct pcm_channel
*c
, int dir
)
245 struct via_info
*via
= devinfo
;
246 struct via_chinfo
*ch
= (dir
== PCMDIR_PLAY
)? &via
->pch
: &via
->rch
;
252 ch
->sgd_table
= &via
->sgd_table
[(dir
== PCMDIR_PLAY
)? 0 : SEGS_PER_CHAN
];
253 if (ch
->dir
== PCMDIR_PLAY
) {
254 ch
->base
= VIA_PLAY_DMAOPS_BASE
;
255 ch
->count
= VIA_PLAY_DMAOPS_COUNT
;
256 ch
->ctrl
= VIA_PLAY_CONTROL
;
257 ch
->mode
= VIA_PLAY_MODE
;
259 ch
->base
= VIA_RECORD_DMAOPS_BASE
;
260 ch
->count
= VIA_RECORD_DMAOPS_COUNT
;
261 ch
->ctrl
= VIA_RECORD_CONTROL
;
262 ch
->mode
= VIA_RECORD_MODE
;
265 if (sndbuf_alloc(ch
->buffer
, via
->parent_dmat
, via
->bufsz
) == -1)
271 viachan_setformat(kobj_t obj
, void *data
, u_int32_t format
)
273 struct via_chinfo
*ch
= data
;
274 struct via_info
*via
= ch
->parent
;
278 if (format
& AFMT_STEREO
)
279 mode_set
|= VIA_RPMODE_STEREO
;
280 if (format
& AFMT_S16_LE
)
281 mode_set
|= VIA_RPMODE_16BIT
;
283 DEB(printf("set format: dir = %d, format=%x\n", ch
->dir
, format
));
284 mode
= via_rd(via
, ch
->mode
, 1);
285 mode
&= ~(VIA_RPMODE_16BIT
| VIA_RPMODE_STEREO
);
287 via_wr(via
, ch
->mode
, mode
, 1);
293 viachan_setspeed(kobj_t obj
, void *data
, u_int32_t speed
)
295 struct via_chinfo
*ch
= data
;
296 struct via_info
*via
= ch
->parent
;
300 * Basic AC'97 defines a 48 kHz sample rate only. For other rates,
301 * upsampling is required.
303 * The VT82C686A does not perform upsampling, and neither do we.
304 * If the codec supports variable-rate audio (i.e. does the upsampling
305 * itself), then negotiate the rate with the codec. Otherwise,
306 * return 48 kHz cuz that's all you got.
308 if (via
->codec_caps
& AC97_EXTCAP_VRA
) {
309 reg
= (ch
->dir
== PCMDIR_PLAY
)? AC97_REGEXT_FDACRATE
: AC97_REGEXT_LADCRATE
;
310 return ac97_setrate(via
->codec
, reg
, speed
);
316 viachan_setblocksize(kobj_t obj
, void *data
, u_int32_t blocksize
)
318 struct via_chinfo
*ch
= data
;
320 ch
->blksz
= blocksize
;
321 sndbuf_resize(ch
->buffer
, SEGS_PER_CHAN
, ch
->blksz
);
327 viachan_trigger(kobj_t obj
, void *data
, int go
)
329 struct via_chinfo
*ch
= data
;
330 struct via_info
*via
= ch
->parent
;
331 struct via_dma_op
*ado
;
333 if (go
== PCMTRIG_EMLDMAWR
|| go
== PCMTRIG_EMLDMARD
)
337 DEB(printf("ado located at va=%p pa=%x\n", ado
, vtophys(ado
)));
339 if (go
== PCMTRIG_START
) {
341 via_wr(via
, ch
->base
, vtophys(ado
), 4);
342 via_wr(via
, ch
->ctrl
, VIA_RPCTRL_START
, 1);
344 via_wr(via
, ch
->ctrl
, VIA_RPCTRL_TERMINATE
, 1);
346 DEB(printf("viachan_trigger: go=%d\n", go
));
351 viachan_getptr(kobj_t obj
, void *data
)
353 struct via_chinfo
*ch
= data
;
354 struct via_info
*via
= ch
->parent
;
355 struct via_dma_op
*ado
;
356 int ptr
, base
, base1
, len
, seg
;
359 base1
= via_rd(via
, ch
->base
, 4);
360 len
= via_rd(via
, ch
->count
, 4);
361 base
= via_rd(via
, ch
->base
, 4);
362 if (base
!= base1
) /* Avoid race hazard */
363 len
= via_rd(via
, ch
->count
, 4);
365 DEB(printf("viachan_getptr: len / base = %x / %x\n", len
, base
));
367 /* Base points to SGD segment to do, one past current */
369 /* Determine how many segments have been done */
370 seg
= (base
- vtophys(ado
)) / sizeof(struct via_dma_op
);
374 /* Now work out offset: seg less count */
375 ptr
= (seg
* sndbuf_getsize(ch
->buffer
) / SEGS_PER_CHAN
) - len
;
376 if (ch
->dir
== PCMDIR_REC
) {
377 /* DMA appears to operate on memory 'lines' of 32 bytes */
378 /* so don't return any part line - it isn't in RAM yet */
382 DEB(printf("return ptr=%d\n", ptr
));
386 static struct pcmchan_caps
*
387 viachan_getcaps(kobj_t obj
, void *data
)
389 struct via_chinfo
*ch
= data
;
390 struct via_info
*via
= ch
->parent
;
392 return (via
->codec_caps
& AC97_EXTCAP_VRA
)? &via_vracaps
: &via_caps
;
395 static kobj_method_t viachan_methods
[] = {
396 KOBJMETHOD(channel_init
, viachan_init
),
397 KOBJMETHOD(channel_setformat
, viachan_setformat
),
398 KOBJMETHOD(channel_setspeed
, viachan_setspeed
),
399 KOBJMETHOD(channel_setblocksize
, viachan_setblocksize
),
400 KOBJMETHOD(channel_trigger
, viachan_trigger
),
401 KOBJMETHOD(channel_getptr
, viachan_getptr
),
402 KOBJMETHOD(channel_getcaps
, viachan_getcaps
),
405 CHANNEL_DECLARE(viachan
);
407 /* -------------------------------------------------------------------- */
412 struct via_info
*via
= p
;
415 /* DEB(printf("viachan_intr\n")); */
417 st
= via_rd(via
, VIA_PLAY_STAT
, 1);
418 if (st
& VIA_RPSTAT_INTR
) {
419 via_wr(via
, VIA_PLAY_STAT
, VIA_RPSTAT_INTR
, 1);
420 chn_intr(via
->pch
.channel
);
424 st
= via_rd(via
, VIA_RECORD_STAT
, 1);
425 if (st
& VIA_RPSTAT_INTR
) {
426 via_wr(via
, VIA_RECORD_STAT
, VIA_RPSTAT_INTR
, 1);
427 chn_intr(via
->rch
.channel
);
432 * Probe and attach the card
435 via_probe(device_t dev
)
437 if (pci_get_devid(dev
) == VIA_PCI_ID
) {
438 device_set_desc(dev
, "VIA VT82C686A");
446 dma_cb(void *p
, bus_dma_segment_t
*bds
, int a
, int b
)
452 via_attach(device_t dev
)
454 struct via_info
*via
= 0;
455 char status
[SND_STATUSLEN
];
458 if ((via
= kmalloc(sizeof *via
, M_DEVBUF
, M_NOWAIT
| M_ZERO
)) == NULL
) {
459 device_printf(dev
, "cannot allocate softc\n");
464 data
= pci_read_config(dev
, PCIR_COMMAND
, 2);
465 data
|= (PCIM_CMD_PORTEN
| PCIM_CMD_BUSMASTEREN
);
466 pci_write_config(dev
, PCIR_COMMAND
, data
, 2);
467 data
= pci_read_config(dev
, PCIR_COMMAND
, 2);
469 /* Wake up and reset AC97 if necessary */
470 data
= pci_read_config(dev
, VIA_AC97STATUS
, 1);
472 if ((data
& VIA_AC97STATUS_RDY
) == 0) {
473 /* Cold reset per ac97r2.3 spec (page 95) */
474 pci_write_config(dev
, VIA_ACLINKCTRL
, VIA_ACLINK_EN
, 1); /* Assert low */
475 DELAY(100); /* Wait T_rst_low */
476 pci_write_config(dev
, VIA_ACLINKCTRL
, VIA_ACLINK_EN
| VIA_ACLINK_NRST
, 1); /* Assert high */
477 DELAY(5); /* Wait T_rst2clk */
478 pci_write_config(dev
, VIA_ACLINKCTRL
, VIA_ACLINK_EN
, 1); /* Assert low */
481 pci_write_config(dev
, VIA_ACLINKCTRL
, VIA_ACLINK_EN
, 1); /* Force no sync */
483 pci_write_config(dev
, VIA_ACLINKCTRL
, VIA_ACLINK_EN
| VIA_ACLINK_SYNC
, 1); /* Sync */
484 DELAY(5); /* Wait T_sync_high */
485 pci_write_config(dev
, VIA_ACLINKCTRL
, VIA_ACLINK_EN
, 1); /* Force no sync */
486 DELAY(5); /* Wait T_sync2clk */
489 /* Power everything up */
490 pci_write_config(dev
, VIA_ACLINKCTRL
, VIA_ACLINK_DESIRED
, 1);
492 /* Wait for codec to become ready (largest reported delay here 310ms) */
493 for (cnt
= 0; cnt
< 2000; cnt
++) {
494 data
= pci_read_config(dev
, VIA_AC97STATUS
, 1);
495 if (data
& VIA_AC97STATUS_RDY
)
500 via
->regid
= PCIR_MAPS
;
501 via
->reg
= bus_alloc_resource(dev
, SYS_RES_IOPORT
, &via
->regid
, 0, ~0, 1, RF_ACTIVE
);
503 device_printf(dev
, "cannot allocate bus resource.");
506 via
->st
= rman_get_bustag(via
->reg
);
507 via
->sh
= rman_get_bushandle(via
->reg
);
509 via
->bufsz
= pcm_getbuffersize(dev
, 4096, VIA_DEFAULT_BUFSZ
, 65536);
512 via
->irq
= bus_alloc_resource(dev
, SYS_RES_IRQ
, &via
->irqid
, 0, ~0, 1, RF_ACTIVE
| RF_SHAREABLE
);
513 if (!via
->irq
|| snd_setup_intr(dev
, via
->irq
, 0, via_intr
, via
, &via
->ih
, NULL
)) {
514 device_printf(dev
, "unable to map interrupt\n");
518 via_wr(via
, VIA_PLAY_MODE
, VIA_RPMODE_AUTOSTART
| VIA_RPMODE_INTR_FLAG
| VIA_RPMODE_INTR_EOL
, 1);
519 via_wr(via
, VIA_RECORD_MODE
, VIA_RPMODE_AUTOSTART
| VIA_RPMODE_INTR_FLAG
| VIA_RPMODE_INTR_EOL
, 1);
521 via
->codec
= AC97_CREATE(dev
, via
, via_ac97
);
525 if (mixer_init(dev
, ac97_getmixerclass(), via
->codec
))
528 via
->codec_caps
= ac97_getextcaps(via
->codec
);
529 ac97_setextmode(via
->codec
,
530 via
->codec_caps
& (AC97_EXTCAP_VRA
| AC97_EXTCAP_VRM
));
532 /* DMA tag for buffers */
533 if (bus_dma_tag_create(/*parent*/NULL
, /*alignment*/2, /*boundary*/0,
534 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT
,
535 /*highaddr*/BUS_SPACE_MAXADDR
,
536 /*filter*/NULL
, /*filterarg*/NULL
,
537 /*maxsize*/via
->bufsz
, /*nsegments*/1, /*maxsegz*/0x3ffff,
538 /*flags*/0, &via
->parent_dmat
) != 0) {
539 device_printf(dev
, "unable to create dma tag\n");
544 * DMA tag for SGD table. The 686 uses scatter/gather DMA and
545 * requires a list in memory of work to do. We need only 16 bytes
546 * for this list, and it is wasteful to allocate 16K.
548 if (bus_dma_tag_create(/*parent*/NULL
, /*alignment*/2, /*boundary*/0,
549 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT
,
550 /*highaddr*/BUS_SPACE_MAXADDR
,
551 /*filter*/NULL
, /*filterarg*/NULL
,
552 /*maxsize*/NSEGS
* sizeof(struct via_dma_op
),
553 /*nsegments*/1, /*maxsegz*/0x3ffff,
554 /*flags*/0, &via
->sgd_dmat
) != 0) {
555 device_printf(dev
, "unable to create dma tag\n");
559 if (bus_dmamem_alloc(via
->sgd_dmat
, (void **)&via
->sgd_table
, BUS_DMA_NOWAIT
, &via
->sgd_dmamap
) == -1)
561 if (bus_dmamap_load(via
->sgd_dmat
, via
->sgd_dmamap
, via
->sgd_table
, NSEGS
* sizeof(struct via_dma_op
), dma_cb
, 0, 0))
564 ksnprintf(status
, SND_STATUSLEN
, "at io 0x%lx irq %ld", rman_get_start(via
->reg
), rman_get_start(via
->irq
));
567 if (pcm_register(dev
, via
, 1, 1)) goto bad
;
568 pcm_addchan(dev
, PCMDIR_PLAY
, &viachan_class
, via
);
569 pcm_addchan(dev
, PCMDIR_REC
, &viachan_class
, via
);
570 pcm_setstatus(dev
, status
);
573 if (via
->codec
) ac97_destroy(via
->codec
);
574 if (via
->reg
) bus_release_resource(dev
, SYS_RES_IOPORT
, via
->regid
, via
->reg
);
575 if (via
->ih
) bus_teardown_intr(dev
, via
->irq
, via
->ih
);
576 if (via
->irq
) bus_release_resource(dev
, SYS_RES_IRQ
, via
->irqid
, via
->irq
);
577 if (via
->parent_dmat
) bus_dma_tag_destroy(via
->parent_dmat
);
578 if (via
->sgd_dmamap
) bus_dmamap_unload(via
->sgd_dmat
, via
->sgd_dmamap
);
579 if (via
->sgd_dmat
) bus_dma_tag_destroy(via
->sgd_dmat
);
580 if (via
) kfree(via
, M_DEVBUF
);
585 via_detach(device_t dev
)
588 struct via_info
*via
= 0;
590 r
= pcm_unregister(dev
);
594 via
= pcm_getdevinfo(dev
);
595 bus_release_resource(dev
, SYS_RES_IOPORT
, via
->regid
, via
->reg
);
596 bus_teardown_intr(dev
, via
->irq
, via
->ih
);
597 bus_release_resource(dev
, SYS_RES_IRQ
, via
->irqid
, via
->irq
);
598 bus_dma_tag_destroy(via
->parent_dmat
);
599 bus_dmamap_unload(via
->sgd_dmat
, via
->sgd_dmamap
);
600 bus_dma_tag_destroy(via
->sgd_dmat
);
601 kfree(via
, M_DEVBUF
);
606 static device_method_t via_methods
[] = {
607 DEVMETHOD(device_probe
, via_probe
),
608 DEVMETHOD(device_attach
, via_attach
),
609 DEVMETHOD(device_detach
, via_detach
),
613 static driver_t via_driver
= {
619 DRIVER_MODULE(snd_via82c686
, pci
, via_driver
, pcm_devclass
, 0, 0);
620 MODULE_DEPEND(snd_via82c686
, snd_pcm
, PCM_MINVER
, PCM_PREFVER
, PCM_MAXVER
);
621 MODULE_VERSION(snd_via82c686
, 1);