csapcm.c revision 126695
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 126695 2004-03-06 15:52:42Z matk $");
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};
74
75/* -------------------------------------------------------------------- */
76
77/* prototypes */
78static int      csa_init(struct csa_info *);
79static void     csa_intr(void *);
80static void	csa_setplaysamplerate(csa_res *resp, u_long ulInRate);
81static void	csa_setcapturesamplerate(csa_res *resp, u_long ulOutRate);
82static void	csa_startplaydma(struct csa_info *csa);
83static void	csa_startcapturedma(struct csa_info *csa);
84static void	csa_stopplaydma(struct csa_info *csa);
85static void	csa_stopcapturedma(struct csa_info *csa);
86static int	csa_startdsp(csa_res *resp);
87static int	csa_allocres(struct csa_info *scp, device_t dev);
88static void	csa_releaseres(struct csa_info *scp, device_t dev);
89
90static u_int32_t csa_playfmt[] = {
91	AFMT_U8,
92	AFMT_STEREO | AFMT_U8,
93	AFMT_S8,
94	AFMT_STEREO | AFMT_S8,
95	AFMT_S16_LE,
96	AFMT_STEREO | AFMT_S16_LE,
97	AFMT_S16_BE,
98	AFMT_STEREO | AFMT_S16_BE,
99	0
100};
101static struct pcmchan_caps csa_playcaps = {8000, 48000, csa_playfmt, 0};
102
103static u_int32_t csa_recfmt[] = {
104	AFMT_S16_LE,
105	AFMT_STEREO | AFMT_S16_LE,
106	0
107};
108static struct pcmchan_caps csa_reccaps = {11025, 48000, csa_recfmt, 0};
109
110/* -------------------------------------------------------------------- */
111
112static int
113csa_active(struct csa_info *csa, int run)
114{
115	int old, go;
116
117	old = csa->active;
118	csa->active += run;
119
120	if ((csa->active == 0 && old == 1) || (csa->active == 1 && old == 0)) {
121		go = csa->active;
122		if (csa->card->active)
123			return csa->card->active(go);
124	}
125	return 0;
126}
127
128/* -------------------------------------------------------------------- */
129/* ac97 codec */
130
131static int
132csa_rdcd(kobj_t obj, void *devinfo, int regno)
133{
134	u_int32_t data;
135	struct csa_info *csa = (struct csa_info *)devinfo;
136
137	csa_active(csa, 1);
138	if (csa_readcodec(&csa->res, regno + BA0_AC97_RESET, &data))
139		data = 0;
140	csa_active(csa, -1);
141
142	return data;
143}
144
145static int
146csa_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data)
147{
148	struct csa_info *csa = (struct csa_info *)devinfo;
149
150	csa_active(csa, 1);
151	csa_writecodec(&csa->res, regno + BA0_AC97_RESET, data);
152	csa_active(csa, -1);
153
154	return 0;
155}
156
157static kobj_method_t csa_ac97_methods[] = {
158    	KOBJMETHOD(ac97_read,		csa_rdcd),
159    	KOBJMETHOD(ac97_write,		csa_wrcd),
160	{ 0, 0 }
161};
162AC97_DECLARE(csa_ac97);
163
164static void
165csa_setplaysamplerate(csa_res *resp, u_long ulInRate)
166{
167	u_long ulTemp1, ulTemp2;
168	u_long ulPhiIncr;
169	u_long ulCorrectionPerGOF, ulCorrectionPerSec;
170	u_long ulOutRate;
171
172	ulOutRate = 48000;
173
174	/*
175	 * Compute the values used to drive the actual sample rate conversion.
176	 * The following formulas are being computed, using inline assembly
177	 * since we need to use 64 bit arithmetic to compute the values:
178	 *
179	 *     ulPhiIncr = floor((Fs,in * 2^26) / Fs,out)
180	 *     ulCorrectionPerGOF = floor((Fs,in * 2^26 - Fs,out * ulPhiIncr) /
181	 *                                GOF_PER_SEC)
182	 *     ulCorrectionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -
183	 *                          GOF_PER_SEC * ulCorrectionPerGOF
184	 *
185	 * i.e.
186	 *
187	 *     ulPhiIncr:ulOther = dividend:remainder((Fs,in * 2^26) / Fs,out)
188	 *     ulCorrectionPerGOF:ulCorrectionPerSec =
189	 *         dividend:remainder(ulOther / GOF_PER_SEC)
190	 */
191	ulTemp1 = ulInRate << 16;
192	ulPhiIncr = ulTemp1 / ulOutRate;
193	ulTemp1 -= ulPhiIncr * ulOutRate;
194	ulTemp1 <<= 10;
195	ulPhiIncr <<= 10;
196	ulTemp2 = ulTemp1 / ulOutRate;
197	ulPhiIncr += ulTemp2;
198	ulTemp1 -= ulTemp2 * ulOutRate;
199	ulCorrectionPerGOF = ulTemp1 / GOF_PER_SEC;
200	ulTemp1 -= ulCorrectionPerGOF * GOF_PER_SEC;
201	ulCorrectionPerSec = ulTemp1;
202
203	/*
204	 * Fill in the SampleRateConverter control block.
205	 */
206	csa_writemem(resp, BA1_PSRC, ((ulCorrectionPerSec << 16) & 0xFFFF0000) | (ulCorrectionPerGOF & 0xFFFF));
207	csa_writemem(resp, BA1_PPI, ulPhiIncr);
208}
209
210static void
211csa_setcapturesamplerate(csa_res *resp, u_long ulOutRate)
212{
213	u_long ulPhiIncr, ulCoeffIncr, ulTemp1, ulTemp2;
214	u_long ulCorrectionPerGOF, ulCorrectionPerSec, ulInitialDelay;
215	u_long dwFrameGroupLength, dwCnt;
216	u_long ulInRate;
217
218	ulInRate = 48000;
219
220	/*
221	 * We can only decimate by up to a factor of 1/9th the hardware rate.
222	 * Return an error if an attempt is made to stray outside that limit.
223	 */
224	if((ulOutRate * 9) < ulInRate)
225		return;
226
227	/*
228	 * We can not capture at at rate greater than the Input Rate (48000).
229	 * Return an error if an attempt is made to stray outside that limit.
230	 */
231	if(ulOutRate > ulInRate)
232		return;
233
234	/*
235	 * Compute the values used to drive the actual sample rate conversion.
236	 * The following formulas are being computed, using inline assembly
237	 * since we need to use 64 bit arithmetic to compute the values:
238	 *
239	 *     ulCoeffIncr = -floor((Fs,out * 2^23) / Fs,in)
240	 *     ulPhiIncr = floor((Fs,in * 2^26) / Fs,out)
241	 *     ulCorrectionPerGOF = floor((Fs,in * 2^26 - Fs,out * ulPhiIncr) /
242	 *                                GOF_PER_SEC)
243	 *     ulCorrectionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -
244	 *                          GOF_PER_SEC * ulCorrectionPerGOF
245	 *     ulInitialDelay = ceil((24 * Fs,in) / Fs,out)
246	 *
247	 * i.e.
248	 *
249	 *     ulCoeffIncr = neg(dividend((Fs,out * 2^23) / Fs,in))
250	 *     ulPhiIncr:ulOther = dividend:remainder((Fs,in * 2^26) / Fs,out)
251	 *     ulCorrectionPerGOF:ulCorrectionPerSec =
252	 *         dividend:remainder(ulOther / GOF_PER_SEC)
253	 *     ulInitialDelay = dividend(((24 * Fs,in) + Fs,out - 1) / Fs,out)
254	 */
255	ulTemp1 = ulOutRate << 16;
256	ulCoeffIncr = ulTemp1 / ulInRate;
257	ulTemp1 -= ulCoeffIncr * ulInRate;
258	ulTemp1 <<= 7;
259	ulCoeffIncr <<= 7;
260	ulCoeffIncr += ulTemp1 / ulInRate;
261	ulCoeffIncr ^= 0xFFFFFFFF;
262	ulCoeffIncr++;
263	ulTemp1 = ulInRate << 16;
264	ulPhiIncr = ulTemp1 / ulOutRate;
265	ulTemp1 -= ulPhiIncr * ulOutRate;
266	ulTemp1 <<= 10;
267	ulPhiIncr <<= 10;
268	ulTemp2 = ulTemp1 / ulOutRate;
269	ulPhiIncr += ulTemp2;
270	ulTemp1 -= ulTemp2 * ulOutRate;
271	ulCorrectionPerGOF = ulTemp1 / GOF_PER_SEC;
272	ulTemp1 -= ulCorrectionPerGOF * GOF_PER_SEC;
273	ulCorrectionPerSec = ulTemp1;
274	ulInitialDelay = ((ulInRate * 24) + ulOutRate - 1) / ulOutRate;
275
276	/*
277	 * Fill in the VariDecimate control block.
278	 */
279	csa_writemem(resp, BA1_CSRC,
280		     ((ulCorrectionPerSec << 16) & 0xFFFF0000) | (ulCorrectionPerGOF & 0xFFFF));
281	csa_writemem(resp, BA1_CCI, ulCoeffIncr);
282	csa_writemem(resp, BA1_CD,
283	     (((BA1_VARIDEC_BUF_1 + (ulInitialDelay << 2)) << 16) & 0xFFFF0000) | 0x80);
284	csa_writemem(resp, BA1_CPI, ulPhiIncr);
285
286	/*
287	 * Figure out the frame group length for the write back task.  Basically,
288	 * this is just the factors of 24000 (2^6*3*5^3) that are not present in
289	 * the output sample rate.
290	 */
291	dwFrameGroupLength = 1;
292	for(dwCnt = 2; dwCnt <= 64; dwCnt *= 2)
293	{
294		if(((ulOutRate / dwCnt) * dwCnt) !=
295		   ulOutRate)
296		{
297			dwFrameGroupLength *= 2;
298		}
299	}
300	if(((ulOutRate / 3) * 3) !=
301	   ulOutRate)
302	{
303		dwFrameGroupLength *= 3;
304	}
305	for(dwCnt = 5; dwCnt <= 125; dwCnt *= 5)
306	{
307		if(((ulOutRate / dwCnt) * dwCnt) !=
308		   ulOutRate)
309		{
310			dwFrameGroupLength *= 5;
311		}
312	}
313
314	/*
315	 * Fill in the WriteBack control block.
316	 */
317	csa_writemem(resp, BA1_CFG1, dwFrameGroupLength);
318	csa_writemem(resp, BA1_CFG2, (0x00800000 | dwFrameGroupLength));
319	csa_writemem(resp, BA1_CCST, 0x0000FFFF);
320	csa_writemem(resp, BA1_CSPB, ((65536 * ulOutRate) / 24000));
321	csa_writemem(resp, (BA1_CSPB + 4), 0x0000FFFF);
322}
323
324static void
325csa_startplaydma(struct csa_info *csa)
326{
327	csa_res *resp;
328	u_long ul;
329
330	if (!csa->pch.dma) {
331		resp = &csa->res;
332		ul = csa_readmem(resp, BA1_PCTL);
333		ul &= 0x0000ffff;
334		csa_writemem(resp, BA1_PCTL, ul | csa->pctl);
335		csa_writemem(resp, BA1_PVOL, 0x80008000);
336		csa->pch.dma = 1;
337	}
338}
339
340static void
341csa_startcapturedma(struct csa_info *csa)
342{
343	csa_res *resp;
344	u_long ul;
345
346	if (!csa->rch.dma) {
347		resp = &csa->res;
348		ul = csa_readmem(resp, BA1_CCTL);
349		ul &= 0xffff0000;
350		csa_writemem(resp, BA1_CCTL, ul | csa->cctl);
351		csa_writemem(resp, BA1_CVOL, 0x80008000);
352		csa->rch.dma = 1;
353	}
354}
355
356static void
357csa_stopplaydma(struct csa_info *csa)
358{
359	csa_res *resp;
360	u_long ul;
361
362	if (csa->pch.dma) {
363		resp = &csa->res;
364		ul = csa_readmem(resp, BA1_PCTL);
365		csa->pctl = ul & 0xffff0000;
366		csa_writemem(resp, BA1_PCTL, ul & 0x0000ffff);
367		csa_writemem(resp, BA1_PVOL, 0xffffffff);
368		csa->pch.dma = 0;
369
370		/*
371		 * The bitwise pointer of the serial FIFO in the DSP
372		 * seems to make an error upon starting or stopping the
373		 * DSP. Clear the FIFO and correct the pointer if we
374		 * are not capturing.
375		 */
376		if (!csa->rch.dma) {
377			csa_clearserialfifos(resp);
378			csa_writeio(resp, BA0_SERBSP, 0);
379		}
380	}
381}
382
383static void
384csa_stopcapturedma(struct csa_info *csa)
385{
386	csa_res *resp;
387	u_long ul;
388
389	if (csa->rch.dma) {
390		resp = &csa->res;
391		ul = csa_readmem(resp, BA1_CCTL);
392		csa->cctl = ul & 0x0000ffff;
393		csa_writemem(resp, BA1_CCTL, ul & 0xffff0000);
394		csa_writemem(resp, BA1_CVOL, 0xffffffff);
395		csa->rch.dma = 0;
396
397		/*
398		 * The bitwise pointer of the serial FIFO in the DSP
399		 * seems to make an error upon starting or stopping the
400		 * DSP. Clear the FIFO and correct the pointer if we
401		 * are not playing.
402		 */
403		if (!csa->pch.dma) {
404			csa_clearserialfifos(resp);
405			csa_writeio(resp, BA0_SERBSP, 0);
406		}
407	}
408}
409
410static int
411csa_startdsp(csa_res *resp)
412{
413	int i;
414	u_long ul;
415
416	/*
417	 * Set the frame timer to reflect the number of cycles per frame.
418	 */
419	csa_writemem(resp, BA1_FRMT, 0xadf);
420
421	/*
422	 * Turn on the run, run at frame, and DMA enable bits in the local copy of
423	 * the SP control register.
424	 */
425	csa_writemem(resp, BA1_SPCR, SPCR_RUN | SPCR_RUNFR | SPCR_DRQEN);
426
427	/*
428	 * Wait until the run at frame bit resets itself in the SP control
429	 * register.
430	 */
431	ul = 0;
432	for (i = 0 ; i < 25 ; i++) {
433		/*
434		 * Wait a little bit, so we don't issue PCI reads too frequently.
435		 */
436		DELAY(50);
437		/*
438		 * Fetch the current value of the SP status register.
439		 */
440		ul = csa_readmem(resp, BA1_SPCR);
441
442		/*
443		 * If the run at frame bit has reset, then stop waiting.
444		 */
445		if((ul & SPCR_RUNFR) == 0)
446			break;
447	}
448	/*
449	 * If the run at frame bit never reset, then return an error.
450	 */
451	if((ul & SPCR_RUNFR) != 0)
452		return (EAGAIN);
453
454	return (0);
455}
456
457static int
458csa_setupchan(struct csa_chinfo *ch)
459{
460	struct csa_info *csa = ch->parent;
461	csa_res *resp = &csa->res;
462	u_long pdtc, tmp;
463
464	if (ch->dir == PCMDIR_PLAY) {
465		/* direction */
466		csa_writemem(resp, BA1_PBA, sndbuf_getbufaddr(ch->buffer));
467
468		/* format */
469		csa->pfie = csa_readmem(resp, BA1_PFIE) & ~0x0000f03f;
470		if (!(ch->fmt & AFMT_SIGNED))
471			csa->pfie |= 0x8000;
472		if (ch->fmt & AFMT_BIGENDIAN)
473			csa->pfie |= 0x4000;
474		if (!(ch->fmt & AFMT_STEREO))
475			csa->pfie |= 0x2000;
476		if (ch->fmt & AFMT_8BIT)
477			csa->pfie |= 0x1000;
478		csa_writemem(resp, BA1_PFIE, csa->pfie);
479
480		tmp = 4;
481		if (ch->fmt & AFMT_16BIT)
482			tmp <<= 1;
483		if (ch->fmt & AFMT_STEREO)
484			tmp <<= 1;
485		tmp--;
486
487		pdtc = csa_readmem(resp, BA1_PDTC) & ~0x000001ff;
488		pdtc |= tmp;
489		csa_writemem(resp, BA1_PDTC, pdtc);
490
491		/* rate */
492		csa_setplaysamplerate(resp, ch->spd);
493	} else if (ch->dir == PCMDIR_REC) {
494		/* direction */
495		csa_writemem(resp, BA1_CBA, sndbuf_getbufaddr(ch->buffer));
496
497		/* format */
498		csa_writemem(resp, BA1_CIE, (csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000001);
499
500		/* rate */
501		csa_setcapturesamplerate(resp, ch->spd);
502	}
503	return 0;
504}
505
506/* -------------------------------------------------------------------- */
507/* channel interface */
508
509static void *
510csachan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
511{
512	struct csa_info *csa = devinfo;
513	struct csa_chinfo *ch = (dir == PCMDIR_PLAY)? &csa->pch : &csa->rch;
514
515	ch->parent = csa;
516	ch->channel = c;
517	ch->buffer = b;
518	ch->dir = dir;
519	if (sndbuf_alloc(ch->buffer, csa->parent_dmat, CS461x_BUFFSIZE) == -1) return NULL;
520	return ch;
521}
522
523static int
524csachan_setformat(kobj_t obj, void *data, u_int32_t format)
525{
526	struct csa_chinfo *ch = data;
527
528	ch->fmt = format;
529	return 0;
530}
531
532static int
533csachan_setspeed(kobj_t obj, void *data, u_int32_t speed)
534{
535	struct csa_chinfo *ch = data;
536
537	ch->spd = speed;
538	return ch->spd; /* XXX calc real speed */
539}
540
541static int
542csachan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
543{
544	return CS461x_BUFFSIZE / 2;
545}
546
547static int
548csachan_trigger(kobj_t obj, void *data, int go)
549{
550	struct csa_chinfo *ch = data;
551	struct csa_info *csa = ch->parent;
552
553	if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
554		return 0;
555
556	if (go == PCMTRIG_START) {
557		csa_active(csa, 1);
558		csa_setupchan(ch);
559		if (ch->dir == PCMDIR_PLAY)
560			csa_startplaydma(csa);
561		else
562			csa_startcapturedma(csa);
563	} else {
564		if (ch->dir == PCMDIR_PLAY)
565			csa_stopplaydma(csa);
566		else
567			csa_stopcapturedma(csa);
568		csa_active(csa, -1);
569	}
570	return 0;
571}
572
573static int
574csachan_getptr(kobj_t obj, void *data)
575{
576	struct csa_chinfo *ch = data;
577	struct csa_info *csa = ch->parent;
578	csa_res *resp;
579	int ptr;
580
581	resp = &csa->res;
582
583	if (ch->dir == PCMDIR_PLAY) {
584		ptr = csa_readmem(resp, BA1_PBA) - sndbuf_getbufaddr(ch->buffer);
585		if ((ch->fmt & AFMT_U8) != 0 || (ch->fmt & AFMT_S8) != 0)
586			ptr >>= 1;
587	} else {
588		ptr = csa_readmem(resp, BA1_CBA) - sndbuf_getbufaddr(ch->buffer);
589		if ((ch->fmt & AFMT_U8) != 0 || (ch->fmt & AFMT_S8) != 0)
590			ptr >>= 1;
591	}
592
593	return (ptr);
594}
595
596static struct pcmchan_caps *
597csachan_getcaps(kobj_t obj, void *data)
598{
599	struct csa_chinfo *ch = data;
600	return (ch->dir == PCMDIR_PLAY)? &csa_playcaps : &csa_reccaps;
601}
602
603static kobj_method_t csachan_methods[] = {
604    	KOBJMETHOD(channel_init,		csachan_init),
605    	KOBJMETHOD(channel_setformat,		csachan_setformat),
606    	KOBJMETHOD(channel_setspeed,		csachan_setspeed),
607    	KOBJMETHOD(channel_setblocksize,	csachan_setblocksize),
608    	KOBJMETHOD(channel_trigger,		csachan_trigger),
609    	KOBJMETHOD(channel_getptr,		csachan_getptr),
610    	KOBJMETHOD(channel_getcaps,		csachan_getcaps),
611	{ 0, 0 }
612};
613CHANNEL_DECLARE(csachan);
614
615/* -------------------------------------------------------------------- */
616/* The interrupt handler */
617static void
618csa_intr(void *p)
619{
620	struct csa_info *csa = p;
621
622	if ((csa->binfo->hisr & HISR_VC0) != 0)
623		chn_intr(csa->pch.channel);
624	if ((csa->binfo->hisr & HISR_VC1) != 0)
625		chn_intr(csa->rch.channel);
626}
627
628/* -------------------------------------------------------------------- */
629
630/*
631 * Probe and attach the card
632 */
633
634static int
635csa_init(struct csa_info *csa)
636{
637	csa_res *resp;
638
639	resp = &csa->res;
640
641	csa->pfie = 0;
642	csa_stopplaydma(csa);
643	csa_stopcapturedma(csa);
644
645	if (csa_startdsp(resp))
646		return (1);
647
648	/* Crank up the power on the DAC and ADC. */
649	csa_setplaysamplerate(resp, 8000);
650	csa_setcapturesamplerate(resp, 8000);
651
652	return 0;
653}
654
655/* Allocates resources. */
656static int
657csa_allocres(struct csa_info *csa, device_t dev)
658{
659	csa_res *resp;
660
661	resp = &csa->res;
662	if (resp->io == NULL) {
663		resp->io = bus_alloc_resource(dev, SYS_RES_MEMORY, &resp->io_rid, 0, ~0, 1, RF_ACTIVE);
664		if (resp->io == NULL)
665			return (1);
666	}
667	if (resp->mem == NULL) {
668		resp->mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &resp->mem_rid, 0, ~0, 1, RF_ACTIVE);
669		if (resp->mem == NULL)
670			return (1);
671	}
672	if (resp->irq == NULL) {
673		resp->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &resp->irq_rid, 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
674		if (resp->irq == NULL)
675			return (1);
676	}
677	if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/CS461x_BUFFSIZE, /*boundary*/CS461x_BUFFSIZE,
678			       /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
679			       /*highaddr*/BUS_SPACE_MAXADDR,
680			       /*filter*/NULL, /*filterarg*/NULL,
681			       /*maxsize*/CS461x_BUFFSIZE, /*nsegments*/1, /*maxsegz*/0x3ffff,
682			       /*flags*/0, /*lockfunc*/busdma_lock_mutex,
683			       /*lockarg*/&Giant, &csa->parent_dmat) != 0)
684		return (1);
685
686	return (0);
687}
688
689/* Releases resources. */
690static void
691csa_releaseres(struct csa_info *csa, device_t dev)
692{
693	csa_res *resp;
694
695	resp = &csa->res;
696	if (resp->irq != NULL) {
697		if (csa->ih)
698			bus_teardown_intr(dev, resp->irq, csa->ih);
699		bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq);
700		resp->irq = NULL;
701	}
702	if (resp->io != NULL) {
703		bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
704		resp->io = NULL;
705	}
706	if (resp->mem != NULL) {
707		bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
708		resp->mem = NULL;
709	}
710	if (csa->parent_dmat != NULL) {
711		bus_dma_tag_destroy(csa->parent_dmat);
712		csa->parent_dmat = NULL;
713	}
714	if (csa != NULL) {
715		free(csa, M_DEVBUF);
716		csa = NULL;
717	}
718}
719
720static int
721pcmcsa_probe(device_t dev)
722{
723	char *s;
724	struct sndcard_func *func;
725
726	/* The parent device has already been probed. */
727
728	func = device_get_ivars(dev);
729	if (func == NULL || func->func != SCF_PCM)
730		return (ENXIO);
731
732	s = "CS461x PCM Audio";
733
734	device_set_desc(dev, s);
735	return (0);
736}
737
738static int
739pcmcsa_attach(device_t dev)
740{
741	struct csa_info *csa;
742	csa_res *resp;
743	int unit;
744	char status[SND_STATUSLEN];
745	struct ac97_info *codec;
746	struct sndcard_func *func;
747
748	csa = malloc(sizeof(*csa), M_DEVBUF, M_NOWAIT | M_ZERO);
749	if (csa == NULL)
750		return (ENOMEM);
751	unit = device_get_unit(dev);
752	func = device_get_ivars(dev);
753	csa->binfo = func->varinfo;
754	/*
755	 * Fake the status of DMA so that the initial value of
756	 * PCTL and CCTL can be stored into csa->pctl and csa->cctl,
757	 * respectively.
758	 */
759	csa->pch.dma = csa->rch.dma = 1;
760	csa->active = 0;
761	csa->card = csa->binfo->card;
762
763	/* Allocate the resources. */
764	resp = &csa->res;
765	resp->io_rid = PCIR_BAR(0);
766	resp->mem_rid = PCIR_BAR(1);
767	resp->irq_rid = 0;
768	if (csa_allocres(csa, dev)) {
769		csa_releaseres(csa, dev);
770		return (ENXIO);
771	}
772
773	csa_active(csa, 1);
774	if (csa_init(csa)) {
775		csa_releaseres(csa, dev);
776		return (ENXIO);
777	}
778	codec = AC97_CREATE(dev, csa, csa_ac97);
779	if (codec == NULL) {
780		csa_releaseres(csa, dev);
781		return (ENXIO);
782	}
783	if (csa->card->inv_eapd)
784		ac97_setflags(codec, AC97_F_EAPD_INV);
785	if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) {
786		ac97_destroy(codec);
787		csa_releaseres(csa, dev);
788		return (ENXIO);
789	}
790
791	snprintf(status, SND_STATUSLEN, "at irq %ld %s",
792			rman_get_start(resp->irq),PCM_KLDSTRING(snd_csa));
793
794	/* Enable interrupt. */
795	if (snd_setup_intr(dev, resp->irq, INTR_MPSAFE, csa_intr, csa, &csa->ih)) {
796		ac97_destroy(codec);
797		csa_releaseres(csa, dev);
798		return (ENXIO);
799	}
800	csa_writemem(resp, BA1_PFIE, csa_readmem(resp, BA1_PFIE) & ~0x0000f03f);
801	csa_writemem(resp, BA1_CIE, (csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000001);
802	csa_active(csa, -1);
803
804	if (pcm_register(dev, csa, 1, 1)) {
805		ac97_destroy(codec);
806		csa_releaseres(csa, dev);
807		return (ENXIO);
808	}
809	pcm_addchan(dev, PCMDIR_REC, &csachan_class, csa);
810	pcm_addchan(dev, PCMDIR_PLAY, &csachan_class, csa);
811	pcm_setstatus(dev, status);
812
813	return (0);
814}
815
816static int
817pcmcsa_detach(device_t dev)
818{
819	int r;
820	struct csa_info *csa;
821
822	r = pcm_unregister(dev);
823	if (r)
824		return r;
825
826	csa = pcm_getdevinfo(dev);
827	csa_releaseres(csa, dev);
828
829	return 0;
830}
831
832static device_method_t pcmcsa_methods[] = {
833	/* Device interface */
834	DEVMETHOD(device_probe , pcmcsa_probe ),
835	DEVMETHOD(device_attach, pcmcsa_attach),
836	DEVMETHOD(device_detach, pcmcsa_detach),
837
838	{ 0, 0 },
839};
840
841static driver_t pcmcsa_driver = {
842	"pcm",
843	pcmcsa_methods,
844	PCM_SOFTC_SIZE,
845};
846
847DRIVER_MODULE(snd_csapcm, csa, pcmcsa_driver, pcm_devclass, 0, 0);
848MODULE_DEPEND(snd_csapcm, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER);
849MODULE_DEPEND(snd_csapcm, snd_csa, 1, 1, 1);
850MODULE_VERSION(snd_csapcm, 1);
851