source: GPL/alsa-kernel/pci/emu10k1/emupcm.c@ 18

Last change on this file since 18 was 18, checked in by vladest, 20 years ago

initial import

File size: 66.0 KB
Line 
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3 * Creative Labs, Inc.
4 * Routines for control of EMU10K1 chips / PCM routines
5 *
6 * BUGS:
7 * --
8 *
9 * TODO:
10 * --
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 */
27
28#define __NO_VERSION__
29#include <sound/driver.h>
30#include <linux/slab.h>
31#include <linux/time.h>
32#include <sound/core.h>
33#include <sound/emu10k1.h>
34
35static inline snd_ctl_elem_id_t *snd_ctl_build_ioff(snd_ctl_elem_id_t *dst_id,
36 snd_kcontrol_t *src_kctl,
37 unsigned int offset)
38{
39 *dst_id = src_kctl->id;
40 dst_id->index += offset;
41 dst_id->numid += offset;
42 return dst_id;
43}
44
45static void snd_emu10k1_pcm_interrupt(emu10k1_t *emu, emu10k1_voice_t *voice)
46{
47 emu10k1_pcm_t *epcm;
48
49 if ((epcm = voice->epcm) == NULL)
50 return;
51 if (epcm->substream == NULL)
52 return;
53#if 0
54 printk("IRQ: position = 0x%x, period = 0x%x, size = 0x%x\n",
55 epcm->substream->runtime->hw->pointer(emu, epcm->substream),
56 snd_pcm_lib_period_bytes(epcm->substream),
57 snd_pcm_lib_buffer_bytes(epcm->substream));
58#endif
59 snd_pcm_period_elapsed(epcm->substream);
60}
61
62static void snd_emu10k1_pcm_ac97adc_interrupt(emu10k1_t *emu, unsigned int status)
63{
64#if 0
65 if (status & IPR_ADCBUFHALFFULL) {
66 if (emu->pcm_capture_substream->runtime->mode == SNDRV_PCM_MODE_FRAME)
67 return;
68 }
69#endif
70 snd_pcm_period_elapsed(emu->pcm_capture_substream);
71}
72
73static void snd_emu10k1_pcm_ac97mic_interrupt(emu10k1_t *emu, unsigned int status)
74{
75#if 0
76 if (status & IPR_MICBUFHALFFULL) {
77 if (emu->pcm_capture_mic_substream->runtime->mode == SNDRV_PCM_MODE_FRAME)
78 return;
79 }
80#endif
81 snd_pcm_period_elapsed(emu->pcm_capture_mic_substream);
82}
83
84static void snd_emu10k1_pcm_efx_interrupt(emu10k1_t *emu, unsigned int status)
85{
86#if 0
87 if (status & IPR_EFXBUFHALFFULL) {
88 if (emu->pcm_capture_efx_substream->runtime->mode == SNDRV_PCM_MODE_FRAME)
89 return;
90 }
91#endif
92 snd_pcm_period_elapsed(emu->pcm_capture_efx_substream);
93}
94
95static snd_pcm_uframes_t snd_emu10k1_efx_playback_pointer(snd_pcm_substream_t * substream)
96{
97 emu10k1_t *emu = snd_pcm_substream_chip(substream);
98 snd_pcm_runtime_t *runtime = substream->runtime;
99 emu10k1_pcm_t *epcm = runtime->private_data;
100 unsigned int ptr;
101
102 if (!epcm->running)
103 return 0;
104 ptr = snd_emu10k1_ptr_read(emu, CCCA, epcm->voices[0]->number) & 0x00ffffff;
105 ptr += runtime->buffer_size;
106 ptr -= epcm->ccca_start_addr;
107 ptr %= runtime->buffer_size;
108
109 return ptr;
110}
111
112static int snd_emu10k1_pcm_channel_alloc(emu10k1_pcm_t * epcm, int voices)
113{
114 int err, i;
115
116 if (epcm->voices[1] != NULL && voices < 2) {
117 snd_emu10k1_voice_free(epcm->emu, epcm->voices[1]);
118 epcm->voices[1] = NULL;
119 }
120 for (i = 0; i < voices; i++) {
121 if (epcm->voices[i] == NULL)
122 break;
123 }
124 if (i == voices)
125 return 0; /* already allocated */
126 for (i = 0; i < ARRAY_SIZE(epcm->voices); i++) {
127 if (epcm->voices[i]) {
128 snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]);
129 epcm->voices[i] = NULL;
130 }
131 }
132 err = snd_emu10k1_voice_alloc(epcm->emu,
133 epcm->type == PLAYBACK_EMUVOICE ? EMU10K1_PCM : EMU10K1_EFX,
134 voices,
135 &epcm->voices[0]);
136 if (err < 0)
137 return err;
138 epcm->voices[0]->epcm = epcm;
139 if (voices > 1) {
140 for (i = 1; i < voices; i++) {
141 epcm->voices[i] = &epcm->emu->voices[epcm->voices[0]->number + i];
142 epcm->voices[i]->epcm = epcm;
143 }
144 }
145 if (epcm->extra == NULL) {
146 err = snd_emu10k1_voice_alloc(epcm->emu,
147 epcm->type == PLAYBACK_EMUVOICE ? EMU10K1_PCM : EMU10K1_EFX,
148 1,
149 &epcm->extra);
150 if (err < 0) {
151 // printk("pcm_channel_alloc: failed extra: voices=%d, frame=%d\n", voices, frame);
152 for (i = 0; i < voices; i++) {
153 snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]);
154 epcm->voices[i] = NULL;
155 }
156 return err;
157 }
158 epcm->extra->epcm = epcm;
159 epcm->extra->interrupt = snd_emu10k1_pcm_interrupt;
160 }
161 return 0;
162}
163
164static unsigned int capture_period_sizes[31] = {
165 384, 448, 512, 640,
166 384*2, 448*2, 512*2, 640*2,
167 384*4, 448*4, 512*4, 640*4,
168 384*8, 448*8, 512*8, 640*8,
169 384*16, 448*16, 512*16, 640*16,
170 384*32, 448*32, 512*32, 640*32,
171 384*64, 448*64, 512*64, 640*64,
172 384*128,448*128,512*128
173};
174
175static snd_pcm_hw_constraint_list_t hw_constraints_capture_period_sizes = {
176 31,
177 capture_period_sizes,
178 0
179};
180
181static unsigned int capture_rates[8] = {
182 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000
183};
184
185static snd_pcm_hw_constraint_list_t hw_constraints_capture_rates = {
186 8,
187 capture_rates,
188 0
189};
190
191static unsigned int snd_emu10k1_capture_rate_reg(unsigned int rate)
192{
193 switch (rate) {
194 case 8000: return ADCCR_SAMPLERATE_8;
195 case 11025: return ADCCR_SAMPLERATE_11;
196 case 16000: return ADCCR_SAMPLERATE_16;
197 case 22050: return ADCCR_SAMPLERATE_22;
198 case 24000: return ADCCR_SAMPLERATE_24;
199 case 32000: return ADCCR_SAMPLERATE_32;
200 case 44100: return ADCCR_SAMPLERATE_44;
201 case 48000: return ADCCR_SAMPLERATE_48;
202 default:
203 snd_BUG();
204 return ADCCR_SAMPLERATE_8;
205 }
206}
207
208static unsigned int snd_emu10k1_audigy_capture_rate_reg(unsigned int rate)
209{
210 switch (rate) {
211 case 8000: return A_ADCCR_SAMPLERATE_8;
212 case 11025: return A_ADCCR_SAMPLERATE_11;
213 case 12000: return A_ADCCR_SAMPLERATE_12; /* really supported? */
214 case 16000: return ADCCR_SAMPLERATE_16;
215 case 22050: return ADCCR_SAMPLERATE_22;
216 case 24000: return ADCCR_SAMPLERATE_24;
217 case 32000: return ADCCR_SAMPLERATE_32;
218 case 44100: return ADCCR_SAMPLERATE_44;
219 case 48000: return ADCCR_SAMPLERATE_48;
220 default:
221 snd_BUG();
222 return A_ADCCR_SAMPLERATE_8;
223 }
224}
225
226static unsigned int emu10k1_calc_pitch_target(unsigned int rate)
227{
228 unsigned int pitch_target;
229
230 pitch_target = (rate << 8) / 375;
231 pitch_target = (pitch_target >> 1) + (pitch_target & 1);
232 return pitch_target;
233}
234
235#define PITCH_48000 0x00004000
236#define PITCH_96000 0x00008000
237#define PITCH_85000 0x00007155
238#define PITCH_80726 0x00006ba2
239#define PITCH_67882 0x00005a82
240#define PITCH_57081 0x00004c1c
241
242static unsigned int emu10k1_select_interprom(unsigned int pitch_target)
243{
244 if (pitch_target == PITCH_48000)
245 return CCCA_INTERPROM_0;
246 else if (pitch_target < PITCH_48000)
247 return CCCA_INTERPROM_1;
248 else if (pitch_target >= PITCH_96000)
249 return CCCA_INTERPROM_0;
250 else if (pitch_target >= PITCH_85000)
251 return CCCA_INTERPROM_6;
252 else if (pitch_target >= PITCH_80726)
253 return CCCA_INTERPROM_5;
254 else if (pitch_target >= PITCH_67882)
255 return CCCA_INTERPROM_4;
256 else if (pitch_target >= PITCH_57081)
257 return CCCA_INTERPROM_3;
258 else
259 return CCCA_INTERPROM_2;
260}
261
262/*
263 * calculate cache invalidate size
264 *
265 * stereo: channel is stereo
266 * w_16: using 16bit samples
267 *
268 * returns: cache invalidate size in samples
269 */
270static int inline emu10k1_ccis(int stereo, int w_16)
271{
272 if (w_16) {
273 return stereo ? 24 : 26;
274 } else {
275 return stereo ? 24*2 : 26*2;
276 }
277}
278
279static void snd_emu10k1_pcm_init_voice(emu10k1_t *emu,
280 int master, int extra,
281 emu10k1_voice_t *evoice,
282 unsigned int start_addr,
283 unsigned int end_addr,
284 emu10k1_pcm_mixer_t *mix)
285{
286 snd_pcm_substream_t *substream = evoice->epcm->substream;
287 snd_pcm_runtime_t *runtime = substream->runtime;
288 unsigned int silent_page, tmp;
289 int voice, stereo, w_16;
290 unsigned char attn, send_amount[8];
291 unsigned char send_routing[8];
292 unsigned long flags;
293 unsigned int pitch_target;
294 unsigned int ccis;
295
296 voice = evoice->number;
297 stereo = runtime->channels == 2;
298 w_16 = snd_pcm_format_width(runtime->format) == 16;
299
300 if (!extra && stereo) {
301 start_addr >>= 1;
302 end_addr >>= 1;
303 }
304 if (w_16) {
305 start_addr >>= 1;
306 end_addr >>= 1;
307 }
308
309 spin_lock_irqsave(&emu->reg_lock, flags);
310
311 /* volume parameters */
312 if (extra) {
313 attn = 0;
314 memset(send_routing, 0, sizeof(send_routing));
315 send_routing[0] = 0;
316 send_routing[1] = 1;
317 send_routing[2] = 2;
318 send_routing[3] = 3;
319 memset(send_amount, 0, sizeof(send_amount));
320 } else {
321 /* mono, left, right (master voice = left) */
322 tmp = stereo ? (master ? 1 : 2) : 0;
323 memcpy(send_routing, &mix->send_routing[tmp][0], 8);
324 memcpy(send_amount, &mix->send_volume[tmp][0], 8);
325 }
326
327 ccis = emu10k1_ccis(stereo, w_16);
328
329 if (master) {
330 evoice->epcm->ccca_start_addr = start_addr + ccis;
331 if (extra) {
332 start_addr += ccis;
333 end_addr += ccis;
334 }
335 if (stereo && !extra) {
336 snd_emu10k1_ptr_write(emu, CPF, voice, CPF_STEREO_MASK);
337 snd_emu10k1_ptr_write(emu, CPF, (voice + 1), CPF_STEREO_MASK);
338 } else {
339 snd_emu10k1_ptr_write(emu, CPF, voice, 0);
340 }
341 }
342
343 // setup routing
344 if (emu->audigy) {
345 snd_emu10k1_ptr_write(emu, A_FXRT1, voice,
346 snd_emu10k1_compose_audigy_fxrt1(send_routing));
347 snd_emu10k1_ptr_write(emu, A_FXRT2, voice,
348 snd_emu10k1_compose_audigy_fxrt2(send_routing));
349 snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, voice,
350 ((unsigned int)send_amount[4] << 24) |
351 ((unsigned int)send_amount[5] << 16) |
352 ((unsigned int)send_amount[6] << 8) |
353 (unsigned int)send_amount[7]);
354 } else
355 snd_emu10k1_ptr_write(emu, FXRT, voice,
356 snd_emu10k1_compose_send_routing(send_routing));
357 // Stop CA
358 // Assumption that PT is already 0 so no harm overwriting
359 snd_emu10k1_ptr_write(emu, PTRX, voice, (send_amount[0] << 8) | send_amount[1]);
360 snd_emu10k1_ptr_write(emu, DSL, voice, end_addr | (send_amount[3] << 24));
361 snd_emu10k1_ptr_write(emu, PSST, voice, start_addr | (send_amount[2] << 24));
362 pitch_target = emu10k1_calc_pitch_target(runtime->rate);
363 if (extra)
364 snd_emu10k1_ptr_write(emu, CCCA, voice, start_addr |
365 emu10k1_select_interprom(pitch_target) |
366 (w_16 ? 0 : CCCA_8BITSELECT));
367 else
368 snd_emu10k1_ptr_write(emu, CCCA, voice, (start_addr + ccis) |
369 emu10k1_select_interprom(pitch_target) |
370 (w_16 ? 0 : CCCA_8BITSELECT));
371 // Clear filter delay memory
372 snd_emu10k1_ptr_write(emu, Z1, voice, 0);
373 snd_emu10k1_ptr_write(emu, Z2, voice, 0);
374 // invalidate maps
375 silent_page = ((unsigned int)emu->silent_page.addr << 1) | MAP_PTI_MASK;
376 snd_emu10k1_ptr_write(emu, MAPA, voice, silent_page);
377 snd_emu10k1_ptr_write(emu, MAPB, voice, silent_page);
378 // modulation envelope
379 snd_emu10k1_ptr_write(emu, CVCF, voice, 0xffff);
380 snd_emu10k1_ptr_write(emu, VTFT, voice, 0xffff);
381 snd_emu10k1_ptr_write(emu, ATKHLDM, voice, 0);
382 snd_emu10k1_ptr_write(emu, DCYSUSM, voice, 0x007f);
383 snd_emu10k1_ptr_write(emu, LFOVAL1, voice, 0x8000);
384 snd_emu10k1_ptr_write(emu, LFOVAL2, voice, 0x8000);
385 snd_emu10k1_ptr_write(emu, FMMOD, voice, 0);
386 snd_emu10k1_ptr_write(emu, TREMFRQ, voice, 0);
387 snd_emu10k1_ptr_write(emu, FM2FRQ2, voice, 0);
388 snd_emu10k1_ptr_write(emu, ENVVAL, voice, 0x8000);
389 // volume envelope
390 snd_emu10k1_ptr_write(emu, ATKHLDV, voice, 0x7f7f);
391 snd_emu10k1_ptr_write(emu, ENVVOL, voice, 0x0000);
392 // filter envelope
393 snd_emu10k1_ptr_write(emu, PEFE_FILTERAMOUNT, voice, 0x7f);
394 // pitch envelope
395 snd_emu10k1_ptr_write(emu, PEFE_PITCHAMOUNT, voice, 0);
396
397 spin_unlock_irqrestore(&emu->reg_lock, flags);
398}
399
400static int snd_emu10k1_playback_hw_params(snd_pcm_substream_t * substream,
401 snd_pcm_hw_params_t * hw_params)
402{
403 emu10k1_t *emu = snd_pcm_substream_chip(substream);
404 snd_pcm_runtime_t *runtime = substream->runtime;
405 emu10k1_pcm_t *epcm = runtime->private_data;
406 int err;
407
408 if ((err = snd_emu10k1_pcm_channel_alloc(epcm, params_channels(hw_params))) < 0)
409 return err;
410 if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
411 return err;
412 if (err > 0) { /* change */
413 snd_util_memblk_t *memblk;
414 if (epcm->memblk != NULL)
415 snd_emu10k1_free_pages(emu, epcm->memblk);
416 memblk = snd_emu10k1_alloc_pages(emu, substream);
417 if ((epcm->memblk = memblk) == NULL || ((emu10k1_memblk_t *)memblk)->mapped_page < 0) {
418 epcm->start_addr = 0;
419 return -ENOMEM;
420 }
421 epcm->start_addr = ((emu10k1_memblk_t *)memblk)->mapped_page << PAGE_SHIFT;
422 }
423 return 0;
424}
425
426static int snd_emu10k1_playback_hw_free(snd_pcm_substream_t * substream)
427{
428 emu10k1_t *emu = snd_pcm_substream_chip(substream);
429 snd_pcm_runtime_t *runtime = substream->runtime;
430 emu10k1_pcm_t *epcm;
431
432 if (runtime->private_data == NULL)
433 return 0;
434 epcm = runtime->private_data;
435 if (epcm->extra) {
436 snd_emu10k1_voice_free(epcm->emu, epcm->extra);
437 epcm->extra = NULL;
438 }
439 if (epcm->voices[1]) {
440 snd_emu10k1_voice_free(epcm->emu, epcm->voices[1]);
441 epcm->voices[1] = NULL;
442 }
443 if (epcm->voices[0]) {
444 snd_emu10k1_voice_free(epcm->emu, epcm->voices[0]);
445 epcm->voices[0] = NULL;
446 }
447 if (epcm->memblk) {
448 snd_emu10k1_free_pages(emu, epcm->memblk);
449 epcm->memblk = NULL;
450 epcm->start_addr = 0;
451 }
452 snd_pcm_lib_free_pages(substream);
453 return 0;
454}
455
456static int snd_emu10k1_efx_playback_hw_free(snd_pcm_substream_t * substream)
457{
458 emu10k1_t *emu = snd_pcm_substream_chip(substream);
459 snd_pcm_runtime_t *runtime = substream->runtime;
460 emu10k1_pcm_t *epcm;
461 int i;
462
463 if (runtime->private_data == NULL)
464 return 0;
465 epcm = runtime->private_data;
466 if (epcm->extra) {
467 snd_emu10k1_voice_free(epcm->emu, epcm->extra);
468 epcm->extra = NULL;
469 }
470 for (i=0; i < NUM_EFX_PLAYBACK; i++) {
471 if (epcm->voices[i]) {
472 snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]);
473 epcm->voices[i] = NULL;
474 }
475 }
476 if (epcm->memblk) {
477 snd_emu10k1_free_pages(emu, epcm->memblk);
478 epcm->memblk = NULL;
479 epcm->start_addr = 0;
480 }
481 snd_pcm_lib_free_pages(substream);
482 return 0;
483}
484
485static int snd_emu10k1_playback_prepare(snd_pcm_substream_t * substream)
486{
487 emu10k1_t *emu = snd_pcm_substream_chip(substream);
488 snd_pcm_runtime_t *runtime = substream->runtime;
489 emu10k1_pcm_t *epcm = runtime->private_data;
490 unsigned int start_addr, end_addr;
491
492 start_addr = epcm->start_addr;
493 end_addr = snd_pcm_lib_period_bytes(substream);
494 if (runtime->channels == 2) {
495 start_addr >>= 1;
496 end_addr >>= 1;
497 }
498 end_addr += start_addr;
499 snd_emu10k1_pcm_init_voice(emu, 1, 1, epcm->extra,
500 start_addr, end_addr, NULL);
501 start_addr = epcm->start_addr;
502 end_addr = epcm->start_addr + snd_pcm_lib_buffer_bytes(substream);
503 snd_emu10k1_pcm_init_voice(emu, 1, 0, epcm->voices[0],
504 start_addr, end_addr,
505 &emu->pcm_mixer[substream->number]);
506 if (epcm->voices[1])
507 snd_emu10k1_pcm_init_voice(emu, 0, 0, epcm->voices[1],
508 start_addr, end_addr,
509 &emu->pcm_mixer[substream->number]);
510 return 0;
511}
512
513static int snd_emu10k1_efx_playback_prepare(snd_pcm_substream_t * substream)
514{
515 emu10k1_t *emu = snd_pcm_substream_chip(substream);
516 snd_pcm_runtime_t *runtime = substream->runtime;
517 emu10k1_pcm_t *epcm = runtime->private_data;
518 unsigned int start_addr, end_addr;
519 unsigned int channel_size;
520 int i;
521
522 start_addr = epcm->start_addr;
523 end_addr = epcm->start_addr + snd_pcm_lib_buffer_bytes(substream);
524
525 /*
526 * the kX driver leaves some space between voices
527 */
528 channel_size = ( end_addr - start_addr ) / NUM_EFX_PLAYBACK;
529
530 snd_emu10k1_pcm_init_voice(emu, 1, 1, epcm->extra,
531 start_addr, start_addr + (channel_size / 2), NULL);
532
533 /* only difference with the master voice is we use it for the pointer */
534 snd_emu10k1_pcm_init_voice(emu, 1, 0, epcm->voices[0],
535 start_addr, start_addr + channel_size,
536 &emu->efx_pcm_mixer[0]);
537
538 start_addr += channel_size;
539 for (i = 1; i < NUM_EFX_PLAYBACK; i++) {
540 snd_emu10k1_pcm_init_voice(emu, 0, 0, epcm->voices[i],
541 start_addr, start_addr + channel_size,
542 &emu->efx_pcm_mixer[i]);
543 start_addr += channel_size;
544 }
545
546 return 0;
547}
548
549static snd_pcm_hardware_t snd_emu10k1_efx_playback =
550{
551/*.info = */ (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_NONINTERLEAVED |
552 SNDRV_PCM_INFO_BLOCK_TRANSFER |
553 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE),
554/*.formats = */ SNDRV_PCM_FMTBIT_S16_LE,
555/*.rates = */ SNDRV_PCM_RATE_48000,
556/*.rate_min = */ 48000,
557/*.rate_max = */ 48000,
558/*.channels_min = */ NUM_EFX_PLAYBACK,
559/*.channels_max = */ NUM_EFX_PLAYBACK,
560/*.buffer_bytes_max = */ (64*1024),
561/*.period_bytes_min = */ 64,
562/*.period_bytes_max = */ (64*1024),
563/*.periods_min = */ 2,
564/*.periods_max = */ 2,
565/*.fifo_size = */ 0
566};
567
568static int snd_emu10k1_capture_hw_params(snd_pcm_substream_t * substream,
569 snd_pcm_hw_params_t * hw_params)
570{
571 return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
572}
573
574static int snd_emu10k1_capture_hw_free(snd_pcm_substream_t * substream)
575{
576 return snd_pcm_lib_free_pages(substream);
577}
578
579static int snd_emu10k1_capture_prepare(snd_pcm_substream_t * substream)
580{
581 emu10k1_t *emu = snd_pcm_substream_chip(substream);
582 snd_pcm_runtime_t *runtime = substream->runtime;
583 emu10k1_pcm_t *epcm = runtime->private_data;
584 int idx;
585
586 /* zeroing the buffer size will stop capture */
587 snd_emu10k1_ptr_write(emu, epcm->capture_bs_reg, 0, 0);
588 switch (epcm->type) {
589 case CAPTURE_AC97ADC:
590 snd_emu10k1_ptr_write(emu, ADCCR, 0, 0);
591 break;
592 case CAPTURE_EFX:
593 if (emu->audigy) {
594 snd_emu10k1_ptr_write(emu, A_FXWC1, 0, 0);
595 snd_emu10k1_ptr_write(emu, A_FXWC2, 0, 0);
596 } else
597 snd_emu10k1_ptr_write(emu, FXWC, 0, 0);
598 break;
599 default:
600 break;
601 }
602 snd_emu10k1_ptr_write(emu, epcm->capture_ba_reg, 0, runtime->dma_addr);
603 epcm->capture_bufsize = snd_pcm_lib_buffer_bytes(substream);
604 epcm->capture_bs_val = 0;
605 for (idx = 0; idx < 31; idx++) {
606 if (capture_period_sizes[idx] == epcm->capture_bufsize) {
607 epcm->capture_bs_val = idx + 1;
608 break;
609 }
610 }
611 if (epcm->capture_bs_val == 0) {
612 snd_BUG();
613 epcm->capture_bs_val++;
614 }
615 if (epcm->type == CAPTURE_AC97ADC) {
616 epcm->capture_cr_val = emu->audigy ? A_ADCCR_LCHANENABLE : ADCCR_LCHANENABLE;
617 if (runtime->channels > 1)
618 epcm->capture_cr_val |= emu->audigy ? A_ADCCR_RCHANENABLE : ADCCR_RCHANENABLE;
619 epcm->capture_cr_val |= emu->audigy ?
620 snd_emu10k1_audigy_capture_rate_reg(runtime->rate) :
621 snd_emu10k1_capture_rate_reg(runtime->rate);
622 }
623 return 0;
624}
625
626static void snd_emu10k1_playback_invalidate_cache(emu10k1_t *emu, int extra, emu10k1_voice_t *evoice)
627{
628 snd_pcm_runtime_t *runtime;
629 unsigned int voice, stereo, i, ccis, cra = 64, cs, sample;
630
631 if (evoice == NULL)
632 return;
633 runtime = evoice->epcm->substream->runtime;
634 voice = evoice->number;
635 stereo = (!extra && runtime->channels == 2);
636 sample = snd_pcm_format_width(runtime->format) == 16 ? 0 : 0x80808080;
637 ccis = emu10k1_ccis(stereo, sample == 0);
638 // set cs to 2 * number of cache registers beside the invalidated
639 cs = (sample == 0) ? (32-ccis) : (64-ccis+1) >> 1;
640 if (cs > 16) cs = 16;
641 for (i = 0; i < cs; i++) {
642 snd_emu10k1_ptr_write(emu, CD0 + i, voice, sample);
643 if (stereo) {
644 snd_emu10k1_ptr_write(emu, CD0 + i, voice + 1, sample);
645 }
646 }
647 // reset cache
648 snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice, 0);
649 snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice, cra);
650 if (stereo) {
651 snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice + 1, 0);
652 snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice + 1, cra);
653 }
654 // fill cache
655 snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice, ccis);
656 if (stereo) {
657 snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice+1, ccis);
658 }
659}
660
661static void snd_emu10k1_playback_prepare_voice(emu10k1_t *emu, emu10k1_voice_t *evoice,
662 int master, int extra,
663 emu10k1_pcm_mixer_t *mix)
664{
665 snd_pcm_substream_t *substream;
666 snd_pcm_runtime_t *runtime;
667 unsigned int attn, vattn;
668 unsigned int voice, tmp;
669
670 if (evoice == NULL) /* skip second voice for mono */
671 return;
672 substream = evoice->epcm->substream;
673 runtime = substream->runtime;
674 voice = evoice->number;
675 attn = extra ? 0 : 0x00ff;
676 tmp = runtime->channels == 2 ? (master ? 1 : 2) : 0;
677 vattn = mix != NULL ? (mix->attn[tmp] << 16) : 0;
678 snd_emu10k1_ptr_write(emu, IFATN, voice, attn);
679 snd_emu10k1_ptr_write(emu, VTFT, voice, vattn | 0xffff);
680 snd_emu10k1_ptr_write(emu, CVCF, voice, vattn | 0xffff);
681 snd_emu10k1_ptr_write(emu, DCYSUSV, voice, 0x7f7f);
682 snd_emu10k1_voice_clear_loop_stop(emu, voice);
683}
684
685static void snd_emu10k1_playback_trigger_voice(emu10k1_t *emu, emu10k1_voice_t *evoice, int master, int extra)
686{
687 snd_pcm_substream_t *substream;
688 snd_pcm_runtime_t *runtime;
689 unsigned int voice, pitch, pitch_target;
690
691 if (evoice == NULL) /* skip second voice for mono */
692 return;
693 substream = evoice->epcm->substream;
694 runtime = substream->runtime;
695 voice = evoice->number;
696
697 pitch = snd_emu10k1_rate_to_pitch(runtime->rate) >> 8;
698 pitch_target = emu10k1_calc_pitch_target(runtime->rate);
699 snd_emu10k1_ptr_write(emu, PTRX_PITCHTARGET, voice, pitch_target);
700 if (master || evoice->epcm->type == PLAYBACK_EFX)
701 snd_emu10k1_ptr_write(emu, CPF_CURRENTPITCH, voice, pitch_target);
702 snd_emu10k1_ptr_write(emu, IP, voice, pitch);
703 if (extra)
704 snd_emu10k1_voice_intr_enable(emu, voice);
705}
706
707static void snd_emu10k1_playback_stop_voice(emu10k1_t *emu, emu10k1_voice_t *evoice)
708{
709 unsigned int voice;
710
711 if (evoice == NULL)
712 return;
713 voice = evoice->number;
714 snd_emu10k1_voice_intr_disable(emu, voice);
715 snd_emu10k1_ptr_write(emu, PTRX_PITCHTARGET, voice, 0);
716 snd_emu10k1_ptr_write(emu, CPF_CURRENTPITCH, voice, 0);
717 snd_emu10k1_ptr_write(emu, IFATN, voice, 0xffff);
718 snd_emu10k1_ptr_write(emu, VTFT, voice, 0xffff);
719 snd_emu10k1_ptr_write(emu, CVCF, voice, 0xffff);
720 snd_emu10k1_ptr_write(emu, IP, voice, 0);
721}
722
723static int snd_emu10k1_playback_trigger(snd_pcm_substream_t * substream,
724 int cmd)
725{
726 emu10k1_t *emu = snd_pcm_substream_chip(substream);
727 snd_pcm_runtime_t *runtime = substream->runtime;
728 emu10k1_pcm_t *epcm = runtime->private_data;
729 emu10k1_pcm_mixer_t *mix;
730 int result = 0;
731
732 spin_lock(&emu->reg_lock);
733 switch (cmd) {
734 case SNDRV_PCM_TRIGGER_START:
735 // hmm this should cause full and half full interrupt to be raised?
736 snd_emu10k1_playback_invalidate_cache(emu, 1, epcm->extra); /* do we need this? */
737 snd_emu10k1_playback_invalidate_cache(emu, 0, epcm->voices[0]);
738 /* follow thru */
739 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
740 mix = &emu->pcm_mixer[substream->number];
741 snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 1, 0, mix);
742 snd_emu10k1_playback_prepare_voice(emu, epcm->voices[1], 0, 0, mix);
743 snd_emu10k1_playback_prepare_voice(emu, epcm->extra, 1, 1, NULL);
744 snd_emu10k1_playback_trigger_voice(emu, epcm->voices[0], 1, 0);
745 snd_emu10k1_playback_trigger_voice(emu, epcm->voices[1], 0, 0);
746 snd_emu10k1_playback_trigger_voice(emu, epcm->extra, 1, 1);
747 epcm->running = 1;
748 break;
749 case SNDRV_PCM_TRIGGER_STOP:
750 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
751 epcm->running = 0;
752 snd_emu10k1_playback_stop_voice(emu, epcm->voices[0]);
753 snd_emu10k1_playback_stop_voice(emu, epcm->voices[1]);
754 snd_emu10k1_playback_stop_voice(emu, epcm->extra);
755 break;
756 default:
757 result = -EINVAL;
758 break;
759 }
760 spin_unlock(&emu->reg_lock);
761 return result;
762}
763
764static int snd_emu10k1_capture_trigger(snd_pcm_substream_t * substream,
765 int cmd)
766{
767 emu10k1_t *emu = snd_pcm_substream_chip(substream);
768 snd_pcm_runtime_t *runtime = substream->runtime;
769 emu10k1_pcm_t *epcm = runtime->private_data;
770 int result = 0;
771
772 // printk("trigger - emu10k1 = %p, cmd = %i, pointer = %i\n", emu, cmd, substream->ops->pointer(substream));
773 spin_lock(&emu->reg_lock);
774 switch (cmd) {
775 case SNDRV_PCM_TRIGGER_START:
776 outl(epcm->capture_ipr, emu->port + IPR);
777 snd_emu10k1_intr_enable(emu, epcm->capture_inte);
778 // printk("adccr = 0x%x, adcbs = 0x%x\n", epcm->adccr, epcm->adcbs);
779 switch (epcm->type) {
780 case CAPTURE_AC97ADC:
781 snd_emu10k1_ptr_write(emu, ADCCR, 0, epcm->capture_cr_val);
782 break;
783 case CAPTURE_EFX:
784 if (emu->audigy) {
785 snd_emu10k1_ptr_write(emu, A_FXWC1, 0, epcm->capture_cr_val);
786 snd_emu10k1_ptr_write(emu, A_FXWC2, 0, epcm->capture_cr_val2);
787 } else
788 snd_emu10k1_ptr_write(emu, FXWC, 0, epcm->capture_cr_val);
789 break;
790 default:
791 break;
792 }
793 snd_emu10k1_ptr_write(emu, epcm->capture_bs_reg, 0, epcm->capture_bs_val);
794 epcm->running = 1;
795 epcm->first_ptr = 1;
796 break;
797 case SNDRV_PCM_TRIGGER_STOP:
798 epcm->running = 0;
799 snd_emu10k1_intr_disable(emu, epcm->capture_inte);
800 outl(epcm->capture_ipr, emu->port + IPR);
801 snd_emu10k1_ptr_write(emu, epcm->capture_bs_reg, 0, 0);
802 switch (epcm->type) {
803 case CAPTURE_AC97ADC:
804 snd_emu10k1_ptr_write(emu, ADCCR, 0, 0);
805 break;
806 case CAPTURE_EFX:
807 if (emu->audigy) {
808 snd_emu10k1_ptr_write(emu, A_FXWC1, 0, 0);
809 snd_emu10k1_ptr_write(emu, A_FXWC2, 0, 0);
810 } else
811 snd_emu10k1_ptr_write(emu, FXWC, 0, 0);
812 break;
813 default:
814 break;
815 }
816 break;
817 default:
818 result = -EINVAL;
819 }
820 spin_unlock(&emu->reg_lock);
821 return result;
822}
823
824static snd_pcm_uframes_t snd_emu10k1_playback_pointer(snd_pcm_substream_t * substream)
825{
826 emu10k1_t *emu = snd_pcm_substream_chip(substream);
827 snd_pcm_runtime_t *runtime = substream->runtime;
828 emu10k1_pcm_t *epcm = runtime->private_data;
829 unsigned int ptr;
830
831 if (!epcm->running)
832 return 0;
833 ptr = snd_emu10k1_ptr_read(emu, CCCA, epcm->voices[0]->number) & 0x00ffffff;
834#if 0 /* Perex's code */
835 ptr += runtime->buffer_size;
836 ptr -= epcm->ccca_start_addr;
837 ptr %= runtime->buffer_size;
838#else /* EMU10K1 Open Source code from Creative */
839 if (ptr < epcm->ccca_start_addr)
840 ptr += runtime->buffer_size - epcm->ccca_start_addr;
841 else {
842 ptr -= epcm->ccca_start_addr;
843 if (ptr >= runtime->buffer_size)
844 ptr -= runtime->buffer_size;
845 }
846#endif
847 // printk("ptr = 0x%x, buffer_size = 0x%x, period_size = 0x%x\n", ptr, runtime->buffer_size, runtime->period_size);
848 return ptr;
849}
850
851static int snd_emu10k1_efx_playback_trigger(snd_pcm_substream_t * substream,
852 int cmd)
853{
854 emu10k1_t *emu = snd_pcm_substream_chip(substream);
855 snd_pcm_runtime_t *runtime = substream->runtime;
856 emu10k1_pcm_t *epcm = runtime->private_data;
857 int i;
858 int result = 0;
859
860 spin_lock(&emu->reg_lock);
861 switch (cmd) {
862 case SNDRV_PCM_TRIGGER_START:
863 // prepare voices
864 for (i = 0; i < NUM_EFX_PLAYBACK; i++) {
865 snd_emu10k1_playback_invalidate_cache(emu, 0, epcm->voices[i]);
866 }
867 snd_emu10k1_playback_invalidate_cache(emu, 1, epcm->extra);
868
869 /* follow thru */
870 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
871 snd_emu10k1_playback_prepare_voice(emu, epcm->extra, 1, 1, NULL);
872 snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 0, 0,
873 &emu->efx_pcm_mixer[0]);
874 for (i = 1; i < NUM_EFX_PLAYBACK; i++)
875 snd_emu10k1_playback_prepare_voice(emu, epcm->voices[i], 0, 0,
876 &emu->efx_pcm_mixer[i]);
877 snd_emu10k1_playback_trigger_voice(emu, epcm->voices[0], 0, 0);
878 snd_emu10k1_playback_trigger_voice(emu, epcm->extra, 1, 1);
879 for (i = 1; i < NUM_EFX_PLAYBACK; i++)
880 snd_emu10k1_playback_trigger_voice(emu, epcm->voices[i], 0, 0);
881 epcm->running = 1;
882 break;
883 case SNDRV_PCM_TRIGGER_STOP:
884 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
885 epcm->running = 0;
886 for (i = 0; i < NUM_EFX_PLAYBACK; i++) {
887 snd_emu10k1_playback_stop_voice(emu, epcm->voices[i]);
888 }
889 snd_emu10k1_playback_stop_voice(emu, epcm->extra);
890 break;
891 default:
892 result = -EINVAL;
893 break;
894 }
895 spin_unlock(&emu->reg_lock);
896 return result;
897}
898
899static snd_pcm_uframes_t snd_emu10k1_capture_pointer(snd_pcm_substream_t * substream)
900{
901 emu10k1_t *emu = snd_pcm_substream_chip(substream);
902 snd_pcm_runtime_t *runtime = substream->runtime;
903 emu10k1_pcm_t *epcm = runtime->private_data;
904 unsigned int ptr;
905
906 if (!epcm->running)
907 return 0;
908 if (epcm->first_ptr) {
909 udelay(50); // hack, it takes awhile until capture is started
910 epcm->first_ptr = 0;
911 }
912 ptr = snd_emu10k1_ptr_read(emu, epcm->capture_idx_reg, 0) & 0x0000ffff;
913 return bytes_to_frames(runtime, ptr);
914}
915
916/*
917 * Playback support device description
918 */
919
920#if 0
921int snd_emu10k1_playback_ioctl(snd_pcm_substream_t *substream, unsigned int cmd, void *arg)
922{
923 switch(cmd) {
924 case SNDRV_PCM_IOCTL1_SETVOLUME:
925 {
926 emu10k1_pcm_mixer_t *mix;
927 snd_pcm_volume_t *volume = (snd_pcm_volume_t *)arg;
928 emu10k1_t *emu = snd_pcm_substream_chip(substream);
929 snd_ctl_elem_value_t *ucontrol;
930 snd_ctl_elem_info_t *uinfo;
931 void *iwishihadmorestack;
932 int range;
933
934
935 iwishihadmorestack = kmalloc(sizeof(snd_ctl_elem_value_t) + sizeof(snd_ctl_elem_info_t), GFP_KERNEL);
936 if(iwishihadmorestack == NULL) {
937 kfree(iwishihadmorestack);
938 return -ENOMEM;
939 }
940 ucontrol = (snd_ctl_elem_value_t *)iwishihadmorestack;
941 uinfo = (snd_ctl_elem_info_t *)(ucontrol + 1);
942
943 mix = &emu->pcm_mixer[substream->number];
944 mix->ctl_attn->info(mix->ctl_attn, uinfo);
945 range = uinfo->value.integer.max - uinfo->value.integer.min;
946
947 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
948 ucontrol->value.integer.value[1] = (volume->volume[SNDRV_PCM_VOL_FRONT_LEFT] * range)/SNDRV_PCM_VOL_MAX;
949 ucontrol->value.integer.value[2] = (volume->volume[SNDRV_PCM_VOL_FRONT_RIGHT] * range)/SNDRV_PCM_VOL_MAX;
950 }
951 else
952 if (mix->epcm->voices[0])
953 ucontrol->value.integer.value[0] = (volume->volume[SNDRV_PCM_VOL_FRONT_LEFT] * range)/SNDRV_PCM_VOL_MAX;
954
955 mix->ctl_attn->put(mix->ctl_attn, ucontrol);
956 kfree(iwishihadmorestack);
957 return 0;
958 }
959 case SNDRV_PCM_IOCTL1_GETVOLUME:
960 {
961 emu10k1_pcm_mixer_t *mix;
962 snd_pcm_volume_t *volume = (snd_pcm_volume_t *)arg;
963 emu10k1_t *emu = snd_pcm_substream_chip(substream);
964 int range;
965 snd_ctl_elem_value_t *ucontrol;
966 snd_ctl_elem_info_t *uinfo;
967 void *iwishihadmorestack;
968
969 iwishihadmorestack = kmalloc(sizeof(snd_ctl_elem_value_t) + sizeof(snd_ctl_elem_info_t), GFP_KERNEL);
970 if(iwishihadmorestack == NULL) {
971 return -ENOMEM;
972 }
973 ucontrol = (snd_ctl_elem_value_t *)iwishihadmorestack;
974 uinfo = (snd_ctl_elem_info_t *)(ucontrol + 1);
975
976 mix = &emu->pcm_mixer[substream->number];
977 mix->ctl_attn->info(mix->ctl_attn, uinfo);
978 range = uinfo->value.integer.max - uinfo->value.integer.min;
979 if(range == 0) {
980 kfree(iwishihadmorestack);
981 return -EPERM;
982 }
983 mix->ctl_attn->get(mix->ctl_attn, ucontrol);
984
985 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
986 volume->nrchannels = 2;
987 volume->volume[SNDRV_PCM_VOL_FRONT_LEFT] = (ucontrol->value.integer.value[1] * SNDRV_PCM_VOL_MAX) / range;
988 volume->volume[SNDRV_PCM_VOL_FRONT_RIGHT] = (ucontrol->value.integer.value[2] * SNDRV_PCM_VOL_MAX) / range;
989 volume->volume[SNDRV_PCM_VOL_REAR_LEFT] = volume->volume[SNDRV_PCM_VOL_FRONT_LEFT];
990 volume->volume[SNDRV_PCM_VOL_REAR_RIGHT] = volume->volume[SNDRV_PCM_VOL_FRONT_RIGHT];
991 }
992 else
993 if (mix->epcm->voices[0]){
994 volume->nrchannels = 1;
995 volume->volume[SNDRV_PCM_VOL_FRONT_LEFT] = (ucontrol->value.integer.value[0] * SNDRV_PCM_VOL_MAX) / range;
996 volume->volume[SNDRV_PCM_VOL_FRONT_RIGHT] = volume->volume[SNDRV_PCM_VOL_FRONT_LEFT];
997 volume->volume[SNDRV_PCM_VOL_REAR_LEFT] = volume->volume[SNDRV_PCM_VOL_FRONT_LEFT];
998 volume->volume[SNDRV_PCM_VOL_REAR_RIGHT] = volume->volume[SNDRV_PCM_VOL_FRONT_RIGHT];
999 }
1000 kfree(iwishihadmorestack);
1001 return 0;
1002 }
1003
1004 }
1005 return snd_pcm_lib_ioctl(substream, cmd, arg);
1006}
1007#endif
1008
1009static snd_pcm_hardware_t snd_emu10k1_playback =
1010{
1011 /* info: */ (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1012 SNDRV_PCM_INFO_BLOCK_TRANSFER |
1013 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE),
1014 /* formats: */ SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
1015 SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_96000,
1016 /* rate_min: */ 4000,
1017 /* rate_max: */ 96000,
1018 /* channels_min: */ 1,
1019 /* channels_max: */ 2,
1020 /* buffer_bytes_max: */ (128*1024),
1021 /* period_bytes_min: */ 64,
1022 /* period_bytes_max: */ (128*1024),
1023 /* periods_min: */ 1,
1024 /* periods_max: */ 1024,
1025 /* fifo_size: */ 0,
1026};
1027
1028/*
1029 * Capture support device description
1030 */
1031
1032static snd_pcm_hardware_t snd_emu10k1_capture =
1033{
1034 /* info: */ (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1035 SNDRV_PCM_INFO_BLOCK_TRANSFER |
1036 SNDRV_PCM_INFO_MMAP_VALID),
1037 /* formats: */ SNDRV_PCM_FMTBIT_S16_LE,
1038 /* rates: */ SNDRV_PCM_RATE_8000_48000,
1039 /* rate_min: */ 8000,
1040 /* rate_max: */ 48000,
1041 /* channels_min: */ 1,
1042 /* channels_max: */ 2,
1043 /* buffer_bytes_max: */ (64*1024),
1044 /* period_bytes_min: */ 384,
1045 /* period_bytes_max: */ (64*1024),
1046 /* periods_min: */ 2,
1047 /* periods_max: */ 2,
1048 /* fifo_size: */ 0,
1049};
1050
1051/*
1052 *
1053 */
1054
1055static void snd_emu10k1_pcm_mixer_notify1(emu10k1_t *emu, snd_kcontrol_t *kctl, int idx, int activate)
1056{
1057 snd_ctl_elem_id_t id;
1058
1059 if (! kctl)
1060 return;
1061 if (activate)
1062 kctl->vd[idx].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
1063 else
1064 kctl->vd[idx].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
1065 snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE |
1066 SNDRV_CTL_EVENT_MASK_INFO,
1067 snd_ctl_build_ioff(&id, kctl, idx));
1068}
1069
1070static void snd_emu10k1_pcm_mixer_notify(emu10k1_t *emu, int idx, int activate)
1071{
1072 snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_send_routing, idx, activate);
1073 snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_send_volume, idx, activate);
1074 snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_attn, idx, activate);
1075}
1076
1077static void snd_emu10k1_pcm_efx_mixer_notify(emu10k1_t *emu, int idx, int activate)
1078{
1079 snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_efx_send_routing, idx, activate);
1080 snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_efx_send_volume, idx, activate);
1081 snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_efx_attn, idx, activate);
1082}
1083
1084static void snd_emu10k1_pcm_free_substream(snd_pcm_runtime_t *runtime)
1085{
1086 emu10k1_pcm_t *epcm = runtime->private_data;
1087 if (epcm)
1088 kfree(epcm);
1089}
1090
1091static int snd_emu10k1_efx_playback_close(snd_pcm_substream_t * substream)
1092{
1093 emu10k1_t *emu = snd_pcm_substream_chip(substream);
1094 emu10k1_pcm_mixer_t *mix;
1095 int i;
1096
1097 for (i=0; i < NUM_EFX_PLAYBACK; i++) {
1098 mix = &emu->efx_pcm_mixer[i];
1099 mix->epcm = NULL;
1100 snd_emu10k1_pcm_efx_mixer_notify(emu, i, 0);
1101 }
1102 return 0;
1103}
1104
1105static int snd_emu10k1_efx_playback_open(snd_pcm_substream_t * substream)
1106{
1107 emu10k1_t *emu = snd_pcm_substream_chip(substream);
1108 emu10k1_pcm_t *epcm;
1109 emu10k1_pcm_mixer_t *mix;
1110 snd_pcm_runtime_t *runtime = substream->runtime;
1111 int i;
1112
1113 epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
1114 if (epcm == NULL)
1115 return -ENOMEM;
1116 epcm->emu = emu;
1117 epcm->type = PLAYBACK_EFX;
1118 epcm->substream = substream;
1119
1120 emu->pcm_playback_efx_substream = substream;
1121
1122 runtime->private_data = epcm;
1123 runtime->private_free = snd_emu10k1_pcm_free_substream;
1124 runtime->hw = snd_emu10k1_efx_playback;
1125
1126 for (i=0; i < NUM_EFX_PLAYBACK; i++) {
1127 mix = &emu->efx_pcm_mixer[i];
1128 mix->send_routing[0][0] = i;
1129 memset(&mix->send_volume, 0, sizeof(mix->send_volume));
1130 mix->send_volume[0][0] = 255;
1131 mix->attn[0] = 0xffff;
1132 mix->epcm = epcm;
1133 snd_emu10k1_pcm_efx_mixer_notify(emu, i, 1);
1134 }
1135 return 0;
1136}
1137
1138static int snd_emu10k1_playback_open(snd_pcm_substream_t * substream)
1139{
1140 emu10k1_t *emu = snd_pcm_substream_chip(substream);
1141 emu10k1_pcm_t *epcm;
1142 emu10k1_pcm_mixer_t *mix;
1143 snd_pcm_runtime_t *runtime = substream->runtime;
1144 int i, err;
1145
1146 epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
1147 if (epcm == NULL)
1148 return -ENOMEM;
1149 epcm->emu = emu;
1150 epcm->type = PLAYBACK_EMUVOICE;
1151 epcm->substream = substream;
1152 runtime->private_data = epcm;
1153 runtime->private_free = snd_emu10k1_pcm_free_substream;
1154 runtime->hw = snd_emu10k1_playback;
1155 if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) {
1156 kfree(epcm);
1157 return err;
1158 }
1159 if ((err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX)) < 0) {
1160 kfree(epcm);
1161 return err;
1162 }
1163 mix = &emu->pcm_mixer[substream->number];
1164 for (i = 0; i < 4; i++)
1165 mix->send_routing[0][i] = mix->send_routing[1][i] = mix->send_routing[2][i] = i;
1166 memset(&mix->send_volume, 0, sizeof(mix->send_volume));
1167 mix->send_volume[0][0] = mix->send_volume[0][1] =
1168 mix->send_volume[1][0] = mix->send_volume[2][1] = 255;
1169 mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff;
1170 mix->epcm = epcm;
1171 snd_emu10k1_pcm_mixer_notify(emu, substream->number, 1);
1172 return 0;
1173}
1174
1175static int snd_emu10k1_playback_close(snd_pcm_substream_t * substream)
1176{
1177 emu10k1_t *emu = snd_pcm_substream_chip(substream);
1178 emu10k1_pcm_mixer_t *mix = &emu->pcm_mixer[substream->number];
1179
1180 mix->epcm = NULL;
1181 snd_emu10k1_pcm_mixer_notify(emu, substream->number, 0);
1182 return 0;
1183}
1184
1185static int snd_emu10k1_capture_open(snd_pcm_substream_t * substream)
1186{
1187 emu10k1_t *emu = snd_pcm_substream_chip(substream);
1188 snd_pcm_runtime_t *runtime = substream->runtime;
1189 emu10k1_pcm_t *epcm;
1190
1191 epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
1192 if (epcm == NULL)
1193 return -ENOMEM;
1194 epcm->emu = emu;
1195 epcm->type = CAPTURE_AC97ADC;
1196 epcm->substream = substream;
1197 epcm->capture_ipr = IPR_ADCBUFFULL|IPR_ADCBUFHALFFULL;
1198 epcm->capture_inte = INTE_ADCBUFENABLE;
1199 epcm->capture_ba_reg = ADCBA;
1200 epcm->capture_bs_reg = ADCBS;
1201 epcm->capture_idx_reg = emu->audigy ? A_ADCIDX : ADCIDX;
1202 runtime->private_data = epcm;
1203 runtime->private_free = snd_emu10k1_pcm_free_substream;
1204 runtime->hw = snd_emu10k1_capture;
1205 emu->capture_interrupt = snd_emu10k1_pcm_ac97adc_interrupt;
1206 emu->pcm_capture_substream = substream;
1207 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_capture_period_sizes);
1208 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_capture_rates);
1209 return 0;
1210}
1211
1212static int snd_emu10k1_capture_close(snd_pcm_substream_t * substream)
1213{
1214 emu10k1_t *emu = snd_pcm_substream_chip(substream);
1215
1216 emu->capture_interrupt = NULL;
1217 emu->pcm_capture_substream = NULL;
1218 return 0;
1219}
1220
1221static int snd_emu10k1_capture_mic_open(snd_pcm_substream_t * substream)
1222{
1223 emu10k1_t *emu = snd_pcm_substream_chip(substream);
1224 emu10k1_pcm_t *epcm;
1225 snd_pcm_runtime_t *runtime = substream->runtime;
1226
1227 epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
1228 if (epcm == NULL)
1229 return -ENOMEM;
1230 epcm->emu = emu;
1231 epcm->type = CAPTURE_AC97MIC;
1232 epcm->substream = substream;
1233 epcm->capture_ipr = IPR_MICBUFFULL|IPR_MICBUFHALFFULL;
1234 epcm->capture_inte = INTE_MICBUFENABLE;
1235 epcm->capture_ba_reg = MICBA;
1236 epcm->capture_bs_reg = MICBS;
1237 epcm->capture_idx_reg = emu->audigy ? A_MICIDX : MICIDX;
1238 substream->runtime->private_data = epcm;
1239 substream->runtime->private_free = snd_emu10k1_pcm_free_substream;
1240 runtime->hw = snd_emu10k1_capture;
1241 runtime->hw.rates = SNDRV_PCM_RATE_8000;
1242 runtime->hw.rate_min = runtime->hw.rate_max = 8000;
1243 runtime->hw.channels_min = 1;
1244 emu->capture_mic_interrupt = snd_emu10k1_pcm_ac97mic_interrupt;
1245 emu->pcm_capture_mic_substream = substream;
1246 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_capture_period_sizes);
1247 return 0;
1248}
1249
1250static int snd_emu10k1_capture_mic_close(snd_pcm_substream_t * substream)
1251{
1252 emu10k1_t *emu = snd_pcm_substream_chip(substream);
1253
1254 emu->capture_interrupt = NULL;
1255 emu->pcm_capture_mic_substream = NULL;
1256 return 0;
1257}
1258
1259static int snd_emu10k1_capture_efx_open(snd_pcm_substream_t * substream)
1260{
1261 emu10k1_t *emu = snd_pcm_substream_chip(substream);
1262 emu10k1_pcm_t *epcm;
1263 snd_pcm_runtime_t *runtime = substream->runtime;
1264 int nefx = emu->audigy ? 64 : 32;
1265 int idx;
1266
1267 epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
1268 if (epcm == NULL)
1269 return -ENOMEM;
1270 epcm->emu = emu;
1271 epcm->type = CAPTURE_EFX;
1272 epcm->substream = substream;
1273 epcm->capture_ipr = IPR_EFXBUFFULL|IPR_EFXBUFHALFFULL;
1274 epcm->capture_inte = INTE_EFXBUFENABLE;
1275 epcm->capture_ba_reg = FXBA;
1276 epcm->capture_bs_reg = FXBS;
1277 epcm->capture_idx_reg = FXIDX;
1278 substream->runtime->private_data = epcm;
1279 substream->runtime->private_free = snd_emu10k1_pcm_free_substream;
1280 runtime->hw = snd_emu10k1_capture;
1281 runtime->hw.rates = SNDRV_PCM_RATE_48000;
1282 runtime->hw.rate_min = runtime->hw.rate_max = 48000;
1283 spin_lock_irq(&emu->reg_lock);
1284 runtime->hw.channels_min = runtime->hw.channels_max = 0;
1285 for (idx = 0; idx < nefx; idx++) {
1286 if (emu->efx_voices_mask[idx/32] & (1 << (idx%32))) {
1287 runtime->hw.channels_min++;
1288 runtime->hw.channels_max++;
1289 }
1290 }
1291 epcm->capture_cr_val = emu->efx_voices_mask[0];
1292 epcm->capture_cr_val2 = emu->efx_voices_mask[1];
1293 spin_unlock_irq(&emu->reg_lock);
1294 emu->capture_efx_interrupt = snd_emu10k1_pcm_efx_interrupt;
1295 emu->pcm_capture_efx_substream = substream;
1296 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_capture_period_sizes);
1297 return 0;
1298}
1299
1300static int snd_emu10k1_capture_efx_close(snd_pcm_substream_t * substream)
1301{
1302 emu10k1_t *emu = snd_pcm_substream_chip(substream);
1303
1304 emu->capture_interrupt = NULL;
1305 emu->pcm_capture_efx_substream = NULL;
1306 return 0;
1307}
1308
1309static snd_pcm_ops_t snd_emu10k1_playback_ops = {
1310 snd_emu10k1_playback_open,
1311 snd_emu10k1_playback_close,
1312 snd_pcm_lib_ioctl,
1313 snd_emu10k1_playback_hw_params,
1314 snd_emu10k1_playback_hw_free,
1315 snd_emu10k1_playback_prepare,
1316 snd_emu10k1_playback_trigger,
1317 snd_emu10k1_playback_pointer,0,0,
1318 snd_pcm_sgbuf_ops_page,0
1319};
1320
1321static snd_pcm_ops_t snd_emu10k1_capture_ops = {
1322 snd_emu10k1_capture_open,
1323 snd_emu10k1_capture_close,
1324 snd_pcm_lib_ioctl,
1325 snd_emu10k1_capture_hw_params,
1326 snd_emu10k1_capture_hw_free,
1327 snd_emu10k1_capture_prepare,
1328 snd_emu10k1_capture_trigger,
1329 snd_emu10k1_capture_pointer,0,0,0,0
1330};
1331
1332/* EFX playback */
1333static snd_pcm_ops_t snd_emu10k1_efx_playback_ops = {
1334 /*.open = */ snd_emu10k1_efx_playback_open,
1335 /*.close = */ snd_emu10k1_efx_playback_close,
1336 /*.ioctl = */ snd_pcm_lib_ioctl,
1337 /*.hw_params = */ snd_emu10k1_playback_hw_params,
1338 /*.hw_free = */ snd_emu10k1_efx_playback_hw_free,
1339 /*.prepare = */ snd_emu10k1_efx_playback_prepare,
1340 /*.trigger = */ snd_emu10k1_efx_playback_trigger,
1341 /*.pointer = */ snd_emu10k1_efx_playback_pointer,
1342 0,0,
1343 /*.page = */ snd_pcm_sgbuf_ops_page,
1344 0
1345};
1346
1347static void snd_emu10k1_pcm_free(snd_pcm_t *pcm)
1348{
1349 emu10k1_t *emu = pcm->private_data;
1350 emu->pcm = NULL;
1351 snd_pcm_lib_preallocate_free_for_all(pcm);
1352}
1353
1354int __devinit snd_emu10k1_pcm(emu10k1_t * emu, int device, snd_pcm_t ** rpcm)
1355{
1356 snd_pcm_t *pcm;
1357 snd_pcm_substream_t *substream;
1358 int err;
1359
1360 if (rpcm)
1361 *rpcm = NULL;
1362
1363 if ((err = snd_pcm_new(emu->card, "emu10k1", device, 32, 1, &pcm)) < 0)
1364 return err;
1365
1366 pcm->private_data = emu;
1367 pcm->private_free = snd_emu10k1_pcm_free;
1368
1369 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_playback_ops);
1370 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_ops);
1371
1372 pcm->info_flags = 0;
1373 pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
1374 strcpy(pcm->name, "EMU10K1");
1375 emu->pcm = pcm;
1376
1377 for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next)
1378 if ((err = snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV_SG, snd_dma_pci_data(emu->pci), 64*1024, 64*1024)) < 0)
1379 return err;
1380
1381 for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; substream; substream = substream->next)
1382 snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024);
1383
1384 if (rpcm)
1385 *rpcm = pcm;
1386
1387 return 0;
1388}
1389
1390int __devinit snd_emu10k1_pcm_multi(emu10k1_t * emu, int device, snd_pcm_t ** rpcm)
1391{
1392 snd_pcm_t *pcm;
1393 snd_pcm_substream_t *substream;
1394 int err;
1395
1396 if (rpcm)
1397 *rpcm = NULL;
1398
1399 if ((err = snd_pcm_new(emu->card, "emu10k1", device, 1, 0, &pcm)) < 0)
1400 return err;
1401
1402 pcm->private_data = emu;
1403 pcm->private_free = snd_emu10k1_pcm_free;
1404
1405 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_efx_playback_ops);
1406
1407 pcm->info_flags = 0;
1408 pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
1409 strcpy(pcm->name, "EMU10K1 multichannel EFX");
1410 emu->pcm = pcm;
1411
1412 for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next)
1413 if ((err = snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV_SG, snd_dma_pci_data(emu->pci), 64*1024, 64*1024)) < 0)
1414 return err;
1415
1416 if (rpcm)
1417 *rpcm = pcm;
1418
1419 return 0;
1420}
1421
1422static snd_pcm_ops_t snd_emu10k1_capture_mic_ops = {
1423 snd_emu10k1_capture_mic_open,
1424 snd_emu10k1_capture_mic_close,
1425 snd_pcm_lib_ioctl,
1426 snd_emu10k1_capture_hw_params,
1427 snd_emu10k1_capture_hw_free,
1428 snd_emu10k1_capture_prepare,
1429 snd_emu10k1_capture_trigger,
1430 snd_emu10k1_capture_pointer,0,0,0,0
1431};
1432
1433static void snd_emu10k1_pcm_mic_free(snd_pcm_t *pcm)
1434{
1435 emu10k1_t *emu = pcm->private_data;
1436 emu->pcm_mic = NULL;
1437 snd_pcm_lib_preallocate_free_for_all(pcm);
1438}
1439
1440int __devinit snd_emu10k1_pcm_mic(emu10k1_t * emu, int device, snd_pcm_t ** rpcm)
1441{
1442 snd_pcm_t *pcm;
1443 int err;
1444
1445 if (rpcm)
1446 *rpcm = NULL;
1447
1448 if ((err = snd_pcm_new(emu->card, "emu10k1 mic", device, 0, 1, &pcm)) < 0)
1449 return err;
1450
1451 pcm->private_data = emu;
1452 pcm->private_free = snd_emu10k1_pcm_mic_free;
1453
1454 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_mic_ops);
1455
1456 pcm->info_flags = 0;
1457 strcpy(pcm->name, "EMU10K1 MIC");
1458 emu->pcm_mic = pcm;
1459
1460 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024);
1461
1462 if (rpcm)
1463 *rpcm = pcm;
1464 return 0;
1465}
1466
1467
1468static int snd_emu10k1_pcm_efx_voices_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
1469{
1470 emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
1471 int nefx = emu->audigy ? 64 : 32;
1472 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1473 uinfo->count = nefx;
1474 uinfo->value.integer.min = 0;
1475 uinfo->value.integer.max = 1;
1476 return 0;
1477}
1478
1479static int snd_emu10k1_pcm_efx_voices_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1480{
1481 emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
1482 int nefx = emu->audigy ? 64 : 32;
1483 int idx;
1484
1485 spin_lock_irq(&emu->reg_lock);
1486 for (idx = 0; idx < nefx; idx++)
1487 ucontrol->value.integer.value[idx] = (emu->efx_voices_mask[idx / 32] & (1 << (idx % 32))) ? 1 : 0;
1488 spin_unlock_irq(&emu->reg_lock);
1489 return 0;
1490}
1491
1492static int snd_emu10k1_pcm_efx_voices_mask_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1493{
1494 emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
1495 unsigned int nval[2], bits;
1496 int nefx = emu->audigy ? 64 : 32;
1497 int nefxb = emu->audigy ? 7 : 6;
1498 int change, idx;
1499
1500 nval[0] = nval[1] = 0;
1501 for (idx = 0, bits = 0; idx < nefx; idx++)
1502 if (ucontrol->value.integer.value[idx]) {
1503 nval[idx / 32] |= 1 << (idx % 32);
1504 bits++;
1505 }
1506 for (idx = 0; idx < nefxb; idx++)
1507 if (1 << idx == bits)
1508 break;
1509 if (idx >= nefxb)
1510 return -EINVAL;
1511 spin_lock_irq(&emu->reg_lock);
1512 change = (nval[0] != emu->efx_voices_mask[0]) ||
1513 (nval[1] != emu->efx_voices_mask[1]);
1514 emu->efx_voices_mask[0] = nval[0];
1515 emu->efx_voices_mask[1] = nval[1];
1516 spin_unlock_irq(&emu->reg_lock);
1517 return change;
1518}
1519
1520static snd_kcontrol_new_t snd_emu10k1_pcm_efx_voices_mask = {
1521 SNDRV_CTL_ELEM_IFACE_PCM,0,0,
1522 "Captured FX8010 Outputs",0,0, 0,
1523 snd_emu10k1_pcm_efx_voices_mask_info,
1524 snd_emu10k1_pcm_efx_voices_mask_get,
1525 snd_emu10k1_pcm_efx_voices_mask_put,0
1526};
1527
1528static snd_pcm_ops_t snd_emu10k1_capture_efx_ops = {
1529 snd_emu10k1_capture_efx_open,
1530 snd_emu10k1_capture_efx_close,
1531 snd_pcm_lib_ioctl,
1532 snd_emu10k1_capture_hw_params,
1533 snd_emu10k1_capture_hw_free,
1534 snd_emu10k1_capture_prepare,
1535 snd_emu10k1_capture_trigger,
1536 snd_emu10k1_capture_pointer,0,0,0,0
1537};
1538
1539
1540/* EFX playback */
1541
1542#define INITIAL_TRAM_SHIFT 14
1543#define INITIAL_TRAM_POS(size) ((((size) / 2) - INITIAL_TRAM_SHIFT) - 1)
1544
1545static void snd_emu10k1_fx8010_playback_irq(emu10k1_t *emu, void *private_data)
1546{
1547 snd_pcm_substream_t *substream = private_data;
1548 snd_pcm_period_elapsed(substream);
1549}
1550
1551static void snd_emu10k1_fx8010_playback_tram_poke1(unsigned short *dst_left,
1552 unsigned short *dst_right,
1553 unsigned short *src,
1554 unsigned int count,
1555 unsigned int tram_shift)
1556{
1557 // printk("tram_poke1: dst_left = 0x%p, dst_right = 0x%p, src = 0x%p, count = 0x%x\n", dst_left, dst_right, src, count);
1558 if ((tram_shift & 1) == 0) {
1559 while (count--) {
1560 *dst_left-- = *src++;
1561 *dst_right-- = *src++;
1562 }
1563 } else {
1564 while (count--) {
1565 *dst_right-- = *src++;
1566 *dst_left-- = *src++;
1567 }
1568 }
1569}
1570
1571
1572static void fx8010_pb_trans_copy(snd_pcm_substream_t *substream,
1573 snd_pcm_indirect_t *rec, size_t bytes)
1574{
1575 emu10k1_t *emu = snd_pcm_substream_chip(substream);
1576 snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
1577 unsigned int tram_size = pcm->buffer_size;
1578 unsigned short *src = (unsigned short *)(substream->runtime->dma_area + rec->sw_data);
1579 unsigned int frames = bytes >> 2, count;
1580 unsigned int tram_pos = pcm->tram_pos;
1581 unsigned int tram_shift = pcm->tram_shift;
1582
1583 while (frames > tram_pos) {
1584 count = tram_pos + 1;
1585 snd_emu10k1_fx8010_playback_tram_poke1((unsigned short *)emu->fx8010.etram_pages.area + tram_pos,
1586 (unsigned short *)emu->fx8010.etram_pages.area + tram_pos + tram_size / 2,
1587 src, count, tram_shift);
1588 src += count * 2;
1589 frames -= count;
1590 tram_pos = (tram_size / 2) - 1;
1591 tram_shift++;
1592 }
1593 snd_emu10k1_fx8010_playback_tram_poke1((unsigned short *)emu->fx8010.etram_pages.area + tram_pos,
1594 (unsigned short *)emu->fx8010.etram_pages.area + tram_pos + tram_size / 2,
1595 src, frames, tram_shift);
1596 tram_pos -= frames;
1597 pcm->tram_pos = tram_pos;
1598 pcm->tram_shift = tram_shift;
1599}
1600
1601static int snd_emu10k1_fx8010_playback_transfer(snd_pcm_substream_t *substream)
1602{
1603 emu10k1_t *emu = snd_pcm_substream_chip(substream);
1604 snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
1605
1606 snd_pcm_indirect_playback_transfer(substream, &pcm->pcm_rec, fx8010_pb_trans_copy);
1607 return 0;
1608}
1609
1610static int snd_emu10k1_fx8010_playback_hw_params(snd_pcm_substream_t * substream,
1611 snd_pcm_hw_params_t * hw_params)
1612{
1613 return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
1614}
1615
1616static int snd_emu10k1_fx8010_playback_hw_free(snd_pcm_substream_t * substream)
1617{
1618 emu10k1_t *emu = snd_pcm_substream_chip(substream);
1619 snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
1620 unsigned int i;
1621
1622 for (i = 0; i < pcm->channels; i++)
1623 snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + 0x80 + pcm->etram[i], 0, 0);
1624 snd_pcm_lib_free_pages(substream);
1625 return 0;
1626}
1627
1628static int snd_emu10k1_fx8010_playback_prepare(snd_pcm_substream_t * substream)
1629{
1630 emu10k1_t *emu = snd_pcm_substream_chip(substream);
1631 snd_pcm_runtime_t *runtime = substream->runtime;
1632 snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
1633 unsigned int i;
1634
1635 // printk("prepare: etram_pages = 0x%p, dma_area = 0x%x, buffer_size = 0x%x (0x%x)\n", emu->fx8010.etram_pages, runtime->dma_area, runtime->buffer_size, runtime->buffer_size << 2);
1636 memset(&pcm->pcm_rec, 0, sizeof(pcm->pcm_rec));
1637 pcm->pcm_rec.hw_buffer_size = pcm->buffer_size * 2; /* byte size */
1638 pcm->pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
1639 pcm->tram_pos = INITIAL_TRAM_POS(pcm->buffer_size);
1640 pcm->tram_shift = 0;
1641 snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_running, 0, 0); /* reset */
1642 snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 0); /* reset */
1643 snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_size, 0, runtime->buffer_size);
1644 snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_ptr, 0, 0); /* reset ptr number */
1645 snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_count, 0, runtime->period_size);
1646 snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_tmpcount, 0, runtime->period_size);
1647 for (i = 0; i < pcm->channels; i++)
1648 snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + 0x80 + pcm->etram[i], 0, (TANKMEMADDRREG_READ|TANKMEMADDRREG_ALIGN) + i * (runtime->buffer_size / pcm->channels));
1649 return 0;
1650}
1651
1652static int snd_emu10k1_fx8010_playback_trigger(snd_pcm_substream_t * substream, int cmd)
1653{
1654 emu10k1_t *emu = snd_pcm_substream_chip(substream);
1655 snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
1656 int result = 0;
1657
1658 spin_lock(&emu->reg_lock);
1659 switch (cmd) {
1660 case SNDRV_PCM_TRIGGER_START:
1661 /* follow thru */
1662 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1663#ifdef EMU10K1_SET_AC3_IEC958
1664 {
1665 int i;
1666 for (i = 0; i < 3; i++) {
1667 unsigned int bits;
1668 bits = SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
1669 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS |
1670 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT | SPCS_NOTAUDIODATA;
1671 snd_emu10k1_ptr_write(emu, SPCS0 + i, 0, bits);
1672 }
1673 }
1674#endif
1675 result = snd_emu10k1_fx8010_register_irq_handler(emu, snd_emu10k1_fx8010_playback_irq, pcm->gpr_running, substream, &pcm->irq);
1676 if (result < 0)
1677 goto __err;
1678 snd_emu10k1_fx8010_playback_transfer(substream); /* roll the ball */
1679 snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 1);
1680 break;
1681 case SNDRV_PCM_TRIGGER_STOP:
1682 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1683 snd_emu10k1_fx8010_unregister_irq_handler(emu, pcm->irq); pcm->irq = NULL;
1684 snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 0);
1685 pcm->tram_pos = INITIAL_TRAM_POS(pcm->buffer_size);
1686 pcm->tram_shift = 0;
1687 break;
1688 default:
1689 result = -EINVAL;
1690 break;
1691 }
1692__err:
1693 spin_unlock(&emu->reg_lock);
1694 return result;
1695}
1696
1697static snd_pcm_uframes_t snd_emu10k1_fx8010_playback_pointer(snd_pcm_substream_t * substream)
1698{
1699 emu10k1_t *emu = snd_pcm_substream_chip(substream);
1700 snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
1701 size_t ptr; /* byte pointer */
1702
1703 if (!snd_emu10k1_ptr_read(emu, emu->gpr_base + pcm->gpr_trigger, 0))
1704 return 0;
1705 ptr = snd_emu10k1_ptr_read(emu, emu->gpr_base + pcm->gpr_ptr, 0) << 2;
1706 return snd_pcm_indirect_playback_pointer(substream, &pcm->pcm_rec, ptr);
1707}
1708
1709static snd_pcm_hardware_t snd_emu10k1_fx8010_playback =
1710{
1711 /* .info = */ (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1712 /* /* SNDRV_PCM_INFO_MMAP_VALID | */ SNDRV_PCM_INFO_PAUSE),
1713 /* .formats = */ SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
1714 /* .rates = */ SNDRV_PCM_RATE_48000,
1715 /* .rate_min = */ 48000,
1716 /* .rate_max = */ 48000,
1717 /* .channels_min = */ 1,
1718 /* .channels_max = */ 1,
1719 /* .buffer_bytes_max = */ (128*1024),
1720 /* .period_bytes_min = */ 1024,
1721 /* .period_bytes_max = */ (128*1024),
1722 /* .periods_min = */ 1,
1723 /* .periods_max = */ 1024,
1724 /* .fifo_size = */ 0,
1725};
1726
1727static int snd_emu10k1_fx8010_playback_open(snd_pcm_substream_t * substream)
1728{
1729 emu10k1_t *emu = snd_pcm_substream_chip(substream);
1730 snd_pcm_runtime_t *runtime = substream->runtime;
1731 snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
1732
1733 runtime->hw = snd_emu10k1_fx8010_playback;
1734 runtime->hw.channels_min = runtime->hw.channels_max = pcm->channels;
1735 runtime->hw.period_bytes_max = (pcm->buffer_size * 2) / 2;
1736 spin_lock_irq(&emu->reg_lock);
1737 if (pcm->valid == 0) {
1738 spin_unlock_irq(&emu->reg_lock);
1739 return -ENODEV;
1740 }
1741 pcm->opened = 1;
1742 spin_unlock_irq(&emu->reg_lock);
1743 return 0;
1744}
1745
1746static int snd_emu10k1_fx8010_playback_close(snd_pcm_substream_t * substream)
1747{
1748 emu10k1_t *emu = snd_pcm_substream_chip(substream);
1749 snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
1750
1751 spin_lock_irq(&emu->reg_lock);
1752 pcm->opened = 0;
1753 spin_unlock_irq(&emu->reg_lock);
1754 return 0;
1755}
1756
1757static snd_pcm_ops_t snd_emu10k1_fx8010_playback_ops = {
1758 /*.open = */ snd_emu10k1_fx8010_playback_open,
1759 /*.close = */ snd_emu10k1_fx8010_playback_close,
1760 /*.ioctl = */ snd_pcm_lib_ioctl,
1761 /*.hw_params = */ snd_emu10k1_fx8010_playback_hw_params,
1762 /*.hw_free = */ snd_emu10k1_fx8010_playback_hw_free,
1763 /*.prepare = */ snd_emu10k1_fx8010_playback_prepare,
1764 /*.trigger = */ snd_emu10k1_fx8010_playback_trigger,
1765 /*.pointer = */ snd_emu10k1_fx8010_playback_pointer,
1766 NULL, NULL, NULL,
1767 /*.ack = */ snd_emu10k1_fx8010_playback_transfer,
1768};
1769
1770static void snd_emu10k1_pcm_efx_free(snd_pcm_t *pcm)
1771{
1772 emu10k1_t *emu = pcm->private_data;
1773 emu->pcm_efx = NULL;
1774 snd_pcm_lib_preallocate_free_for_all(pcm);
1775}
1776
1777int __devinit snd_emu10k1_pcm_efx(emu10k1_t * emu, int device, snd_pcm_t ** rpcm)
1778{
1779 snd_pcm_t *pcm;
1780 snd_kcontrol_t *kctl;
1781 int err;
1782
1783 if (rpcm)
1784 *rpcm = NULL;
1785
1786 if ((err = snd_pcm_new(emu->card, "emu10k1 efx", device, 8, 1, &pcm)) < 0)
1787 return err;
1788
1789 pcm->private_data = emu;
1790 pcm->private_free = snd_emu10k1_pcm_efx_free;
1791
1792 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_fx8010_playback_ops);
1793 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_efx_ops);
1794
1795 pcm->info_flags = 0;
1796 strcpy(pcm->name, "EMU10K1 EFX");
1797 emu->pcm_efx = pcm;
1798 if (rpcm)
1799 *rpcm = pcm;
1800
1801 /* EFX capture - record the "FXBUS2" channels, by default we connect the EXTINs
1802 * to these
1803 */
1804
1805 /* emu->efx_voices_mask[0] = FXWC_DEFAULTROUTE_C | FXWC_DEFAULTROUTE_A; */
1806 if (emu->audigy) {
1807 emu->efx_voices_mask[0] = 0;
1808 emu->efx_voices_mask[1] = 0xffff;
1809 } else {
1810 emu->efx_voices_mask[0] = 0xffff0000;
1811 emu->efx_voices_mask[1] = 0;
1812 }
1813
1814 kctl = snd_ctl_new1(&snd_emu10k1_pcm_efx_voices_mask, emu);
1815 if (!kctl)
1816 return -ENOMEM;
1817 kctl->id.device = device;
1818 snd_ctl_add(emu->card, kctl);
1819 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024);
1820
1821 return 0;
1822}
1823
Note: See TracBrowser for help on using the repository browser.