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