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