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