xref: /freebsd/sys/dev/sound/pci/csapcm.c (revision 716fd348)
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*/NULL, /*lockarg*/NULL,
720 			       &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 	char status[SND_STATUSLEN];
781 	struct ac97_info *codec;
782 	struct sndcard_func *func;
783 
784 	csa = malloc(sizeof(*csa), M_DEVBUF, M_WAITOK | M_ZERO);
785 	func = device_get_ivars(dev);
786 	csa->binfo = func->varinfo;
787 	/*
788 	 * Fake the status of DMA so that the initial value of
789 	 * PCTL and CCTL can be stored into csa->pctl and csa->cctl,
790 	 * respectively.
791 	 */
792 	csa->pch.dma = csa->rch.dma = 1;
793 	csa->active = 0;
794 	csa->card = csa->binfo->card;
795 
796 	/* Allocate the resources. */
797 	resp = &csa->res;
798 	resp->io_rid = PCIR_BAR(0);
799 	resp->mem_rid = PCIR_BAR(1);
800 	resp->irq_rid = 0;
801 	if (csa_allocres(csa, dev)) {
802 		csa_releaseres(csa, dev);
803 		return (ENXIO);
804 	}
805 
806 	csa_active(csa, 1);
807 	if (csa_init(csa)) {
808 		csa_releaseres(csa, dev);
809 		return (ENXIO);
810 	}
811 	codec = AC97_CREATE(dev, csa, csa_ac97);
812 	if (codec == NULL) {
813 		csa_releaseres(csa, dev);
814 		return (ENXIO);
815 	}
816 	if (csa->card->inv_eapd)
817 		ac97_setflags(codec, AC97_F_EAPD_INV);
818 	if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) {
819 		ac97_destroy(codec);
820 		csa_releaseres(csa, dev);
821 		return (ENXIO);
822 	}
823 
824 	snprintf(status, SND_STATUSLEN, "at irq %jd %s",
825 			rman_get_start(resp->irq),PCM_KLDSTRING(snd_csa));
826 
827 	/* Enable interrupt. */
828 	if (snd_setup_intr(dev, resp->irq, 0, csa_intr, csa, &csa->ih)) {
829 		ac97_destroy(codec);
830 		csa_releaseres(csa, dev);
831 		return (ENXIO);
832 	}
833 	csa_writemem(resp, BA1_PFIE, csa_readmem(resp, BA1_PFIE) & ~0x0000f03f);
834 	csa_writemem(resp, BA1_CIE, (csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000001);
835 	csa_active(csa, -1);
836 
837 	if (pcm_register(dev, csa, 1, 1)) {
838 		ac97_destroy(codec);
839 		csa_releaseres(csa, dev);
840 		return (ENXIO);
841 	}
842 	pcm_addchan(dev, PCMDIR_REC, &csachan_class, csa);
843 	pcm_addchan(dev, PCMDIR_PLAY, &csachan_class, csa);
844 	pcm_setstatus(dev, status);
845 
846 	return (0);
847 }
848 
849 static int
850 pcmcsa_detach(device_t dev)
851 {
852 	int r;
853 	struct csa_info *csa;
854 
855 	r = pcm_unregister(dev);
856 	if (r)
857 		return r;
858 
859 	csa = pcm_getdevinfo(dev);
860 	csa_releaseres(csa, dev);
861 
862 	return 0;
863 }
864 
865 static void
866 csa_ac97_suspend(struct csa_info *csa)
867 {
868 	int count, i;
869 	uint32_t tmp;
870 
871 	for (count = 0x2, i=0;
872 	    (count <= CS461x_AC97_HIGHESTREGTORESTORE) &&
873 	    (i < CS461x_AC97_NUMBER_RESTORE_REGS);
874 	    count += 2, i++)
875 		csa_readcodec(&csa->res, BA0_AC97_RESET + count, &csa->ac97[i]);
876 
877 	/* mute the outputs */
878 	csa_writecodec(&csa->res, BA0_AC97_MASTER_VOLUME, 0x8000);
879 	csa_writecodec(&csa->res, BA0_AC97_HEADPHONE_VOLUME, 0x8000);
880 	csa_writecodec(&csa->res, BA0_AC97_MASTER_VOLUME_MONO, 0x8000);
881 	csa_writecodec(&csa->res, BA0_AC97_PCM_OUT_VOLUME, 0x8000);
882 	/* save the registers that cause pops */
883 	csa_readcodec(&csa->res, BA0_AC97_POWERDOWN, &csa->ac97_powerdown);
884 	csa_readcodec(&csa->res, BA0_AC97_GENERAL_PURPOSE,
885 	    &csa->ac97_general_purpose);
886 
887 	/*
888 	 * And power down everything on the AC97 codec. Well, for now,
889 	 * only power down the DAC/ADC and MIXER VREFON components.
890 	 * trouble with removing VREF.
891 	 */
892 
893 	/* MIXVON */
894 	csa_readcodec(&csa->res, BA0_AC97_POWERDOWN, &tmp);
895 	csa_writecodec(&csa->res, BA0_AC97_POWERDOWN,
896 	    tmp | CS_AC97_POWER_CONTROL_MIXVON);
897 	/* ADC */
898 	csa_readcodec(&csa->res, BA0_AC97_POWERDOWN, &tmp);
899 	csa_writecodec(&csa->res, BA0_AC97_POWERDOWN,
900 	    tmp | CS_AC97_POWER_CONTROL_ADC);
901 	/* DAC */
902 	csa_readcodec(&csa->res, BA0_AC97_POWERDOWN, &tmp);
903 	csa_writecodec(&csa->res, BA0_AC97_POWERDOWN,
904 	    tmp | CS_AC97_POWER_CONTROL_DAC);
905 }
906 
907 static void
908 csa_ac97_resume(struct csa_info *csa)
909 {
910 	int count, i;
911 
912 	/*
913 	 * First, we restore the state of the general purpose register.  This
914 	 * contains the mic select (mic1 or mic2) and if we restore this after
915 	 * we restore the mic volume/boost state and mic2 was selected at
916 	 * suspend time, we will end up with a brief period of time where mic1
917 	 * is selected with the volume/boost settings for mic2, causing
918 	 * acoustic feedback.  So we restore the general purpose register
919 	 * first, thereby getting the correct mic selected before we restore
920 	 * the mic volume/boost.
921 	 */
922 	csa_writecodec(&csa->res, BA0_AC97_GENERAL_PURPOSE,
923 	    csa->ac97_general_purpose);
924 	/*
925 	 * Now, while the outputs are still muted, restore the state of power
926 	 * on the AC97 part.
927 	 */
928 	csa_writecodec(&csa->res, BA0_AC97_POWERDOWN, csa->ac97_powerdown);
929 	/*
930 	 * Restore just the first set of registers, from register number
931 	 * 0x02 to the register number that ulHighestRegToRestore specifies.
932 	 */
933 	for (count = 0x2, i=0;
934 	    (count <= CS461x_AC97_HIGHESTREGTORESTORE) &&
935 	    (i < CS461x_AC97_NUMBER_RESTORE_REGS);
936 	    count += 2, i++)
937 		csa_writecodec(&csa->res, BA0_AC97_RESET + count, csa->ac97[i]);
938 }
939 
940 static int
941 pcmcsa_suspend(device_t dev)
942 {
943 	struct csa_info *csa;
944 	csa_res *resp;
945 
946 	csa = pcm_getdevinfo(dev);
947 	resp = &csa->res;
948 
949 	csa_active(csa, 1);
950 
951 	/* playback interrupt disable */
952 	csa_writemem(resp, BA1_PFIE,
953 	    (csa_readmem(resp, BA1_PFIE) & ~0x0000f03f) | 0x00000010);
954 	/* capture interrupt disable */
955 	csa_writemem(resp, BA1_CIE,
956 	    (csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000011);
957 	csa_stopplaydma(csa);
958 	csa_stopcapturedma(csa);
959 
960 	csa_ac97_suspend(csa);
961 
962 	csa_resetdsp(resp);
963 
964 	csa_stopdsp(resp);
965 	/*
966 	 *  Power down the DAC and ADC.  For now leave the other areas on.
967 	 */
968 	csa_writecodec(&csa->res, BA0_AC97_POWERDOWN, 0x300);
969 	/*
970 	 *  Power down the PLL.
971 	 */
972 	csa_writemem(resp, BA0_CLKCR1, 0);
973 	/*
974 	 * Turn off the Processor by turning off the software clock
975 	 * enable flag in the clock control register.
976 	 */
977 	csa_writemem(resp, BA0_CLKCR1,
978 	    csa_readmem(resp, BA0_CLKCR1) & ~CLKCR1_SWCE);
979 
980 	csa_active(csa, -1);
981 
982 	return 0;
983 }
984 
985 static int
986 pcmcsa_resume(device_t dev)
987 {
988 	struct csa_info *csa;
989 	csa_res *resp;
990 
991 	csa = pcm_getdevinfo(dev);
992 	resp = &csa->res;
993 
994 	csa_active(csa, 1);
995 
996 	/* cs_hardware_init */
997 	csa_stopplaydma(csa);
998 	csa_stopcapturedma(csa);
999 	csa_ac97_resume(csa);
1000 	if (csa_startdsp(resp))
1001 		return (ENXIO);
1002 	/* Enable interrupts on the part. */
1003 	if ((csa_readio(resp, BA0_HISR) & HISR_INTENA) == 0)
1004 		csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
1005 	/* playback interrupt enable */
1006 	csa_writemem(resp, BA1_PFIE, csa_readmem(resp, BA1_PFIE) & ~0x0000f03f);
1007 	/* capture interrupt enable */
1008 	csa_writemem(resp, BA1_CIE,
1009 	    (csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000001);
1010 	/* cs_restart_part */
1011 	csa_setupchan(&csa->pch);
1012 	csa_startplaydma(csa);
1013 	csa_setupchan(&csa->rch);
1014 	csa_startcapturedma(csa);
1015 
1016 	csa_active(csa, -1);
1017 
1018 	return 0;
1019 }
1020 
1021 static device_method_t pcmcsa_methods[] = {
1022 	/* Device interface */
1023 	DEVMETHOD(device_probe , pcmcsa_probe ),
1024 	DEVMETHOD(device_attach, pcmcsa_attach),
1025 	DEVMETHOD(device_detach, pcmcsa_detach),
1026 	DEVMETHOD(device_suspend, pcmcsa_suspend),
1027 	DEVMETHOD(device_resume, pcmcsa_resume),
1028 
1029 	{ 0, 0 },
1030 };
1031 
1032 static driver_t pcmcsa_driver = {
1033 	"pcm",
1034 	pcmcsa_methods,
1035 	PCM_SOFTC_SIZE,
1036 };
1037 
1038 DRIVER_MODULE(snd_csapcm, csa, pcmcsa_driver, 0, 0);
1039 MODULE_DEPEND(snd_csapcm, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
1040 MODULE_DEPEND(snd_csapcm, snd_csa, 1, 1, 1);
1041 MODULE_VERSION(snd_csapcm, 1);
1042