Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * linux/sound/oss/dmasound/trans_16.c | |
3 | * | |
4 | * 16 bit translation routines. Only used by Power mac at present. | |
5 | * | |
6 | * See linux/sound/oss/dmasound/dmasound_core.c for copyright and | |
7 | * history prior to 08/02/2001. | |
8 | * | |
9 | * 08/02/2001 Iain Sandoe | |
10 | * split from dmasound_awacs.c | |
11 | * 11/29/2003 Renzo Davoli (King Enzo) | |
12 | * - input resampling (for soft rate < hard rate) | |
13 | * - software line in gain control | |
14 | */ | |
15 | ||
16 | #include <linux/soundcard.h> | |
17 | #include <asm/uaccess.h> | |
18 | #include "dmasound.h" | |
19 | ||
9a472911 | 20 | extern int expand_bal; /* Balance factor for expanding (not volume!) */ |
1da177e4 LT |
21 | static short dmasound_alaw2dma16[] ; |
22 | static short dmasound_ulaw2dma16[] ; | |
23 | ||
24 | static ssize_t pmac_ct_law(const u_char __user *userPtr, size_t userCount, | |
25 | u_char frame[], ssize_t *frameUsed, | |
26 | ssize_t frameLeft); | |
27 | static ssize_t pmac_ct_s8(const u_char __user *userPtr, size_t userCount, | |
28 | u_char frame[], ssize_t *frameUsed, | |
29 | ssize_t frameLeft); | |
30 | static ssize_t pmac_ct_u8(const u_char __user *userPtr, size_t userCount, | |
31 | u_char frame[], ssize_t *frameUsed, | |
32 | ssize_t frameLeft); | |
33 | static ssize_t pmac_ct_s16(const u_char __user *userPtr, size_t userCount, | |
34 | u_char frame[], ssize_t *frameUsed, | |
35 | ssize_t frameLeft); | |
36 | static ssize_t pmac_ct_u16(const u_char __user *userPtr, size_t userCount, | |
37 | u_char frame[], ssize_t *frameUsed, | |
38 | ssize_t frameLeft); | |
39 | ||
40 | static ssize_t pmac_ctx_law(const u_char __user *userPtr, size_t userCount, | |
41 | u_char frame[], ssize_t *frameUsed, | |
42 | ssize_t frameLeft); | |
43 | static ssize_t pmac_ctx_s8(const u_char __user *userPtr, size_t userCount, | |
44 | u_char frame[], ssize_t *frameUsed, | |
45 | ssize_t frameLeft); | |
46 | static ssize_t pmac_ctx_u8(const u_char __user *userPtr, size_t userCount, | |
47 | u_char frame[], ssize_t *frameUsed, | |
48 | ssize_t frameLeft); | |
49 | static ssize_t pmac_ctx_s16(const u_char __user *userPtr, size_t userCount, | |
50 | u_char frame[], ssize_t *frameUsed, | |
51 | ssize_t frameLeft); | |
52 | static ssize_t pmac_ctx_u16(const u_char __user *userPtr, size_t userCount, | |
53 | u_char frame[], ssize_t *frameUsed, | |
54 | ssize_t frameLeft); | |
55 | ||
56 | static ssize_t pmac_ct_s16_read(const u_char __user *userPtr, size_t userCount, | |
57 | u_char frame[], ssize_t *frameUsed, | |
58 | ssize_t frameLeft); | |
59 | static ssize_t pmac_ct_u16_read(const u_char __user *userPtr, size_t userCount, | |
60 | u_char frame[], ssize_t *frameUsed, | |
61 | ssize_t frameLeft); | |
62 | ||
63 | /*** Translations ************************************************************/ | |
64 | ||
65 | static int expand_data; /* Data for expanding */ | |
66 | ||
67 | static ssize_t pmac_ct_law(const u_char __user *userPtr, size_t userCount, | |
68 | u_char frame[], ssize_t *frameUsed, | |
69 | ssize_t frameLeft) | |
70 | { | |
71 | short *table = dmasound.soft.format == AFMT_MU_LAW | |
72 | ? dmasound_ulaw2dma16 : dmasound_alaw2dma16; | |
73 | ssize_t count, used; | |
74 | short *p = (short *) &frame[*frameUsed]; | |
75 | int val, stereo = dmasound.soft.stereo; | |
76 | ||
77 | frameLeft >>= 2; | |
78 | if (stereo) | |
79 | userCount >>= 1; | |
80 | used = count = min_t(unsigned long, userCount, frameLeft); | |
81 | while (count > 0) { | |
82 | u_char data; | |
83 | if (get_user(data, userPtr++)) | |
84 | return -EFAULT; | |
85 | val = table[data]; | |
86 | *p++ = val; | |
87 | if (stereo) { | |
88 | if (get_user(data, userPtr++)) | |
89 | return -EFAULT; | |
90 | val = table[data]; | |
91 | } | |
92 | *p++ = val; | |
93 | count--; | |
94 | } | |
95 | *frameUsed += used * 4; | |
96 | return stereo? used * 2: used; | |
97 | } | |
98 | ||
99 | ||
100 | static ssize_t pmac_ct_s8(const u_char __user *userPtr, size_t userCount, | |
101 | u_char frame[], ssize_t *frameUsed, | |
102 | ssize_t frameLeft) | |
103 | { | |
104 | ssize_t count, used; | |
105 | short *p = (short *) &frame[*frameUsed]; | |
106 | int val, stereo = dmasound.soft.stereo; | |
107 | ||
108 | frameLeft >>= 2; | |
109 | if (stereo) | |
110 | userCount >>= 1; | |
111 | used = count = min_t(unsigned long, userCount, frameLeft); | |
112 | while (count > 0) { | |
113 | u_char data; | |
114 | if (get_user(data, userPtr++)) | |
115 | return -EFAULT; | |
116 | val = data << 8; | |
117 | *p++ = val; | |
118 | if (stereo) { | |
119 | if (get_user(data, userPtr++)) | |
120 | return -EFAULT; | |
121 | val = data << 8; | |
122 | } | |
123 | *p++ = val; | |
124 | count--; | |
125 | } | |
126 | *frameUsed += used * 4; | |
127 | return stereo? used * 2: used; | |
128 | } | |
129 | ||
130 | ||
131 | static ssize_t pmac_ct_u8(const u_char __user *userPtr, size_t userCount, | |
132 | u_char frame[], ssize_t *frameUsed, | |
133 | ssize_t frameLeft) | |
134 | { | |
135 | ssize_t count, used; | |
136 | short *p = (short *) &frame[*frameUsed]; | |
137 | int val, stereo = dmasound.soft.stereo; | |
138 | ||
139 | frameLeft >>= 2; | |
140 | if (stereo) | |
141 | userCount >>= 1; | |
142 | used = count = min_t(unsigned long, userCount, frameLeft); | |
143 | while (count > 0) { | |
144 | u_char data; | |
145 | if (get_user(data, userPtr++)) | |
146 | return -EFAULT; | |
147 | val = (data ^ 0x80) << 8; | |
148 | *p++ = val; | |
149 | if (stereo) { | |
150 | if (get_user(data, userPtr++)) | |
151 | return -EFAULT; | |
152 | val = (data ^ 0x80) << 8; | |
153 | } | |
154 | *p++ = val; | |
155 | count--; | |
156 | } | |
157 | *frameUsed += used * 4; | |
158 | return stereo? used * 2: used; | |
159 | } | |
160 | ||
161 | ||
162 | static ssize_t pmac_ct_s16(const u_char __user *userPtr, size_t userCount, | |
163 | u_char frame[], ssize_t *frameUsed, | |
164 | ssize_t frameLeft) | |
165 | { | |
166 | ssize_t count, used; | |
167 | int stereo = dmasound.soft.stereo; | |
168 | short *fp = (short *) &frame[*frameUsed]; | |
169 | ||
170 | frameLeft >>= 2; | |
171 | userCount >>= (stereo? 2: 1); | |
172 | used = count = min_t(unsigned long, userCount, frameLeft); | |
173 | if (!stereo) { | |
174 | short __user *up = (short __user *) userPtr; | |
175 | while (count > 0) { | |
176 | short data; | |
177 | if (get_user(data, up++)) | |
178 | return -EFAULT; | |
179 | *fp++ = data; | |
180 | *fp++ = data; | |
181 | count--; | |
182 | } | |
183 | } else { | |
184 | if (copy_from_user(fp, userPtr, count * 4)) | |
185 | return -EFAULT; | |
186 | } | |
187 | *frameUsed += used * 4; | |
188 | return stereo? used * 4: used * 2; | |
189 | } | |
190 | ||
191 | static ssize_t pmac_ct_u16(const u_char __user *userPtr, size_t userCount, | |
192 | u_char frame[], ssize_t *frameUsed, | |
193 | ssize_t frameLeft) | |
194 | { | |
195 | ssize_t count, used; | |
196 | int mask = (dmasound.soft.format == AFMT_U16_LE? 0x0080: 0x8000); | |
197 | int stereo = dmasound.soft.stereo; | |
198 | short *fp = (short *) &frame[*frameUsed]; | |
199 | short __user *up = (short __user *) userPtr; | |
200 | ||
201 | frameLeft >>= 2; | |
202 | userCount >>= (stereo? 2: 1); | |
203 | used = count = min_t(unsigned long, userCount, frameLeft); | |
204 | while (count > 0) { | |
205 | short data; | |
206 | if (get_user(data, up++)) | |
207 | return -EFAULT; | |
208 | data ^= mask; | |
209 | *fp++ = data; | |
210 | if (stereo) { | |
211 | if (get_user(data, up++)) | |
212 | return -EFAULT; | |
213 | data ^= mask; | |
214 | } | |
215 | *fp++ = data; | |
216 | count--; | |
217 | } | |
218 | *frameUsed += used * 4; | |
219 | return stereo? used * 4: used * 2; | |
220 | } | |
221 | ||
222 | ||
223 | static ssize_t pmac_ctx_law(const u_char __user *userPtr, size_t userCount, | |
224 | u_char frame[], ssize_t *frameUsed, | |
225 | ssize_t frameLeft) | |
226 | { | |
227 | unsigned short *table = (unsigned short *) | |
228 | (dmasound.soft.format == AFMT_MU_LAW | |
229 | ? dmasound_ulaw2dma16 : dmasound_alaw2dma16); | |
230 | unsigned int data = expand_data; | |
231 | unsigned int *p = (unsigned int *) &frame[*frameUsed]; | |
232 | int bal = expand_bal; | |
233 | int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; | |
234 | int utotal, ftotal; | |
235 | int stereo = dmasound.soft.stereo; | |
236 | ||
237 | frameLeft >>= 2; | |
238 | if (stereo) | |
239 | userCount >>= 1; | |
240 | ftotal = frameLeft; | |
241 | utotal = userCount; | |
242 | while (frameLeft) { | |
243 | u_char c; | |
244 | if (bal < 0) { | |
245 | if (userCount == 0) | |
246 | break; | |
247 | if (get_user(c, userPtr++)) | |
248 | return -EFAULT; | |
249 | data = table[c]; | |
250 | if (stereo) { | |
251 | if (get_user(c, userPtr++)) | |
252 | return -EFAULT; | |
253 | data = (data << 16) + table[c]; | |
254 | } else | |
255 | data = (data << 16) + data; | |
256 | userCount--; | |
257 | bal += hSpeed; | |
258 | } | |
259 | *p++ = data; | |
260 | frameLeft--; | |
261 | bal -= sSpeed; | |
262 | } | |
263 | expand_bal = bal; | |
264 | expand_data = data; | |
265 | *frameUsed += (ftotal - frameLeft) * 4; | |
266 | utotal -= userCount; | |
267 | return stereo? utotal * 2: utotal; | |
268 | } | |
269 | ||
270 | static ssize_t pmac_ctx_s8(const u_char __user *userPtr, size_t userCount, | |
271 | u_char frame[], ssize_t *frameUsed, | |
272 | ssize_t frameLeft) | |
273 | { | |
274 | unsigned int *p = (unsigned int *) &frame[*frameUsed]; | |
275 | unsigned int data = expand_data; | |
276 | int bal = expand_bal; | |
277 | int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; | |
278 | int stereo = dmasound.soft.stereo; | |
279 | int utotal, ftotal; | |
280 | ||
281 | frameLeft >>= 2; | |
282 | if (stereo) | |
283 | userCount >>= 1; | |
284 | ftotal = frameLeft; | |
285 | utotal = userCount; | |
286 | while (frameLeft) { | |
287 | u_char c; | |
288 | if (bal < 0) { | |
289 | if (userCount == 0) | |
290 | break; | |
291 | if (get_user(c, userPtr++)) | |
292 | return -EFAULT; | |
293 | data = c << 8; | |
294 | if (stereo) { | |
295 | if (get_user(c, userPtr++)) | |
296 | return -EFAULT; | |
297 | data = (data << 16) + (c << 8); | |
298 | } else | |
299 | data = (data << 16) + data; | |
300 | userCount--; | |
301 | bal += hSpeed; | |
302 | } | |
303 | *p++ = data; | |
304 | frameLeft--; | |
305 | bal -= sSpeed; | |
306 | } | |
307 | expand_bal = bal; | |
308 | expand_data = data; | |
309 | *frameUsed += (ftotal - frameLeft) * 4; | |
310 | utotal -= userCount; | |
311 | return stereo? utotal * 2: utotal; | |
312 | } | |
313 | ||
314 | ||
315 | static ssize_t pmac_ctx_u8(const u_char __user *userPtr, size_t userCount, | |
316 | u_char frame[], ssize_t *frameUsed, | |
317 | ssize_t frameLeft) | |
318 | { | |
319 | unsigned int *p = (unsigned int *) &frame[*frameUsed]; | |
320 | unsigned int data = expand_data; | |
321 | int bal = expand_bal; | |
322 | int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; | |
323 | int stereo = dmasound.soft.stereo; | |
324 | int utotal, ftotal; | |
325 | ||
326 | frameLeft >>= 2; | |
327 | if (stereo) | |
328 | userCount >>= 1; | |
329 | ftotal = frameLeft; | |
330 | utotal = userCount; | |
331 | while (frameLeft) { | |
332 | u_char c; | |
333 | if (bal < 0) { | |
334 | if (userCount == 0) | |
335 | break; | |
336 | if (get_user(c, userPtr++)) | |
337 | return -EFAULT; | |
338 | data = (c ^ 0x80) << 8; | |
339 | if (stereo) { | |
340 | if (get_user(c, userPtr++)) | |
341 | return -EFAULT; | |
342 | data = (data << 16) + ((c ^ 0x80) << 8); | |
343 | } else | |
344 | data = (data << 16) + data; | |
345 | userCount--; | |
346 | bal += hSpeed; | |
347 | } | |
348 | *p++ = data; | |
349 | frameLeft--; | |
350 | bal -= sSpeed; | |
351 | } | |
352 | expand_bal = bal; | |
353 | expand_data = data; | |
354 | *frameUsed += (ftotal - frameLeft) * 4; | |
355 | utotal -= userCount; | |
356 | return stereo? utotal * 2: utotal; | |
357 | } | |
358 | ||
359 | ||
360 | static ssize_t pmac_ctx_s16(const u_char __user *userPtr, size_t userCount, | |
361 | u_char frame[], ssize_t *frameUsed, | |
362 | ssize_t frameLeft) | |
363 | { | |
364 | unsigned int *p = (unsigned int *) &frame[*frameUsed]; | |
365 | unsigned int data = expand_data; | |
366 | unsigned short __user *up = (unsigned short __user *) userPtr; | |
367 | int bal = expand_bal; | |
368 | int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; | |
369 | int stereo = dmasound.soft.stereo; | |
370 | int utotal, ftotal; | |
371 | ||
372 | frameLeft >>= 2; | |
373 | userCount >>= (stereo? 2: 1); | |
374 | ftotal = frameLeft; | |
375 | utotal = userCount; | |
376 | while (frameLeft) { | |
377 | unsigned short c; | |
378 | if (bal < 0) { | |
379 | if (userCount == 0) | |
380 | break; | |
381 | if (get_user(data, up++)) | |
382 | return -EFAULT; | |
383 | if (stereo) { | |
384 | if (get_user(c, up++)) | |
385 | return -EFAULT; | |
386 | data = (data << 16) + c; | |
387 | } else | |
388 | data = (data << 16) + data; | |
389 | userCount--; | |
390 | bal += hSpeed; | |
391 | } | |
392 | *p++ = data; | |
393 | frameLeft--; | |
394 | bal -= sSpeed; | |
395 | } | |
396 | expand_bal = bal; | |
397 | expand_data = data; | |
398 | *frameUsed += (ftotal - frameLeft) * 4; | |
399 | utotal -= userCount; | |
400 | return stereo? utotal * 4: utotal * 2; | |
401 | } | |
402 | ||
403 | ||
404 | static ssize_t pmac_ctx_u16(const u_char __user *userPtr, size_t userCount, | |
405 | u_char frame[], ssize_t *frameUsed, | |
406 | ssize_t frameLeft) | |
407 | { | |
408 | int mask = (dmasound.soft.format == AFMT_U16_LE? 0x0080: 0x8000); | |
409 | unsigned int *p = (unsigned int *) &frame[*frameUsed]; | |
410 | unsigned int data = expand_data; | |
411 | unsigned short __user *up = (unsigned short __user *) userPtr; | |
412 | int bal = expand_bal; | |
413 | int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; | |
414 | int stereo = dmasound.soft.stereo; | |
415 | int utotal, ftotal; | |
416 | ||
417 | frameLeft >>= 2; | |
418 | userCount >>= (stereo? 2: 1); | |
419 | ftotal = frameLeft; | |
420 | utotal = userCount; | |
421 | while (frameLeft) { | |
422 | unsigned short c; | |
423 | if (bal < 0) { | |
424 | if (userCount == 0) | |
425 | break; | |
426 | if (get_user(data, up++)) | |
427 | return -EFAULT; | |
428 | data ^= mask; | |
429 | if (stereo) { | |
430 | if (get_user(c, up++)) | |
431 | return -EFAULT; | |
432 | data = (data << 16) + (c ^ mask); | |
433 | } else | |
434 | data = (data << 16) + data; | |
435 | userCount--; | |
436 | bal += hSpeed; | |
437 | } | |
438 | *p++ = data; | |
439 | frameLeft--; | |
440 | bal -= sSpeed; | |
441 | } | |
442 | expand_bal = bal; | |
443 | expand_data = data; | |
444 | *frameUsed += (ftotal - frameLeft) * 4; | |
445 | utotal -= userCount; | |
446 | return stereo? utotal * 4: utotal * 2; | |
447 | } | |
448 | ||
449 | /* data in routines... */ | |
450 | ||
451 | static ssize_t pmac_ct_s8_read(const u_char __user *userPtr, size_t userCount, | |
452 | u_char frame[], ssize_t *frameUsed, | |
453 | ssize_t frameLeft) | |
454 | { | |
455 | ssize_t count, used; | |
456 | short *p = (short *) &frame[*frameUsed]; | |
457 | int val, stereo = dmasound.soft.stereo; | |
458 | ||
459 | frameLeft >>= 2; | |
460 | if (stereo) | |
461 | userCount >>= 1; | |
462 | used = count = min_t(unsigned long, userCount, frameLeft); | |
463 | while (count > 0) { | |
464 | u_char data; | |
465 | ||
466 | val = *p++; | |
467 | val = (val * software_input_volume) >> 7; | |
468 | data = val >> 8; | |
469 | if (put_user(data, (u_char __user *)userPtr++)) | |
470 | return -EFAULT; | |
471 | if (stereo) { | |
472 | val = *p; | |
473 | val = (val * software_input_volume) >> 7; | |
474 | data = val >> 8; | |
475 | if (put_user(data, (u_char __user *)userPtr++)) | |
476 | return -EFAULT; | |
477 | } | |
478 | p++; | |
479 | count--; | |
480 | } | |
481 | *frameUsed += used * 4; | |
482 | return stereo? used * 2: used; | |
483 | } | |
484 | ||
485 | ||
486 | static ssize_t pmac_ct_u8_read(const u_char __user *userPtr, size_t userCount, | |
487 | u_char frame[], ssize_t *frameUsed, | |
488 | ssize_t frameLeft) | |
489 | { | |
490 | ssize_t count, used; | |
491 | short *p = (short *) &frame[*frameUsed]; | |
492 | int val, stereo = dmasound.soft.stereo; | |
493 | ||
494 | frameLeft >>= 2; | |
495 | if (stereo) | |
496 | userCount >>= 1; | |
497 | used = count = min_t(unsigned long, userCount, frameLeft); | |
498 | while (count > 0) { | |
499 | u_char data; | |
500 | ||
501 | val = *p++; | |
502 | val = (val * software_input_volume) >> 7; | |
503 | data = (val >> 8) ^ 0x80; | |
504 | if (put_user(data, (u_char __user *)userPtr++)) | |
505 | return -EFAULT; | |
506 | if (stereo) { | |
507 | val = *p; | |
508 | val = (val * software_input_volume) >> 7; | |
509 | data = (val >> 8) ^ 0x80; | |
510 | if (put_user(data, (u_char __user *)userPtr++)) | |
511 | return -EFAULT; | |
512 | } | |
513 | p++; | |
514 | count--; | |
515 | } | |
516 | *frameUsed += used * 4; | |
517 | return stereo? used * 2: used; | |
518 | } | |
519 | ||
520 | static ssize_t pmac_ct_s16_read(const u_char __user *userPtr, size_t userCount, | |
521 | u_char frame[], ssize_t *frameUsed, | |
522 | ssize_t frameLeft) | |
523 | { | |
524 | ssize_t count, used; | |
525 | int stereo = dmasound.soft.stereo; | |
526 | short *fp = (short *) &frame[*frameUsed]; | |
527 | short __user *up = (short __user *) userPtr; | |
528 | ||
529 | frameLeft >>= 2; | |
530 | userCount >>= (stereo? 2: 1); | |
531 | used = count = min_t(unsigned long, userCount, frameLeft); | |
532 | while (count > 0) { | |
533 | short data; | |
534 | ||
535 | data = *fp++; | |
536 | data = (data * software_input_volume) >> 7; | |
537 | if (put_user(data, up++)) | |
538 | return -EFAULT; | |
539 | if (stereo) { | |
540 | data = *fp; | |
541 | data = (data * software_input_volume) >> 7; | |
542 | if (put_user(data, up++)) | |
543 | return -EFAULT; | |
544 | } | |
545 | fp++; | |
546 | count--; | |
547 | } | |
548 | *frameUsed += used * 4; | |
549 | return stereo? used * 4: used * 2; | |
550 | } | |
551 | ||
552 | static ssize_t pmac_ct_u16_read(const u_char __user *userPtr, size_t userCount, | |
553 | u_char frame[], ssize_t *frameUsed, | |
554 | ssize_t frameLeft) | |
555 | { | |
556 | ssize_t count, used; | |
557 | int mask = (dmasound.soft.format == AFMT_U16_LE? 0x0080: 0x8000); | |
558 | int stereo = dmasound.soft.stereo; | |
559 | short *fp = (short *) &frame[*frameUsed]; | |
560 | short __user *up = (short __user *) userPtr; | |
561 | ||
562 | frameLeft >>= 2; | |
563 | userCount >>= (stereo? 2: 1); | |
564 | used = count = min_t(unsigned long, userCount, frameLeft); | |
565 | while (count > 0) { | |
566 | int data; | |
567 | ||
568 | data = *fp++; | |
569 | data = (data * software_input_volume) >> 7; | |
570 | data ^= mask; | |
571 | if (put_user(data, up++)) | |
572 | return -EFAULT; | |
573 | if (stereo) { | |
574 | data = *fp; | |
575 | data = (data * software_input_volume) >> 7; | |
576 | data ^= mask; | |
577 | if (put_user(data, up++)) | |
578 | return -EFAULT; | |
579 | } | |
580 | fp++; | |
581 | count--; | |
582 | } | |
583 | *frameUsed += used * 4; | |
584 | return stereo? used * 4: used * 2; | |
585 | } | |
586 | ||
587 | /* data in routines (reducing speed)... */ | |
588 | ||
589 | static ssize_t pmac_ctx_s8_read(const u_char __user *userPtr, size_t userCount, | |
590 | u_char frame[], ssize_t *frameUsed, | |
591 | ssize_t frameLeft) | |
592 | { | |
593 | short *p = (short *) &frame[*frameUsed]; | |
594 | int bal = expand_read_bal; | |
595 | int vall,valr, stereo = dmasound.soft.stereo; | |
596 | int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; | |
597 | int utotal, ftotal; | |
598 | ||
599 | frameLeft >>= 2; | |
600 | if (stereo) | |
601 | userCount >>= 1; | |
602 | ftotal = frameLeft; | |
603 | utotal = userCount; | |
604 | while (frameLeft) { | |
605 | u_char data; | |
606 | ||
607 | if (bal<0 && userCount == 0) | |
608 | break; | |
609 | vall = *p++; | |
610 | vall = (vall * software_input_volume) >> 7; | |
611 | if (stereo) { | |
612 | valr = *p; | |
613 | valr = (valr * software_input_volume) >> 7; | |
614 | } | |
615 | p++; | |
616 | if (bal < 0) { | |
617 | data = vall >> 8; | |
618 | if (put_user(data, (u_char __user *)userPtr++)) | |
619 | return -EFAULT; | |
620 | if (stereo) { | |
621 | data = valr >> 8; | |
622 | if (put_user(data, (u_char __user *)userPtr++)) | |
623 | return -EFAULT; | |
624 | } | |
625 | userCount--; | |
626 | bal += hSpeed; | |
627 | } | |
628 | frameLeft--; | |
629 | bal -= sSpeed; | |
630 | } | |
631 | expand_read_bal=bal; | |
632 | *frameUsed += (ftotal - frameLeft) * 4; | |
633 | utotal -= userCount; | |
634 | return stereo? utotal * 2: utotal; | |
635 | } | |
636 | ||
637 | ||
638 | static ssize_t pmac_ctx_u8_read(const u_char __user *userPtr, size_t userCount, | |
639 | u_char frame[], ssize_t *frameUsed, | |
640 | ssize_t frameLeft) | |
641 | { | |
642 | short *p = (short *) &frame[*frameUsed]; | |
643 | int bal = expand_read_bal; | |
644 | int vall,valr, stereo = dmasound.soft.stereo; | |
645 | int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; | |
646 | int utotal, ftotal; | |
647 | ||
648 | frameLeft >>= 2; | |
649 | if (stereo) | |
650 | userCount >>= 1; | |
651 | ftotal = frameLeft; | |
652 | utotal = userCount; | |
653 | while (frameLeft) { | |
654 | u_char data; | |
655 | ||
656 | if (bal<0 && userCount == 0) | |
657 | break; | |
658 | ||
659 | vall = *p++; | |
660 | vall = (vall * software_input_volume) >> 7; | |
661 | if (stereo) { | |
662 | valr = *p; | |
663 | valr = (valr * software_input_volume) >> 7; | |
664 | } | |
665 | p++; | |
666 | if (bal < 0) { | |
667 | data = (vall >> 8) ^ 0x80; | |
668 | if (put_user(data, (u_char __user *)userPtr++)) | |
669 | return -EFAULT; | |
670 | if (stereo) { | |
671 | data = (valr >> 8) ^ 0x80; | |
672 | if (put_user(data, (u_char __user *)userPtr++)) | |
673 | return -EFAULT; | |
674 | } | |
675 | userCount--; | |
676 | bal += hSpeed; | |
677 | } | |
678 | frameLeft--; | |
679 | bal -= sSpeed; | |
680 | } | |
681 | expand_read_bal=bal; | |
682 | *frameUsed += (ftotal - frameLeft) * 4; | |
683 | utotal -= userCount; | |
684 | return stereo? utotal * 2: utotal; | |
685 | } | |
686 | ||
687 | static ssize_t pmac_ctx_s16_read(const u_char __user *userPtr, size_t userCount, | |
688 | u_char frame[], ssize_t *frameUsed, | |
689 | ssize_t frameLeft) | |
690 | { | |
691 | int bal = expand_read_bal; | |
692 | short *fp = (short *) &frame[*frameUsed]; | |
693 | short __user *up = (short __user *) userPtr; | |
694 | int stereo = dmasound.soft.stereo; | |
695 | int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; | |
696 | int utotal, ftotal; | |
697 | ||
698 | frameLeft >>= 2; | |
699 | userCount >>= (stereo? 2: 1); | |
700 | ftotal = frameLeft; | |
701 | utotal = userCount; | |
702 | while (frameLeft) { | |
703 | int datal,datar; | |
704 | ||
705 | if (bal<0 && userCount == 0) | |
706 | break; | |
707 | ||
708 | datal = *fp++; | |
709 | datal = (datal * software_input_volume) >> 7; | |
710 | if (stereo) { | |
711 | datar = *fp; | |
712 | datar = (datar * software_input_volume) >> 7; | |
713 | } | |
714 | fp++; | |
715 | if (bal < 0) { | |
716 | if (put_user(datal, up++)) | |
717 | return -EFAULT; | |
718 | if (stereo) { | |
719 | if (put_user(datar, up++)) | |
720 | return -EFAULT; | |
721 | } | |
722 | userCount--; | |
723 | bal += hSpeed; | |
724 | } | |
725 | frameLeft--; | |
726 | bal -= sSpeed; | |
727 | } | |
728 | expand_read_bal=bal; | |
729 | *frameUsed += (ftotal - frameLeft) * 4; | |
730 | utotal -= userCount; | |
731 | return stereo? utotal * 4: utotal * 2; | |
732 | } | |
733 | ||
734 | static ssize_t pmac_ctx_u16_read(const u_char __user *userPtr, size_t userCount, | |
735 | u_char frame[], ssize_t *frameUsed, | |
736 | ssize_t frameLeft) | |
737 | { | |
738 | int bal = expand_read_bal; | |
739 | int mask = (dmasound.soft.format == AFMT_U16_LE? 0x0080: 0x8000); | |
740 | short *fp = (short *) &frame[*frameUsed]; | |
741 | short __user *up = (short __user *) userPtr; | |
742 | int stereo = dmasound.soft.stereo; | |
743 | int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; | |
744 | int utotal, ftotal; | |
745 | ||
746 | frameLeft >>= 2; | |
747 | userCount >>= (stereo? 2: 1); | |
748 | ftotal = frameLeft; | |
749 | utotal = userCount; | |
750 | while (frameLeft) { | |
751 | int datal,datar; | |
752 | ||
753 | if (bal<0 && userCount == 0) | |
754 | break; | |
755 | ||
756 | datal = *fp++; | |
757 | datal = (datal * software_input_volume) >> 7; | |
758 | datal ^= mask; | |
759 | if (stereo) { | |
760 | datar = *fp; | |
761 | datar = (datar * software_input_volume) >> 7; | |
762 | datar ^= mask; | |
763 | } | |
764 | fp++; | |
765 | if (bal < 0) { | |
766 | if (put_user(datal, up++)) | |
767 | return -EFAULT; | |
768 | if (stereo) { | |
769 | if (put_user(datar, up++)) | |
770 | return -EFAULT; | |
771 | } | |
772 | userCount--; | |
773 | bal += hSpeed; | |
774 | } | |
775 | frameLeft--; | |
776 | bal -= sSpeed; | |
777 | } | |
778 | expand_read_bal=bal; | |
779 | *frameUsed += (ftotal - frameLeft) * 4; | |
780 | utotal -= userCount; | |
781 | return stereo? utotal * 4: utotal * 2; | |
782 | } | |
783 | ||
784 | ||
785 | TRANS transAwacsNormal = { | |
786 | .ct_ulaw= pmac_ct_law, | |
787 | .ct_alaw= pmac_ct_law, | |
788 | .ct_s8= pmac_ct_s8, | |
789 | .ct_u8= pmac_ct_u8, | |
790 | .ct_s16be= pmac_ct_s16, | |
791 | .ct_u16be= pmac_ct_u16, | |
792 | .ct_s16le= pmac_ct_s16, | |
793 | .ct_u16le= pmac_ct_u16, | |
794 | }; | |
795 | ||
796 | TRANS transAwacsExpand = { | |
797 | .ct_ulaw= pmac_ctx_law, | |
798 | .ct_alaw= pmac_ctx_law, | |
799 | .ct_s8= pmac_ctx_s8, | |
800 | .ct_u8= pmac_ctx_u8, | |
801 | .ct_s16be= pmac_ctx_s16, | |
802 | .ct_u16be= pmac_ctx_u16, | |
803 | .ct_s16le= pmac_ctx_s16, | |
804 | .ct_u16le= pmac_ctx_u16, | |
805 | }; | |
806 | ||
807 | TRANS transAwacsNormalRead = { | |
808 | .ct_s8= pmac_ct_s8_read, | |
809 | .ct_u8= pmac_ct_u8_read, | |
810 | .ct_s16be= pmac_ct_s16_read, | |
811 | .ct_u16be= pmac_ct_u16_read, | |
812 | .ct_s16le= pmac_ct_s16_read, | |
813 | .ct_u16le= pmac_ct_u16_read, | |
814 | }; | |
815 | ||
816 | TRANS transAwacsExpandRead = { | |
817 | .ct_s8= pmac_ctx_s8_read, | |
818 | .ct_u8= pmac_ctx_u8_read, | |
819 | .ct_s16be= pmac_ctx_s16_read, | |
820 | .ct_u16be= pmac_ctx_u16_read, | |
821 | .ct_s16le= pmac_ctx_s16_read, | |
822 | .ct_u16le= pmac_ctx_u16_read, | |
823 | }; | |
824 | ||
825 | /* translation tables */ | |
826 | /* 16 bit mu-law */ | |
827 | ||
828 | static short dmasound_ulaw2dma16[] = { | |
829 | -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956, | |
830 | -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764, | |
831 | -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412, | |
832 | -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316, | |
833 | -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140, | |
834 | -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, | |
835 | -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004, | |
836 | -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, | |
837 | -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436, | |
838 | -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, | |
839 | -876, -844, -812, -780, -748, -716, -684, -652, | |
840 | -620, -588, -556, -524, -492, -460, -428, -396, | |
841 | -372, -356, -340, -324, -308, -292, -276, -260, | |
842 | -244, -228, -212, -196, -180, -164, -148, -132, | |
843 | -120, -112, -104, -96, -88, -80, -72, -64, | |
844 | -56, -48, -40, -32, -24, -16, -8, 0, | |
845 | 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956, | |
846 | 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, | |
847 | 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412, | |
848 | 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316, | |
849 | 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140, | |
850 | 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092, | |
851 | 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004, | |
852 | 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980, | |
853 | 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436, | |
854 | 1372, 1308, 1244, 1180, 1116, 1052, 988, 924, | |
855 | 876, 844, 812, 780, 748, 716, 684, 652, | |
856 | 620, 588, 556, 524, 492, 460, 428, 396, | |
857 | 372, 356, 340, 324, 308, 292, 276, 260, | |
858 | 244, 228, 212, 196, 180, 164, 148, 132, | |
859 | 120, 112, 104, 96, 88, 80, 72, 64, | |
860 | 56, 48, 40, 32, 24, 16, 8, 0, | |
861 | }; | |
862 | ||
863 | /* 16 bit A-law */ | |
864 | ||
865 | static short dmasound_alaw2dma16[] = { | |
866 | -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, | |
867 | -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, | |
868 | -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, | |
869 | -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, | |
870 | -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944, | |
871 | -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136, | |
872 | -11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472, | |
873 | -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568, | |
874 | -344, -328, -376, -360, -280, -264, -312, -296, | |
875 | -472, -456, -504, -488, -408, -392, -440, -424, | |
876 | -88, -72, -120, -104, -24, -8, -56, -40, | |
877 | -216, -200, -248, -232, -152, -136, -184, -168, | |
878 | -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184, | |
879 | -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, | |
880 | -688, -656, -752, -720, -560, -528, -624, -592, | |
881 | -944, -912, -1008, -976, -816, -784, -880, -848, | |
882 | 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, | |
883 | 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, | |
884 | 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, | |
885 | 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, | |
886 | 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, | |
887 | 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, | |
888 | 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, | |
889 | 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, | |
890 | 344, 328, 376, 360, 280, 264, 312, 296, | |
891 | 472, 456, 504, 488, 408, 392, 440, 424, | |
892 | 88, 72, 120, 104, 24, 8, 56, 40, | |
893 | 216, 200, 248, 232, 152, 136, 184, 168, | |
894 | 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, | |
895 | 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, | |
896 | 688, 656, 752, 720, 560, 528, 624, 592, | |
897 | 944, 912, 1008, 976, 816, 784, 880, 848, | |
898 | }; |