ds1.c revision 61456
1/*
2 * Copyright (c) 2000 Cameron Grant <cg@freebsd.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, WHETHERIN 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 THEPOSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/dev/sound/pci/ds1.c 61456 2000-06-09 16:44:30Z dan $
27 */
28
29#include "pci.h"
30#include "pcm.h"
31
32#include <dev/sound/pcm/sound.h>
33#include <dev/sound/pcm/ac97.h>
34
35#include <pci/pcireg.h>
36#include <pci/pcivar.h>
37
38#include <dev/sound/pci/ds1.h>
39#include <dev/sound/pci/ds1-fw.h>
40
41/* -------------------------------------------------------------------- */
42
43#define	DS1_CHANS 4
44#define DS1_RECPRIMARY 0
45
46struct pbank {
47	volatile u_int32_t	Format;
48	volatile u_int32_t	LoopDefault;
49	volatile u_int32_t	PgBase;
50	volatile u_int32_t	PgLoop;
51	volatile u_int32_t	PgLoopEnd;
52	volatile u_int32_t	PgLoopFrac;
53	volatile u_int32_t	PgDeltaEnd;
54	volatile u_int32_t	LpfKEnd;
55	volatile u_int32_t	EgGainEnd;
56	volatile u_int32_t	LchGainEnd;
57	volatile u_int32_t	RchGainEnd;
58	volatile u_int32_t	Effect1GainEnd;
59	volatile u_int32_t	Effect2GainEnd;
60	volatile u_int32_t	Effect3GainEnd;
61	volatile u_int32_t	LpfQ;
62	volatile u_int32_t	Status;
63	volatile u_int32_t	NumOfFrames;
64	volatile u_int32_t	LoopCount;
65	volatile u_int32_t	PgStart;
66	volatile u_int32_t	PgStartFrac;
67	volatile u_int32_t	PgDelta;
68	volatile u_int32_t	LpfK;
69	volatile u_int32_t	EgGain;
70	volatile u_int32_t	LchGain;
71	volatile u_int32_t	RchGain;
72	volatile u_int32_t	Effect1Gain;
73	volatile u_int32_t	Effect2Gain;
74	volatile u_int32_t	Effect3Gain;
75	volatile u_int32_t	LpfD1;
76	volatile u_int32_t	LpfD2;
77};
78
79struct rbank {
80	volatile u_int32_t	PgBase;
81	volatile u_int32_t	PgLoopEnd;
82	volatile u_int32_t	PgStart;
83	volatile u_int32_t	NumOfLoops;
84};
85
86struct sc_info;
87
88/* channel registers */
89struct sc_pchinfo {
90	int run, spd, dir, fmt;
91	snd_dbuf *buffer;
92	pcm_channel *channel;
93	volatile struct pbank *lslot, *rslot;
94	int lsnum, rsnum;
95	struct sc_info *parent;
96};
97
98struct sc_rchinfo {
99	int run, spd, dir, fmt, num;
100	snd_dbuf *buffer;
101	pcm_channel *channel;
102	volatile struct rbank *slot;
103	struct sc_info *parent;
104};
105
106/* device private data */
107struct sc_info {
108	device_t	dev;
109	u_int32_t 	type, rev;
110	u_int32_t	cd2id, ctrlbase;
111
112	bus_space_tag_t st;
113	bus_space_handle_t sh;
114	bus_dma_tag_t parent_dmat;
115
116	struct resource *reg, *irq;
117	int		regid, irqid;
118	void		*ih;
119
120	u_int32_t *pbase, pbankbase, pbanksize;
121	volatile struct pbank *pbank[2 * 64];
122	volatile struct rbank *rbank;
123	int pslotfree, currbank, pchn, rchn;
124
125	struct sc_pchinfo pch[DS1_CHANS];
126	struct sc_rchinfo rch[2];
127};
128
129struct {
130	u_int32_t dev, subdev;
131	char *name;
132	u_int32_t *mcode;
133} ds_devs[] = {
134/* Beware, things know the indexes here */
135	{0x00041073, 0, 		"Yamaha DS-1 (YMF724)", CntrlInst},
136	{0x000d1073, 0, 		"Yamaha DS-1E (YMF724F)", CntrlInst1E},
137	{0x00051073, 0, 		"Yamaha DS-1? (YMF734)", CntrlInst},
138	{0x00081073, 0, 		"Yamaha DS-1? (YMF737)", CntrlInst},
139	{0x00201073, 0, 		"Yamaha DS-1? (YMF738)", CntrlInst},
140	{0x00061073, 0, 		"Yamaha DS-1? (YMF738_TEG)", CntrlInst},
141	{0x000a1073, 0x00041073, 	"Yamaha DS-1 (YMF740)", CntrlInst},
142	{0x000a1073, 0x000a1073,  	"Yamaha DS-1 (YMF740B)", CntrlInst},
143/*8*/	{0x000a1073, 0x53328086,	"Yamaha DS-1 (YMF740I)", CntrlInst},
144	{0x000a1073, 0, 		"Yamaha DS-1 (YMF740?)", CntrlInst},
145	{0x000c1073, 0, 		"Yamaha DS-1E (YMF740C)", CntrlInst1E},
146/*11*/	{0x00101073, 0, 		"Yamaha DS-1E (YMF744)", CntrlInst1E},
147	{0x00121073, 0, 		"Yamaha DS-1E (YMF754)", CntrlInst1E},
148	{0, 0, NULL, NULL}
149};
150
151/* -------------------------------------------------------------------- */
152
153/*
154 * prototypes
155 */
156
157/* channel interface */
158static void *ds1pchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
159static int ds1pchan_setdir(void *data, int dir);
160static int ds1pchan_setformat(void *data, u_int32_t format);
161static int ds1pchan_setspeed(void *data, u_int32_t speed);
162static int ds1pchan_setblocksize(void *data, u_int32_t blocksize);
163static int ds1pchan_trigger(void *data, int go);
164static int ds1pchan_getptr(void *data);
165static pcmchan_caps *ds1pchan_getcaps(void *data);
166
167static void *ds1rchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
168static int ds1rchan_setdir(void *data, int dir);
169static int ds1rchan_setformat(void *data, u_int32_t format);
170static int ds1rchan_setspeed(void *data, u_int32_t speed);
171static int ds1rchan_setblocksize(void *data, u_int32_t blocksize);
172static int ds1rchan_trigger(void *data, int go);
173static int ds1rchan_getptr(void *data);
174static pcmchan_caps *ds1rchan_getcaps(void *data);
175
176/* talk to the codec - called from ac97.c */
177static u_int32_t ds_rdcd(void *, int);
178static void  	 ds_wrcd(void *, int, u_int32_t);
179
180/* stuff */
181static int       ds_init(struct sc_info *);
182static void      ds_intr(void *);
183
184/* talk to the card */
185static u_int32_t ds_rd(struct sc_info *, int, int);
186static void 	 ds_wr(struct sc_info *, int, u_int32_t, int);
187
188/* -------------------------------------------------------------------- */
189
190static pcmchan_caps ds_reccaps = {
191	4000, 48000,
192	AFMT_STEREO | AFMT_U8 | AFMT_S8 | AFMT_S16_LE | AFMT_U16_LE,
193	AFMT_STEREO | AFMT_S16_LE
194};
195
196static pcmchan_caps ds_playcaps = {
197	4000, 96000,
198	AFMT_STEREO | AFMT_U8 | AFMT_S16_LE,
199	AFMT_STEREO | AFMT_S16_LE
200};
201
202static pcm_channel ds_pchantemplate = {
203	ds1pchan_init,
204	ds1pchan_setdir,
205	ds1pchan_setformat,
206	ds1pchan_setspeed,
207	ds1pchan_setblocksize,
208	ds1pchan_trigger,
209	ds1pchan_getptr,
210	ds1pchan_getcaps,
211};
212
213static pcm_channel ds_rchantemplate = {
214	ds1rchan_init,
215	ds1rchan_setdir,
216	ds1rchan_setformat,
217	ds1rchan_setspeed,
218	ds1rchan_setblocksize,
219	ds1rchan_trigger,
220	ds1rchan_getptr,
221	ds1rchan_getcaps,
222};
223
224/* -------------------------------------------------------------------- */
225/* Hardware */
226static u_int32_t
227ds_rd(struct sc_info *sc, int regno, int size)
228{
229	switch (size) {
230	case 1:
231		return bus_space_read_1(sc->st, sc->sh, regno);
232	case 2:
233		return bus_space_read_2(sc->st, sc->sh, regno);
234	case 4:
235		return bus_space_read_4(sc->st, sc->sh, regno);
236	default:
237		return 0xffffffff;
238	}
239}
240
241static void
242ds_wr(struct sc_info *sc, int regno, u_int32_t data, int size)
243{
244	switch (size) {
245	case 1:
246		bus_space_write_1(sc->st, sc->sh, regno, data);
247		break;
248	case 2:
249		bus_space_write_2(sc->st, sc->sh, regno, data);
250		break;
251	case 4:
252		bus_space_write_4(sc->st, sc->sh, regno, data);
253		break;
254	}
255}
256
257static void
258wrl(struct sc_info *sc, u_int32_t *ptr, u_int32_t val)
259{
260	*(volatile u_int32_t *)ptr = val;
261	bus_space_barrier(sc->sh, sc->st, 0, 0, BUS_SPACE_BARRIER_WRITE);
262}
263
264/* ac97 codec */
265static int
266ds_cdbusy(struct sc_info *sc, int sec)
267{
268	int i, reg;
269
270	reg = sec? YDSXGR_SECSTATUSADR : YDSXGR_PRISTATUSADR;
271	i = YDSXG_AC97TIMEOUT;
272	while (i > 0) {
273		if (!(ds_rd(sc, reg, 2) & 0x8000))
274			return 0;
275		i--;
276	}
277	return ETIMEDOUT;
278}
279
280static u_int32_t
281ds_initcd(void *devinfo)
282{
283	struct sc_info *sc = (struct sc_info *)devinfo;
284	u_int32_t x;
285
286	x = pci_read_config(sc->dev, PCIR_DSXGCTRL, 1);
287	if (x & 0x03) {
288		pci_write_config(sc->dev, PCIR_DSXGCTRL, x & ~0x03, 1);
289		pci_write_config(sc->dev, PCIR_DSXGCTRL, x | 0x03, 1);
290		pci_write_config(sc->dev, PCIR_DSXGCTRL, x & ~0x03, 1);
291		/*
292		 * The YMF740 on some Intel motherboards requires a pretty
293		 * hefty delay after this reset for some reason...  Otherwise:
294		 * "pcm0: ac97 codec init failed"
295		 * Maybe this is needed for all YMF740's?
296		 * 400ms and 500ms here seem to work, 300ms does not.
297		 */
298		if (sc->type == 8)
299			DELAY(400000);
300	}
301
302	return ds_cdbusy(sc, 0);
303}
304
305static u_int32_t
306ds_rdcd(void *devinfo, int regno)
307{
308	struct sc_info *sc = (struct sc_info *)devinfo;
309	int sec, cid, i;
310	u_int32_t cmd, reg;
311
312	sec = regno & 0x100;
313	regno &= 0xff;
314	cid = sec? (sc->cd2id << 8) : 0;
315	reg = sec? YDSXGR_SECSTATUSDATA : YDSXGR_PRISTATUSDATA;
316	if (sec && cid == 0)
317		return 0xffffffff;
318
319	cmd = YDSXG_AC97READCMD | cid | regno;
320	ds_wr(sc, YDSXGR_AC97CMDADR, cmd, 2);
321
322	if (ds_cdbusy(sc, sec))
323		return 0xffffffff;
324
325	if (sc->type == 11 && sc->rev < 2)
326		for (i = 0; i < 600; i++)
327			ds_rd(sc, reg, 2);
328
329	return ds_rd(sc, reg, 2);
330}
331
332static void
333ds_wrcd(void *devinfo, int regno, u_int32_t data)
334{
335	struct sc_info *sc = (struct sc_info *)devinfo;
336	int sec, cid;
337	u_int32_t cmd;
338
339	sec = regno & 0x100;
340	regno &= 0xff;
341	cid = sec? (sc->cd2id << 8) : 0;
342	if (sec && cid == 0)
343		return;
344
345	cmd = YDSXG_AC97WRITECMD | cid | regno;
346	cmd <<= 16;
347	cmd |= data;
348	ds_wr(sc, YDSXGR_AC97CMDDATA, cmd, 4);
349
350	ds_cdbusy(sc, sec);
351}
352
353static void
354ds_enadsp(struct sc_info *sc, int on)
355{
356	u_int32_t v, i;
357
358	v = on? 1 : 0;
359	if (on) {
360		ds_wr(sc, YDSXGR_CONFIG, 0x00000001, 4);
361	} else {
362		if (ds_rd(sc, YDSXGR_CONFIG, 4))
363			ds_wr(sc, YDSXGR_CONFIG, 0x00000000, 4);
364		i = YDSXG_WORKBITTIMEOUT;
365		while (i > 0) {
366			if (!(ds_rd(sc, YDSXGR_CONFIG, 4) & 0x00000002))
367				break;
368			i--;
369		}
370	}
371}
372
373static volatile struct pbank *
374ds_allocpslot(struct sc_info *sc)
375{
376	int slot;
377
378	if (sc->pslotfree > 63)
379		return NULL;
380	slot = sc->pslotfree++;
381	return sc->pbank[slot * 2];
382}
383
384static int
385ds_initpbank(volatile struct pbank *pb, int ch, int b16, int stereo, u_int32_t rate, void *base, u_int32_t len)
386{
387	u_int32_t lv[] = {1, 1, 0, 0, 0};
388	u_int32_t rv[] = {1, 0, 1, 0, 0};
389	u_int32_t e1[] = {0, 0, 0, 0, 0};
390	u_int32_t e2[] = {1, 0, 0, 1, 0};
391	u_int32_t e3[] = {1, 0, 0, 0, 1};
392	int ss, i;
393	u_int32_t delta;
394
395	struct {
396		int rate, fK, fQ;
397	} speedinfo[] = {
398		{  100, 0x00570000, 0x35280000},
399		{ 2000, 0x06aa0000, 0x34a70000},
400		{ 8000, 0x18b20000, 0x32020000},
401		{11025, 0x20930000, 0x31770000},
402		{16000, 0x2b9a0000, 0x31390000},
403		{22050, 0x35a10000, 0x31c90000},
404		{32000, 0x3eaa0000, 0x33d00000},
405/*		{44100, 0x04646000, 0x370a0000},
406*/		{48000, 0x40000000, 0x40000000},
407	};
408
409	ss = b16? 1 : 0;
410	ss += stereo? 1 : 0;
411	delta = (65536 * rate) / 48000;
412	i = 0;
413	while (i < 7 && speedinfo[i].rate < rate)
414		i++;
415
416	pb->Format = stereo? 0x00010000 : 0;
417	pb->Format |= b16? 0 : 0x80000000;
418	pb->Format |= (stereo && (ch == 2 || ch == 4))? 0x00000001 : 0;
419	pb->LoopDefault = 0;
420	pb->PgBase = base? vtophys(base) : 0;
421	pb->PgLoop = 0;
422	pb->PgLoopEnd = len >> ss;
423	pb->PgLoopFrac = 0;
424	pb->Status = 0;
425	pb->NumOfFrames = 0;
426	pb->LoopCount = 0;
427	pb->PgStart = 0;
428	pb->PgStartFrac = 0;
429	pb->PgDelta = pb->PgDeltaEnd = delta << 12;
430	pb->LpfQ = speedinfo[i].fQ;
431	pb->LpfK = pb->LpfKEnd = speedinfo[i].fK;
432	pb->LpfD1 = pb->LpfD2 = 0;
433	pb->EgGain = pb->EgGainEnd = 0x40000000;
434	pb->LchGain = pb->LchGainEnd = lv[ch] * 0x40000000;
435	pb->RchGain = pb->RchGainEnd = rv[ch] * 0x40000000;
436	pb->Effect1Gain = pb->Effect1GainEnd = e1[ch] * 0x40000000;
437	pb->Effect2Gain = pb->Effect2GainEnd = e2[ch] * 0x40000000;
438	pb->Effect3Gain = pb->Effect3GainEnd = e3[ch] * 0x40000000;
439
440	return 0;
441}
442
443static void
444ds_enapslot(struct sc_info *sc, int slot, int go)
445{
446	wrl(sc, &sc->pbase[slot + 1], go? (sc->pbankbase + 2 * slot * sc->pbanksize) : 0);
447	/* printf("pbase[%d] = 0x%x\n", slot + 1, go? (sc->pbankbase + 2 * slot * sc->pbanksize) : 0); */
448}
449
450static void
451ds_setuppch(struct sc_pchinfo *ch)
452{
453	int stereo, b16, c, sz;
454	void *buf;
455
456	stereo = (ch->fmt & AFMT_STEREO)? 1 : 0;
457	b16 = (ch->fmt & AFMT_16BIT)? 1 : 0;
458	c = stereo? 1 : 0;
459	buf = ch->buffer->buf;
460	sz = ch->buffer->bufsize;
461
462	ds_initpbank(ch->lslot, c, stereo, b16, ch->spd, buf, sz);
463	ds_initpbank(ch->lslot + 1, c, stereo, b16, ch->spd, buf, sz);
464	ds_initpbank(ch->rslot, 2, stereo, b16, ch->spd, buf, sz);
465	ds_initpbank(ch->rslot + 1, 2, stereo, b16, ch->spd, buf, sz);
466}
467
468static void
469ds_setuprch(struct sc_rchinfo *ch)
470{
471	struct sc_info *sc = ch->parent;
472	int stereo, b16, i, sz, pri;
473	u_int32_t x, y;
474	void *buf;
475
476	stereo = (ch->fmt & AFMT_STEREO)? 1 : 0;
477	b16 = (ch->fmt & AFMT_16BIT)? 1 : 0;
478	buf = ch->buffer->buf;
479	sz = ch->buffer->bufsize;
480	pri = (ch->num == DS1_RECPRIMARY)? 1 : 0;
481
482	for (i = 0; i < 2; i++) {
483		ch->slot[i].PgBase = vtophys(buf);
484		ch->slot[i].PgLoopEnd = sz;
485		ch->slot[i].PgStart = 0;
486		ch->slot[i].NumOfLoops = 0;
487	}
488	x = (b16? 0x00 : 0x01) | (stereo? 0x02 : 0x00);
489	y = (48000 * 4096) / ch->spd;
490	y--;
491	/* printf("pri = %d, x = %d, y = %d\n", pri, x, y); */
492	ds_wr(sc, pri? YDSXGR_ADCFORMAT : YDSXGR_RECFORMAT, x, 4);
493	ds_wr(sc, pri? YDSXGR_ADCSLOTSR : YDSXGR_RECSLOTSR, y, 4);
494}
495
496/* play channel interface */
497static void *
498ds1pchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
499{
500	struct sc_info *sc = devinfo;
501	struct sc_pchinfo *ch;
502
503	KASSERT(dir == PCMDIR_PLAY, ("ds1pchan_init: bad direction"));
504
505	ch = &sc->pch[sc->pchn++];
506	ch->buffer = b;
507	ch->buffer->bufsize = 4096;
508	ch->parent = sc;
509	ch->channel = c;
510	ch->dir = dir;
511	ch->fmt = AFMT_U8;
512	ch->spd = 8000;
513	ch->run = 0;
514	if (chn_allocbuf(ch->buffer, sc->parent_dmat) == -1)
515		return NULL;
516	else {
517		ch->lsnum = sc->pslotfree;
518		ch->lslot = ds_allocpslot(sc);
519		ch->rsnum = sc->pslotfree;
520		ch->rslot = ds_allocpslot(sc);
521		ds_setuppch(ch);
522		return ch;
523	}
524}
525
526static int
527ds1pchan_setdir(void *data, int dir)
528{
529	return 0;
530}
531
532static int
533ds1pchan_setformat(void *data, u_int32_t format)
534{
535	struct sc_pchinfo *ch = data;
536
537	ch->fmt = format;
538
539	return 0;
540}
541
542static int
543ds1pchan_setspeed(void *data, u_int32_t speed)
544{
545	struct sc_pchinfo *ch = data;
546
547	ch->spd = speed;
548
549	return speed;
550}
551
552static int
553ds1pchan_setblocksize(void *data, u_int32_t blocksize)
554{
555	return blocksize;
556}
557
558/* semantic note: must start at beginning of buffer */
559static int
560ds1pchan_trigger(void *data, int go)
561{
562	struct sc_pchinfo *ch = data;
563	struct sc_info *sc = ch->parent;
564	int stereo;
565
566	if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
567		return 0;
568	stereo = (ch->fmt & AFMT_STEREO)? 1 : 0;
569	if (go == PCMTRIG_START) {
570		ch->run = 1;
571		ds_setuppch(ch);
572		ds_enapslot(sc, ch->lsnum, 1);
573		ds_enapslot(sc, ch->rsnum, stereo);
574		ds_wr(sc, YDSXGR_MODE, 0x00000003, 4);
575	} else {
576		ch->run = 0;
577		/* ds_setuppch(ch); */
578		ds_enapslot(sc, ch->lsnum, 0);
579		ds_enapslot(sc, ch->rsnum, 0);
580	}
581
582	return 0;
583}
584
585static int
586ds1pchan_getptr(void *data)
587{
588	struct sc_pchinfo *ch = data;
589	struct sc_info *sc = ch->parent;
590	volatile struct pbank *bank;
591	int ss;
592	u_int32_t ptr;
593
594	ss = (ch->fmt & AFMT_STEREO)? 1 : 0;
595	ss += (ch->fmt & AFMT_16BIT)? 1 : 0;
596
597	bank = ch->lslot + sc->currbank;
598	/* printf("getptr: %d\n", bank->PgStart << ss); */
599	ptr = bank->PgStart;
600	ptr <<= ss;
601	return ptr;
602}
603
604static pcmchan_caps *
605ds1pchan_getcaps(void *data)
606{
607	return &ds_playcaps;
608}
609
610/* record channel interface */
611static void *
612ds1rchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
613{
614	struct sc_info *sc = devinfo;
615	struct sc_rchinfo *ch;
616
617	KASSERT(dir == PCMDIR_REC, ("ds1rchan_init: bad direction"));
618
619	ch = &sc->rch[sc->rchn];
620	ch->num = sc->rchn++;
621	ch->buffer = b;
622	ch->buffer->bufsize = 4096;
623	ch->parent = sc;
624	ch->channel = c;
625	ch->dir = dir;
626	ch->fmt = AFMT_U8;
627	ch->spd = 8000;
628	if (chn_allocbuf(ch->buffer, sc->parent_dmat) == -1)
629		return NULL;
630	else {
631		ch->slot = (ch->num == DS1_RECPRIMARY)? sc->rbank + 2: sc->rbank;
632		ds_setuprch(ch);
633		return ch;
634	}
635}
636
637static int
638ds1rchan_setdir(void *data, int dir)
639{
640	return 0;
641}
642
643static int
644ds1rchan_setformat(void *data, u_int32_t format)
645{
646	struct sc_rchinfo *ch = data;
647
648	ch->fmt = format;
649
650	return 0;
651}
652
653static int
654ds1rchan_setspeed(void *data, u_int32_t speed)
655{
656	struct sc_rchinfo *ch = data;
657
658	ch->spd = speed;
659
660	return speed;
661}
662
663static int
664ds1rchan_setblocksize(void *data, u_int32_t blocksize)
665{
666	return blocksize;
667}
668
669/* semantic note: must start at beginning of buffer */
670static int
671ds1rchan_trigger(void *data, int go)
672{
673	struct sc_rchinfo *ch = data;
674	struct sc_info *sc = ch->parent;
675	u_int32_t x;
676
677	if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
678		return 0;
679	if (go == PCMTRIG_START) {
680		ch->run = 1;
681		ds_setuprch(ch);
682		x = ds_rd(sc, YDSXGR_MAPOFREC, 4);
683		x |= (ch->num == DS1_RECPRIMARY)? 0x02 : 0x01;
684		ds_wr(sc, YDSXGR_MAPOFREC, x, 4);
685		ds_wr(sc, YDSXGR_MODE, 0x00000003, 4);
686	} else {
687		ch->run = 0;
688		x = ds_rd(sc, YDSXGR_MAPOFREC, 4);
689		x &= ~((ch->num == DS1_RECPRIMARY)? 0x02 : 0x01);
690		ds_wr(sc, YDSXGR_MAPOFREC, x, 4);
691	}
692
693	return 0;
694}
695
696static int
697ds1rchan_getptr(void *data)
698{
699	struct sc_rchinfo *ch = data;
700	struct sc_info *sc = ch->parent;
701
702	return ch->slot[sc->currbank].PgStart;
703}
704
705static pcmchan_caps *
706ds1rchan_getcaps(void *data)
707{
708	return &ds_reccaps;
709}
710
711/* The interrupt handler */
712static void
713ds_intr(void *p)
714{
715	struct sc_info *sc = (struct sc_info *)p;
716	u_int32_t i, x;
717
718	i = ds_rd(sc, YDSXGR_STATUS, 4);
719	if (i & 0x00008000)
720		device_printf(sc->dev, "timeout irq\n");
721	if (i & 0x80008000) {
722		ds_wr(sc, YDSXGR_STATUS, i & 0x80008000, 4);
723		sc->currbank = ds_rd(sc, YDSXGR_CTRLSELECT, 4) & 0x00000001;
724
725		x = 0;
726		for (i = 0; i < DS1_CHANS; i++) {
727			if (sc->pch[i].run) {
728				x = 1;
729				chn_intr(sc->pch[i].channel);
730			}
731		}
732		for (i = 0; i < 2; i++) {
733			if (sc->rch[i].run) {
734				x = 1;
735				chn_intr(sc->rch[i].channel);
736			}
737		}
738		i = ds_rd(sc, YDSXGR_MODE, 4);
739		if (x)
740			ds_wr(sc, YDSXGR_MODE, i | 0x00000002, 4);
741
742	}
743}
744
745/* -------------------------------------------------------------------- */
746
747/*
748 * Probe and attach the card
749 */
750
751static void
752ds_setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
753{
754	struct sc_info *sc = arg;
755
756	sc->ctrlbase = error? 0 : (u_int32_t)segs->ds_addr;
757
758	if (bootverbose) {
759		printf("ds1: setmap (%lx, %lx), nseg=%d, error=%d\n",
760		       (unsigned long)segs->ds_addr, (unsigned long)segs->ds_len,
761		       nseg, error);
762	}
763}
764
765static int
766ds_init(struct sc_info *sc)
767{
768	int i;
769	u_int32_t *ci, r, pcs, rcs, ecs, ws, memsz, cb;
770	u_int8_t *t;
771	void *buf;
772	bus_dmamap_t map;
773
774	ci = ds_devs[sc->type].mcode;
775
776	ds_wr(sc, YDSXGR_NATIVEDACOUTVOL, 0x00000000, 4);
777	ds_enadsp(sc, 0);
778	ds_wr(sc, YDSXGR_MODE, 0x00010000, 4);
779	ds_wr(sc, YDSXGR_MODE, 0x00000000, 4);
780	ds_wr(sc, YDSXGR_MAPOFREC, 0x00000000, 4);
781	ds_wr(sc, YDSXGR_MAPOFEFFECT, 0x00000000, 4);
782	ds_wr(sc, YDSXGR_PLAYCTRLBASE, 0x00000000, 4);
783	ds_wr(sc, YDSXGR_RECCTRLBASE, 0x00000000, 4);
784	ds_wr(sc, YDSXGR_EFFCTRLBASE, 0x00000000, 4);
785	r = ds_rd(sc, YDSXGR_GLOBALCTRL, 2);
786	ds_wr(sc, YDSXGR_GLOBALCTRL, r & ~0x0007, 2);
787
788	for (i = 0; i < YDSXG_DSPLENGTH; i += 4)
789		ds_wr(sc, YDSXGR_DSPINSTRAM + i, DspInst[i >> 2], 4);
790
791	for (i = 0; i < YDSXG_CTRLLENGTH; i += 4)
792		ds_wr(sc, YDSXGR_CTRLINSTRAM + i, ci[i >> 2], 4);
793
794	ds_enadsp(sc, 1);
795
796	pcs = 0;
797	for (i = 100; i > 0; i--) {
798		pcs = ds_rd(sc, YDSXGR_PLAYCTRLSIZE, 4) << 2;
799		if (pcs == sizeof(struct pbank))
800			break;
801		DELAY(1000);
802	}
803	if (pcs != sizeof(struct pbank)) {
804		device_printf(sc->dev, "preposterous playctrlsize (%d)\n", pcs);
805		return -1;
806	}
807	rcs = ds_rd(sc, YDSXGR_RECCTRLSIZE, 4) << 2;
808	ecs = ds_rd(sc, YDSXGR_EFFCTRLSIZE, 4) << 2;
809	ws = ds_rd(sc, YDSXGR_WORKSIZE, 4) << 2;
810
811	memsz = 64 * 2 * pcs + 2 * 2 * rcs + 5 * 2 * ecs + ws;
812	memsz += (64 + 1) * 4;
813
814	if (bus_dmamem_alloc(sc->parent_dmat, &buf, BUS_DMA_NOWAIT, &map))
815		return -1;
816	if (bus_dmamap_load(sc->parent_dmat, map, buf, memsz, ds_setmap, sc, 0)
817	    || !sc->ctrlbase) {
818		device_printf(sc->dev, "pcs=%d, rcs=%d, ecs=%d, ws=%d, memsz=%d\n",
819			      pcs, rcs, ecs, ws, memsz);
820		return -1;
821	}
822
823	cb = 0;
824	t = buf;
825	ds_wr(sc, YDSXGR_WORKBASE, sc->ctrlbase + cb, 4);
826	cb += ws;
827	sc->pbase = (u_int32_t *)(t + cb);
828	/* printf("pbase = %p -> 0x%x\n", sc->pbase, sc->ctrlbase + cb); */
829	ds_wr(sc, YDSXGR_PLAYCTRLBASE, sc->ctrlbase + cb, 4);
830	cb += (64 + 1) * 4;
831	sc->rbank = (struct rbank *)(t + cb);
832	ds_wr(sc, YDSXGR_RECCTRLBASE, sc->ctrlbase + cb, 4);
833	cb += 2 * 2 * rcs;
834	ds_wr(sc, YDSXGR_EFFCTRLBASE, sc->ctrlbase + cb, 4);
835	cb += 5 * 2 * ecs;
836
837	sc->pbankbase = sc->ctrlbase + cb;
838	sc->pbanksize = pcs;
839	for (i = 0; i < 64; i++) {
840		wrl(sc, &sc->pbase[i + 1], 0);
841		sc->pbank[i * 2] = (struct pbank *)(t + cb);
842		/* printf("pbank[%d] = %p -> 0x%x; ", i * 2, (struct pbank *)(t + cb), sc->ctrlbase + cb - vtophys(t + cb)); */
843		cb += pcs;
844		sc->pbank[i * 2 + 1] = (struct pbank *)(t + cb);
845		/* printf("pbank[%d] = %p -> 0x%x\n", i * 2 + 1, (struct pbank *)(t + cb), sc->ctrlbase + cb - vtophys(t + cb)); */
846		cb += pcs;
847	}
848	wrl(sc, &sc->pbase[0], DS1_CHANS * 2);
849
850	sc->pchn = sc->rchn = 0;
851	ds_wr(sc, YDSXGR_NATIVEDACOUTVOL, 0x3fff3fff, 4);
852	ds_wr(sc, YDSXGR_NATIVEADCINVOL, 0x3fff3fff, 4);
853	ds_wr(sc, YDSXGR_NATIVEDACINVOL, 0x3fff3fff, 4);
854	return 0;
855}
856
857static int
858ds_finddev(u_int32_t dev, u_int32_t subdev)
859{
860	int i;
861
862	for (i = 0; ds_devs[i].dev; i++) {
863		if (ds_devs[i].dev == dev &&
864		    (ds_devs[i].subdev == subdev || ds_devs[i].subdev == 0))
865			return i;
866	}
867	return -1;
868}
869
870static int
871ds_pci_probe(device_t dev)
872{
873	int i;
874	u_int32_t subdev;
875
876	subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev);
877	i = ds_finddev(pci_get_devid(dev), subdev);
878	if (i >= 0) {
879		device_set_desc(dev, ds_devs[i].name);
880		return 0;
881	} else
882		return ENXIO;
883}
884
885static int
886ds_pci_attach(device_t dev)
887{
888	snddev_info    *d;
889	u_int32_t	data;
890	u_int32_t subdev, i;
891	struct sc_info *sc;
892	struct ac97_info *codec;
893	char 		status[SND_STATUSLEN];
894
895	d = device_get_softc(dev);
896	if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT)) == NULL) {
897		device_printf(dev, "cannot allocate softc\n");
898		return ENXIO;
899	}
900
901	bzero(sc, sizeof(*sc));
902	sc->dev = dev;
903	subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev);
904	sc->type = ds_finddev(pci_get_devid(dev), subdev);
905	sc->rev = pci_get_revid(dev);
906
907	data = pci_read_config(dev, PCIR_COMMAND, 2);
908	data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
909	pci_write_config(dev, PCIR_COMMAND, data, 2);
910	data = pci_read_config(dev, PCIR_COMMAND, 2);
911
912	sc->regid = PCIR_MAPS;
913	sc->reg = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->regid,
914					     0, ~0, 1, RF_ACTIVE);
915	if (!sc->reg) {
916		device_printf(dev, "unable to map register space\n");
917		goto bad;
918	}
919
920	sc->st = rman_get_bustag(sc->reg);
921	sc->sh = rman_get_bushandle(sc->reg);
922
923	if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
924		/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
925		/*highaddr*/BUS_SPACE_MAXADDR,
926		/*filter*/NULL, /*filterarg*/NULL,
927		/*maxsize*/65536, /*nsegments*/1, /*maxsegz*/0x3ffff,
928		/*flags*/0, &sc->parent_dmat) != 0) {
929		device_printf(dev, "unable to create dma tag\n");
930		goto bad;
931	}
932
933	if (ds_init(sc) == -1) {
934		device_printf(dev, "unable to initialize the card\n");
935		goto bad;
936	}
937
938	codec = ac97_create(dev, sc, ds_initcd, ds_rdcd, ds_wrcd);
939	if (codec == NULL)
940		goto bad;
941	mixer_init(d, &ac97_mixer, codec);
942
943	sc->irqid = 0;
944	sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irqid,
945				 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
946	if (!sc->irq ||
947	    bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY, ds_intr, sc, &sc->ih)) {
948		device_printf(dev, "unable to map interrupt\n");
949		goto bad;
950	}
951
952	snprintf(status, SND_STATUSLEN, "at memory 0x%lx irq %ld",
953		 rman_get_start(sc->reg), rman_get_start(sc->irq));
954
955	if (pcm_register(dev, sc, DS1_CHANS, 2))
956		goto bad;
957	for (i = 0; i < DS1_CHANS; i++)
958		pcm_addchan(dev, PCMDIR_PLAY, &ds_pchantemplate, sc);
959	for (i = 0; i < 2; i++)
960		pcm_addchan(dev, PCMDIR_REC, &ds_rchantemplate, sc);
961	pcm_setstatus(dev, status);
962
963	return 0;
964
965bad:
966	if (sc->reg)
967		bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg);
968	if (sc->ih)
969		bus_teardown_intr(dev, sc->irq, sc->ih);
970	if (sc->irq)
971		bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
972	free(sc, M_DEVBUF);
973	return ENXIO;
974}
975
976static device_method_t ds1_methods[] = {
977	/* Device interface */
978	DEVMETHOD(device_probe,		ds_pci_probe),
979	DEVMETHOD(device_attach,	ds_pci_attach),
980
981	{ 0, 0 }
982};
983
984static driver_t ds1_driver = {
985	"pcm",
986	ds1_methods,
987	sizeof(snddev_info),
988};
989
990static devclass_t pcm_devclass;
991
992DRIVER_MODULE(ds1, pci, ds1_driver, pcm_devclass, 0, 0);
993