xref: /freebsd/sys/dev/sound/pci/csapcm.c (revision 6b3455a7665208c366849f0b2b3bc916fb97516e)
1 /*
2  * Copyright (c) 1999 Seigo Tanimura
3  * All rights reserved.
4  *
5  * Portions of this source are based on cwcealdr.cpp and dhwiface.cpp in
6  * cwcealdr1.zip, the sample sources by Crystal Semiconductor.
7  * Copyright (c) 1996-1998 Crystal Semiconductor Corp.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 #include <sys/soundcard.h>
32 #include <dev/sound/pcm/sound.h>
33 #include <dev/sound/pcm/ac97.h>
34 #include <dev/sound/chip.h>
35 #include <dev/sound/pci/csareg.h>
36 #include <dev/sound/pci/csavar.h>
37 
38 #include <dev/pci/pcireg.h>
39 #include <dev/pci/pcivar.h>
40 
41 SND_DECLARE_FILE("$FreeBSD$");
42 
43 /* Buffer size on dma transfer. Fixed for CS416x. */
44 #define CS461x_BUFFSIZE   (4 * 1024)
45 
46 #define GOF_PER_SEC 200
47 
48 /* device private data */
49 struct csa_info;
50 
51 struct csa_chinfo {
52 	struct csa_info *parent;
53 	struct pcm_channel *channel;
54 	struct snd_dbuf *buffer;
55 	int dir;
56 	u_int32_t fmt, spd;
57 	int dma;
58 };
59 
60 struct csa_info {
61 	csa_res		res; /* resource */
62 	void		*ih; /* Interrupt cookie */
63 	bus_dma_tag_t	parent_dmat; /* DMA tag */
64 	struct csa_bridgeinfo *binfo; /* The state of the parent. */
65 	struct csa_card *card;
66 
67 	int active;
68 	/* Contents of board's registers */
69 	u_long		pfie;
70 	u_long		pctl;
71 	u_long		cctl;
72 	struct csa_chinfo pch, rch;
73 };
74 
75 /* -------------------------------------------------------------------- */
76 
77 /* prototypes */
78 static int      csa_init(struct csa_info *);
79 static void     csa_intr(void *);
80 static void	csa_setplaysamplerate(csa_res *resp, u_long ulInRate);
81 static void	csa_setcapturesamplerate(csa_res *resp, u_long ulOutRate);
82 static void	csa_startplaydma(struct csa_info *csa);
83 static void	csa_startcapturedma(struct csa_info *csa);
84 static void	csa_stopplaydma(struct csa_info *csa);
85 static void	csa_stopcapturedma(struct csa_info *csa);
86 static int	csa_startdsp(csa_res *resp);
87 static int	csa_allocres(struct csa_info *scp, device_t dev);
88 static void	csa_releaseres(struct csa_info *scp, device_t dev);
89 
90 static u_int32_t csa_playfmt[] = {
91 	AFMT_U8,
92 	AFMT_STEREO | AFMT_U8,
93 	AFMT_S8,
94 	AFMT_STEREO | AFMT_S8,
95 	AFMT_S16_LE,
96 	AFMT_STEREO | AFMT_S16_LE,
97 	AFMT_S16_BE,
98 	AFMT_STEREO | AFMT_S16_BE,
99 	0
100 };
101 static struct pcmchan_caps csa_playcaps = {8000, 48000, csa_playfmt, 0};
102 
103 static u_int32_t csa_recfmt[] = {
104 	AFMT_S16_LE,
105 	AFMT_STEREO | AFMT_S16_LE,
106 	0
107 };
108 static struct pcmchan_caps csa_reccaps = {11025, 48000, csa_recfmt, 0};
109 
110 /* -------------------------------------------------------------------- */
111 
112 static int
113 csa_active(struct csa_info *csa, int run)
114 {
115 	int old, go;
116 
117 	old = csa->active;
118 	csa->active += run;
119 
120 	if ((csa->active == 0 && old == 1) || (csa->active == 1 && old == 0)) {
121 		go = csa->active;
122 		if (csa->card->active)
123 			return csa->card->active(go);
124 	}
125 	return 0;
126 }
127 
128 /* -------------------------------------------------------------------- */
129 /* ac97 codec */
130 
131 static int
132 csa_rdcd(kobj_t obj, void *devinfo, int regno)
133 {
134 	u_int32_t data;
135 	struct csa_info *csa = (struct csa_info *)devinfo;
136 
137 	csa_active(csa, 1);
138 	if (csa_readcodec(&csa->res, regno + BA0_AC97_RESET, &data))
139 		data = 0;
140 	csa_active(csa, -1);
141 
142 	return data;
143 }
144 
145 static int
146 csa_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data)
147 {
148 	struct csa_info *csa = (struct csa_info *)devinfo;
149 
150 	csa_active(csa, 1);
151 	csa_writecodec(&csa->res, regno + BA0_AC97_RESET, data);
152 	csa_active(csa, -1);
153 
154 	return 0;
155 }
156 
157 static kobj_method_t csa_ac97_methods[] = {
158     	KOBJMETHOD(ac97_read,		csa_rdcd),
159     	KOBJMETHOD(ac97_write,		csa_wrcd),
160 	{ 0, 0 }
161 };
162 AC97_DECLARE(csa_ac97);
163 
164 static void
165 csa_setplaysamplerate(csa_res *resp, u_long ulInRate)
166 {
167 	u_long ulTemp1, ulTemp2;
168 	u_long ulPhiIncr;
169 	u_long ulCorrectionPerGOF, ulCorrectionPerSec;
170 	u_long ulOutRate;
171 
172 	ulOutRate = 48000;
173 
174 	/*
175 	 * Compute the values used to drive the actual sample rate conversion.
176 	 * The following formulas are being computed, using inline assembly
177 	 * since we need to use 64 bit arithmetic to compute the values:
178 	 *
179 	 *     ulPhiIncr = floor((Fs,in * 2^26) / Fs,out)
180 	 *     ulCorrectionPerGOF = floor((Fs,in * 2^26 - Fs,out * ulPhiIncr) /
181 	 *                                GOF_PER_SEC)
182 	 *     ulCorrectionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -
183 	 *                          GOF_PER_SEC * ulCorrectionPerGOF
184 	 *
185 	 * i.e.
186 	 *
187 	 *     ulPhiIncr:ulOther = dividend:remainder((Fs,in * 2^26) / Fs,out)
188 	 *     ulCorrectionPerGOF:ulCorrectionPerSec =
189 	 *         dividend:remainder(ulOther / GOF_PER_SEC)
190 	 */
191 	ulTemp1 = ulInRate << 16;
192 	ulPhiIncr = ulTemp1 / ulOutRate;
193 	ulTemp1 -= ulPhiIncr * ulOutRate;
194 	ulTemp1 <<= 10;
195 	ulPhiIncr <<= 10;
196 	ulTemp2 = ulTemp1 / ulOutRate;
197 	ulPhiIncr += ulTemp2;
198 	ulTemp1 -= ulTemp2 * ulOutRate;
199 	ulCorrectionPerGOF = ulTemp1 / GOF_PER_SEC;
200 	ulTemp1 -= ulCorrectionPerGOF * GOF_PER_SEC;
201 	ulCorrectionPerSec = ulTemp1;
202 
203 	/*
204 	 * Fill in the SampleRateConverter control block.
205 	 */
206 	csa_writemem(resp, BA1_PSRC, ((ulCorrectionPerSec << 16) & 0xFFFF0000) | (ulCorrectionPerGOF & 0xFFFF));
207 	csa_writemem(resp, BA1_PPI, ulPhiIncr);
208 }
209 
210 static void
211 csa_setcapturesamplerate(csa_res *resp, u_long ulOutRate)
212 {
213 	u_long ulPhiIncr, ulCoeffIncr, ulTemp1, ulTemp2;
214 	u_long ulCorrectionPerGOF, ulCorrectionPerSec, ulInitialDelay;
215 	u_long dwFrameGroupLength, dwCnt;
216 	u_long ulInRate;
217 
218 	ulInRate = 48000;
219 
220 	/*
221 	 * We can only decimate by up to a factor of 1/9th the hardware rate.
222 	 * Return an error if an attempt is made to stray outside that limit.
223 	 */
224 	if((ulOutRate * 9) < ulInRate)
225 		return;
226 
227 	/*
228 	 * We can not capture at at rate greater than the Input Rate (48000).
229 	 * Return an error if an attempt is made to stray outside that limit.
230 	 */
231 	if(ulOutRate > ulInRate)
232 		return;
233 
234 	/*
235 	 * Compute the values used to drive the actual sample rate conversion.
236 	 * The following formulas are being computed, using inline assembly
237 	 * since we need to use 64 bit arithmetic to compute the values:
238 	 *
239 	 *     ulCoeffIncr = -floor((Fs,out * 2^23) / Fs,in)
240 	 *     ulPhiIncr = floor((Fs,in * 2^26) / Fs,out)
241 	 *     ulCorrectionPerGOF = floor((Fs,in * 2^26 - Fs,out * ulPhiIncr) /
242 	 *                                GOF_PER_SEC)
243 	 *     ulCorrectionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -
244 	 *                          GOF_PER_SEC * ulCorrectionPerGOF
245 	 *     ulInitialDelay = ceil((24 * Fs,in) / Fs,out)
246 	 *
247 	 * i.e.
248 	 *
249 	 *     ulCoeffIncr = neg(dividend((Fs,out * 2^23) / Fs,in))
250 	 *     ulPhiIncr:ulOther = dividend:remainder((Fs,in * 2^26) / Fs,out)
251 	 *     ulCorrectionPerGOF:ulCorrectionPerSec =
252 	 *         dividend:remainder(ulOther / GOF_PER_SEC)
253 	 *     ulInitialDelay = dividend(((24 * Fs,in) + Fs,out - 1) / Fs,out)
254 	 */
255 	ulTemp1 = ulOutRate << 16;
256 	ulCoeffIncr = ulTemp1 / ulInRate;
257 	ulTemp1 -= ulCoeffIncr * ulInRate;
258 	ulTemp1 <<= 7;
259 	ulCoeffIncr <<= 7;
260 	ulCoeffIncr += ulTemp1 / ulInRate;
261 	ulCoeffIncr ^= 0xFFFFFFFF;
262 	ulCoeffIncr++;
263 	ulTemp1 = ulInRate << 16;
264 	ulPhiIncr = ulTemp1 / ulOutRate;
265 	ulTemp1 -= ulPhiIncr * ulOutRate;
266 	ulTemp1 <<= 10;
267 	ulPhiIncr <<= 10;
268 	ulTemp2 = ulTemp1 / ulOutRate;
269 	ulPhiIncr += ulTemp2;
270 	ulTemp1 -= ulTemp2 * ulOutRate;
271 	ulCorrectionPerGOF = ulTemp1 / GOF_PER_SEC;
272 	ulTemp1 -= ulCorrectionPerGOF * GOF_PER_SEC;
273 	ulCorrectionPerSec = ulTemp1;
274 	ulInitialDelay = ((ulInRate * 24) + ulOutRate - 1) / ulOutRate;
275 
276 	/*
277 	 * Fill in the VariDecimate control block.
278 	 */
279 	csa_writemem(resp, BA1_CSRC,
280 		     ((ulCorrectionPerSec << 16) & 0xFFFF0000) | (ulCorrectionPerGOF & 0xFFFF));
281 	csa_writemem(resp, BA1_CCI, ulCoeffIncr);
282 	csa_writemem(resp, BA1_CD,
283 	     (((BA1_VARIDEC_BUF_1 + (ulInitialDelay << 2)) << 16) & 0xFFFF0000) | 0x80);
284 	csa_writemem(resp, BA1_CPI, ulPhiIncr);
285 
286 	/*
287 	 * Figure out the frame group length for the write back task.  Basically,
288 	 * this is just the factors of 24000 (2^6*3*5^3) that are not present in
289 	 * the output sample rate.
290 	 */
291 	dwFrameGroupLength = 1;
292 	for(dwCnt = 2; dwCnt <= 64; dwCnt *= 2)
293 	{
294 		if(((ulOutRate / dwCnt) * dwCnt) !=
295 		   ulOutRate)
296 		{
297 			dwFrameGroupLength *= 2;
298 		}
299 	}
300 	if(((ulOutRate / 3) * 3) !=
301 	   ulOutRate)
302 	{
303 		dwFrameGroupLength *= 3;
304 	}
305 	for(dwCnt = 5; dwCnt <= 125; dwCnt *= 5)
306 	{
307 		if(((ulOutRate / dwCnt) * dwCnt) !=
308 		   ulOutRate)
309 		{
310 			dwFrameGroupLength *= 5;
311 		}
312 	}
313 
314 	/*
315 	 * Fill in the WriteBack control block.
316 	 */
317 	csa_writemem(resp, BA1_CFG1, dwFrameGroupLength);
318 	csa_writemem(resp, BA1_CFG2, (0x00800000 | dwFrameGroupLength));
319 	csa_writemem(resp, BA1_CCST, 0x0000FFFF);
320 	csa_writemem(resp, BA1_CSPB, ((65536 * ulOutRate) / 24000));
321 	csa_writemem(resp, (BA1_CSPB + 4), 0x0000FFFF);
322 }
323 
324 static void
325 csa_startplaydma(struct csa_info *csa)
326 {
327 	csa_res *resp;
328 	u_long ul;
329 
330 	if (!csa->pch.dma) {
331 		resp = &csa->res;
332 		ul = csa_readmem(resp, BA1_PCTL);
333 		ul &= 0x0000ffff;
334 		csa_writemem(resp, BA1_PCTL, ul | csa->pctl);
335 		csa_writemem(resp, BA1_PVOL, 0x80008000);
336 		csa->pch.dma = 1;
337 	}
338 }
339 
340 static void
341 csa_startcapturedma(struct csa_info *csa)
342 {
343 	csa_res *resp;
344 	u_long ul;
345 
346 	if (!csa->rch.dma) {
347 		resp = &csa->res;
348 		ul = csa_readmem(resp, BA1_CCTL);
349 		ul &= 0xffff0000;
350 		csa_writemem(resp, BA1_CCTL, ul | csa->cctl);
351 		csa_writemem(resp, BA1_CVOL, 0x80008000);
352 		csa->rch.dma = 1;
353 	}
354 }
355 
356 static void
357 csa_stopplaydma(struct csa_info *csa)
358 {
359 	csa_res *resp;
360 	u_long ul;
361 
362 	if (csa->pch.dma) {
363 		resp = &csa->res;
364 		ul = csa_readmem(resp, BA1_PCTL);
365 		csa->pctl = ul & 0xffff0000;
366 		csa_writemem(resp, BA1_PCTL, ul & 0x0000ffff);
367 		csa_writemem(resp, BA1_PVOL, 0xffffffff);
368 		csa->pch.dma = 0;
369 
370 		/*
371 		 * The bitwise pointer of the serial FIFO in the DSP
372 		 * seems to make an error upon starting or stopping the
373 		 * DSP. Clear the FIFO and correct the pointer if we
374 		 * are not capturing.
375 		 */
376 		if (!csa->rch.dma) {
377 			csa_clearserialfifos(resp);
378 			csa_writeio(resp, BA0_SERBSP, 0);
379 		}
380 	}
381 }
382 
383 static void
384 csa_stopcapturedma(struct csa_info *csa)
385 {
386 	csa_res *resp;
387 	u_long ul;
388 
389 	if (csa->rch.dma) {
390 		resp = &csa->res;
391 		ul = csa_readmem(resp, BA1_CCTL);
392 		csa->cctl = ul & 0x0000ffff;
393 		csa_writemem(resp, BA1_CCTL, ul & 0xffff0000);
394 		csa_writemem(resp, BA1_CVOL, 0xffffffff);
395 		csa->rch.dma = 0;
396 
397 		/*
398 		 * The bitwise pointer of the serial FIFO in the DSP
399 		 * seems to make an error upon starting or stopping the
400 		 * DSP. Clear the FIFO and correct the pointer if we
401 		 * are not playing.
402 		 */
403 		if (!csa->pch.dma) {
404 			csa_clearserialfifos(resp);
405 			csa_writeio(resp, BA0_SERBSP, 0);
406 		}
407 	}
408 }
409 
410 static int
411 csa_startdsp(csa_res *resp)
412 {
413 	int i;
414 	u_long ul;
415 
416 	/*
417 	 * Set the frame timer to reflect the number of cycles per frame.
418 	 */
419 	csa_writemem(resp, BA1_FRMT, 0xadf);
420 
421 	/*
422 	 * Turn on the run, run at frame, and DMA enable bits in the local copy of
423 	 * the SP control register.
424 	 */
425 	csa_writemem(resp, BA1_SPCR, SPCR_RUN | SPCR_RUNFR | SPCR_DRQEN);
426 
427 	/*
428 	 * Wait until the run at frame bit resets itself in the SP control
429 	 * register.
430 	 */
431 	ul = 0;
432 	for (i = 0 ; i < 25 ; i++) {
433 		/*
434 		 * Wait a little bit, so we don't issue PCI reads too frequently.
435 		 */
436 		DELAY(50);
437 		/*
438 		 * Fetch the current value of the SP status register.
439 		 */
440 		ul = csa_readmem(resp, BA1_SPCR);
441 
442 		/*
443 		 * If the run at frame bit has reset, then stop waiting.
444 		 */
445 		if((ul & SPCR_RUNFR) == 0)
446 			break;
447 	}
448 	/*
449 	 * If the run at frame bit never reset, then return an error.
450 	 */
451 	if((ul & SPCR_RUNFR) != 0)
452 		return (EAGAIN);
453 
454 	return (0);
455 }
456 
457 static int
458 csa_setupchan(struct csa_chinfo *ch)
459 {
460 	struct csa_info *csa = ch->parent;
461 	csa_res *resp = &csa->res;
462 	u_long pdtc, tmp;
463 
464 	if (ch->dir == PCMDIR_PLAY) {
465 		/* direction */
466 		csa_writemem(resp, BA1_PBA, sndbuf_getbufaddr(ch->buffer));
467 
468 		/* format */
469 		csa->pfie = csa_readmem(resp, BA1_PFIE) & ~0x0000f03f;
470 		if (!(ch->fmt & AFMT_SIGNED))
471 			csa->pfie |= 0x8000;
472 		if (ch->fmt & AFMT_BIGENDIAN)
473 			csa->pfie |= 0x4000;
474 		if (!(ch->fmt & AFMT_STEREO))
475 			csa->pfie |= 0x2000;
476 		if (ch->fmt & AFMT_8BIT)
477 			csa->pfie |= 0x1000;
478 		csa_writemem(resp, BA1_PFIE, csa->pfie);
479 
480 		tmp = 4;
481 		if (ch->fmt & AFMT_16BIT)
482 			tmp <<= 1;
483 		if (ch->fmt & AFMT_STEREO)
484 			tmp <<= 1;
485 		tmp--;
486 
487 		pdtc = csa_readmem(resp, BA1_PDTC) & ~0x000001ff;
488 		pdtc |= tmp;
489 		csa_writemem(resp, BA1_PDTC, pdtc);
490 
491 		/* rate */
492 		csa_setplaysamplerate(resp, ch->spd);
493 	} else if (ch->dir == PCMDIR_REC) {
494 		/* direction */
495 		csa_writemem(resp, BA1_CBA, sndbuf_getbufaddr(ch->buffer));
496 
497 		/* format */
498 		csa_writemem(resp, BA1_CIE, (csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000001);
499 
500 		/* rate */
501 		csa_setcapturesamplerate(resp, ch->spd);
502 	}
503 	return 0;
504 }
505 
506 /* -------------------------------------------------------------------- */
507 /* channel interface */
508 
509 static void *
510 csachan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
511 {
512 	struct csa_info *csa = devinfo;
513 	struct csa_chinfo *ch = (dir == PCMDIR_PLAY)? &csa->pch : &csa->rch;
514 
515 	ch->parent = csa;
516 	ch->channel = c;
517 	ch->buffer = b;
518 	ch->dir = dir;
519 	if (sndbuf_alloc(ch->buffer, csa->parent_dmat, CS461x_BUFFSIZE) == -1) return NULL;
520 	return ch;
521 }
522 
523 static int
524 csachan_setformat(kobj_t obj, void *data, u_int32_t format)
525 {
526 	struct csa_chinfo *ch = data;
527 
528 	ch->fmt = format;
529 	return 0;
530 }
531 
532 static int
533 csachan_setspeed(kobj_t obj, void *data, u_int32_t speed)
534 {
535 	struct csa_chinfo *ch = data;
536 
537 	ch->spd = speed;
538 	return ch->spd; /* XXX calc real speed */
539 }
540 
541 static int
542 csachan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
543 {
544 	return CS461x_BUFFSIZE / 2;
545 }
546 
547 static int
548 csachan_trigger(kobj_t obj, void *data, int go)
549 {
550 	struct csa_chinfo *ch = data;
551 	struct csa_info *csa = ch->parent;
552 
553 	if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
554 		return 0;
555 
556 	if (go == PCMTRIG_START) {
557 		csa_active(csa, 1);
558 		csa_setupchan(ch);
559 		if (ch->dir == PCMDIR_PLAY)
560 			csa_startplaydma(csa);
561 		else
562 			csa_startcapturedma(csa);
563 	} else {
564 		if (ch->dir == PCMDIR_PLAY)
565 			csa_stopplaydma(csa);
566 		else
567 			csa_stopcapturedma(csa);
568 		csa_active(csa, -1);
569 	}
570 	return 0;
571 }
572 
573 static int
574 csachan_getptr(kobj_t obj, void *data)
575 {
576 	struct csa_chinfo *ch = data;
577 	struct csa_info *csa = ch->parent;
578 	csa_res *resp;
579 	int ptr;
580 
581 	resp = &csa->res;
582 
583 	if (ch->dir == PCMDIR_PLAY) {
584 		ptr = csa_readmem(resp, BA1_PBA) - sndbuf_getbufaddr(ch->buffer);
585 		if ((ch->fmt & AFMT_U8) != 0 || (ch->fmt & AFMT_S8) != 0)
586 			ptr >>= 1;
587 	} else {
588 		ptr = csa_readmem(resp, BA1_CBA) - sndbuf_getbufaddr(ch->buffer);
589 		if ((ch->fmt & AFMT_U8) != 0 || (ch->fmt & AFMT_S8) != 0)
590 			ptr >>= 1;
591 	}
592 
593 	return (ptr);
594 }
595 
596 static struct pcmchan_caps *
597 csachan_getcaps(kobj_t obj, void *data)
598 {
599 	struct csa_chinfo *ch = data;
600 	return (ch->dir == PCMDIR_PLAY)? &csa_playcaps : &csa_reccaps;
601 }
602 
603 static kobj_method_t csachan_methods[] = {
604     	KOBJMETHOD(channel_init,		csachan_init),
605     	KOBJMETHOD(channel_setformat,		csachan_setformat),
606     	KOBJMETHOD(channel_setspeed,		csachan_setspeed),
607     	KOBJMETHOD(channel_setblocksize,	csachan_setblocksize),
608     	KOBJMETHOD(channel_trigger,		csachan_trigger),
609     	KOBJMETHOD(channel_getptr,		csachan_getptr),
610     	KOBJMETHOD(channel_getcaps,		csachan_getcaps),
611 	{ 0, 0 }
612 };
613 CHANNEL_DECLARE(csachan);
614 
615 /* -------------------------------------------------------------------- */
616 /* The interrupt handler */
617 static void
618 csa_intr(void *p)
619 {
620 	struct csa_info *csa = p;
621 
622 	if ((csa->binfo->hisr & HISR_VC0) != 0)
623 		chn_intr(csa->pch.channel);
624 	if ((csa->binfo->hisr & HISR_VC1) != 0)
625 		chn_intr(csa->rch.channel);
626 }
627 
628 /* -------------------------------------------------------------------- */
629 
630 /*
631  * Probe and attach the card
632  */
633 
634 static int
635 csa_init(struct csa_info *csa)
636 {
637 	csa_res *resp;
638 
639 	resp = &csa->res;
640 
641 	csa->pfie = 0;
642 	csa_stopplaydma(csa);
643 	csa_stopcapturedma(csa);
644 
645 	if (csa_startdsp(resp))
646 		return (1);
647 
648 	/* Crank up the power on the DAC and ADC. */
649 	csa_setplaysamplerate(resp, 8000);
650 	csa_setcapturesamplerate(resp, 8000);
651 
652 	return 0;
653 }
654 
655 /* Allocates resources. */
656 static int
657 csa_allocres(struct csa_info *csa, device_t dev)
658 {
659 	csa_res *resp;
660 
661 	resp = &csa->res;
662 	if (resp->io == NULL) {
663 		resp->io = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
664 			&resp->io_rid, RF_ACTIVE);
665 		if (resp->io == NULL)
666 			return (1);
667 	}
668 	if (resp->mem == NULL) {
669 		resp->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
670 			&resp->mem_rid, RF_ACTIVE);
671 		if (resp->mem == NULL)
672 			return (1);
673 	}
674 	if (resp->irq == NULL) {
675 		resp->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
676 			&resp->irq_rid, RF_ACTIVE | RF_SHAREABLE);
677 		if (resp->irq == NULL)
678 			return (1);
679 	}
680 	if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/CS461x_BUFFSIZE, /*boundary*/CS461x_BUFFSIZE,
681 			       /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
682 			       /*highaddr*/BUS_SPACE_MAXADDR,
683 			       /*filter*/NULL, /*filterarg*/NULL,
684 			       /*maxsize*/CS461x_BUFFSIZE, /*nsegments*/1, /*maxsegz*/0x3ffff,
685 			       /*flags*/0, /*lockfunc*/busdma_lock_mutex,
686 			       /*lockarg*/&Giant, &csa->parent_dmat) != 0)
687 		return (1);
688 
689 	return (0);
690 }
691 
692 /* Releases resources. */
693 static void
694 csa_releaseres(struct csa_info *csa, device_t dev)
695 {
696 	csa_res *resp;
697 
698 	resp = &csa->res;
699 	if (resp->irq != NULL) {
700 		if (csa->ih)
701 			bus_teardown_intr(dev, resp->irq, csa->ih);
702 		bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq);
703 		resp->irq = NULL;
704 	}
705 	if (resp->io != NULL) {
706 		bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
707 		resp->io = NULL;
708 	}
709 	if (resp->mem != NULL) {
710 		bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
711 		resp->mem = NULL;
712 	}
713 	if (csa->parent_dmat != NULL) {
714 		bus_dma_tag_destroy(csa->parent_dmat);
715 		csa->parent_dmat = NULL;
716 	}
717 	if (csa != NULL) {
718 		free(csa, M_DEVBUF);
719 		csa = NULL;
720 	}
721 }
722 
723 static int
724 pcmcsa_probe(device_t dev)
725 {
726 	char *s;
727 	struct sndcard_func *func;
728 
729 	/* The parent device has already been probed. */
730 
731 	func = device_get_ivars(dev);
732 	if (func == NULL || func->func != SCF_PCM)
733 		return (ENXIO);
734 
735 	s = "CS461x PCM Audio";
736 
737 	device_set_desc(dev, s);
738 	return (0);
739 }
740 
741 static int
742 pcmcsa_attach(device_t dev)
743 {
744 	struct csa_info *csa;
745 	csa_res *resp;
746 	int unit;
747 	char status[SND_STATUSLEN];
748 	struct ac97_info *codec;
749 	struct sndcard_func *func;
750 
751 	csa = malloc(sizeof(*csa), M_DEVBUF, M_NOWAIT | M_ZERO);
752 	if (csa == NULL)
753 		return (ENOMEM);
754 	unit = device_get_unit(dev);
755 	func = device_get_ivars(dev);
756 	csa->binfo = func->varinfo;
757 	/*
758 	 * Fake the status of DMA so that the initial value of
759 	 * PCTL and CCTL can be stored into csa->pctl and csa->cctl,
760 	 * respectively.
761 	 */
762 	csa->pch.dma = csa->rch.dma = 1;
763 	csa->active = 0;
764 	csa->card = csa->binfo->card;
765 
766 	/* Allocate the resources. */
767 	resp = &csa->res;
768 	resp->io_rid = PCIR_BAR(0);
769 	resp->mem_rid = PCIR_BAR(1);
770 	resp->irq_rid = 0;
771 	if (csa_allocres(csa, dev)) {
772 		csa_releaseres(csa, dev);
773 		return (ENXIO);
774 	}
775 
776 	csa_active(csa, 1);
777 	if (csa_init(csa)) {
778 		csa_releaseres(csa, dev);
779 		return (ENXIO);
780 	}
781 	codec = AC97_CREATE(dev, csa, csa_ac97);
782 	if (codec == NULL) {
783 		csa_releaseres(csa, dev);
784 		return (ENXIO);
785 	}
786 	if (csa->card->inv_eapd)
787 		ac97_setflags(codec, AC97_F_EAPD_INV);
788 	if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) {
789 		ac97_destroy(codec);
790 		csa_releaseres(csa, dev);
791 		return (ENXIO);
792 	}
793 
794 	snprintf(status, SND_STATUSLEN, "at irq %ld %s",
795 			rman_get_start(resp->irq),PCM_KLDSTRING(snd_csa));
796 
797 	/* Enable interrupt. */
798 	if (snd_setup_intr(dev, resp->irq, 0, csa_intr, csa, &csa->ih)) {
799 		ac97_destroy(codec);
800 		csa_releaseres(csa, dev);
801 		return (ENXIO);
802 	}
803 	csa_writemem(resp, BA1_PFIE, csa_readmem(resp, BA1_PFIE) & ~0x0000f03f);
804 	csa_writemem(resp, BA1_CIE, (csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000001);
805 	csa_active(csa, -1);
806 
807 	if (pcm_register(dev, csa, 1, 1)) {
808 		ac97_destroy(codec);
809 		csa_releaseres(csa, dev);
810 		return (ENXIO);
811 	}
812 	pcm_addchan(dev, PCMDIR_REC, &csachan_class, csa);
813 	pcm_addchan(dev, PCMDIR_PLAY, &csachan_class, csa);
814 	pcm_setstatus(dev, status);
815 
816 	return (0);
817 }
818 
819 static int
820 pcmcsa_detach(device_t dev)
821 {
822 	int r;
823 	struct csa_info *csa;
824 
825 	r = pcm_unregister(dev);
826 	if (r)
827 		return r;
828 
829 	csa = pcm_getdevinfo(dev);
830 	csa_releaseres(csa, dev);
831 
832 	return 0;
833 }
834 
835 static device_method_t pcmcsa_methods[] = {
836 	/* Device interface */
837 	DEVMETHOD(device_probe , pcmcsa_probe ),
838 	DEVMETHOD(device_attach, pcmcsa_attach),
839 	DEVMETHOD(device_detach, pcmcsa_detach),
840 
841 	{ 0, 0 },
842 };
843 
844 static driver_t pcmcsa_driver = {
845 	"pcm",
846 	pcmcsa_methods,
847 	PCM_SOFTC_SIZE,
848 };
849 
850 DRIVER_MODULE(snd_csapcm, csa, pcmcsa_driver, pcm_devclass, 0, 0);
851 MODULE_DEPEND(snd_csapcm, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
852 MODULE_DEPEND(snd_csapcm, snd_csa, 1, 1, 1);
853 MODULE_VERSION(snd_csapcm, 1);
854