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