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