[TG3]: Set minimal hw interrupt mitigation.
[linux-2.6/verdex.git] / sound / oss / emu10k1 / cardwi.c
blob8bbf44b881b40d3c3f2f7904e002a09769a74795
1 /*
2 **********************************************************************
3 * cardwi.c - PCM input HAL for emu10k1 driver
4 * Copyright 1999, 2000 Creative Labs, Inc.
6 **********************************************************************
8 * Date Author Summary of changes
9 * ---- ------ ------------------
10 * October 20, 1999 Bertrand Lee base code release
12 **********************************************************************
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License as
16 * published by the Free Software Foundation; either version 2 of
17 * the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public
25 * License along with this program; if not, write to the Free
26 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
27 * USA.
29 **********************************************************************
32 #include <linux/poll.h>
33 #include "hwaccess.h"
34 #include "timer.h"
35 #include "recmgr.h"
36 #include "audio.h"
37 #include "cardwi.h"
39 /**
40 * query_format - returns a valid sound format
42 * This function will return a valid sound format as close
43 * to the requested one as possible.
45 static void query_format(int recsrc, struct wave_format *wave_fmt)
48 switch (recsrc) {
49 case WAVERECORD_AC97:
51 if ((wave_fmt->channels != 1) && (wave_fmt->channels != 2))
52 wave_fmt->channels = 2;
54 if (wave_fmt->samplingrate >= (0xBB80 + 0xAC44) / 2)
55 wave_fmt->samplingrate = 0xBB80;
56 else if (wave_fmt->samplingrate >= (0xAC44 + 0x7D00) / 2)
57 wave_fmt->samplingrate = 0xAC44;
58 else if (wave_fmt->samplingrate >= (0x7D00 + 0x5DC0) / 2)
59 wave_fmt->samplingrate = 0x7D00;
60 else if (wave_fmt->samplingrate >= (0x5DC0 + 0x5622) / 2)
61 wave_fmt->samplingrate = 0x5DC0;
62 else if (wave_fmt->samplingrate >= (0x5622 + 0x3E80) / 2)
63 wave_fmt->samplingrate = 0x5622;
64 else if (wave_fmt->samplingrate >= (0x3E80 + 0x2B11) / 2)
65 wave_fmt->samplingrate = 0x3E80;
66 else if (wave_fmt->samplingrate >= (0x2B11 + 0x1F40) / 2)
67 wave_fmt->samplingrate = 0x2B11;
68 else
69 wave_fmt->samplingrate = 0x1F40;
71 switch (wave_fmt->id) {
72 case AFMT_S16_LE:
73 wave_fmt->bitsperchannel = 16;
74 break;
75 case AFMT_U8:
76 wave_fmt->bitsperchannel = 8;
77 break;
78 default:
79 wave_fmt->id = AFMT_S16_LE;
80 wave_fmt->bitsperchannel = 16;
81 break;
84 break;
86 /* these can't be changed from the original values */
87 case WAVERECORD_MIC:
88 case WAVERECORD_FX:
89 break;
91 default:
92 BUG();
93 break;
96 wave_fmt->bytesperchannel = wave_fmt->bitsperchannel >> 3;
97 wave_fmt->bytespersample = wave_fmt->channels * wave_fmt->bytesperchannel;
98 wave_fmt->bytespersec = wave_fmt->bytespersample * wave_fmt->samplingrate;
99 wave_fmt->bytespervoicesample = wave_fmt->bytespersample;
102 static int alloc_buffer(struct emu10k1_card *card, struct wavein_buffer *buffer)
104 buffer->addr = pci_alloc_consistent(card->pci_dev, buffer->size * buffer->cov,
105 &buffer->dma_handle);
106 if (buffer->addr == NULL)
107 return -1;
109 return 0;
112 static void free_buffer(struct emu10k1_card *card, struct wavein_buffer *buffer)
114 if (buffer->addr != NULL)
115 pci_free_consistent(card->pci_dev, buffer->size * buffer->cov,
116 buffer->addr, buffer->dma_handle);
119 int emu10k1_wavein_open(struct emu10k1_wavedevice *wave_dev)
121 struct emu10k1_card *card = wave_dev->card;
122 struct wiinst *wiinst = wave_dev->wiinst;
123 struct wiinst **wiinst_tmp = NULL;
124 u16 delay;
125 unsigned long flags;
127 DPF(2, "emu10k1_wavein_open()\n");
129 switch (wiinst->recsrc) {
130 case WAVERECORD_AC97:
131 wiinst_tmp = &card->wavein.ac97;
132 break;
133 case WAVERECORD_MIC:
134 wiinst_tmp = &card->wavein.mic;
135 break;
136 case WAVERECORD_FX:
137 wiinst_tmp = &card->wavein.fx;
138 break;
139 default:
140 BUG();
141 break;
144 spin_lock_irqsave(&card->lock, flags);
145 if (*wiinst_tmp != NULL) {
146 spin_unlock_irqrestore(&card->lock, flags);
147 return -1;
150 *wiinst_tmp = wiinst;
151 spin_unlock_irqrestore(&card->lock, flags);
153 /* handle 8 bit recording */
154 if (wiinst->format.bytesperchannel == 1) {
155 if (wiinst->buffer.size > 0x8000) {
156 wiinst->buffer.size = 0x8000;
157 wiinst->buffer.sizeregval = 0x1f;
158 } else
159 wiinst->buffer.sizeregval += 4;
161 wiinst->buffer.cov = 2;
162 } else
163 wiinst->buffer.cov = 1;
165 if (alloc_buffer(card, &wiinst->buffer) < 0) {
166 ERROR();
167 return -1;
170 emu10k1_set_record_src(card, wiinst);
172 emu10k1_reset_record(card, &wiinst->buffer);
174 wiinst->buffer.hw_pos = 0;
175 wiinst->buffer.pos = 0;
176 wiinst->buffer.bytestocopy = 0;
178 delay = (48000 * wiinst->buffer.fragment_size) / wiinst->format.bytespersec;
180 emu10k1_timer_install(card, &wiinst->timer, delay / 2);
182 wiinst->state = WAVE_STATE_OPEN;
184 return 0;
187 void emu10k1_wavein_close(struct emu10k1_wavedevice *wave_dev)
189 struct emu10k1_card *card = wave_dev->card;
190 struct wiinst *wiinst = wave_dev->wiinst;
191 unsigned long flags;
193 DPF(2, "emu10k1_wavein_close()\n");
195 emu10k1_wavein_stop(wave_dev);
197 emu10k1_timer_uninstall(card, &wiinst->timer);
199 free_buffer(card, &wiinst->buffer);
201 spin_lock_irqsave(&card->lock, flags);
202 switch (wave_dev->wiinst->recsrc) {
203 case WAVERECORD_AC97:
204 card->wavein.ac97 = NULL;
205 break;
206 case WAVERECORD_MIC:
207 card->wavein.mic = NULL;
208 break;
209 case WAVERECORD_FX:
210 card->wavein.fx = NULL;
211 break;
212 default:
213 BUG();
214 break;
216 spin_unlock_irqrestore(&card->lock, flags);
218 wiinst->state = WAVE_STATE_CLOSED;
221 void emu10k1_wavein_start(struct emu10k1_wavedevice *wave_dev)
223 struct emu10k1_card *card = wave_dev->card;
224 struct wiinst *wiinst = wave_dev->wiinst;
226 DPF(2, "emu10k1_wavein_start()\n");
228 emu10k1_start_record(card, &wiinst->buffer);
229 emu10k1_timer_enable(wave_dev->card, &wiinst->timer);
231 wiinst->state |= WAVE_STATE_STARTED;
234 void emu10k1_wavein_stop(struct emu10k1_wavedevice *wave_dev)
236 struct emu10k1_card *card = wave_dev->card;
237 struct wiinst *wiinst = wave_dev->wiinst;
239 DPF(2, "emu10k1_wavein_stop()\n");
241 if (!(wiinst->state & WAVE_STATE_STARTED))
242 return;
244 emu10k1_timer_disable(card, &wiinst->timer);
245 emu10k1_stop_record(card, &wiinst->buffer);
247 wiinst->state &= ~WAVE_STATE_STARTED;
250 int emu10k1_wavein_setformat(struct emu10k1_wavedevice *wave_dev, struct wave_format *format)
252 struct emu10k1_card *card = wave_dev->card;
253 struct wiinst *wiinst = wave_dev->wiinst;
254 u16 delay;
256 DPF(2, "emu10k1_wavein_setformat()\n");
258 if (wiinst->state & WAVE_STATE_STARTED)
259 return -1;
261 query_format(wiinst->recsrc, format);
263 if ((wiinst->format.samplingrate != format->samplingrate)
264 || (wiinst->format.bitsperchannel != format->bitsperchannel)
265 || (wiinst->format.channels != format->channels)) {
267 wiinst->format = *format;
269 if (wiinst->state == WAVE_STATE_CLOSED)
270 return 0;
272 wiinst->buffer.size *= wiinst->buffer.cov;
274 if (wiinst->format.bytesperchannel == 1) {
275 wiinst->buffer.cov = 2;
276 wiinst->buffer.size /= wiinst->buffer.cov;
277 } else
278 wiinst->buffer.cov = 1;
280 emu10k1_timer_uninstall(card, &wiinst->timer);
282 delay = (48000 * wiinst->buffer.fragment_size) / wiinst->format.bytespersec;
284 emu10k1_timer_install(card, &wiinst->timer, delay / 2);
287 return 0;
290 void emu10k1_wavein_getxfersize(struct wiinst *wiinst, u32 * size)
292 struct wavein_buffer *buffer = &wiinst->buffer;
294 *size = buffer->bytestocopy;
296 if (wiinst->mmapped)
297 return;
299 if (*size > buffer->size) {
300 *size = buffer->size;
301 buffer->pos = buffer->hw_pos;
302 buffer->bytestocopy = buffer->size;
303 DPF(1, "buffer overrun\n");
307 static void copy_block(u8 __user *dst, u8 * src, u32 str, u32 len, u8 cov)
309 if (cov == 1)
310 __copy_to_user(dst, src + str, len);
311 else {
312 u8 byte;
313 u32 i;
315 src += 1 + 2 * str;
317 for (i = 0; i < len; i++) {
318 byte = src[2 * i] ^ 0x80;
319 __copy_to_user(dst + i, &byte, 1);
324 void emu10k1_wavein_xferdata(struct wiinst *wiinst, u8 __user *data, u32 * size)
326 struct wavein_buffer *buffer = &wiinst->buffer;
327 u32 sizetocopy, sizetocopy_now, start;
328 unsigned long flags;
330 sizetocopy = min_t(u32, buffer->size, *size);
331 *size = sizetocopy;
333 if (!sizetocopy)
334 return;
336 spin_lock_irqsave(&wiinst->lock, flags);
337 start = buffer->pos;
338 buffer->pos += sizetocopy;
339 buffer->pos %= buffer->size;
340 buffer->bytestocopy -= sizetocopy;
341 sizetocopy_now = buffer->size - start;
343 spin_unlock_irqrestore(&wiinst->lock, flags);
345 if (sizetocopy > sizetocopy_now) {
346 sizetocopy -= sizetocopy_now;
348 copy_block(data, buffer->addr, start, sizetocopy_now, buffer->cov);
349 copy_block(data + sizetocopy_now, buffer->addr, 0, sizetocopy, buffer->cov);
350 } else {
351 copy_block(data, buffer->addr, start, sizetocopy, buffer->cov);
355 void emu10k1_wavein_update(struct emu10k1_card *card, struct wiinst *wiinst)
357 u32 hw_pos;
358 u32 diff;
360 /* There is no actual start yet */
361 if (!(wiinst->state & WAVE_STATE_STARTED)) {
362 hw_pos = wiinst->buffer.hw_pos;
363 } else {
364 /* hw_pos in byte units */
365 hw_pos = sblive_readptr(card, wiinst->buffer.idxreg, 0) / wiinst->buffer.cov;
368 diff = (wiinst->buffer.size + hw_pos - wiinst->buffer.hw_pos) % wiinst->buffer.size;
369 wiinst->total_recorded += diff;
370 wiinst->buffer.bytestocopy += diff;
372 wiinst->buffer.hw_pos = hw_pos;