via82c686.c revision 64439
1/*
2 * Copyright (c) 2000 David Jones <dej@ox.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
13 *
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
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/dev/sound/pci/via82c686.c 64439 2000-08-09 00:55:55Z cg $
27 */
28
29#include <dev/sound/pcm/sound.h>
30#include <dev/sound/pcm/ac97.h>
31
32#include <pci/pcireg.h>
33#include <pci/pcivar.h>
34#include <sys/sysctl.h>
35
36#include <dev/sound/pci/via82c686.h>
37
38#define VIA_PCI_ID 0x30581106
39#define	NSEGS		16	/* Number of segments in SGD table */
40
41#define SEGS_PER_CHAN	(NSEGS/2)
42
43#undef DEB
44#define DEB(x)
45
46struct via_info;
47
48struct via_chinfo {
49	struct via_info *parent;
50	pcm_channel *channel;
51	snd_dbuf *buffer;
52	int dir;
53};
54
55struct via_info {
56	bus_space_tag_t st;
57	bus_space_handle_t sh;
58	bus_dma_tag_t	parent_dmat;
59	bus_dma_tag_t	sgd_dmat;
60
61	struct via_chinfo pch, rch;
62	struct via_dma_op *sgd_table;
63	u_int16_t	codec_caps;
64};
65
66static u_int32_t via_rd(struct via_info *via, int regno, int size);
67static void via_wr(struct via_info *, int regno, u_int32_t data, int size);
68
69int via_waitready_codec(struct via_info *via);
70int via_waitvalid_codec(struct via_info *via);
71u_int32_t via_read_codec(void *addr, int reg);
72void via_write_codec(void *addr, int reg, u_int32_t val);
73
74static void via_intr(void *);
75bus_dmamap_callback_t dma_cb;
76
77
78/* channel interface */
79static void *viachan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
80static int viachan_setdir(void *data, int dir);
81static int viachan_setformat(void *data, u_int32_t format);
82static int viachan_setspeed(void *data, u_int32_t speed);
83static int viachan_setblocksize(void *data, u_int32_t blocksize);
84static int viachan_trigger(void *data, int go);
85static int viachan_getptr(void *data);
86static pcmchan_caps *viachan_getcaps(void *data);
87
88static pcmchan_caps via_playcaps = {
89	4000, 48000,
90	AFMT_STEREO | AFMT_U8 | AFMT_S16_LE,
91	AFMT_STEREO | AFMT_S16_LE
92};
93
94static pcmchan_caps via_reccaps = {
95	4000, 48000,
96	AFMT_STEREO | AFMT_U8 | AFMT_S16_LE,
97	AFMT_STEREO | AFMT_S16_LE
98};
99
100static pcm_channel via_chantemplate = {
101	viachan_init,
102	viachan_setdir,
103	viachan_setformat,
104	viachan_setspeed,
105	viachan_setblocksize,
106	viachan_trigger,
107	viachan_getptr,
108	viachan_getcaps,
109};
110
111
112/*
113 *  Probe and attach the card
114 */
115static int
116via_probe(device_t dev)
117{
118	if (pci_get_devid(dev) == VIA_PCI_ID) {
119	    device_set_desc(dev, "VIA VT82C686A AC'97 Audio");
120	    return 0;
121	}
122	return ENXIO;
123}
124
125
126void dma_cb(void *p, bus_dma_segment_t *bds, int a, int b)
127{
128}
129
130
131static int
132via_attach(device_t dev)
133{
134	snddev_info	*d;
135	struct via_info *via = 0;
136	struct ac97_info *codec;
137	char		status[SND_STATUSLEN];
138
139	u_int32_t	data;
140	struct resource *reg = 0;
141	int		regid;
142	struct resource *irq = 0;
143	void		*ih = 0;
144	int		irqid;
145
146	u_int16_t	v;
147	bus_dmamap_t	sgd_dma_map;
148
149	d = device_get_softc(dev);
150	if ((via = malloc(sizeof *via, M_DEVBUF, M_NOWAIT)) == NULL) {
151		device_printf(dev, "cannot allocate softc\n");
152		return ENXIO;
153	}
154	bzero(via, sizeof *via);
155
156	/* Get resources */
157	data = pci_read_config(dev, PCIR_COMMAND, 2);
158	data |= (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN);
159	pci_write_config(dev, PCIR_COMMAND, data, 2);
160	data = pci_read_config(dev, PCIR_COMMAND, 2);
161
162	pci_write_config(dev, VIA_PCICONF_MISC,
163		VIA_PCICONF_ACLINKENAB | VIA_PCICONF_ACSGD |
164		VIA_PCICONF_ACNOTRST | VIA_PCICONF_ACVSR, 1);
165
166	regid = PCIR_MAPS;
167	reg = bus_alloc_resource(dev, SYS_RES_IOPORT, &regid,
168		0, ~0, 1, RF_ACTIVE);
169	if (!reg) {
170		device_printf(dev, "via: Cannot allocate bus resource.");
171		goto bad;
172	}
173	via->st = rman_get_bustag(reg);
174	via->sh = rman_get_bushandle(reg);
175
176	irqid = 0;
177	irq = bus_alloc_resource(dev, SYS_RES_IRQ, &irqid,
178		0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
179	if (!irq
180	    || bus_setup_intr(dev, irq, INTR_TYPE_TTY, via_intr, via, &ih)){
181		device_printf(dev, "unable to map interrupt\n");
182		goto bad;
183	}
184
185	via_wr(via, VIA_PLAY_MODE,
186		VIA_RPMODE_AUTOSTART |
187		VIA_RPMODE_INTR_FLAG | VIA_RPMODE_INTR_EOL, 1);
188	via_wr(via, VIA_RECORD_MODE,
189		VIA_RPMODE_AUTOSTART |
190		VIA_RPMODE_INTR_FLAG | VIA_RPMODE_INTR_EOL, 1);
191
192	codec = ac97_create(dev, via, NULL,
193		via_read_codec, via_write_codec);
194	if (!codec) goto bad;
195
196	mixer_init(d, &ac97_mixer, codec);
197
198	/*
199	 *  The mixer init resets the codec.  So enabling VRA must be done
200	 *  afterwards.
201	 */
202	v = via_read_codec(via, AC97_REG_EXT_AUDIO_ID);
203	v &= (AC97_ENAB_VRA | AC97_ENAB_MICVRA);
204	via_write_codec(via, AC97_REG_EXT_AUDIO_STAT, v);
205	via->codec_caps = v;
206	{
207	v = via_read_codec(via, AC97_REG_EXT_AUDIO_STAT);
208	DEB(printf("init: codec stat: %d\n", v));
209	}
210
211	if (!(v & AC97_CODEC_DOES_VRA)) {
212		/* no VRA => can do only 48 kbps */
213		via_playcaps.minspeed = 48000;
214		via_reccaps.minspeed = 48000;
215	}
216
217	/* DMA tag for buffers */
218	if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
219		/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
220		/*highaddr*/BUS_SPACE_MAXADDR,
221		/*filter*/NULL, /*filterarg*/NULL,
222		/*maxsize*/VIA_BUFFSIZE, /*nsegments*/1, /*maxsegz*/0x3ffff,
223		/*flags*/0, &via->parent_dmat) != 0) {
224		device_printf(dev, "unable to create dma tag\n");
225		goto bad;
226	}
227
228	/*
229	 *  DMA tag for SGD table.  The 686 uses scatter/gather DMA and
230	 *  requires a list in memory of work to do.  We need only 16 bytes
231	 *  for this list, and it is wasteful to allocate 16K.
232	 */
233	if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
234		/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
235		/*highaddr*/BUS_SPACE_MAXADDR,
236		/*filter*/NULL, /*filterarg*/NULL,
237		/*maxsize*/NSEGS * sizeof(struct via_dma_op),
238		/*nsegments*/1, /*maxsegz*/0x3ffff,
239		/*flags*/0, &via->sgd_dmat) != 0) {
240		device_printf(dev, "unable to create dma tag\n");
241		goto bad;
242	}
243
244	if (bus_dmamem_alloc(via->sgd_dmat, (void **)&via->sgd_table,
245		BUS_DMA_NOWAIT, &sgd_dma_map) == -1) goto bad;
246	if (bus_dmamap_load(via->sgd_dmat, sgd_dma_map, via->sgd_table,
247		NSEGS * sizeof(struct via_dma_op), dma_cb, 0, 0)) goto bad;
248
249	snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld",
250		rman_get_start(reg), rman_get_start(irq));
251
252	/* Register */
253	if (pcm_register(dev, via, 1, 1)) goto bad;
254	pcm_addchan(dev, PCMDIR_PLAY, &via_chantemplate, via);
255	pcm_addchan(dev, PCMDIR_REC, &via_chantemplate, via);
256	pcm_setstatus(dev, status);
257	return 0;
258bad:
259	if (via) free(via, M_DEVBUF);
260	bus_release_resource(dev, SYS_RES_IOPORT, regid, reg);
261	if (ih) bus_teardown_intr(dev, irq, ih);
262	if (irq) bus_release_resource(dev, SYS_RES_IRQ, irqid, irq);
263	return ENXIO;
264}
265
266
267static device_method_t via_methods[] = {
268	DEVMETHOD(device_probe,		via_probe),
269	DEVMETHOD(device_attach,	via_attach),
270	{ 0, 0}
271};
272
273static driver_t via_driver = {
274	"pcm",
275	via_methods,
276	sizeof(snddev_info),
277};
278
279static devclass_t pcm_devclass;
280
281DRIVER_MODULE(via, pci, via_driver, pcm_devclass, 0, 0);
282MODULE_DEPEND(via, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER);
283MODULE_VERSION(via, 1);
284
285
286static u_int32_t
287via_rd(struct via_info *via, int regno, int size)
288{
289
290	switch (size) {
291	case 1:
292		return bus_space_read_1(via->st, via->sh, regno);
293	case 2:
294		return bus_space_read_2(via->st, via->sh, regno);
295	case 4:
296		return bus_space_read_4(via->st, via->sh, regno);
297	default:
298		return 0xFFFFFFFF;
299	}
300}
301
302
303static void
304via_wr(struct via_info *via, int regno, u_int32_t data, int size)
305{
306
307	switch (size) {
308	case 1:
309		bus_space_write_1(via->st, via->sh, regno, data);
310		break;
311	case 2:
312		bus_space_write_2(via->st, via->sh, regno, data);
313		break;
314	case 4:
315		bus_space_write_4(via->st, via->sh, regno, data);
316		break;
317	}
318}
319
320
321/* Codec interface */
322int
323via_waitready_codec(struct via_info *via)
324{
325	int i;
326
327	/* poll until codec not busy */
328	for (i = 0; (i < TIMEOUT) &&
329	    (via_rd(via, VIA_CODEC_CTL, 4) & VIA_CODEC_BUSY); i++)
330		DELAY(1);
331	if (i >= TIMEOUT) {
332		printf("via: codec busy\n");
333		return 1;
334	}
335
336	return 0;
337}
338
339
340int
341via_waitvalid_codec(struct via_info *via)
342{
343	int i;
344
345	/* poll until codec valid */
346	for (i = 0; (i < TIMEOUT) &&
347	    !(via_rd(via, VIA_CODEC_CTL, 4) & VIA_CODEC_PRIVALID); i++)
348		    DELAY(1);
349	if (i >= TIMEOUT) {
350		printf("via: codec invalid\n");
351		return 1;
352	}
353
354	return 0;
355}
356
357
358void
359via_write_codec(void *addr, int reg, u_int32_t val)
360{
361	struct via_info *via = addr;
362
363	if (via_waitready_codec(via)) return;
364
365	via_wr(via, VIA_CODEC_CTL,
366		VIA_CODEC_PRIVALID | VIA_CODEC_INDEX(reg) | val, 4);
367}
368
369
370u_int32_t
371via_read_codec(void *addr, int reg)
372{
373	struct via_info *via = addr;
374
375	if (via_waitready_codec(via))
376		return 1;
377
378	via_wr(via, VIA_CODEC_CTL,
379	    VIA_CODEC_PRIVALID | VIA_CODEC_READ | VIA_CODEC_INDEX(reg),4);
380
381	if (via_waitready_codec(via))
382		return 1;
383
384	if (via_waitvalid_codec(via))
385		return 1;
386
387	return via_rd(via, VIA_CODEC_CTL, 2);
388}
389
390
391/* channel interface */
392static void *
393viachan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
394{
395	struct via_info *via = devinfo;
396	struct via_chinfo *ch = (dir == PCMDIR_PLAY) ? &via->pch : &via->rch;
397
398	ch->parent = via;
399	ch->channel = c;
400	ch->buffer = b;
401	b->bufsize = VIA_BUFFSIZE;
402
403	if (chn_allocbuf(ch->buffer, via->parent_dmat) == -1) return NULL;
404	return ch;
405}
406
407static int
408viachan_setdir(void *data, int dir)
409{
410	struct via_chinfo *ch = data;
411	struct via_info *via = ch->parent;
412	struct via_dma_op *ado;
413	int i, chunk_size;
414	int	phys_addr, flag;
415
416	ch->dir = dir;
417	/*
418	 *  Build the scatter/gather DMA (SGD) table.
419	 *  There are four slots in the table: two for play, two for record.
420	 *  This creates two half-buffers, one of which is playing; the other
421	 *  is feeding.
422	 */
423	ado = via->sgd_table;
424	chunk_size = ch->buffer->bufsize / SEGS_PER_CHAN;
425
426	if (dir == PCMDIR_REC) {
427		ado += SEGS_PER_CHAN;
428	}
429
430DEB(printf("SGD table located at va %p\n", ado));
431	phys_addr = vtophys(ch->buffer->buf);
432	for (i = 0; i < SEGS_PER_CHAN; i++) {
433		ado->ptr = phys_addr;
434		flag = (i == SEGS_PER_CHAN-1) ?
435			VIA_DMAOP_EOL : VIA_DMAOP_FLAG;
436		ado->flags = flag | chunk_size;
437DEB(printf("ado->ptr/flags = %x/%x\n", phys_addr, flag));
438		phys_addr += chunk_size;
439		ado++;
440	}
441	return 0;
442}
443
444static int
445viachan_setformat(void *data, u_int32_t format)
446{
447	struct via_chinfo *ch = data;
448	struct via_info *via = ch->parent;
449	int	mode, mode_set;
450
451	mode_set = 0;
452	if (format & AFMT_STEREO)
453		mode_set |= VIA_RPMODE_STEREO;
454	if (format & AFMT_S16_LE)
455		mode_set |= VIA_RPMODE_16BIT;
456
457	/* Set up for output format */
458	if (ch->dir == PCMDIR_PLAY) {
459DEB(printf("set play format: %x\n", format));
460		mode = via_rd(via, VIA_PLAY_MODE, 1);
461		mode &= ~(VIA_RPMODE_16BIT | VIA_RPMODE_STEREO);
462		mode |= mode_set;
463		via_wr(via, VIA_PLAY_MODE, mode, 1);
464	}
465	else {
466DEB(printf("set record format: %x\n", format));
467		mode = via_rd(via, VIA_RECORD_MODE, 1);
468		mode &= ~(VIA_RPMODE_16BIT | VIA_RPMODE_STEREO);
469		mode |= mode_set;
470		via_wr(via, VIA_RECORD_MODE, mode, 1);
471	}
472
473	return 0;
474}
475
476static int
477viachan_setspeed(void *data, u_int32_t speed)
478{
479	struct via_chinfo *ch = data;
480	struct via_info *via = ch->parent;
481
482	/*
483	 *  Basic AC'97 defines a 48 kHz sample rate only.  For other rates,
484	 *  upsampling is required.
485	 *
486	 *  The VT82C686A does not perform upsampling, and neither do we.
487	 *  If the codec supports variable-rate audio (i.e. does the upsampling
488	 *  itself), then negotiate the rate with the codec.  Otherwise,
489	 *  return 48 kHz cuz that's all you got.
490	 */
491	if (ch->dir == PCMDIR_PLAY) {
492DEB(printf("requested play speed: %d\n", speed));
493		if (via->codec_caps & AC97_CODEC_DOES_VRA) {
494			via_write_codec(via, AC97_REG_EXT_DAC_RATE, speed);
495			speed = via_read_codec(via, AC97_REG_EXT_DAC_RATE);
496		}
497		else {
498DEB(printf("VRA not supported!\n"));
499			speed = 48000;
500		}
501DEB(printf("obtained play speed: %d\n", speed));
502	}
503	else {
504DEB(printf("requested record speed: %d\n", speed));
505		if (via->codec_caps & AC97_CODEC_DOES_VRA) {
506			via_write_codec(via, AC97_REG_EXT_ADC_RATE, speed);
507			speed = via_read_codec(via, AC97_REG_EXT_ADC_RATE);
508		}
509		else {
510DEB(printf("VRA not supported!\n"));
511			speed = 48000;
512		}
513DEB(printf("obtained record speed: %d\n", speed));
514	}
515	return speed;
516}
517
518static int
519viachan_setblocksize(void *data, u_int32_t blocksize)
520{
521	struct via_chinfo *ch = data;
522
523	return ch->buffer->bufsize / 2;
524}
525
526static int
527viachan_trigger(void *data, int go)
528{
529	struct via_chinfo *ch = data;
530	struct via_info *via = ch->parent;
531	struct via_dma_op *ado;
532
533	if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) return 0;
534	if (ch->dir == PCMDIR_PLAY) {
535		if (go == PCMTRIG_START) {
536			ado = &via->sgd_table[0];
537DEB(printf("ado located at va=%p pa=%x\n", ado, vtophys(ado)));
538			via_wr(via, VIA_PLAY_DMAOPS_BASE, vtophys(ado),4);
539			via_wr(via, VIA_PLAY_CONTROL,
540				VIA_RPCTRL_START, 1);
541		}
542		else {
543			/* Stop DMA */
544			via_wr(via, VIA_PLAY_CONTROL,
545				VIA_RPCTRL_TERMINATE, 1);
546		}
547	} else {
548		if (go == PCMTRIG_START) {
549			ado = &via->sgd_table[SEGS_PER_CHAN];
550DEB(printf("ado located at va=%p pa=%x\n", ado, vtophys(ado)));
551			via_wr(via, VIA_RECORD_DMAOPS_BASE,
552				vtophys(ado),4);
553			via_wr(via, VIA_RECORD_CONTROL,
554				VIA_RPCTRL_START, 1);
555		}
556		else {
557			/* Stop DMA */
558			via_wr(via, VIA_RECORD_CONTROL,
559				VIA_RPCTRL_TERMINATE, 1);
560		}
561	}
562
563DEB(printf("viachan_trigger: go=%d\n", go));
564	return 0;
565}
566
567static int
568viachan_getptr(void *data)
569{
570	struct via_chinfo *ch = data;
571	struct via_info *via = ch->parent;
572	struct via_dma_op *ado;
573	int	ptr, base, len, seg;
574	int base1;
575
576	if (ch->dir == PCMDIR_PLAY) {
577		ado = &via->sgd_table[0];
578		base1 = via_rd(via, VIA_PLAY_DMAOPS_BASE, 4);
579		len = via_rd(via, VIA_PLAY_DMAOPS_COUNT, 4);
580		base = via_rd(via, VIA_PLAY_DMAOPS_BASE, 4);
581		if (base != base1) {	/* Avoid race hazzard	*/
582			len = via_rd(via, VIA_PLAY_DMAOPS_COUNT, 4);
583		}
584DEB(printf("viachan_getptr: len / base = %x / %x\n", len, base));
585
586		/* Base points to SGD segment to do, one past current */
587
588		/* Determine how many segments have been done */
589		seg = (base - vtophys(ado)) / sizeof(struct via_dma_op);
590		if (seg == 0) seg = SEGS_PER_CHAN;
591
592		/* Now work out offset: seg less count */
593		ptr = seg * ch->buffer->bufsize / SEGS_PER_CHAN - len;
594DEB(printf("return ptr=%d\n", ptr));
595		return ptr;
596	}
597	else {
598		base1 = via_rd(via, VIA_RECORD_DMAOPS_BASE, 4);
599		ado = &via->sgd_table[SEGS_PER_CHAN];
600		len = via_rd(via, VIA_RECORD_DMAOPS_COUNT, 4);
601		base = via_rd(via, VIA_RECORD_DMAOPS_BASE, 4);
602		if (base != base1) {	/* Avoid race hazzard	*/
603			len = via_rd(via, VIA_RECORD_DMAOPS_COUNT, 4);
604		}
605DEB(printf("viachan_getptr: len / base = %x / %x\n", len, base));
606
607		/* Base points to next block to do, one past current */
608
609		/* Determine how many segments have been done */
610		seg = (base - vtophys(ado)) / sizeof(struct via_dma_op);
611		if (seg == 0) seg = SEGS_PER_CHAN;
612
613		/* Now work out offset: seg less count */
614		ptr = seg * ch->buffer->bufsize / SEGS_PER_CHAN - len;
615
616		/* DMA appears to operate on memory 'lines' of 32 bytes	*/
617		/* so don't return any part line - it isn't in RAM yet	*/
618		ptr = ptr & ~0x1f;
619DEB(printf("return ptr=%d\n", ptr));
620		return ptr;
621	}
622	return 0;
623}
624
625static pcmchan_caps *
626viachan_getcaps(void *data)
627{
628	struct via_chinfo *ch = data;
629	return (ch->dir == PCMDIR_PLAY) ? &via_playcaps : &via_reccaps;
630}
631
632static void
633via_intr(void *p)
634{
635	struct via_info *via = p;
636	int		st;
637
638DEB(printf("viachan_intr\n"));
639	/* Read channel */
640	st = via_rd(via, VIA_PLAY_STAT, 1);
641	if (st & VIA_RPSTAT_INTR) {
642		via_wr(via, VIA_PLAY_STAT, VIA_RPSTAT_INTR, 1);
643		chn_intr(via->pch.channel);
644	}
645
646	/* Write channel */
647	st = via_rd(via, VIA_RECORD_STAT, 1);
648	if (st & VIA_RPSTAT_INTR) {
649		via_wr(via, VIA_RECORD_STAT, VIA_RPSTAT_INTR, 1);
650		chn_intr(via->rch.channel);
651	}
652}
653
654
655