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