source: cmedia/trunk/Sblive/cardwi.c@ 354

Last change on this file since 354 was 354, checked in by stevenhl, 17 years ago

Import untested baseline cmedia sources, work products and binaries
Binaries and work products should be deleted from repository.
once new builds are verified to work.

File size: 12.9 KB
Line 
1/* $Id: cardwi.c,v 1.1 2000/04/23 14:55:42 ktk Exp $ */
2
3
4/*
5 **********************************************************************
6 * cardwi.c - PCM input HAL for emu10k1 driver
7 * Copyright 1999, 2000 Creative Labs, Inc.
8 *
9 **********************************************************************
10 *
11 * Date Author Summary of changes
12 * ---- ------ ------------------
13 * October 20, 1999 Bertrand Lee base code release
14 *
15 **********************************************************************
16 *
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License as
19 * published by the Free Software Foundation; either version 2 of
20 * the License, or (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public
28 * License along with this program; if not, write to the Free
29 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
30 * USA.
31 *
32 **********************************************************************
33 */
34
35#include "hwaccess.h"
36#include "recmgr.h"
37#include "audio.h"
38#include "cardwi.h"
39
40void query_format(int recsrc, struct wave_format *wave_fmt)
41{
42
43 switch (recsrc) {
44 case WAVERECORD_AC97:
45
46 if ((wave_fmt->channels != 2) && (wave_fmt->channels != 1))
47 wave_fmt->channels = 2;
48
49 if (wave_fmt->samplingrate >= (0xBB80 + 0xAC44) / 2)
50 wave_fmt->samplingrate = 0xBB80;
51 else if (wave_fmt->samplingrate >= (0xAC44 + 0x7D00) / 2)
52 wave_fmt->samplingrate = 0xAC44;
53 else if (wave_fmt->samplingrate >= (0x7D00 + 0x5DC0) / 2)
54 wave_fmt->samplingrate = 0x7D00;
55 else if (wave_fmt->samplingrate >= (0x5DC0 + 0x5622) / 2)
56 wave_fmt->samplingrate = 0x5DC0;
57 else if (wave_fmt->samplingrate >= (0x5622 + 0x3E80) / 2)
58 wave_fmt->samplingrate = 0x5622;
59 else if (wave_fmt->samplingrate >= (0x3E80 + 0x2B11) / 2)
60 wave_fmt->samplingrate = 0x3E80;
61 else if (wave_fmt->samplingrate >= (0x2B11 + 0x1F40) / 2)
62 wave_fmt->samplingrate = 0x2B11;
63 else
64 wave_fmt->samplingrate = 0x1F40;
65
66 if ((wave_fmt->bitsperchannel != 16) && (wave_fmt->bitsperchannel != 8))
67 wave_fmt->bitsperchannel = 16;
68
69 break;
70
71 case WAVERECORD_MIC:
72 wave_fmt->channels = 1;
73 wave_fmt->samplingrate = 0x1F40;
74 wave_fmt->bitsperchannel = 8;
75 break;
76
77 case WAVERECORD_FX:
78 wave_fmt->channels = 2;
79 wave_fmt->samplingrate = 0xBB80;
80 wave_fmt->bitsperchannel = 16;
81 break;
82
83 default:
84 break;
85 }
86
87 return;
88}
89
90static int alloc_recbuffer(struct wave_in *wave_in, u32 * bufsize, u8 ** buffer)
91{
92 u32 reqsize;
93 int i, j;
94 u32 size[4];
95
96 /* NOTE: record buffer size only can be certain sizes. If the requested
97 * size is not a nice size, use the smaller nearest size. The minimum size is 1k. */
98 if (!wave_in->rec_ptr->is_16bit)
99 *bufsize <<= 1;
100
101 if (*bufsize >= 0x10000) {
102 *bufsize = reqsize = 0x10000;
103 wave_in->rec_ptr->bufsize = 31;
104 } else {
105 reqsize = 0;
106 size[0] = 384;
107 size[1] = 448;
108 size[2] = 512;
109 size[3] = 640;
110
111 for (i = 0; i < 8; i++)
112 for (j = 0; j < 4; j++)
113 if (*bufsize >= size[j]) {
114 reqsize = size[j];
115 size[j] = size[j] * 2;
116 wave_in->rec_ptr->bufsize = i * 4 + j + 1;
117 } else
118 goto exitloop;
119 exitloop:
120 if (reqsize == 0) {
121 reqsize = 384;
122 wave_in->rec_ptr->bufsize = 1;
123 }
124
125 *bufsize = reqsize;
126 }
127
128 DPD(2, "bufsizereg: %x\n", wave_in->rec_ptr->bufsize);
129
130 /* Recording buffer must be continuous and page-aligned */
131 if ((wave_in->memhandle = emu10k1_alloc_memphysical(reqsize)) == NULL)
132 return CTSTATUS_ERROR;
133
134 DPD(2, "recbufsize: %x\n", *bufsize);
135
136 *buffer = (u8 *) wave_in->memhandle->virtaddx;
137
138 return CTSTATUS_SUCCESS;
139}
140
141static int get_recbuffer(struct emu10k1_card *card, struct wave_in *wave_in, u32 * size)
142{
143 u8 *buffer;
144
145 wave_in->rec_ptr->card = card;
146 wave_in->rec_ptr->recpos = 0;
147 wave_in->rec_ptr->samplingrate = wave_in->wave_fmt.samplingrate;
148 wave_in->rec_ptr->is_stereo = (wave_in->wave_fmt.channels == 2) ? 1 : 0;
149 wave_in->rec_ptr->is_16bit = (wave_in->wave_fmt.bitsperchannel == 16) ? 1 : 0;
150
151 /* Allocate buffer here */
152 if (alloc_recbuffer(wave_in, size, &buffer) != CTSTATUS_SUCCESS) {
153 ERROR();
154 return CTSTATUS_ERROR;
155 }
156
157 /* recbufsize contains actual record buffer size */
158 /* for 8 bit samples the size is twice the requested */
159 /* value since we only make use of one in every two bytes */
160 wave_in->rec_ptr->recbufsize = *size;
161 wave_in->rec_ptr->recbuffer = buffer;
162 wave_in->rec_ptr->busaddx = wave_in->memhandle->busaddx;
163
164 return CTSTATUS_SUCCESS;
165}
166
167static void dealloc_recbuffer(struct wave_in *wave_in)
168{
169 emu10k1_free_memphysical(wave_in->memhandle);
170 return;
171}
172
173int emu10k1_wavein_open(struct emu10k1_wavedevice *wave_dev)
174{
175 struct emu10k1_card *card = wave_dev->card;
176 struct wiinst *wiinst = wave_dev->wiinst;
177 struct wave_in *wave_in;
178 struct wave_in **wave_in_tmp = NULL;
179 u32 buffsize, bytespersec, delay;
180 unsigned long flags;
181
182 DPF(2, "emu10k1_wavein_open()\n");
183
184 if ((wave_in = (struct wave_in *) kmalloc(sizeof(struct wave_in), GFP_KERNEL)) == NULL) {
185 ERROR();
186 return CTSTATUS_ERROR;
187 }
188
189 wave_in->state = CARDWAVE_STATE_STOPPED;
190 wave_in->wave_fmt = wiinst->wave_fmt;
191 wave_in->memhandle = NULL;
192 wave_in->timer = NULL;
193
194 switch (wiinst->recsrc) {
195 case WAVERECORD_AC97:
196 wave_in_tmp = &card->wavein->ac97;
197 break;
198 case WAVERECORD_MIC:
199 wave_in_tmp = &card->wavein->mic;
200 break;
201 case WAVERECORD_FX:
202 wave_in_tmp = &card->wavein->fx;
203 break;
204 default:
205 break;
206 }
207
208 spin_lock_irqsave(&card->lock, flags);
209 if (*wave_in_tmp != NULL) {
210 spin_unlock_irqrestore(&card->lock, flags);
211 kfree(wave_in);
212 return CTSTATUS_ERROR;
213 }
214
215 *wave_in_tmp = wave_in;
216 spin_unlock_irqrestore(&card->lock, flags);
217
218 wiinst->wave_in = wave_in;
219
220 if ((wave_in->rec_ptr = (struct record *) kmalloc(sizeof(struct record), GFP_KERNEL)) == NULL) {
221 ERROR();
222 emu10k1_wavein_close(wave_dev);
223 return CTSTATUS_ERROR;
224 }
225
226 buffsize = wiinst->fragment_size * wiinst->numfrags;
227
228 if (get_recbuffer(card, wave_in, &buffsize) != CTSTATUS_SUCCESS) {
229 ERROR();
230 emu10k1_wavein_close(wave_dev);
231 return CTSTATUS_ERROR;
232 }
233
234 wiinst->fragment_size = buffsize / wiinst->numfrags;
235
236 /* This callback size returned is the size in the play buffer.
237 * For 8-bit samples, callbacksize of user buffer should be
238 * half of the callbacksize in play buffer. */
239 if (wave_in->wave_fmt.bitsperchannel == 8)
240 wiinst->fragment_size >>= 1;
241
242 wave_in->callbacksize = wiinst->fragment_size;
243
244 emu10k1_set_record_src(wave_in->rec_ptr, wiinst->recsrc);
245
246 bytespersec = wave_in->wave_fmt.channels * (wave_in->wave_fmt.bitsperchannel >> 3) * (wave_in->wave_fmt.samplingrate);
247 delay = (48000 * wave_in->callbacksize) / bytespersec;
248
249 if ((wave_in->timer = emu10k1_timer_install(card, emu10k1_wavein_bh, (unsigned long) wave_dev, delay / 2)) == NULL) {
250 ERROR();
251 emu10k1_wavein_close(wave_dev);
252 return CTSTATUS_ERROR;
253 }
254
255 return CTSTATUS_SUCCESS;
256}
257
258void emu10k1_wavein_close(struct emu10k1_wavedevice *wave_dev)
259{
260 struct emu10k1_card *card = wave_dev->card;
261 struct wave_in *wave_in = wave_dev->wiinst->wave_in;
262 unsigned long flags;
263
264 if (wave_in->state != CARDWAVE_STATE_STOPPED)
265 emu10k1_wavein_stop(wave_dev);
266
267 if (wave_in->timer != NULL)
268 emu10k1_timer_uninstall(card, wave_in->timer);
269
270 if (wave_in->memhandle != NULL)
271 dealloc_recbuffer(wave_in);
272
273 if (wave_in->rec_ptr != NULL)
274 kfree(wave_in->rec_ptr);
275
276 spin_lock_irqsave(&card->lock, flags);
277 switch (wave_dev->wiinst->recsrc) {
278 case WAVERECORD_AC97:
279 card->wavein->ac97 = NULL;
280 break;
281 case WAVERECORD_MIC:
282 card->wavein->mic = NULL;
283 break;
284 case WAVERECORD_FX:
285 card->wavein->fx = NULL;
286 break;
287 default:
288 break;
289 }
290 spin_unlock_irqrestore(&card->lock, flags);
291
292 kfree(wave_in);
293 wave_dev->wiinst->wave_in = NULL;
294
295 return;
296}
297
298void emu10k1_wavein_start(struct emu10k1_wavedevice *wave_dev)
299{
300 struct wave_in *wave_in = wave_dev->wiinst->wave_in;
301
302 DPF(2, "emu10k1_wavein_start()\n");
303
304 if (wave_in->state == CARDWAVE_STATE_STARTED)
305 return;
306
307 emu10k1_start_record(wave_in->rec_ptr);
308 wave_in->state = CARDWAVE_STATE_STARTED;
309
310 emu10k1_timer_enable(wave_dev->card, wave_in->timer);
311
312 return;
313}
314
315void emu10k1_wavein_stop(struct emu10k1_wavedevice *wave_dev)
316{
317 struct wave_in *wave_in = wave_dev->wiinst->wave_in;
318
319 DPF(2, "emu10k1_wavein_stop()\n");
320
321 emu10k1_stop_record(wave_in->rec_ptr);
322 emu10k1_timer_disable(wave_dev->card, wave_in->timer);
323
324 wave_in->rec_ptr->recpos = 0;
325 wave_in->state = CARDWAVE_STATE_STOPPED;
326
327 return;
328}
329
330int emu10k1_wavein_setformat(struct emu10k1_wavedevice *wave_dev)
331{
332 struct emu10k1_card *card = wave_dev->card;
333 struct wiinst *wiinst = wave_dev->wiinst;
334 struct wave_in *wave_in = wiinst->wave_in;
335 u32 bytespersec, delay;
336
337 DPF(2, "emu10k1_wavein_setformat()\n");
338
339 query_format(wiinst->recsrc, &wiinst->wave_fmt);
340
341 if (!wave_in)
342 return CTSTATUS_SUCCESS;
343
344 if (wave_in->state == CARDWAVE_STATE_STARTED) {
345 wiinst->wave_fmt = wave_in->wave_fmt;
346 return CTSTATUS_SUCCESS;
347 }
348
349 if ((wave_in->wave_fmt.samplingrate != wiinst->wave_fmt.samplingrate)
350 || (wave_in->wave_fmt.bitsperchannel != wiinst->wave_fmt.bitsperchannel)
351 || (wave_in->wave_fmt.channels != wiinst->wave_fmt.channels)) {
352
353 emu10k1_timer_uninstall(card, wave_in->timer);
354
355 wave_in->wave_fmt = wiinst->wave_fmt;
356
357 bytespersec = wave_in->wave_fmt.channels * (wave_in->wave_fmt.bitsperchannel >> 3) * (wave_in->wave_fmt.samplingrate);
358 delay = (48000 * wave_in->callbacksize) / bytespersec;
359
360 if ((wave_in->timer = emu10k1_timer_install(card, emu10k1_wavein_bh, (unsigned long) wave_dev, delay / 2)) == NULL) {
361 ERROR();
362 emu10k1_wavein_close(wave_dev);
363 return CTSTATUS_ERROR;
364 }
365 }
366
367 return CTSTATUS_SUCCESS;
368}
369
370void emu10k1_wavein_getxfersize(struct wiinst *wiinst, u32 * size)
371{
372 struct record *rec_ptr = wiinst->wave_in->rec_ptr;
373 u32 curpos = wiinst->curpos;
374
375 *size = curpos - rec_ptr->recpos;
376
377 /* Recpos is the actual position in user buffer and play buffer */
378 if (curpos < rec_ptr->recpos)
379 *size += rec_ptr->recbufsize;
380
381 if (!rec_ptr->is_16bit)
382 *size >>= 1;
383
384 return;
385}
386
387static void copy_s16_to_u8(u8 * dstbuf, s16 * srcbuf, u32 size)
388{
389 u16 sample;
390 u8 byte;
391
392 while (size--) {
393 sample = (*srcbuf) + 32767;
394 byte = (u8) (sample >> 8);
395#ifdef TARGET_OS2
396 *dstbuf = byte;
397#else
398 copy_to_user(dstbuf, &byte, 1);
399#endif
400 dstbuf++;
401 srcbuf++;
402 }
403}
404
405/* transfer the data from the wave device. */
406void emu10k1_wavein_xferdata(struct wiinst *wiinst, u8 * data, u32 * size)
407{
408 struct wave_in *wave_in = wiinst->wave_in;
409 struct record *rec_ptr = wave_in->rec_ptr;
410 u32 sizetocopy, sizetocopy_now, start;
411 unsigned long flags;
412
413 sizetocopy = min(rec_ptr->recbufsize * (rec_ptr->is_16bit + 1) / 2, *size);
414 *size = sizetocopy;
415
416 if (!sizetocopy)
417 return;
418
419 spin_lock_irqsave(&wiinst->lock, flags);
420
421 sizetocopy_now = (rec_ptr->recbufsize - rec_ptr->recpos) * (rec_ptr->is_16bit + 1) / 2;
422
423 start = rec_ptr->recpos;
424
425 if (sizetocopy > sizetocopy_now) {
426 sizetocopy -= sizetocopy_now;
427 rec_ptr->recpos = sizetocopy * 2 / (rec_ptr->is_16bit + 1);
428
429 spin_unlock_irqrestore(&wiinst->lock, flags);
430
431 if (rec_ptr->is_16bit) {
432 copy_to_user(data, rec_ptr->recbuffer + start, sizetocopy_now);
433 copy_to_user(data + sizetocopy_now, rec_ptr->recbuffer, sizetocopy);
434 } else {
435 copy_s16_to_u8(data, (s16 *) (rec_ptr->recbuffer + start), sizetocopy_now);
436 copy_s16_to_u8(data + sizetocopy_now, (s16 *) rec_ptr->recbuffer, sizetocopy);
437 }
438 } else {
439 if (sizetocopy == sizetocopy_now)
440 rec_ptr->recpos = 0;
441 else
442 rec_ptr->recpos += sizetocopy * 2 / (rec_ptr->is_16bit + 1);
443
444 spin_unlock_irqrestore(&wiinst->lock, flags);
445
446 if (rec_ptr->is_16bit)
447 copy_to_user(data, rec_ptr->recbuffer + start, sizetocopy);
448 else
449 copy_s16_to_u8(data, (s16 *) (rec_ptr->recbuffer + start), sizetocopy);
450 }
451
452 return;
453}
454
455/* get the specified control value of the wave device. */
456
457void emu10k1_wavein_update(struct wiinst *wiinst)
458{
459 struct wave_in *wave_in = wiinst->wave_in;
460 u32 curpos;
461
462 /* There is no actual start yet */
463 if (wave_in->state == CARDWAVE_STATE_STOPPED) {
464 curpos = 0;
465 } else {
466 /* curpos in byte units */
467 curpos = sblive_readptr(wave_in->rec_ptr->card, wave_in->rec_ptr->bufidxreg, 0);
468 }
469
470 wiinst->total_recorded += curpos - wiinst->curpos;
471
472 if (curpos < wiinst->curpos)
473 wiinst->total_recorded += wiinst->fragment_size * wiinst->numfrags;
474
475 wiinst->curpos = curpos;
476
477 return;
478}
Note: See TracBrowser for help on using the repository browser.