~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/pci/emu10k1/emupcm.c

Version: ~ [ linux-5.12-rc7 ] ~ [ linux-5.11.13 ] ~ [ linux-5.10.29 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.111 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.186 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.230 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.266 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.266 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 #include <sound/driver.h>
 29 #include <linux/delay.h>
 30 #include <linux/slab.h>
 31 #include <linux/time.h>
 32 #include <linux/init.h>
 33 #include <sound/core.h>
 34 #include <sound/emu10k1.h>
 35 
 36 #define chip_t emu10k1_t
 37 
 38 static void snd_emu10k1_pcm_interrupt(emu10k1_t *emu, emu10k1_voice_t *voice)
 39 {
 40         emu10k1_pcm_t *epcm;
 41 
 42         if ((epcm = voice->epcm) == NULL)
 43                 return;
 44         if (epcm->substream == NULL)
 45                 return;
 46 #if 0
 47         printk("IRQ: position = 0x%x, period = 0x%x, size = 0x%x\n",
 48                         epcm->substream->runtime->hw->pointer(emu, epcm->substream),
 49                         snd_pcm_lib_period_bytes(epcm->substream),
 50                         snd_pcm_lib_buffer_bytes(epcm->substream));
 51 #endif
 52         snd_pcm_period_elapsed(epcm->substream);
 53 }
 54 
 55 static void snd_emu10k1_pcm_ac97adc_interrupt(emu10k1_t *emu, unsigned int status)
 56 {
 57 #if 0
 58         if (status & IPR_ADCBUFHALFFULL) {
 59                 if (emu->pcm_capture_substream->runtime->mode == SNDRV_PCM_MODE_FRAME)
 60                         return;
 61         }
 62 #endif
 63         snd_pcm_period_elapsed(emu->pcm_capture_substream);
 64 }
 65 
 66 static void snd_emu10k1_pcm_ac97mic_interrupt(emu10k1_t *emu, unsigned int status)
 67 {
 68 #if 0
 69         if (status & IPR_MICBUFHALFFULL) {
 70                 if (emu->pcm_capture_mic_substream->runtime->mode == SNDRV_PCM_MODE_FRAME)
 71                         return;
 72         }
 73 #endif
 74         snd_pcm_period_elapsed(emu->pcm_capture_mic_substream);
 75 }
 76 
 77 static void snd_emu10k1_pcm_efx_interrupt(emu10k1_t *emu, unsigned int status)
 78 {
 79 #if 0
 80         if (status & IPR_EFXBUFHALFFULL) {
 81                 if (emu->pcm_capture_efx_substream->runtime->mode == SNDRV_PCM_MODE_FRAME)
 82                         return;
 83         }
 84 #endif
 85         snd_pcm_period_elapsed(emu->pcm_capture_efx_substream);
 86 }
 87 
 88 static int snd_emu10k1_pcm_channel_alloc(emu10k1_pcm_t * epcm, int voices)
 89 {
 90         int err;
 91 
 92         if (epcm->voices[1] != NULL && voices < 2) {
 93                 snd_emu10k1_voice_free(epcm->emu, epcm->voices[1]);
 94                 epcm->voices[1] = NULL;
 95         }
 96         if (voices == 1 && epcm->voices[0] != NULL)
 97                 return 0;               /* already allocated */
 98         if (voices == 2 && epcm->voices[0] != NULL && epcm->voices[1] != NULL)
 99                 return 0;
100         if (voices > 1) {
101                 if (epcm->voices[0] != NULL && epcm->voices[1] == NULL) {
102                         snd_emu10k1_voice_free(epcm->emu, epcm->voices[0]);
103                         epcm->voices[0] = NULL;
104                 }
105         }
106         err = snd_emu10k1_voice_alloc(epcm->emu, EMU10K1_PCM, voices > 1, &epcm->voices[0]);
107         if (err < 0)
108                 return err;
109         epcm->voices[0]->epcm = epcm;
110         if (voices > 1) {
111                 epcm->voices[1] = &epcm->emu->voices[epcm->voices[0]->number + 1];
112                 epcm->voices[1]->epcm = epcm;
113         }
114         if (epcm->extra == NULL) {
115                 err = snd_emu10k1_voice_alloc(epcm->emu, EMU10K1_PCM, 0, &epcm->extra);
116                 if (err < 0) {
117                         // printk("pcm_channel_alloc: failed extra: voices=%d, frame=%d\n", voices, frame);
118                         snd_emu10k1_voice_free(epcm->emu, epcm->voices[0]);
119                         epcm->voices[0] = NULL;
120                         if (epcm->voices[1])
121                                 snd_emu10k1_voice_free(epcm->emu, epcm->voices[1]);
122                         epcm->voices[1] = NULL;
123                         return err;
124                 }
125                 epcm->extra->epcm = epcm;
126                 epcm->extra->interrupt = snd_emu10k1_pcm_interrupt;
127         }
128         return 0;
129 }
130 
131 static unsigned int capture_period_sizes[31] = {
132         384,    448,    512,    640,
133         384*2,  448*2,  512*2,  640*2,
134         384*4,  448*4,  512*4,  640*4,
135         384*8,  448*8,  512*8,  640*8,
136         384*16, 448*16, 512*16, 640*16,
137         384*32, 448*32, 512*32, 640*32,
138         384*64, 448*64, 512*64, 640*64,
139         384*128,448*128,512*128
140 };
141 
142 static snd_pcm_hw_constraint_list_t hw_constraints_capture_period_sizes = {
143         .count = 31,
144         .list = capture_period_sizes,
145         .mask = 0
146 };
147 
148 static unsigned int capture_rates[8] = {
149         8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000
150 };
151 
152 static snd_pcm_hw_constraint_list_t hw_constraints_capture_rates = {
153         .count = 8,
154         .list = capture_rates,
155         .mask = 0
156 };
157 
158 static unsigned int snd_emu10k1_capture_rate_reg(unsigned int rate)
159 {
160         switch (rate) {
161         case 8000:      return ADCCR_SAMPLERATE_8;
162         case 11025:     return ADCCR_SAMPLERATE_11;
163         case 16000:     return ADCCR_SAMPLERATE_16;
164         case 22050:     return ADCCR_SAMPLERATE_22;
165         case 24000:     return ADCCR_SAMPLERATE_24;
166         case 32000:     return ADCCR_SAMPLERATE_32;
167         case 44100:     return ADCCR_SAMPLERATE_44;
168         case 48000:     return ADCCR_SAMPLERATE_48;
169         default:
170                         snd_BUG();
171                         return ADCCR_SAMPLERATE_8;
172         }
173 }
174 
175 static unsigned int snd_emu10k1_audigy_capture_rate_reg(unsigned int rate)
176 {
177         switch (rate) {
178         case 8000:      return A_ADCCR_SAMPLERATE_8;
179         case 11025:     return A_ADCCR_SAMPLERATE_11;
180         case 12000:     return A_ADCCR_SAMPLERATE_12; /* really supported? */
181         case 16000:     return ADCCR_SAMPLERATE_16;
182         case 22050:     return ADCCR_SAMPLERATE_22;
183         case 24000:     return ADCCR_SAMPLERATE_24;
184         case 32000:     return ADCCR_SAMPLERATE_32;
185         case 44100:     return ADCCR_SAMPLERATE_44;
186         case 48000:     return ADCCR_SAMPLERATE_48;
187         default:
188                         snd_BUG();
189                         return A_ADCCR_SAMPLERATE_8;
190         }
191 }
192 
193 static unsigned int emu10k1_calc_pitch_target(unsigned int rate)
194 {
195         unsigned int pitch_target;
196 
197         pitch_target = (rate << 8) / 375;
198         pitch_target = (pitch_target >> 1) + (pitch_target & 1);
199         return pitch_target;
200 }
201 
202 #define PITCH_48000 0x00004000
203 #define PITCH_96000 0x00008000
204 #define PITCH_85000 0x00007155
205 #define PITCH_80726 0x00006ba2
206 #define PITCH_67882 0x00005a82
207 #define PITCH_57081 0x00004c1c
208 
209 static unsigned int emu10k1_select_interprom(unsigned int pitch_target)
210 {
211         if (pitch_target == PITCH_48000)
212                 return CCCA_INTERPROM_0;
213         else if (pitch_target < PITCH_48000)
214                 return CCCA_INTERPROM_1;
215         else if (pitch_target >= PITCH_96000)
216                 return CCCA_INTERPROM_0;
217         else if (pitch_target >= PITCH_85000)
218                 return CCCA_INTERPROM_6;
219         else if (pitch_target >= PITCH_80726)
220                 return CCCA_INTERPROM_5;
221         else if (pitch_target >= PITCH_67882)
222                 return CCCA_INTERPROM_4;
223         else if (pitch_target >= PITCH_57081)
224                 return CCCA_INTERPROM_3;
225         else  
226                 return CCCA_INTERPROM_2;
227 }
228 
229 
230 static void snd_emu10k1_pcm_init_voice(emu10k1_t *emu,
231                                        int master, int extra,
232                                        emu10k1_voice_t *evoice,
233                                        unsigned int start_addr,
234                                        unsigned int end_addr)
235 {
236         snd_pcm_substream_t *substream = evoice->epcm->substream;
237         snd_pcm_runtime_t *runtime = substream->runtime;
238         emu10k1_pcm_mixer_t *mix = &emu->pcm_mixer[substream->number];
239         unsigned int silent_page, tmp;
240         int voice, stereo, w_16;
241         unsigned char attn, send_amount[8];
242         unsigned char send_routing[8];
243         unsigned long flags;
244         unsigned int pitch_target;
245 
246         voice = evoice->number;
247         stereo = runtime->channels == 2;
248         w_16 = snd_pcm_format_width(runtime->format) == 16;
249 
250         if (!extra && stereo) {
251                 start_addr >>= 1;
252                 end_addr >>= 1;
253         }
254         if (w_16) {
255                 start_addr >>= 1;
256                 end_addr >>= 1;
257         }
258 
259         spin_lock_irqsave(&emu->reg_lock, flags);
260 
261         /* volume parameters */
262         if (extra) {
263                 attn = 0;
264                 memset(send_routing, 0, sizeof(send_routing));
265                 send_routing[0] = 0;
266                 send_routing[1] = 1;
267                 send_routing[2] = 2;
268                 send_routing[3] = 3;
269                 memset(send_amount, 0, sizeof(send_amount));
270         } else {
271                 tmp = stereo ? (master ? 1 : 2) : 0;
272                 memcpy(send_routing, &mix->send_routing[tmp][0], 8);
273                 memcpy(send_amount, &mix->send_volume[tmp][0], 8);
274         }
275 
276         if (master) {
277                 unsigned int ccis = stereo ? 28 : 30;
278                 if (w_16)
279                         ccis *= 2;
280                 evoice->epcm->ccca_start_addr = start_addr + ccis;
281                 if (extra) {
282                         start_addr += ccis;
283                         end_addr += ccis;
284                 }
285                 if (stereo && !extra) {
286                         snd_emu10k1_ptr_write(emu, CPF, voice, CPF_STEREO_MASK);
287                         snd_emu10k1_ptr_write(emu, CPF, (voice + 1), CPF_STEREO_MASK);
288                 } else {
289                         snd_emu10k1_ptr_write(emu, CPF, voice, 0);
290                 }
291         }
292 
293         // setup routing
294         if (emu->audigy) {
295                 snd_emu10k1_ptr_write(emu, A_FXRT1, voice,
296                                       ((unsigned int)send_routing[3] << 24) |
297                                       ((unsigned int)send_routing[2] << 16) |
298                                       ((unsigned int)send_routing[1] << 8) |
299                                       (unsigned int)send_routing[0]);
300                 snd_emu10k1_ptr_write(emu, A_FXRT2, voice,
301                                       ((unsigned int)send_routing[7] << 24) |
302                                       ((unsigned int)send_routing[6] << 16) |
303                                       ((unsigned int)send_routing[5] << 8) |
304                                       (unsigned int)send_routing[4]);
305                 snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, voice,
306                                       ((unsigned int)send_amount[4] << 24) |
307                                       ((unsigned int)send_amount[5] << 16) |
308                                       ((unsigned int)send_amount[6] << 8) |
309                                       (unsigned int)send_amount[7]);
310         } else
311                 snd_emu10k1_ptr_write(emu, FXRT, voice,
312                                       snd_emu10k1_compose_send_routing(send_routing));
313         // Stop CA
314         // Assumption that PT is already 0 so no harm overwriting
315         snd_emu10k1_ptr_write(emu, PTRX, voice, (send_amount[0] << 8) | send_amount[1]);
316         snd_emu10k1_ptr_write(emu, DSL, voice, end_addr | (send_amount[3] << 24));
317         snd_emu10k1_ptr_write(emu, PSST, voice, start_addr | (send_amount[2] << 24));
318         pitch_target = emu10k1_calc_pitch_target(runtime->rate);
319         snd_emu10k1_ptr_write(emu, CCCA, voice, evoice->epcm->ccca_start_addr |
320                               emu10k1_select_interprom(pitch_target) |
321                               (w_16 ? 0 : CCCA_8BITSELECT));
322         // Clear filter delay memory
323         snd_emu10k1_ptr_write(emu, Z1, voice, 0);
324         snd_emu10k1_ptr_write(emu, Z2, voice, 0);
325         // invalidate maps
326         silent_page = ((unsigned int)emu->silent_page_dmaaddr << 1) | MAP_PTI_MASK;
327         snd_emu10k1_ptr_write(emu, MAPA, voice, silent_page);
328         snd_emu10k1_ptr_write(emu, MAPB, voice, silent_page);
329         // modulation envelope
330         snd_emu10k1_ptr_write(emu, CVCF, voice, 0xffff);
331         snd_emu10k1_ptr_write(emu, VTFT, voice, 0xffff);
332         snd_emu10k1_ptr_write(emu, ATKHLDM, voice, 0);
333         snd_emu10k1_ptr_write(emu, DCYSUSM, voice, 0x007f);
334         snd_emu10k1_ptr_write(emu, LFOVAL1, voice, 0x8000);
335         snd_emu10k1_ptr_write(emu, LFOVAL2, voice, 0x8000);
336         snd_emu10k1_ptr_write(emu, FMMOD, voice, 0);
337         snd_emu10k1_ptr_write(emu, TREMFRQ, voice, 0);
338         snd_emu10k1_ptr_write(emu, FM2FRQ2, voice, 0);
339         snd_emu10k1_ptr_write(emu, ENVVAL, voice, 0x8000);
340         // volume envelope
341         snd_emu10k1_ptr_write(emu, ATKHLDV, voice, 0x7f7f);
342         snd_emu10k1_ptr_write(emu, ENVVOL, voice, 0x0000);
343         // filter envelope
344         snd_emu10k1_ptr_write(emu, PEFE_FILTERAMOUNT, voice, 0x7f);
345         // pitch envelope
346         snd_emu10k1_ptr_write(emu, PEFE_PITCHAMOUNT, voice, 0);
347 
348         spin_unlock_irqrestore(&emu->reg_lock, flags);
349 }
350 
351 static int snd_emu10k1_playback_hw_params(snd_pcm_substream_t * substream,
352                                           snd_pcm_hw_params_t * hw_params)
353 {
354         emu10k1_t *emu = snd_pcm_substream_chip(substream);
355         snd_pcm_runtime_t *runtime = substream->runtime;
356         emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
357         int err;
358 
359         if ((err = snd_emu10k1_pcm_channel_alloc(epcm, params_channels(hw_params))) < 0)
360                 return err;
361         if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
362                 return err;
363         if (err > 0) {  /* change */
364                 snd_util_memblk_t *memblk;
365                 if (epcm->memblk != NULL)
366                         snd_emu10k1_free_pages(emu, epcm->memblk);
367                 memblk = snd_emu10k1_alloc_pages(emu, substream);
368                 if ((epcm->memblk = memblk) == NULL || ((emu10k1_memblk_t *)memblk)->mapped_page < 0) {
369                         epcm->start_addr = 0;
370                         return -ENOMEM;
371                 }
372                 epcm->start_addr = ((emu10k1_memblk_t *)memblk)->mapped_page << PAGE_SHIFT;
373         }
374         return 0;
375 }
376 
377 static int snd_emu10k1_playback_hw_free(snd_pcm_substream_t * substream)
378 {
379         emu10k1_t *emu = snd_pcm_substream_chip(substream);
380         snd_pcm_runtime_t *runtime = substream->runtime;
381         emu10k1_pcm_t *epcm;
382 
383         if (runtime->private_data == NULL)
384                 return 0;
385         epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
386         if (epcm->extra) {
387                 snd_emu10k1_voice_free(epcm->emu, epcm->extra);
388                 epcm->extra = NULL;
389         }
390         if (epcm->voices[1]) {
391                 snd_emu10k1_voice_free(epcm->emu, epcm->voices[1]);
392                 epcm->voices[1] = NULL;
393         }
394         if (epcm->voices[0]) {
395                 snd_emu10k1_voice_free(epcm->emu, epcm->voices[0]);
396                 epcm->voices[0] = NULL;
397         }
398         if (epcm->memblk) {
399                 snd_emu10k1_free_pages(emu, epcm->memblk);
400                 epcm->memblk = NULL;
401                 epcm->start_addr = 0;
402         }
403         snd_pcm_lib_free_pages(substream);
404         return 0;
405 }
406 
407 static int snd_emu10k1_playback_prepare(snd_pcm_substream_t * substream)
408 {
409         emu10k1_t *emu = snd_pcm_substream_chip(substream);
410         snd_pcm_runtime_t *runtime = substream->runtime;
411         emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
412         unsigned int start_addr, end_addr;
413 
414         start_addr = epcm->start_addr;
415         end_addr = snd_pcm_lib_period_bytes(substream);
416         if (runtime->channels == 2)
417                 end_addr >>= 1;
418         end_addr += start_addr;
419         snd_emu10k1_pcm_init_voice(emu, 1, 1, epcm->extra,
420                                    start_addr, end_addr);
421         end_addr = epcm->start_addr + snd_pcm_lib_buffer_bytes(substream);
422         snd_emu10k1_pcm_init_voice(emu, 1, 0, epcm->voices[0],
423                                    start_addr, end_addr);
424         if (epcm->voices[1])
425                 snd_emu10k1_pcm_init_voice(emu, 0, 0, epcm->voices[1],
426                                            start_addr, end_addr);
427         return 0;
428 }
429 
430 static int snd_emu10k1_capture_hw_params(snd_pcm_substream_t * substream,
431                                          snd_pcm_hw_params_t * hw_params)
432 {
433         return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
434 }
435 
436 static int snd_emu10k1_capture_hw_free(snd_pcm_substream_t * substream)
437 {
438         return snd_pcm_lib_free_pages(substream);
439 }
440 
441 static int snd_emu10k1_capture_prepare(snd_pcm_substream_t * substream)
442 {
443         emu10k1_t *emu = snd_pcm_substream_chip(substream);
444         snd_pcm_runtime_t *runtime = substream->runtime;
445         emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
446         int idx;
447 
448         snd_emu10k1_ptr_write(emu, epcm->capture_bs_reg, 0, 0);
449         switch (epcm->type) {
450         case CAPTURE_AC97ADC:
451                 snd_emu10k1_ptr_write(emu, ADCCR, 0, 0);
452                 break;
453         case CAPTURE_EFX:
454                 snd_emu10k1_ptr_write(emu, FXWC, 0, 0);
455                 break;
456         default:
457                 break;
458         }       
459         snd_emu10k1_ptr_write(emu, epcm->capture_ba_reg, 0, runtime->dma_addr);
460         epcm->capture_bufsize = snd_pcm_lib_buffer_bytes(substream);
461         epcm->capture_bs_val = 0;
462         for (idx = 0; idx < 31; idx++) {
463                 if (capture_period_sizes[idx] == epcm->capture_bufsize) {
464                         epcm->capture_bs_val = idx + 1;
465                         break;
466                 }
467         }
468         if (epcm->capture_bs_val == 0) {
469                 snd_BUG();
470                 epcm->capture_bs_val++;
471         }
472         if (epcm->type == CAPTURE_AC97ADC) {
473                 epcm->capture_cr_val = emu->audigy ? A_ADCCR_LCHANENABLE : ADCCR_LCHANENABLE;
474                 if (runtime->channels > 1)
475                         epcm->capture_cr_val |= emu->audigy ? A_ADCCR_RCHANENABLE : ADCCR_RCHANENABLE;
476                 epcm->capture_cr_val |= emu->audigy ?
477                         snd_emu10k1_audigy_capture_rate_reg(runtime->rate) :
478                         snd_emu10k1_capture_rate_reg(runtime->rate);
479         }
480         return 0;
481 }
482 
483 static void snd_emu10k1_playback_invalidate_cache(emu10k1_t *emu, emu10k1_voice_t *evoice)
484 {
485         snd_pcm_runtime_t *runtime;
486         unsigned int voice, i, ccis, cra = 64, cs, sample;
487 
488         if (evoice == NULL)
489                 return;
490         runtime = evoice->epcm->substream->runtime;
491         voice = evoice->number;
492         sample = snd_pcm_format_width(runtime->format) == 16 ? 0 : 0x80808080;
493         if (runtime->channels > 1) {
494                 ccis = 28;
495                 cs = 4;
496         } else {
497                 ccis = 30;
498                 cs = 2;
499         }
500         if (sample == 0)        /* 16-bit */
501                 ccis *= 2;
502         for (i = 0; i < cs; i++)
503                 snd_emu10k1_ptr_write(emu, CD0 + i, voice, sample);
504         // reset cache
505         snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice, 0);
506         snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice, cra);
507         if (runtime->channels > 1) {
508                 snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice + 1, 0);
509                 snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice + 1, cra);
510         }
511         // fill cache
512         snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice, ccis);
513 }
514 
515 static void snd_emu10k1_playback_trigger_voice(emu10k1_t *emu, emu10k1_voice_t *evoice, int master, int extra)
516 {
517         snd_pcm_substream_t *substream;
518         snd_pcm_runtime_t *runtime;
519         emu10k1_pcm_mixer_t *mix;
520         unsigned int voice, pitch, pitch_target, tmp;
521         unsigned int attn;
522 
523         if (evoice == NULL)     /* skip second voice for mono */
524                 return;
525         substream = evoice->epcm->substream;
526         runtime = substream->runtime;
527         mix = &emu->pcm_mixer[substream->number];
528         voice = evoice->number;
529         pitch = snd_emu10k1_rate_to_pitch(runtime->rate) >> 8;
530         pitch_target = emu10k1_calc_pitch_target(runtime->rate);
531         attn = extra ? 0 : 0x00ff;
532         tmp = runtime->channels == 2 ? (master ? 1 : 2) : 0;
533         snd_emu10k1_ptr_write(emu, IFATN, voice, attn);
534         snd_emu10k1_ptr_write(emu, VTFT, voice, (mix->attn[tmp] << 16) | 0xffff);
535         snd_emu10k1_ptr_write(emu, CVCF, voice, (mix->attn[tmp] << 16) | 0xffff);
536         snd_emu10k1_voice_clear_loop_stop(emu, voice);          
537         if (extra)
538                 snd_emu10k1_voice_intr_enable(emu, voice);
539         snd_emu10k1_ptr_write(emu, DCYSUSV, voice, 0x7f7f);
540         snd_emu10k1_ptr_write(emu, PTRX_PITCHTARGET, voice, pitch_target);
541         if (master)
542                 snd_emu10k1_ptr_write(emu, CPF_CURRENTPITCH, voice, pitch_target);
543         snd_emu10k1_ptr_write(emu, IP, voice, pitch);
544 }
545 
546 static void snd_emu10k1_playback_stop_voice(emu10k1_t *emu, emu10k1_voice_t *evoice)
547 {
548         unsigned int voice;
549 
550         if (evoice == NULL)
551                 return;
552         voice = evoice->number;
553         snd_emu10k1_voice_intr_disable(emu, voice);
554         snd_emu10k1_ptr_write(emu, PTRX_PITCHTARGET, voice, 0);
555         snd_emu10k1_ptr_write(emu, CPF_CURRENTPITCH, voice, 0);
556         snd_emu10k1_ptr_write(emu, IFATN, voice, 0xffff);
557         snd_emu10k1_ptr_write(emu, VTFT, voice, 0xffff);
558         snd_emu10k1_ptr_write(emu, CVCF, voice, 0xffff);
559         snd_emu10k1_ptr_write(emu, IP, voice, 0);
560 }
561 
562 static int snd_emu10k1_playback_trigger(snd_pcm_substream_t * substream,
563                                         int cmd)
564 {
565         emu10k1_t *emu = snd_pcm_substream_chip(substream);
566         snd_pcm_runtime_t *runtime = substream->runtime;
567         emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
568         unsigned long flags;
569         int result = 0;
570 
571         // printk("trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", (int)emu, cmd, substream->ops->pointer(substream));
572         spin_lock_irqsave(&emu->reg_lock, flags);
573         switch (cmd) {
574         case SNDRV_PCM_TRIGGER_START:
575                 snd_emu10k1_playback_invalidate_cache(emu, epcm->extra);        /* do we need this? */
576                 snd_emu10k1_playback_invalidate_cache(emu, epcm->voices[0]);
577                 /* follow thru */
578         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
579                 snd_emu10k1_playback_trigger_voice(emu, epcm->voices[0], 1, 0);
580                 snd_emu10k1_playback_trigger_voice(emu, epcm->voices[1], 0, 0);
581                 snd_emu10k1_playback_trigger_voice(emu, epcm->extra, 1, 1);
582                 epcm->running = 1;
583                 break;
584         case SNDRV_PCM_TRIGGER_STOP:
585         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
586                 epcm->running = 0;
587                 snd_emu10k1_playback_stop_voice(emu, epcm->voices[0]);
588                 snd_emu10k1_playback_stop_voice(emu, epcm->voices[1]);
589                 snd_emu10k1_playback_stop_voice(emu, epcm->extra);
590                 break;
591         default:
592                 result = -EINVAL;
593                 break;
594         }
595         spin_unlock_irqrestore(&emu->reg_lock, flags);
596         return result;
597 }
598 
599 static int snd_emu10k1_capture_trigger(snd_pcm_substream_t * substream,
600                                        int cmd)
601 {
602         emu10k1_t *emu = snd_pcm_substream_chip(substream);
603         snd_pcm_runtime_t *runtime = substream->runtime;
604         emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
605         unsigned long flags;
606         int result = 0;
607 
608         // printk("trigger - emu10k1 = %p, cmd = %i, pointer = %i\n", emu, cmd, substream->ops->pointer(substream));
609         spin_lock_irqsave(&emu->reg_lock, flags);
610         switch (cmd) {
611         case SNDRV_PCM_TRIGGER_START:
612                 outl(epcm->capture_ipr, emu->port + IPR);
613                 snd_emu10k1_intr_enable(emu, epcm->capture_inte);
614                 // printk("adccr = 0x%x, adcbs = 0x%x\n", epcm->adccr, epcm->adcbs);
615                 switch (epcm->type) {
616                 case CAPTURE_AC97ADC:
617                         snd_emu10k1_ptr_write(emu, ADCCR, 0, epcm->capture_cr_val);
618                         break;
619                 case CAPTURE_EFX:
620                         snd_emu10k1_ptr_write(emu, FXWC, 0, epcm->capture_cr_val);
621                         break;
622                 default:        
623                         break;
624                 }
625                 snd_emu10k1_ptr_write(emu, epcm->capture_bs_reg, 0, epcm->capture_bs_val);
626                 epcm->running = 1;
627                 epcm->first_ptr = 1;
628                 break;
629         case SNDRV_PCM_TRIGGER_STOP:
630                 epcm->running = 0;
631                 snd_emu10k1_intr_disable(emu, epcm->capture_inte);
632                 outl(epcm->capture_ipr, emu->port + IPR);
633                 snd_emu10k1_ptr_write(emu, epcm->capture_bs_reg, 0, 0);
634                 switch (epcm->type) {
635                 case CAPTURE_AC97ADC:
636                         snd_emu10k1_ptr_write(emu, ADCCR, 0, 0);
637                         break;
638                 case CAPTURE_EFX:
639                         snd_emu10k1_ptr_write(emu, FXWC, 0, 0);
640                         break;
641                 default:
642                         break;
643                 }
644                 break;
645         default:
646                 result = -EINVAL;
647         }
648         spin_unlock_irqrestore(&emu->reg_lock, flags);
649         return result;
650 }
651 
652 static snd_pcm_uframes_t snd_emu10k1_playback_pointer(snd_pcm_substream_t * substream)
653 {
654         emu10k1_t *emu = snd_pcm_substream_chip(substream);
655         snd_pcm_runtime_t *runtime = substream->runtime;
656         emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
657         unsigned int ptr;
658 
659         if (!epcm->running)
660                 return 0;
661         ptr = snd_emu10k1_ptr_read(emu, CCCA, epcm->voices[0]->number) & 0x00ffffff;
662 #if 0   /* Perex's code */
663         ptr += runtime->buffer_size;
664         ptr -= epcm->ccca_start_addr;
665         ptr %= runtime->buffer_size;
666 #else   /* EMU10K1 Open Source code from Creative */
667         if (ptr < epcm->ccca_start_addr)
668                 ptr += runtime->buffer_size - epcm->ccca_start_addr;
669         else {
670                 ptr -= epcm->ccca_start_addr;
671                 if (ptr >= runtime->buffer_size)
672                         ptr -= runtime->buffer_size;
673         }
674 #endif
675         // printk("ptr = 0x%x, buffer_size = 0x%x, period_size = 0x%x\n", ptr, runtime->buffer_size, runtime->period_size);
676         return ptr;
677 }
678 
679 static snd_pcm_uframes_t snd_emu10k1_capture_pointer(snd_pcm_substream_t * substream)
680 {
681         emu10k1_t *emu = snd_pcm_substream_chip(substream);
682         snd_pcm_runtime_t *runtime = substream->runtime;
683         emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
684         unsigned int ptr;
685 
686         if (!epcm->running)
687                 return 0;
688         if (epcm->first_ptr) {
689                 udelay(50);     // hack, it takes awhile until capture is started
690                 epcm->first_ptr = 0;
691         }
692         ptr = snd_emu10k1_ptr_read(emu, epcm->capture_idx_reg, 0) & 0x0000ffff;
693         return bytes_to_frames(runtime, ptr);
694 }
695 
696 /*
697  *  Playback support device description
698  */
699 
700 static snd_pcm_hardware_t snd_emu10k1_playback =
701 {
702         .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
703                                  SNDRV_PCM_INFO_BLOCK_TRANSFER |
704                                  SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE),
705         .formats =              SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
706         .rates =                SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
707         .rate_min =             4000,
708         .rate_max =             48000,
709         .channels_min =         1,
710         .channels_max =         2,
711         .buffer_bytes_max =     (128*1024),
712         .period_bytes_min =     64,
713         .period_bytes_max =     (128*1024),
714         .periods_min =          1,
715         .periods_max =          1024,
716         .fifo_size =            0,
717 };
718 
719 /*
720  *  Capture support device description
721  */
722 
723 static snd_pcm_hardware_t snd_emu10k1_capture =
724 {
725         .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
726                                  SNDRV_PCM_INFO_BLOCK_TRANSFER |
727                                  SNDRV_PCM_INFO_MMAP_VALID),
728         .formats =              SNDRV_PCM_FMTBIT_S16_LE,
729         .rates =                SNDRV_PCM_RATE_8000_48000,
730         .rate_min =             8000,
731         .rate_max =             48000,
732         .channels_min =         1,
733         .channels_max =         2,
734         .buffer_bytes_max =     (64*1024),
735         .period_bytes_min =     384,
736         .period_bytes_max =     (64*1024),
737         .periods_min =          2,
738         .periods_max =          2,
739         .fifo_size =            0,
740 };
741 
742 /*
743  *
744  */
745 
746 static void snd_emu10k1_pcm_mixer_notify1(emu10k1_t *emu, snd_kcontrol_t *kctl, int idx, int activate)
747 {
748         snd_ctl_elem_id_t id;
749 
750         snd_runtime_check(kctl != NULL, return);
751         if (activate)
752                 kctl->vd[idx].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
753         else
754                 kctl->vd[idx].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
755         snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE |
756                        SNDRV_CTL_EVENT_MASK_INFO,
757                        snd_ctl_build_ioff(&id, kctl, idx));
758 }
759 
760 static void snd_emu10k1_pcm_mixer_notify(emu10k1_t *emu, int idx, int activate)
761 {
762         snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_send_routing, idx, activate);
763         snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_send_volume, idx, activate);
764         snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_attn, idx, activate);
765 }
766 
767 static void snd_emu10k1_pcm_free_substream(snd_pcm_runtime_t *runtime)
768 {
769         emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return);
770 
771         if (epcm)
772                 snd_magic_kfree(epcm);
773 }
774 
775 static int snd_emu10k1_playback_open(snd_pcm_substream_t * substream)
776 {
777         emu10k1_t *emu = snd_pcm_substream_chip(substream);
778         emu10k1_pcm_t *epcm;
779         emu10k1_pcm_mixer_t *mix;
780         snd_pcm_runtime_t *runtime = substream->runtime;
781         int i, err;
782 
783         epcm = snd_magic_kcalloc(emu10k1_pcm_t, 0, GFP_KERNEL);
784         if (epcm == NULL)
785                 return -ENOMEM;
786         epcm->emu = emu;
787         epcm->type = PLAYBACK_EMUVOICE;
788         epcm->substream = substream;
789         runtime->private_data = epcm;
790         runtime->private_free = snd_emu10k1_pcm_free_substream;
791         runtime->hw = snd_emu10k1_playback;
792         if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) {
793                 snd_magic_kfree(epcm);
794                 return err;
795         }
796         if ((err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX)) < 0) {
797                 snd_magic_kfree(epcm);
798                 return err;
799         }
800         mix = &emu->pcm_mixer[substream->number];
801         for (i = 0; i < 4; i++)
802                 mix->send_routing[0][i] = mix->send_routing[1][i] = mix->send_routing[2][i] = i;
803         memset(&mix->send_volume, 0, sizeof(mix->send_volume));
804         mix->send_volume[0][0] = mix->send_volume[0][1] =
805         mix->send_volume[1][0] = mix->send_volume[2][1] = 255;
806         mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff;
807         mix->epcm = epcm;
808         snd_emu10k1_pcm_mixer_notify(emu, substream->number, 1);
809         return 0;
810 }
811 
812 static int snd_emu10k1_playback_close(snd_pcm_substream_t * substream)
813 {
814         emu10k1_t *emu = snd_pcm_substream_chip(substream);
815         emu10k1_pcm_mixer_t *mix = &emu->pcm_mixer[substream->number];
816 
817         mix->epcm = NULL;
818         snd_emu10k1_pcm_mixer_notify(emu, substream->number, 0);
819         return 0;
820 }
821 
822 static int snd_emu10k1_capture_open(snd_pcm_substream_t * substream)
823 {
824         emu10k1_t *emu = snd_pcm_substream_chip(substream);
825         snd_pcm_runtime_t *runtime = substream->runtime;
826         emu10k1_pcm_t *epcm;
827 
828         epcm = snd_magic_kcalloc(emu10k1_pcm_t, 0, GFP_KERNEL);
829         if (epcm == NULL)
830                 return -ENOMEM;
831         epcm->emu = emu;
832         epcm->type = CAPTURE_AC97ADC;
833         epcm->substream = substream;
834         epcm->capture_ipr = IPR_ADCBUFFULL|IPR_ADCBUFHALFFULL;
835         epcm->capture_inte = INTE_ADCBUFENABLE;
836         epcm->capture_ba_reg = ADCBA;
837         epcm->capture_bs_reg = ADCBS;
838         epcm->capture_idx_reg = emu->audigy ? A_ADCIDX : ADCIDX;
839         runtime->private_data = epcm;
840         runtime->private_free = snd_emu10k1_pcm_free_substream;
841         runtime->hw = snd_emu10k1_capture;
842         emu->capture_interrupt = snd_emu10k1_pcm_ac97adc_interrupt;
843         emu->pcm_capture_substream = substream;
844         snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes);
845         snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_capture_rates);
846         return 0;
847 }
848 
849 static int snd_emu10k1_capture_close(snd_pcm_substream_t * substream)
850 {
851         emu10k1_t *emu = snd_pcm_substream_chip(substream);
852 
853         emu->capture_interrupt = NULL;
854         emu->pcm_capture_substream = NULL;
855         return 0;
856 }
857 
858 static int snd_emu10k1_capture_mic_open(snd_pcm_substream_t * substream)
859 {
860         emu10k1_t *emu = snd_pcm_substream_chip(substream);
861         emu10k1_pcm_t *epcm;
862         snd_pcm_runtime_t *runtime = substream->runtime;
863 
864         epcm = snd_magic_kcalloc(emu10k1_pcm_t, 0, GFP_KERNEL);
865         if (epcm == NULL)
866                 return -ENOMEM;
867         epcm->emu = emu;
868         epcm->type = CAPTURE_AC97MIC;
869         epcm->substream = substream;
870         epcm->capture_ipr = IPR_MICBUFFULL|IPR_MICBUFHALFFULL;
871         epcm->capture_inte = INTE_MICBUFENABLE;
872         epcm->capture_ba_reg = MICBA;
873         epcm->capture_bs_reg = MICBS;
874         epcm->capture_idx_reg = MICIDX;
875         substream->runtime->private_data = epcm;
876         substream->runtime->private_free = snd_emu10k1_pcm_free_substream;
877         runtime->hw = snd_emu10k1_capture;
878         runtime->hw.rates = SNDRV_PCM_RATE_8000;
879         runtime->hw.rate_min = runtime->hw.rate_max = 8000;
880         runtime->hw.channels_min = 1;
881         emu->capture_mic_interrupt = snd_emu10k1_pcm_ac97mic_interrupt;
882         emu->pcm_capture_mic_substream = substream;
883         snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes);
884         return 0;
885 }
886 
887 static int snd_emu10k1_capture_mic_close(snd_pcm_substream_t * substream)
888 {
889         emu10k1_t *emu = snd_pcm_substream_chip(substream);
890 
891         emu->capture_interrupt = NULL;
892         emu->pcm_capture_mic_substream = NULL;
893         return 0;
894 }
895 
896 static int snd_emu10k1_capture_efx_open(snd_pcm_substream_t * substream)
897 {
898         emu10k1_t *emu = snd_pcm_substream_chip(substream);
899         emu10k1_pcm_t *epcm;
900         snd_pcm_runtime_t *runtime = substream->runtime;
901         unsigned long flags;
902         int nefx = emu->audigy ? 64 : 32;
903         int idx;
904 
905         epcm = snd_magic_kcalloc(emu10k1_pcm_t, 0, GFP_KERNEL);
906         if (epcm == NULL)
907                 return -ENOMEM;
908         epcm->emu = emu;
909         epcm->type = CAPTURE_EFX;
910         epcm->substream = substream;
911         epcm->capture_ipr = IPR_EFXBUFFULL|IPR_EFXBUFHALFFULL;
912         epcm->capture_inte = INTE_EFXBUFENABLE;
913         epcm->capture_ba_reg = FXBA;
914         epcm->capture_bs_reg = FXBS;
915         epcm->capture_idx_reg = FXIDX;
916         substream->runtime->private_data = epcm;
917         substream->runtime->private_free = snd_emu10k1_pcm_free_substream;
918         runtime->hw = snd_emu10k1_capture;
919         runtime->hw.rates = SNDRV_PCM_RATE_48000;
920         runtime->hw.rate_min = runtime->hw.rate_max = 48000;
921         spin_lock_irqsave(&emu->reg_lock, flags);
922         runtime->hw.channels_min = runtime->hw.channels_max = 0;
923         for (idx = 0; idx < nefx; idx++) {
924                 if (emu->efx_voices_mask[idx/32] & (1 << (idx%32))) {
925                         runtime->hw.channels_min++;
926                         runtime->hw.channels_max++;
927                 }
928         }
929         epcm->capture_cr_val = emu->efx_voices_mask[0];
930         epcm->capture_cr_val2 = emu->efx_voices_mask[1];
931         spin_unlock_irqrestore(&emu->reg_lock, flags);
932         emu->capture_efx_interrupt = snd_emu10k1_pcm_efx_interrupt;
933         emu->pcm_capture_efx_substream = substream;
934         snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes);
935         return 0;
936 }
937 
938 static int snd_emu10k1_capture_efx_close(snd_pcm_substream_t * substream)
939 {
940         emu10k1_t *emu = snd_pcm_substream_chip(substream);
941 
942         emu->capture_interrupt = NULL;
943         emu->pcm_capture_efx_substream = NULL;
944         return 0;
945 }
946 
947 static snd_pcm_ops_t snd_emu10k1_playback_ops = {
948         .open =                 snd_emu10k1_playback_open,
949         .close =                snd_emu10k1_playback_close,
950         .ioctl =                snd_pcm_lib_ioctl,
951         .hw_params =            snd_emu10k1_playback_hw_params,
952         .hw_free =              snd_emu10k1_playback_hw_free,
953         .prepare =              snd_emu10k1_playback_prepare,
954         .trigger =              snd_emu10k1_playback_trigger,
955         .pointer =              snd_emu10k1_playback_pointer,
956         .page =                 snd_pcm_sgbuf_ops_page,
957 };
958 
959 static snd_pcm_ops_t snd_emu10k1_capture_ops = {
960         .open =                 snd_emu10k1_capture_open,
961         .close =                snd_emu10k1_capture_close,
962         .ioctl =                snd_pcm_lib_ioctl,
963         .hw_params =            snd_emu10k1_capture_hw_params,
964         .hw_free =              snd_emu10k1_capture_hw_free,
965         .prepare =              snd_emu10k1_capture_prepare,
966         .trigger =              snd_emu10k1_capture_trigger,
967         .pointer =              snd_emu10k1_capture_pointer,
968 };
969 
970 static void snd_emu10k1_pcm_free(snd_pcm_t *pcm)
971 {
972         emu10k1_t *emu = snd_magic_cast(emu10k1_t, pcm->private_data, return);
973         emu->pcm = NULL;
974         snd_pcm_lib_preallocate_free_for_all(pcm);
975 }
976 
977 int __devinit snd_emu10k1_pcm(emu10k1_t * emu, int device, snd_pcm_t ** rpcm)
978 {
979         snd_pcm_t *pcm;
980         snd_pcm_substream_t *substream;
981         int err;
982 
983         if (rpcm)
984                 *rpcm = NULL;
985 
986         if ((err = snd_pcm_new(emu->card, "emu10k1", device, 32, 1, &pcm)) < 0)
987                 return err;
988 
989         pcm->private_data = emu;
990         pcm->private_free = snd_emu10k1_pcm_free;
991 
992         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_playback_ops);
993         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_ops);
994 
995         pcm->info_flags = 0;
996         pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
997         strcpy(pcm->name, "EMU10K1");
998         emu->pcm = pcm;
999 
1000         for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next)
1001                 if ((err = snd_pcm_lib_preallocate_sg_pages(emu->pci, substream, 64*1024, 64*1024)) < 0)
1002                         return err;
1003 
1004         for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; substream; substream = substream->next)
1005                 snd_pcm_lib_preallocate_pci_pages(emu->pci, substream, 64*1024, 64*1024);
1006 
1007         if (rpcm)
1008                 *rpcm = pcm;
1009 
1010         return 0;
1011 }
1012 
1013 static snd_pcm_ops_t snd_emu10k1_capture_mic_ops = {
1014         .open =                 snd_emu10k1_capture_mic_open,
1015         .close =                snd_emu10k1_capture_mic_close,
1016         .ioctl =                snd_pcm_lib_ioctl,
1017         .hw_params =            snd_emu10k1_capture_hw_params,
1018         .hw_free =              snd_emu10k1_capture_hw_free,
1019         .prepare =              snd_emu10k1_capture_prepare,
1020         .trigger =              snd_emu10k1_capture_trigger,
1021         .pointer =              snd_emu10k1_capture_pointer,
1022 };
1023 
1024 static void snd_emu10k1_pcm_mic_free(snd_pcm_t *pcm)
1025 {
1026         emu10k1_t *emu = snd_magic_cast(emu10k1_t, pcm->private_data, return);
1027         emu->pcm_mic = NULL;
1028         snd_pcm_lib_preallocate_free_for_all(pcm);
1029 }
1030 
1031 int __devinit snd_emu10k1_pcm_mic(emu10k1_t * emu, int device, snd_pcm_t ** rpcm)
1032 {
1033         snd_pcm_t *pcm;
1034         int err;
1035 
1036         if (rpcm)
1037                 *rpcm = NULL;
1038 
1039         if ((err = snd_pcm_new(emu->card, "emu10k1 mic", device, 0, 1, &pcm)) < 0)
1040                 return err;
1041 
1042         pcm->private_data = emu;
1043         pcm->private_free = snd_emu10k1_pcm_mic_free;
1044 
1045         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_mic_ops);
1046 
1047         pcm->info_flags = 0;
1048         strcpy(pcm->name, "EMU10K1 MIC");
1049         emu->pcm_mic = pcm;
1050 
1051         snd_pcm_lib_preallocate_pci_pages_for_all(emu->pci, pcm, 64*1024, 64*1024);
1052 
1053         if (rpcm)
1054                 *rpcm = pcm;
1055         return 0;
1056 }
1057 
1058 static int snd_emu10k1_pcm_efx_voices_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
1059 {
1060         emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
1061         int nefx = emu->audigy ? 64 : 32;
1062         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1063         uinfo->count = nefx;
1064         uinfo->value.integer.min = 0;
1065         uinfo->value.integer.max = 1;
1066         return 0;
1067 }
1068 
1069 static int snd_emu10k1_pcm_efx_voices_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1070 {
1071         emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
1072         unsigned long flags;
1073         int nefx = emu->audigy ? 64 : 32;
1074         int idx;
1075         
1076         spin_lock_irqsave(&emu->reg_lock, flags);
1077         for (idx = 0; idx < nefx; idx++)
1078                 ucontrol->value.integer.value[idx] = (emu->efx_voices_mask[idx / 32] & (1 << (idx % 32))) ? 1 : 0;
1079         spin_unlock_irqrestore(&emu->reg_lock, flags);
1080         return 0;
1081 }
1082 
1083 static int snd_emu10k1_pcm_efx_voices_mask_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1084 {
1085         emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
1086         unsigned long flags;
1087         unsigned int nval[2], bits;
1088         int nefx = emu->audigy ? 64 : 32;
1089         int change, idx;
1090         
1091         nval[0] = nval[1] = 0;
1092         for (idx = 0, bits = 0; idx < nefx; idx++)
1093                 if (ucontrol->value.integer.value[idx]) {
1094                         nval[idx / 32] |= 1 << (idx % 32);
1095                         bits++;
1096                 }
1097         if (bits != 1 && bits != 2 && bits != 4 && bits != 8)
1098                 return -EINVAL;
1099         spin_lock_irqsave(&emu->reg_lock, flags);
1100         change = (nval[0] != emu->efx_voices_mask[0]) ||
1101                 (nval[1] != emu->efx_voices_mask[1]);
1102         emu->efx_voices_mask[0] = nval[0];
1103         emu->efx_voices_mask[1] = nval[1];
1104         spin_unlock_irqrestore(&emu->reg_lock, flags);
1105         return change;
1106 }
1107 
1108 static snd_kcontrol_new_t snd_emu10k1_pcm_efx_voices_mask = {
1109         .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1110         .name = "EFX voices mask",
1111         .info = snd_emu10k1_pcm_efx_voices_mask_info,
1112         .get = snd_emu10k1_pcm_efx_voices_mask_get,
1113         .put = snd_emu10k1_pcm_efx_voices_mask_put
1114 };
1115 
1116 static snd_pcm_ops_t snd_emu10k1_capture_efx_ops = {
1117         .open =                 snd_emu10k1_capture_efx_open,
1118         .close =                snd_emu10k1_capture_efx_close,
1119         .ioctl =                snd_pcm_lib_ioctl,
1120         .hw_params =            snd_emu10k1_capture_hw_params,
1121         .hw_free =              snd_emu10k1_capture_hw_free,
1122         .prepare =              snd_emu10k1_capture_prepare,
1123         .trigger =              snd_emu10k1_capture_trigger,
1124         .pointer =              snd_emu10k1_capture_pointer,
1125 };
1126 
1127 static void snd_emu10k1_pcm_efx_free(snd_pcm_t *pcm)
1128 {
1129         emu10k1_t *emu = snd_magic_cast(emu10k1_t, pcm->private_data, return);
1130         emu->pcm_efx = NULL;
1131         snd_pcm_lib_preallocate_free_for_all(pcm);
1132 }
1133 
1134 int __devinit snd_emu10k1_pcm_efx(emu10k1_t * emu, int device, snd_pcm_t ** rpcm)
1135 {
1136         snd_pcm_t *pcm;
1137         int err;
1138 
1139         if (rpcm)
1140                 *rpcm = NULL;
1141 
1142         if ((err = snd_pcm_new(emu->card, "emu10k1 efx", device, 0, 1, &pcm)) < 0)
1143                 return err;
1144 
1145         pcm->private_data = emu;
1146         pcm->private_free = snd_emu10k1_pcm_efx_free;
1147 
1148         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_efx_ops);
1149 
1150         pcm->info_flags = 0;
1151         strcpy(pcm->name, "EMU10K1 EFX");
1152         emu->pcm_efx = pcm;
1153         if (rpcm)
1154                 *rpcm = pcm;
1155 
1156         emu->efx_voices_mask[0] = FXWC_DEFAULTROUTE_C | FXWC_DEFAULTROUTE_A;
1157         emu->efx_voices_mask[1] = 0;
1158         snd_ctl_add(emu->card, snd_ctl_new1(&snd_emu10k1_pcm_efx_voices_mask, emu));
1159 
1160         snd_pcm_lib_preallocate_pci_pages_for_all(emu->pci, pcm, 64*1024, 64*1024);
1161 
1162         return 0;
1163 }
1164 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp