xref: /freebsd/sys/dev/sound/pci/csapcm.c (revision 6af83ee0d2941d18880b6aaa2b4facd1d30c6106)
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) != 0)
520 		return NULL;
521 	return ch;
522 }
523 
524 static int
525 csachan_setformat(kobj_t obj, void *data, u_int32_t format)
526 {
527 	struct csa_chinfo *ch = data;
528 
529 	ch->fmt = format;
530 	return 0;
531 }
532 
533 static int
534 csachan_setspeed(kobj_t obj, void *data, u_int32_t speed)
535 {
536 	struct csa_chinfo *ch = data;
537 
538 	ch->spd = speed;
539 	return ch->spd; /* XXX calc real speed */
540 }
541 
542 static int
543 csachan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
544 {
545 	return CS461x_BUFFSIZE / 2;
546 }
547 
548 static int
549 csachan_trigger(kobj_t obj, void *data, int go)
550 {
551 	struct csa_chinfo *ch = data;
552 	struct csa_info *csa = ch->parent;
553 
554 	if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
555 		return 0;
556 
557 	if (go == PCMTRIG_START) {
558 		csa_active(csa, 1);
559 		csa_setupchan(ch);
560 		if (ch->dir == PCMDIR_PLAY)
561 			csa_startplaydma(csa);
562 		else
563 			csa_startcapturedma(csa);
564 	} else {
565 		if (ch->dir == PCMDIR_PLAY)
566 			csa_stopplaydma(csa);
567 		else
568 			csa_stopcapturedma(csa);
569 		csa_active(csa, -1);
570 	}
571 	return 0;
572 }
573 
574 static int
575 csachan_getptr(kobj_t obj, void *data)
576 {
577 	struct csa_chinfo *ch = data;
578 	struct csa_info *csa = ch->parent;
579 	csa_res *resp;
580 	int ptr;
581 
582 	resp = &csa->res;
583 
584 	if (ch->dir == PCMDIR_PLAY) {
585 		ptr = csa_readmem(resp, BA1_PBA) - sndbuf_getbufaddr(ch->buffer);
586 		if ((ch->fmt & AFMT_U8) != 0 || (ch->fmt & AFMT_S8) != 0)
587 			ptr >>= 1;
588 	} else {
589 		ptr = csa_readmem(resp, BA1_CBA) - sndbuf_getbufaddr(ch->buffer);
590 		if ((ch->fmt & AFMT_U8) != 0 || (ch->fmt & AFMT_S8) != 0)
591 			ptr >>= 1;
592 	}
593 
594 	return (ptr);
595 }
596 
597 static struct pcmchan_caps *
598 csachan_getcaps(kobj_t obj, void *data)
599 {
600 	struct csa_chinfo *ch = data;
601 	return (ch->dir == PCMDIR_PLAY)? &csa_playcaps : &csa_reccaps;
602 }
603 
604 static kobj_method_t csachan_methods[] = {
605     	KOBJMETHOD(channel_init,		csachan_init),
606     	KOBJMETHOD(channel_setformat,		csachan_setformat),
607     	KOBJMETHOD(channel_setspeed,		csachan_setspeed),
608     	KOBJMETHOD(channel_setblocksize,	csachan_setblocksize),
609     	KOBJMETHOD(channel_trigger,		csachan_trigger),
610     	KOBJMETHOD(channel_getptr,		csachan_getptr),
611     	KOBJMETHOD(channel_getcaps,		csachan_getcaps),
612 	{ 0, 0 }
613 };
614 CHANNEL_DECLARE(csachan);
615 
616 /* -------------------------------------------------------------------- */
617 /* The interrupt handler */
618 static void
619 csa_intr(void *p)
620 {
621 	struct csa_info *csa = p;
622 
623 	if ((csa->binfo->hisr & HISR_VC0) != 0)
624 		chn_intr(csa->pch.channel);
625 	if ((csa->binfo->hisr & HISR_VC1) != 0)
626 		chn_intr(csa->rch.channel);
627 }
628 
629 /* -------------------------------------------------------------------- */
630 
631 /*
632  * Probe and attach the card
633  */
634 
635 static int
636 csa_init(struct csa_info *csa)
637 {
638 	csa_res *resp;
639 
640 	resp = &csa->res;
641 
642 	csa->pfie = 0;
643 	csa_stopplaydma(csa);
644 	csa_stopcapturedma(csa);
645 
646 	if (csa_startdsp(resp))
647 		return (1);
648 
649 	/* Crank up the power on the DAC and ADC. */
650 	csa_setplaysamplerate(resp, 8000);
651 	csa_setcapturesamplerate(resp, 8000);
652 
653 	return 0;
654 }
655 
656 /* Allocates resources. */
657 static int
658 csa_allocres(struct csa_info *csa, device_t dev)
659 {
660 	csa_res *resp;
661 
662 	resp = &csa->res;
663 	if (resp->io == NULL) {
664 		resp->io = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
665 			&resp->io_rid, RF_ACTIVE);
666 		if (resp->io == NULL)
667 			return (1);
668 	}
669 	if (resp->mem == NULL) {
670 		resp->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
671 			&resp->mem_rid, RF_ACTIVE);
672 		if (resp->mem == NULL)
673 			return (1);
674 	}
675 	if (resp->irq == NULL) {
676 		resp->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
677 			&resp->irq_rid, RF_ACTIVE | RF_SHAREABLE);
678 		if (resp->irq == NULL)
679 			return (1);
680 	}
681 	if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/CS461x_BUFFSIZE, /*boundary*/CS461x_BUFFSIZE,
682 			       /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
683 			       /*highaddr*/BUS_SPACE_MAXADDR,
684 			       /*filter*/NULL, /*filterarg*/NULL,
685 			       /*maxsize*/CS461x_BUFFSIZE, /*nsegments*/1, /*maxsegz*/0x3ffff,
686 			       /*flags*/0, /*lockfunc*/busdma_lock_mutex,
687 			       /*lockarg*/&Giant, &csa->parent_dmat) != 0)
688 		return (1);
689 
690 	return (0);
691 }
692 
693 /* Releases resources. */
694 static void
695 csa_releaseres(struct csa_info *csa, device_t dev)
696 {
697 	csa_res *resp;
698 
699 	resp = &csa->res;
700 	if (resp->irq != NULL) {
701 		if (csa->ih)
702 			bus_teardown_intr(dev, resp->irq, csa->ih);
703 		bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq);
704 		resp->irq = NULL;
705 	}
706 	if (resp->io != NULL) {
707 		bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
708 		resp->io = NULL;
709 	}
710 	if (resp->mem != NULL) {
711 		bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
712 		resp->mem = NULL;
713 	}
714 	if (csa->parent_dmat != NULL) {
715 		bus_dma_tag_destroy(csa->parent_dmat);
716 		csa->parent_dmat = NULL;
717 	}
718 	if (csa != NULL) {
719 		free(csa, M_DEVBUF);
720 		csa = NULL;
721 	}
722 }
723 
724 static int
725 pcmcsa_probe(device_t dev)
726 {
727 	char *s;
728 	struct sndcard_func *func;
729 
730 	/* The parent device has already been probed. */
731 
732 	func = device_get_ivars(dev);
733 	if (func == NULL || func->func != SCF_PCM)
734 		return (ENXIO);
735 
736 	s = "CS461x PCM Audio";
737 
738 	device_set_desc(dev, s);
739 	return (0);
740 }
741 
742 static int
743 pcmcsa_attach(device_t dev)
744 {
745 	struct csa_info *csa;
746 	csa_res *resp;
747 	int unit;
748 	char status[SND_STATUSLEN];
749 	struct ac97_info *codec;
750 	struct sndcard_func *func;
751 
752 	csa = malloc(sizeof(*csa), M_DEVBUF, M_NOWAIT | M_ZERO);
753 	if (csa == NULL)
754 		return (ENOMEM);
755 	unit = device_get_unit(dev);
756 	func = device_get_ivars(dev);
757 	csa->binfo = func->varinfo;
758 	/*
759 	 * Fake the status of DMA so that the initial value of
760 	 * PCTL and CCTL can be stored into csa->pctl and csa->cctl,
761 	 * respectively.
762 	 */
763 	csa->pch.dma = csa->rch.dma = 1;
764 	csa->active = 0;
765 	csa->card = csa->binfo->card;
766 
767 	/* Allocate the resources. */
768 	resp = &csa->res;
769 	resp->io_rid = PCIR_BAR(0);
770 	resp->mem_rid = PCIR_BAR(1);
771 	resp->irq_rid = 0;
772 	if (csa_allocres(csa, dev)) {
773 		csa_releaseres(csa, dev);
774 		return (ENXIO);
775 	}
776 
777 	csa_active(csa, 1);
778 	if (csa_init(csa)) {
779 		csa_releaseres(csa, dev);
780 		return (ENXIO);
781 	}
782 	codec = AC97_CREATE(dev, csa, csa_ac97);
783 	if (codec == NULL) {
784 		csa_releaseres(csa, dev);
785 		return (ENXIO);
786 	}
787 	if (csa->card->inv_eapd)
788 		ac97_setflags(codec, AC97_F_EAPD_INV);
789 	if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) {
790 		ac97_destroy(codec);
791 		csa_releaseres(csa, dev);
792 		return (ENXIO);
793 	}
794 
795 	snprintf(status, SND_STATUSLEN, "at irq %ld %s",
796 			rman_get_start(resp->irq),PCM_KLDSTRING(snd_csa));
797 
798 	/* Enable interrupt. */
799 	if (snd_setup_intr(dev, resp->irq, 0, csa_intr, csa, &csa->ih)) {
800 		ac97_destroy(codec);
801 		csa_releaseres(csa, dev);
802 		return (ENXIO);
803 	}
804 	csa_writemem(resp, BA1_PFIE, csa_readmem(resp, BA1_PFIE) & ~0x0000f03f);
805 	csa_writemem(resp, BA1_CIE, (csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000001);
806 	csa_active(csa, -1);
807 
808 	if (pcm_register(dev, csa, 1, 1)) {
809 		ac97_destroy(codec);
810 		csa_releaseres(csa, dev);
811 		return (ENXIO);
812 	}
813 	pcm_addchan(dev, PCMDIR_REC, &csachan_class, csa);
814 	pcm_addchan(dev, PCMDIR_PLAY, &csachan_class, csa);
815 	pcm_setstatus(dev, status);
816 
817 	return (0);
818 }
819 
820 static int
821 pcmcsa_detach(device_t dev)
822 {
823 	int r;
824 	struct csa_info *csa;
825 
826 	r = pcm_unregister(dev);
827 	if (r)
828 		return r;
829 
830 	csa = pcm_getdevinfo(dev);
831 	csa_releaseres(csa, dev);
832 
833 	return 0;
834 }
835 
836 static device_method_t pcmcsa_methods[] = {
837 	/* Device interface */
838 	DEVMETHOD(device_probe , pcmcsa_probe ),
839 	DEVMETHOD(device_attach, pcmcsa_attach),
840 	DEVMETHOD(device_detach, pcmcsa_detach),
841 
842 	{ 0, 0 },
843 };
844 
845 static driver_t pcmcsa_driver = {
846 	"pcm",
847 	pcmcsa_methods,
848 	PCM_SOFTC_SIZE,
849 };
850 
851 DRIVER_MODULE(snd_csapcm, csa, pcmcsa_driver, pcm_devclass, 0, 0);
852 MODULE_DEPEND(snd_csapcm, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
853 MODULE_DEPEND(snd_csapcm, snd_csa, 1, 1, 1);
854 MODULE_VERSION(snd_csapcm, 1);
855