Deleted Added
full compact
csapcm.c (119690) csapcm.c (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
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 119690 2003-09-02 17:30:40Z jhb $");
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
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", rman_get_start(resp->irq));
791 snprintf(status, SND_STATUSLEN, "at irq %ld %s",
792 rman_get_start(resp->irq),PCM_KLDSTRING(snd_csa));
792
793 /* Enable interrupt. */
794 if (snd_setup_intr(dev, resp->irq, INTR_MPSAFE, csa_intr, csa, &csa->ih)) {
795 ac97_destroy(codec);
796 csa_releaseres(csa, dev);
797 return (ENXIO);
798 }
799 csa_writemem(resp, BA1_PFIE, csa_readmem(resp, BA1_PFIE) & ~0x0000f03f);
800 csa_writemem(resp, BA1_CIE, (csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000001);
801 csa_active(csa, -1);
802
803 if (pcm_register(dev, csa, 1, 1)) {
804 ac97_destroy(codec);
805 csa_releaseres(csa, dev);
806 return (ENXIO);
807 }
808 pcm_addchan(dev, PCMDIR_REC, &csachan_class, csa);
809 pcm_addchan(dev, PCMDIR_PLAY, &csachan_class, csa);
810 pcm_setstatus(dev, status);
811
812 return (0);
813}
814
815static int
816pcmcsa_detach(device_t dev)
817{
818 int r;
819 struct csa_info *csa;
820
821 r = pcm_unregister(dev);
822 if (r)
823 return r;
824
825 csa = pcm_getdevinfo(dev);
826 csa_releaseres(csa, dev);
827
828 return 0;
829}
830
831static device_method_t pcmcsa_methods[] = {
832 /* Device interface */
833 DEVMETHOD(device_probe , pcmcsa_probe ),
834 DEVMETHOD(device_attach, pcmcsa_attach),
835 DEVMETHOD(device_detach, pcmcsa_detach),
836
837 { 0, 0 },
838};
839
840static driver_t pcmcsa_driver = {
841 "pcm",
842 pcmcsa_methods,
843 PCM_SOFTC_SIZE,
844};
845
846DRIVER_MODULE(snd_csapcm, csa, pcmcsa_driver, pcm_devclass, 0, 0);
847MODULE_DEPEND(snd_csapcm, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER);
848MODULE_DEPEND(snd_csapcm, snd_csa, 1, 1, 1);
849MODULE_VERSION(snd_csapcm, 1);
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);