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