source: sbliveos2/trunk/sblive/cardwi.c@ 174

Last change on this file since 174 was 142, checked in by ktk, 25 years ago

Import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.4 KB
Line 
1/* $Id: cardwi.c 142 2000-04-23 14:55:46Z ktk $ */
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.