Linux-2.6.12-rc2
[linux-flexiantxendom0-natty.git] / sound / oss / emu10k1 / cardwi.c
1 /*
2  **********************************************************************
3  *     cardwi.c - PCM input HAL for emu10k1 driver
4  *     Copyright 1999, 2000 Creative Labs, Inc.
5  *
6  **********************************************************************
7  *
8  *     Date                 Author          Summary of changes
9  *     ----                 ------          ------------------
10  *     October 20, 1999     Bertrand Lee    base code release
11  *
12  **********************************************************************
13  *
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.
18  *
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.
23  *
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.
28  *
29  **********************************************************************
30  */
31
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"
38
39 /**
40  * query_format - returns a valid sound format
41  *
42  * This function will return a valid sound format as close
43  * to the requested one as possible. 
44  */
45 static void query_format(int recsrc, struct wave_format *wave_fmt)
46 {
47
48         switch (recsrc) {
49         case WAVERECORD_AC97:
50
51                 if ((wave_fmt->channels != 1) && (wave_fmt->channels != 2))
52                         wave_fmt->channels = 2;
53
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;
70
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;
82                 }
83
84                 break;
85
86         /* these can't be changed from the original values */
87         case WAVERECORD_MIC:
88         case WAVERECORD_FX:
89                 break;
90
91         default:
92                 BUG();
93                 break;
94         }
95
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;
100 }
101
102 static int alloc_buffer(struct emu10k1_card *card, struct wavein_buffer *buffer)
103 {
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;
108
109         return 0;
110 }
111
112 static void free_buffer(struct emu10k1_card *card, struct wavein_buffer *buffer)
113 {
114         if (buffer->addr != NULL)
115                 pci_free_consistent(card->pci_dev, buffer->size * buffer->cov,
116                                     buffer->addr, buffer->dma_handle);
117 }
118
119 int emu10k1_wavein_open(struct emu10k1_wavedevice *wave_dev)
120 {
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;
126
127         DPF(2, "emu10k1_wavein_open()\n");
128
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;
142         }
143
144         spin_lock_irqsave(&card->lock, flags);
145         if (*wiinst_tmp != NULL) {
146                 spin_unlock_irqrestore(&card->lock, flags);
147                 return -1;
148         }
149
150         *wiinst_tmp = wiinst;
151         spin_unlock_irqrestore(&card->lock, flags);
152
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;
160
161                 wiinst->buffer.cov = 2;
162         } else
163                 wiinst->buffer.cov = 1;
164
165         if (alloc_buffer(card, &wiinst->buffer) < 0) {
166                 ERROR();
167                 return -1;
168         }
169
170         emu10k1_set_record_src(card, wiinst);
171
172         emu10k1_reset_record(card, &wiinst->buffer);
173
174         wiinst->buffer.hw_pos = 0;
175         wiinst->buffer.pos = 0;
176         wiinst->buffer.bytestocopy = 0;
177
178         delay = (48000 * wiinst->buffer.fragment_size) / wiinst->format.bytespersec;
179
180         emu10k1_timer_install(card, &wiinst->timer, delay / 2);
181
182         wiinst->state = WAVE_STATE_OPEN;
183
184         return 0;
185 }
186
187 void emu10k1_wavein_close(struct emu10k1_wavedevice *wave_dev)
188 {
189         struct emu10k1_card *card = wave_dev->card;
190         struct wiinst *wiinst = wave_dev->wiinst;
191         unsigned long flags;
192
193         DPF(2, "emu10k1_wavein_close()\n");
194
195         emu10k1_wavein_stop(wave_dev);
196
197         emu10k1_timer_uninstall(card, &wiinst->timer);
198
199         free_buffer(card, &wiinst->buffer);
200
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;
215         }
216         spin_unlock_irqrestore(&card->lock, flags);
217
218         wiinst->state = WAVE_STATE_CLOSED;
219 }
220
221 void emu10k1_wavein_start(struct emu10k1_wavedevice *wave_dev)
222 {
223         struct emu10k1_card *card = wave_dev->card;
224         struct wiinst *wiinst = wave_dev->wiinst;
225
226         DPF(2, "emu10k1_wavein_start()\n");
227
228         emu10k1_start_record(card, &wiinst->buffer);
229         emu10k1_timer_enable(wave_dev->card, &wiinst->timer);
230
231         wiinst->state |= WAVE_STATE_STARTED;
232 }
233
234 void emu10k1_wavein_stop(struct emu10k1_wavedevice *wave_dev)
235 {
236         struct emu10k1_card *card = wave_dev->card;
237         struct wiinst *wiinst = wave_dev->wiinst;
238
239         DPF(2, "emu10k1_wavein_stop()\n");
240
241         if (!(wiinst->state & WAVE_STATE_STARTED))
242                 return;
243
244         emu10k1_timer_disable(card, &wiinst->timer);
245         emu10k1_stop_record(card, &wiinst->buffer);
246
247         wiinst->state &= ~WAVE_STATE_STARTED;
248 }
249
250 int emu10k1_wavein_setformat(struct emu10k1_wavedevice *wave_dev, struct wave_format *format)
251 {
252         struct emu10k1_card *card = wave_dev->card;
253         struct wiinst *wiinst = wave_dev->wiinst;
254         u16 delay;
255
256         DPF(2, "emu10k1_wavein_setformat()\n");
257
258         if (wiinst->state & WAVE_STATE_STARTED)
259                 return -1;
260
261         query_format(wiinst->recsrc, format);
262
263         if ((wiinst->format.samplingrate != format->samplingrate)
264             || (wiinst->format.bitsperchannel != format->bitsperchannel)
265             || (wiinst->format.channels != format->channels)) {
266
267                 wiinst->format = *format;
268
269                 if (wiinst->state == WAVE_STATE_CLOSED)
270                         return 0;
271
272                 wiinst->buffer.size *= wiinst->buffer.cov;
273
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;
279
280                 emu10k1_timer_uninstall(card, &wiinst->timer);
281
282                 delay = (48000 * wiinst->buffer.fragment_size) / wiinst->format.bytespersec;
283
284                 emu10k1_timer_install(card, &wiinst->timer, delay / 2);
285         }
286
287         return 0;
288 }
289
290 void emu10k1_wavein_getxfersize(struct wiinst *wiinst, u32 * size)
291 {
292         struct wavein_buffer *buffer = &wiinst->buffer;
293
294         *size = buffer->bytestocopy;
295
296         if (wiinst->mmapped)
297                 return;
298
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");
304         }
305 }
306
307 static void copy_block(u8 __user *dst, u8 * src, u32 str, u32 len, u8 cov)
308 {
309         if (cov == 1)
310                 __copy_to_user(dst, src + str, len);
311         else {
312                 u8 byte;
313                 u32 i;
314
315                 src += 1 + 2 * str;
316
317                 for (i = 0; i < len; i++) {
318                         byte = src[2 * i] ^ 0x80;
319                         __copy_to_user(dst + i, &byte, 1);
320                 }
321         }
322 }
323
324 void emu10k1_wavein_xferdata(struct wiinst *wiinst, u8 __user *data, u32 * size)
325 {
326         struct wavein_buffer *buffer = &wiinst->buffer;
327         u32 sizetocopy, sizetocopy_now, start;
328         unsigned long flags;
329
330         sizetocopy = min_t(u32, buffer->size, *size);
331         *size = sizetocopy;
332
333         if (!sizetocopy)
334                 return;
335
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;
342
343         spin_unlock_irqrestore(&wiinst->lock, flags);
344
345         if (sizetocopy > sizetocopy_now) {
346                 sizetocopy -= sizetocopy_now;
347
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);
352         }
353 }
354
355 void emu10k1_wavein_update(struct emu10k1_card *card, struct wiinst *wiinst)
356 {
357         u32 hw_pos;
358         u32 diff;
359
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;
366         }
367
368         diff = (wiinst->buffer.size + hw_pos - wiinst->buffer.hw_pos) % wiinst->buffer.size;
369         wiinst->total_recorded += diff;
370         wiinst->buffer.bytestocopy += diff;
371
372         wiinst->buffer.hw_pos = hw_pos;
373 }