csapcm.c revision 147626
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
41SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/csapcm.c 147626 2005-06-27 07:43:57Z glebius $");
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 */
49struct csa_info;
50
51struct 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
60struct 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 */
81static int      csa_init(struct csa_info *);
82static void     csa_intr(void *);
83static void	csa_setplaysamplerate(csa_res *resp, u_long ulInRate);
84static void	csa_setcapturesamplerate(csa_res *resp, u_long ulOutRate);
85static void	csa_startplaydma(struct csa_info *csa);
86static void	csa_startcapturedma(struct csa_info *csa);
87static void	csa_stopplaydma(struct csa_info *csa);
88static void	csa_stopcapturedma(struct csa_info *csa);
89static int	csa_startdsp(csa_res *resp);
90static int	csa_stopdsp(csa_res *resp);
91static int	csa_allocres(struct csa_info *scp, device_t dev);
92static void	csa_releaseres(struct csa_info *scp, device_t dev);
93static void	csa_ac97_suspend(struct csa_info *csa);
94static void	csa_ac97_resume(struct csa_info *csa);
95
96static 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};
107static struct pcmchan_caps csa_playcaps = {8000, 48000, csa_playfmt, 0};
108
109static u_int32_t csa_recfmt[] = {
110	AFMT_S16_LE,
111	AFMT_STEREO | AFMT_S16_LE,
112	0
113};
114static struct pcmchan_caps csa_reccaps = {11025, 48000, csa_recfmt, 0};
115
116/* -------------------------------------------------------------------- */
117
118static int
119csa_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
137static int
138csa_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
151static int
152csa_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
163static kobj_method_t csa_ac97_methods[] = {
164    	KOBJMETHOD(ac97_read,		csa_rdcd),
165    	KOBJMETHOD(ac97_write,		csa_wrcd),
166	{ 0, 0 }
167};
168AC97_DECLARE(csa_ac97);
169
170static void
171csa_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
216static void
217csa_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
330static void
331csa_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
346static void
347csa_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
362static void
363csa_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
389static void
390csa_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
416static int
417csa_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
463static int
464csa_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
475static int
476csa_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
527static void *
528csachan_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, CS461x_BUFFSIZE) != 0)
538		return NULL;
539	return ch;
540}
541
542static int
543csachan_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
551static int
552csachan_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
560static int
561csachan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
562{
563	return CS461x_BUFFSIZE / 2;
564}
565
566static int
567csachan_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 (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
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
592static int
593csachan_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
615static struct pcmchan_caps *
616csachan_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
622static 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};
632CHANNEL_DECLARE(csachan);
633
634/* -------------------------------------------------------------------- */
635/* The interrupt handler */
636static void
637csa_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
653static int
654csa_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
671	return 0;
672}
673
674/* Allocates resources. */
675static int
676csa_allocres(struct csa_info *csa, device_t dev)
677{
678	csa_res *resp;
679
680	resp = &csa->res;
681	if (resp->io == NULL) {
682		resp->io = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
683			&resp->io_rid, RF_ACTIVE);
684		if (resp->io == NULL)
685			return (1);
686	}
687	if (resp->mem == NULL) {
688		resp->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
689			&resp->mem_rid, RF_ACTIVE);
690		if (resp->mem == NULL)
691			return (1);
692	}
693	if (resp->irq == NULL) {
694		resp->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
695			&resp->irq_rid, RF_ACTIVE | RF_SHAREABLE);
696		if (resp->irq == NULL)
697			return (1);
698	}
699	if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/CS461x_BUFFSIZE, /*boundary*/CS461x_BUFFSIZE,
700			       /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
701			       /*highaddr*/BUS_SPACE_MAXADDR,
702			       /*filter*/NULL, /*filterarg*/NULL,
703			       /*maxsize*/CS461x_BUFFSIZE, /*nsegments*/1, /*maxsegz*/0x3ffff,
704			       /*flags*/0, /*lockfunc*/busdma_lock_mutex,
705			       /*lockarg*/&Giant, &csa->parent_dmat) != 0)
706		return (1);
707
708	return (0);
709}
710
711/* Releases resources. */
712static void
713csa_releaseres(struct csa_info *csa, device_t dev)
714{
715	csa_res *resp;
716
717	resp = &csa->res;
718	if (resp->irq != NULL) {
719		if (csa->ih)
720			bus_teardown_intr(dev, resp->irq, csa->ih);
721		bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq);
722		resp->irq = NULL;
723	}
724	if (resp->io != NULL) {
725		bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
726		resp->io = NULL;
727	}
728	if (resp->mem != NULL) {
729		bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
730		resp->mem = NULL;
731	}
732	if (csa->parent_dmat != NULL) {
733		bus_dma_tag_destroy(csa->parent_dmat);
734		csa->parent_dmat = NULL;
735	}
736	if (csa != NULL) {
737		free(csa, M_DEVBUF);
738		csa = NULL;
739	}
740}
741
742static int
743pcmcsa_probe(device_t dev)
744{
745	char *s;
746	struct sndcard_func *func;
747
748	/* The parent device has already been probed. */
749
750	func = device_get_ivars(dev);
751	if (func == NULL || func->func != SCF_PCM)
752		return (ENXIO);
753
754	s = "CS461x PCM Audio";
755
756	device_set_desc(dev, s);
757	return (0);
758}
759
760static int
761pcmcsa_attach(device_t dev)
762{
763	struct csa_info *csa;
764	csa_res *resp;
765	int unit;
766	char status[SND_STATUSLEN];
767	struct ac97_info *codec;
768	struct sndcard_func *func;
769
770	csa = malloc(sizeof(*csa), M_DEVBUF, M_NOWAIT | M_ZERO);
771	if (csa == NULL)
772		return (ENOMEM);
773	unit = device_get_unit(dev);
774	func = device_get_ivars(dev);
775	csa->binfo = func->varinfo;
776	/*
777	 * Fake the status of DMA so that the initial value of
778	 * PCTL and CCTL can be stored into csa->pctl and csa->cctl,
779	 * respectively.
780	 */
781	csa->pch.dma = csa->rch.dma = 1;
782	csa->active = 0;
783	csa->card = csa->binfo->card;
784
785	/* Allocate the resources. */
786	resp = &csa->res;
787	resp->io_rid = PCIR_BAR(0);
788	resp->mem_rid = PCIR_BAR(1);
789	resp->irq_rid = 0;
790	if (csa_allocres(csa, dev)) {
791		csa_releaseres(csa, dev);
792		return (ENXIO);
793	}
794
795	csa_active(csa, 1);
796	if (csa_init(csa)) {
797		csa_releaseres(csa, dev);
798		return (ENXIO);
799	}
800	codec = AC97_CREATE(dev, csa, csa_ac97);
801	if (codec == NULL) {
802		csa_releaseres(csa, dev);
803		return (ENXIO);
804	}
805	if (csa->card->inv_eapd)
806		ac97_setflags(codec, AC97_F_EAPD_INV);
807	if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) {
808		ac97_destroy(codec);
809		csa_releaseres(csa, dev);
810		return (ENXIO);
811	}
812
813	snprintf(status, SND_STATUSLEN, "at irq %ld %s",
814			rman_get_start(resp->irq),PCM_KLDSTRING(snd_csa));
815
816	/* Enable interrupt. */
817	if (snd_setup_intr(dev, resp->irq, 0, csa_intr, csa, &csa->ih)) {
818		ac97_destroy(codec);
819		csa_releaseres(csa, dev);
820		return (ENXIO);
821	}
822	csa_writemem(resp, BA1_PFIE, csa_readmem(resp, BA1_PFIE) & ~0x0000f03f);
823	csa_writemem(resp, BA1_CIE, (csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000001);
824	csa_active(csa, -1);
825
826	if (pcm_register(dev, csa, 1, 1)) {
827		ac97_destroy(codec);
828		csa_releaseres(csa, dev);
829		return (ENXIO);
830	}
831	pcm_addchan(dev, PCMDIR_REC, &csachan_class, csa);
832	pcm_addchan(dev, PCMDIR_PLAY, &csachan_class, csa);
833	pcm_setstatus(dev, status);
834
835	return (0);
836}
837
838static int
839pcmcsa_detach(device_t dev)
840{
841	int r;
842	struct csa_info *csa;
843
844	r = pcm_unregister(dev);
845	if (r)
846		return r;
847
848	csa = pcm_getdevinfo(dev);
849	csa_releaseres(csa, dev);
850
851	return 0;
852}
853
854static void
855csa_ac97_suspend(struct csa_info *csa)
856{
857	int count, i;
858	uint32_t tmp;
859
860	for (count = 0x2, i=0;
861	    (count <= CS461x_AC97_HIGHESTREGTORESTORE) &&
862	    (i < CS461x_AC97_NUMBER_RESTORE_REGS);
863	    count += 2, i++)
864		csa_readcodec(&csa->res, BA0_AC97_RESET + count, &csa->ac97[i]);
865
866	/* mute the outputs */
867	csa_writecodec(&csa->res, BA0_AC97_MASTER_VOLUME, 0x8000);
868	csa_writecodec(&csa->res, BA0_AC97_HEADPHONE_VOLUME, 0x8000);
869	csa_writecodec(&csa->res, BA0_AC97_MASTER_VOLUME_MONO, 0x8000);
870	csa_writecodec(&csa->res, BA0_AC97_PCM_OUT_VOLUME, 0x8000);
871	/* save the registers that cause pops */
872	csa_readcodec(&csa->res, BA0_AC97_POWERDOWN, &csa->ac97_powerdown);
873	csa_readcodec(&csa->res, BA0_AC97_GENERAL_PURPOSE,
874	    &csa->ac97_general_purpose);
875
876	/*
877	 * And power down everything on the AC97 codec. Well, for now,
878	 * only power down the DAC/ADC and MIXER VREFON components.
879	 * trouble with removing VREF.
880	 */
881
882	/* MIXVON */
883	csa_readcodec(&csa->res, BA0_AC97_POWERDOWN, &tmp);
884	csa_writecodec(&csa->res, BA0_AC97_POWERDOWN,
885	    tmp | CS_AC97_POWER_CONTROL_MIXVON);
886	/* ADC */
887	csa_readcodec(&csa->res, BA0_AC97_POWERDOWN, &tmp);
888	csa_writecodec(&csa->res, BA0_AC97_POWERDOWN,
889	    tmp | CS_AC97_POWER_CONTROL_ADC);
890	/* DAC */
891	csa_readcodec(&csa->res, BA0_AC97_POWERDOWN, &tmp);
892	csa_writecodec(&csa->res, BA0_AC97_POWERDOWN,
893	    tmp | CS_AC97_POWER_CONTROL_DAC);
894}
895
896static void
897csa_ac97_resume(struct csa_info *csa)
898{
899	int count, i;
900
901	/*
902	 * First, we restore the state of the general purpose register.  This
903	 * contains the mic select (mic1 or mic2) and if we restore this after
904	 * we restore the mic volume/boost state and mic2 was selected at
905	 * suspend time, we will end up with a brief period of time where mic1
906	 * is selected with the volume/boost settings for mic2, causing
907	 * acoustic feedback.  So we restore the general purpose register
908	 * first, thereby getting the correct mic selected before we restore
909	 * the mic volume/boost.
910	 */
911	csa_writecodec(&csa->res, BA0_AC97_GENERAL_PURPOSE,
912	    csa->ac97_general_purpose);
913	/*
914	 * Now, while the outputs are still muted, restore the state of power
915	 * on the AC97 part.
916	 */
917	csa_writecodec(&csa->res, BA0_AC97_POWERDOWN, csa->ac97_powerdown);
918	/*
919	 * Restore just the first set of registers, from register number
920	 * 0x02 to the register number that ulHighestRegToRestore specifies.
921	 */
922	for (count = 0x2, i=0;
923	    (count <= CS461x_AC97_HIGHESTREGTORESTORE) &&
924	    (i < CS461x_AC97_NUMBER_RESTORE_REGS);
925	    count += 2, i++)
926		csa_writecodec(&csa->res, BA0_AC97_RESET + count, csa->ac97[i]);
927}
928
929static int
930pcmcsa_suspend(device_t dev)
931{
932	struct csa_info *csa;
933	csa_res *resp;
934
935	csa = pcm_getdevinfo(dev);
936	resp = &csa->res;
937
938	csa_active(csa, 1);
939
940	/* playback interrupt disable */
941	csa_writemem(resp, BA1_PFIE,
942	    (csa_readmem(resp, BA1_PFIE) & ~0x0000f03f) | 0x00000010);
943	/* capture interrupt disable */
944	csa_writemem(resp, BA1_CIE,
945	    (csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000011);
946	csa_stopplaydma(csa);
947	csa_stopcapturedma(csa);
948
949	csa_ac97_suspend(csa);
950
951	csa_resetdsp(resp);
952
953	csa_stopdsp(resp);
954	/*
955	 *  Power down the DAC and ADC.  For now leave the other areas on.
956	 */
957	csa_writecodec(&csa->res, BA0_AC97_POWERDOWN, 0x300);
958	/*
959	 *  Power down the PLL.
960	 */
961	csa_writemem(resp, BA0_CLKCR1, 0);
962	/*
963	 * Turn off the Processor by turning off the software clock
964	 * enable flag in the clock control register.
965	 */
966	csa_writemem(resp, BA0_CLKCR1,
967	    csa_readmem(resp, BA0_CLKCR1) & ~CLKCR1_SWCE);
968
969	csa_active(csa, -1);
970
971	return 0;
972}
973
974static int
975pcmcsa_resume(device_t dev)
976{
977	struct csa_info *csa;
978	csa_res *resp;
979
980	csa = pcm_getdevinfo(dev);
981	resp = &csa->res;
982
983	csa_active(csa, 1);
984
985	/* cs_hardware_init */
986	csa_stopplaydma(csa);
987	csa_stopcapturedma(csa);
988	csa_ac97_resume(csa);
989	if (csa_startdsp(resp))
990		return (ENXIO);
991	/* Enable interrupts on the part. */
992	if ((csa_readio(resp, BA0_HISR) & HISR_INTENA) == 0)
993		csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
994	/* playback interrupt enable */
995	csa_writemem(resp, BA1_PFIE, csa_readmem(resp, BA1_PFIE) & ~0x0000f03f);
996	/* capture interrupt enable */
997	csa_writemem(resp, BA1_CIE,
998	    (csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000001);
999	/* cs_restart_part */
1000	csa_setupchan(&csa->pch);
1001	csa_startplaydma(csa);
1002	csa_setupchan(&csa->rch);
1003	csa_startcapturedma(csa);
1004
1005	csa_active(csa, -1);
1006
1007	return 0;
1008}
1009
1010static device_method_t pcmcsa_methods[] = {
1011	/* Device interface */
1012	DEVMETHOD(device_probe , pcmcsa_probe ),
1013	DEVMETHOD(device_attach, pcmcsa_attach),
1014	DEVMETHOD(device_detach, pcmcsa_detach),
1015	DEVMETHOD(device_suspend, pcmcsa_suspend),
1016	DEVMETHOD(device_resume, pcmcsa_resume),
1017
1018	{ 0, 0 },
1019};
1020
1021static driver_t pcmcsa_driver = {
1022	"pcm",
1023	pcmcsa_methods,
1024	PCM_SOFTC_SIZE,
1025};
1026
1027DRIVER_MODULE(snd_csapcm, csa, pcmcsa_driver, pcm_devclass, 0, 0);
1028MODULE_DEPEND(snd_csapcm, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
1029MODULE_DEPEND(snd_csapcm, snd_csa, 1, 1, 1);
1030MODULE_VERSION(snd_csapcm, 1);
1031