x86, rwsem: Minor cleanups
[sfrench/cifs-2.6.git] / sound / isa / sb / emu8000_pcm.c
1 /*
2  * pcm emulation on emu8000 wavetable
3  *
4  *  Copyright (C) 2002 Takashi Iwai <tiwai@suse.de>
5  *
6  *   This program is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation; either version 2 of the License, or
9  *   (at your option) any later version.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with this program; if not, write to the Free Software
18  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19  */
20
21 #include "emu8000_local.h"
22 #include <linux/init.h>
23 #include <linux/slab.h>
24 #include <sound/initval.h>
25 #include <sound/pcm.h>
26
27 /*
28  * define the following if you want to use this pcm with non-interleaved mode
29  */
30 /* #define USE_NONINTERLEAVE */
31
32 /* NOTE: for using the non-interleaved mode with alsa-lib, you have to set
33  * mmap_emulation flag to 1 in your .asoundrc, such like
34  *
35  *      pcm.emu8k {
36  *              type plug
37  *              slave.pcm {
38  *                      type hw
39  *                      card 0
40  *                      device 1
41  *                      mmap_emulation 1
42  *              }
43  *      }
44  *
45  * besides, for the time being, the non-interleaved mode doesn't work well on
46  * alsa-lib...
47  */
48
49
50 struct snd_emu8k_pcm {
51         struct snd_emu8000 *emu;
52         struct snd_pcm_substream *substream;
53
54         unsigned int allocated_bytes;
55         struct snd_util_memblk *block;
56         unsigned int offset;
57         unsigned int buf_size;
58         unsigned int period_size;
59         unsigned int loop_start[2];
60         unsigned int pitch;
61         int panning[2];
62         int last_ptr;
63         int period_pos;
64         int voices;
65         unsigned int dram_opened: 1;
66         unsigned int running: 1;
67         unsigned int timer_running: 1;
68         struct timer_list timer;
69         spinlock_t timer_lock;
70 };
71
72 #define LOOP_BLANK_SIZE         8
73
74
75 /*
76  * open up channels for the simultaneous data transfer and playback
77  */
78 static int
79 emu8k_open_dram_for_pcm(struct snd_emu8000 *emu, int channels)
80 {
81         int i;
82
83         /* reserve up to 2 voices for playback */
84         snd_emux_lock_voice(emu->emu, 0);
85         if (channels > 1)
86                 snd_emux_lock_voice(emu->emu, 1);
87
88         /* reserve 28 voices for loading */
89         for (i = channels + 1; i < EMU8000_DRAM_VOICES; i++) {
90                 unsigned int mode = EMU8000_RAM_WRITE;
91                 snd_emux_lock_voice(emu->emu, i);
92 #ifndef USE_NONINTERLEAVE
93                 if (channels > 1 && (i & 1) != 0)
94                         mode |= EMU8000_RAM_RIGHT;
95 #endif
96                 snd_emu8000_dma_chan(emu, i, mode);
97         }
98
99         /* assign voice 31 and 32 to ROM */
100         EMU8000_VTFT_WRITE(emu, 30, 0);
101         EMU8000_PSST_WRITE(emu, 30, 0x1d8);
102         EMU8000_CSL_WRITE(emu, 30, 0x1e0);
103         EMU8000_CCCA_WRITE(emu, 30, 0x1d8);
104         EMU8000_VTFT_WRITE(emu, 31, 0);
105         EMU8000_PSST_WRITE(emu, 31, 0x1d8);
106         EMU8000_CSL_WRITE(emu, 31, 0x1e0);
107         EMU8000_CCCA_WRITE(emu, 31, 0x1d8);
108
109         return 0;
110 }
111
112 /*
113  */
114 static void
115 snd_emu8000_write_wait(struct snd_emu8000 *emu, int can_schedule)
116 {
117         while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) {
118                 if (can_schedule) {
119                         schedule_timeout_interruptible(1);
120                         if (signal_pending(current))
121                                 break;
122                 }
123         }
124 }
125
126 /*
127  * close all channels
128  */
129 static void
130 emu8k_close_dram(struct snd_emu8000 *emu)
131 {
132         int i;
133
134         for (i = 0; i < 2; i++)
135                 snd_emux_unlock_voice(emu->emu, i);
136         for (; i < EMU8000_DRAM_VOICES; i++) {
137                 snd_emu8000_dma_chan(emu, i, EMU8000_RAM_CLOSE);
138                 snd_emux_unlock_voice(emu->emu, i);
139         }
140 }
141
142 /*
143  * convert Hz to AWE32 rate offset (see emux/soundfont.c)
144  */
145
146 #define OFFSET_SAMPLERATE       1011119         /* base = 44100 */
147 #define SAMPLERATE_RATIO        4096
148
149 static int calc_rate_offset(int hz)
150 {
151         return snd_sf_linear_to_log(hz, OFFSET_SAMPLERATE, SAMPLERATE_RATIO);
152 }
153
154
155 /*
156  */
157
158 static struct snd_pcm_hardware emu8k_pcm_hw = {
159 #ifdef USE_NONINTERLEAVE
160         .info =                 SNDRV_PCM_INFO_NONINTERLEAVED,
161 #else
162         .info =                 SNDRV_PCM_INFO_INTERLEAVED,
163 #endif
164         .formats =              SNDRV_PCM_FMTBIT_S16_LE,
165         .rates =                SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
166         .rate_min =             4000,
167         .rate_max =             48000,
168         .channels_min =         1,
169         .channels_max =         2,
170         .buffer_bytes_max =     (128*1024),
171         .period_bytes_min =     1024,
172         .period_bytes_max =     (128*1024),
173         .periods_min =          2,
174         .periods_max =          1024,
175         .fifo_size =            0,
176
177 };
178
179 /*
180  * get the current position at the given channel from CCCA register
181  */
182 static inline int emu8k_get_curpos(struct snd_emu8k_pcm *rec, int ch)
183 {
184         int val = EMU8000_CCCA_READ(rec->emu, ch) & 0xfffffff;
185         val -= rec->loop_start[ch] - 1;
186         return val;
187 }
188
189
190 /*
191  * timer interrupt handler
192  * check the current position and update the period if necessary.
193  */
194 static void emu8k_pcm_timer_func(unsigned long data)
195 {
196         struct snd_emu8k_pcm *rec = (struct snd_emu8k_pcm *)data;
197         int ptr, delta;
198
199         spin_lock(&rec->timer_lock);
200         /* update the current pointer */
201         ptr = emu8k_get_curpos(rec, 0);
202         if (ptr < rec->last_ptr)
203                 delta = ptr + rec->buf_size - rec->last_ptr;
204         else
205                 delta = ptr - rec->last_ptr;
206         rec->period_pos += delta;
207         rec->last_ptr = ptr;
208
209         /* reprogram timer */
210         rec->timer.expires = jiffies + 1;
211         add_timer(&rec->timer);
212
213         /* update period */
214         if (rec->period_pos >= (int)rec->period_size) {
215                 rec->period_pos %= rec->period_size;
216                 spin_unlock(&rec->timer_lock);
217                 snd_pcm_period_elapsed(rec->substream);
218                 return;
219         }
220         spin_unlock(&rec->timer_lock);
221 }
222
223
224 /*
225  * open pcm
226  * creating an instance here
227  */
228 static int emu8k_pcm_open(struct snd_pcm_substream *subs)
229 {
230         struct snd_emu8000 *emu = snd_pcm_substream_chip(subs);
231         struct snd_emu8k_pcm *rec;
232         struct snd_pcm_runtime *runtime = subs->runtime;
233
234         rec = kzalloc(sizeof(*rec), GFP_KERNEL);
235         if (! rec)
236                 return -ENOMEM;
237
238         rec->emu = emu;
239         rec->substream = subs;
240         runtime->private_data = rec;
241
242         spin_lock_init(&rec->timer_lock);
243         init_timer(&rec->timer);
244         rec->timer.function = emu8k_pcm_timer_func;
245         rec->timer.data = (unsigned long)rec;
246
247         runtime->hw = emu8k_pcm_hw;
248         runtime->hw.buffer_bytes_max = emu->mem_size - LOOP_BLANK_SIZE * 3;
249         runtime->hw.period_bytes_max = runtime->hw.buffer_bytes_max / 2;
250
251         /* use timer to update periods.. (specified in msec) */
252         snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME,
253                                      (1000000 + HZ - 1) / HZ, UINT_MAX);
254
255         return 0;
256 }
257
258 static int emu8k_pcm_close(struct snd_pcm_substream *subs)
259 {
260         struct snd_emu8k_pcm *rec = subs->runtime->private_data;
261         kfree(rec);
262         subs->runtime->private_data = NULL;
263         return 0;
264 }
265
266 /*
267  * calculate pitch target
268  */
269 static int calc_pitch_target(int pitch)
270 {
271         int ptarget = 1 << (pitch >> 12);
272         if (pitch & 0x800) ptarget += (ptarget * 0x102e) / 0x2710;
273         if (pitch & 0x400) ptarget += (ptarget * 0x764) / 0x2710;
274         if (pitch & 0x200) ptarget += (ptarget * 0x389) / 0x2710;
275         ptarget += (ptarget >> 1);
276         if (ptarget > 0xffff) ptarget = 0xffff;
277         return ptarget;
278 }
279
280 /*
281  * set up the voice
282  */
283 static void setup_voice(struct snd_emu8k_pcm *rec, int ch)
284 {
285         struct snd_emu8000 *hw = rec->emu;
286         unsigned int temp;
287
288         /* channel to be silent and idle */
289         EMU8000_DCYSUSV_WRITE(hw, ch, 0x0080);
290         EMU8000_VTFT_WRITE(hw, ch, 0x0000FFFF);
291         EMU8000_CVCF_WRITE(hw, ch, 0x0000FFFF);
292         EMU8000_PTRX_WRITE(hw, ch, 0);
293         EMU8000_CPF_WRITE(hw, ch, 0);
294
295         /* pitch offset */
296         EMU8000_IP_WRITE(hw, ch, rec->pitch);
297         /* set envelope parameters */
298         EMU8000_ENVVAL_WRITE(hw, ch, 0x8000);
299         EMU8000_ATKHLD_WRITE(hw, ch, 0x7f7f);
300         EMU8000_DCYSUS_WRITE(hw, ch, 0x7f7f);
301         EMU8000_ENVVOL_WRITE(hw, ch, 0x8000);
302         EMU8000_ATKHLDV_WRITE(hw, ch, 0x7f7f);
303         /* decay/sustain parameter for volume envelope is used
304            for triggerg the voice */
305         /* modulation envelope heights */
306         EMU8000_PEFE_WRITE(hw, ch, 0x0);
307         /* lfo1/2 delay */
308         EMU8000_LFO1VAL_WRITE(hw, ch, 0x8000);
309         EMU8000_LFO2VAL_WRITE(hw, ch, 0x8000);
310         /* lfo1 pitch & cutoff shift */
311         EMU8000_FMMOD_WRITE(hw, ch, 0);
312         /* lfo1 volume & freq */
313         EMU8000_TREMFRQ_WRITE(hw, ch, 0);
314         /* lfo2 pitch & freq */
315         EMU8000_FM2FRQ2_WRITE(hw, ch, 0);
316         /* pan & loop start */
317         temp = rec->panning[ch];
318         temp = (temp <<24) | ((unsigned int)rec->loop_start[ch] - 1);
319         EMU8000_PSST_WRITE(hw, ch, temp);
320         /* chorus & loop end (chorus 8bit, MSB) */
321         temp = 0; // chorus
322         temp = (temp << 24) | ((unsigned int)rec->loop_start[ch] + rec->buf_size - 1);
323         EMU8000_CSL_WRITE(hw, ch, temp);
324         /* Q & current address (Q 4bit value, MSB) */
325         temp = 0; // filterQ
326         temp = (temp << 28) | ((unsigned int)rec->loop_start[ch] - 1);
327         EMU8000_CCCA_WRITE(hw, ch, temp);
328         /* clear unknown registers */
329         EMU8000_00A0_WRITE(hw, ch, 0);
330         EMU8000_0080_WRITE(hw, ch, 0);
331 }
332
333 /*
334  * trigger the voice
335  */
336 static void start_voice(struct snd_emu8k_pcm *rec, int ch)
337 {
338         unsigned long flags;
339         struct snd_emu8000 *hw = rec->emu;
340         unsigned int temp, aux;
341         int pt = calc_pitch_target(rec->pitch);
342
343         /* cutoff and volume */
344         EMU8000_IFATN_WRITE(hw, ch, 0xff00);
345         EMU8000_VTFT_WRITE(hw, ch, 0xffff);
346         EMU8000_CVCF_WRITE(hw, ch, 0xffff);
347         /* trigger envelope */
348         EMU8000_DCYSUSV_WRITE(hw, ch, 0x7f7f);
349         /* set reverb and pitch target */
350         temp = 0; // reverb
351         if (rec->panning[ch] == 0)
352                 aux = 0xff;
353         else
354                 aux = (-rec->panning[ch]) & 0xff;
355         temp = (temp << 8) | (pt << 16) | aux;
356         EMU8000_PTRX_WRITE(hw, ch, temp);
357         EMU8000_CPF_WRITE(hw, ch, pt << 16);
358
359         /* start timer */
360         spin_lock_irqsave(&rec->timer_lock, flags);
361         if (! rec->timer_running) {
362                 rec->timer.expires = jiffies + 1;
363                 add_timer(&rec->timer);
364                 rec->timer_running = 1;
365         }
366         spin_unlock_irqrestore(&rec->timer_lock, flags);
367 }
368
369 /*
370  * stop the voice immediately
371  */
372 static void stop_voice(struct snd_emu8k_pcm *rec, int ch)
373 {
374         unsigned long flags;
375         struct snd_emu8000 *hw = rec->emu;
376
377         EMU8000_DCYSUSV_WRITE(hw, ch, 0x807F);
378
379         /* stop timer */
380         spin_lock_irqsave(&rec->timer_lock, flags);
381         if (rec->timer_running) {
382                 del_timer(&rec->timer);
383                 rec->timer_running = 0;
384         }
385         spin_unlock_irqrestore(&rec->timer_lock, flags);
386 }
387
388 static int emu8k_pcm_trigger(struct snd_pcm_substream *subs, int cmd)
389 {
390         struct snd_emu8k_pcm *rec = subs->runtime->private_data;
391         int ch;
392
393         switch (cmd) {
394         case SNDRV_PCM_TRIGGER_START:
395                 for (ch = 0; ch < rec->voices; ch++)
396                         start_voice(rec, ch);
397                 rec->running = 1;
398                 break;
399         case SNDRV_PCM_TRIGGER_STOP:
400                 rec->running = 0;
401                 for (ch = 0; ch < rec->voices; ch++)
402                         stop_voice(rec, ch);
403                 break;
404         default:
405                 return -EINVAL;
406         }
407         return 0;
408 }
409
410
411 /*
412  * copy / silence ops
413  */
414
415 /*
416  * this macro should be inserted in the copy/silence loops
417  * to reduce the latency.  without this, the system will hang up
418  * during the whole loop.
419  */
420 #define CHECK_SCHEDULER() \
421 do { \
422         cond_resched();\
423         if (signal_pending(current))\
424                 return -EAGAIN;\
425 } while (0)
426
427
428 #ifdef USE_NONINTERLEAVE
429 /* copy one channel block */
430 static int emu8k_transfer_block(struct snd_emu8000 *emu, int offset, unsigned short *buf, int count)
431 {
432         EMU8000_SMALW_WRITE(emu, offset);
433         while (count > 0) {
434                 unsigned short sval;
435                 CHECK_SCHEDULER();
436                 get_user(sval, buf);
437                 EMU8000_SMLD_WRITE(emu, sval);
438                 buf++;
439                 count--;
440         }
441         return 0;
442 }
443
444 static int emu8k_pcm_copy(struct snd_pcm_substream *subs,
445                           int voice,
446                           snd_pcm_uframes_t pos,
447                           void *src,
448                           snd_pcm_uframes_t count)
449 {
450         struct snd_emu8k_pcm *rec = subs->runtime->private_data;
451         struct snd_emu8000 *emu = rec->emu;
452
453         snd_emu8000_write_wait(emu, 1);
454         if (voice == -1) {
455                 unsigned short *buf = src;
456                 int i, err;
457                 count /= rec->voices;
458                 for (i = 0; i < rec->voices; i++) {
459                         err = emu8k_transfer_block(emu, pos + rec->loop_start[i], buf, count);
460                         if (err < 0)
461                                 return err;
462                         buf += count;
463                 }
464                 return 0;
465         } else {
466                 return emu8k_transfer_block(emu, pos + rec->loop_start[voice], src, count);
467         }
468 }
469
470 /* make a channel block silence */
471 static int emu8k_silence_block(struct snd_emu8000 *emu, int offset, int count)
472 {
473         EMU8000_SMALW_WRITE(emu, offset);
474         while (count > 0) {
475                 CHECK_SCHEDULER();
476                 EMU8000_SMLD_WRITE(emu, 0);
477                 count--;
478         }
479         return 0;
480 }
481
482 static int emu8k_pcm_silence(struct snd_pcm_substream *subs,
483                              int voice,
484                              snd_pcm_uframes_t pos,
485                              snd_pcm_uframes_t count)
486 {
487         struct snd_emu8k_pcm *rec = subs->runtime->private_data;
488         struct snd_emu8000 *emu = rec->emu;
489
490         snd_emu8000_write_wait(emu, 1);
491         if (voice == -1 && rec->voices == 1)
492                 voice = 0;
493         if (voice == -1) {
494                 int err;
495                 err = emu8k_silence_block(emu, pos + rec->loop_start[0], count / 2);
496                 if (err < 0)
497                         return err;
498                 return emu8k_silence_block(emu, pos + rec->loop_start[1], count / 2);
499         } else {
500                 return emu8k_silence_block(emu, pos + rec->loop_start[voice], count);
501         }
502 }
503
504 #else /* interleave */
505
506 /*
507  * copy the interleaved data can be done easily by using
508  * DMA "left" and "right" channels on emu8k engine.
509  */
510 static int emu8k_pcm_copy(struct snd_pcm_substream *subs,
511                           int voice,
512                           snd_pcm_uframes_t pos,
513                           void __user *src,
514                           snd_pcm_uframes_t count)
515 {
516         struct snd_emu8k_pcm *rec = subs->runtime->private_data;
517         struct snd_emu8000 *emu = rec->emu;
518         unsigned short __user *buf = src;
519
520         snd_emu8000_write_wait(emu, 1);
521         EMU8000_SMALW_WRITE(emu, pos + rec->loop_start[0]);
522         if (rec->voices > 1)
523                 EMU8000_SMARW_WRITE(emu, pos + rec->loop_start[1]);
524
525         while (count-- > 0) {
526                 unsigned short sval;
527                 CHECK_SCHEDULER();
528                 get_user(sval, buf);
529                 EMU8000_SMLD_WRITE(emu, sval);
530                 buf++;
531                 if (rec->voices > 1) {
532                         CHECK_SCHEDULER();
533                         get_user(sval, buf);
534                         EMU8000_SMRD_WRITE(emu, sval);
535                         buf++;
536                 }
537         }
538         return 0;
539 }
540
541 static int emu8k_pcm_silence(struct snd_pcm_substream *subs,
542                              int voice,
543                              snd_pcm_uframes_t pos,
544                              snd_pcm_uframes_t count)
545 {
546         struct snd_emu8k_pcm *rec = subs->runtime->private_data;
547         struct snd_emu8000 *emu = rec->emu;
548
549         snd_emu8000_write_wait(emu, 1);
550         EMU8000_SMALW_WRITE(emu, rec->loop_start[0] + pos);
551         if (rec->voices > 1)
552                 EMU8000_SMARW_WRITE(emu, rec->loop_start[1] + pos);
553         while (count-- > 0) {
554                 CHECK_SCHEDULER();
555                 EMU8000_SMLD_WRITE(emu, 0);
556                 if (rec->voices > 1) {
557                         CHECK_SCHEDULER();
558                         EMU8000_SMRD_WRITE(emu, 0);
559                 }
560         }
561         return 0;
562 }
563 #endif
564
565
566 /*
567  * allocate a memory block
568  */
569 static int emu8k_pcm_hw_params(struct snd_pcm_substream *subs,
570                                struct snd_pcm_hw_params *hw_params)
571 {
572         struct snd_emu8k_pcm *rec = subs->runtime->private_data;
573
574         if (rec->block) {
575                 /* reallocation - release the old block */
576                 snd_util_mem_free(rec->emu->memhdr, rec->block);
577                 rec->block = NULL;
578         }
579
580         rec->allocated_bytes = params_buffer_bytes(hw_params) + LOOP_BLANK_SIZE * 4;
581         rec->block = snd_util_mem_alloc(rec->emu->memhdr, rec->allocated_bytes);
582         if (! rec->block)
583                 return -ENOMEM;
584         rec->offset = EMU8000_DRAM_OFFSET + (rec->block->offset >> 1); /* in word */
585         /* at least dma_bytes must be set for non-interleaved mode */
586         subs->dma_buffer.bytes = params_buffer_bytes(hw_params);
587
588         return 0;
589 }
590
591 /*
592  * free the memory block
593  */
594 static int emu8k_pcm_hw_free(struct snd_pcm_substream *subs)
595 {
596         struct snd_emu8k_pcm *rec = subs->runtime->private_data;
597
598         if (rec->block) {
599                 int ch;
600                 for (ch = 0; ch < rec->voices; ch++)
601                         stop_voice(rec, ch); // to be sure
602                 if (rec->dram_opened)
603                         emu8k_close_dram(rec->emu);
604                 snd_util_mem_free(rec->emu->memhdr, rec->block);
605                 rec->block = NULL;
606         }
607         return 0;
608 }
609
610 /*
611  */
612 static int emu8k_pcm_prepare(struct snd_pcm_substream *subs)
613 {
614         struct snd_emu8k_pcm *rec = subs->runtime->private_data;
615
616         rec->pitch = 0xe000 + calc_rate_offset(subs->runtime->rate);
617         rec->last_ptr = 0;
618         rec->period_pos = 0;
619
620         rec->buf_size = subs->runtime->buffer_size;
621         rec->period_size = subs->runtime->period_size;
622         rec->voices = subs->runtime->channels;
623         rec->loop_start[0] = rec->offset + LOOP_BLANK_SIZE;
624         if (rec->voices > 1)
625                 rec->loop_start[1] = rec->loop_start[0] + rec->buf_size + LOOP_BLANK_SIZE;
626         if (rec->voices > 1) {
627                 rec->panning[0] = 0xff;
628                 rec->panning[1] = 0x00;
629         } else
630                 rec->panning[0] = 0x80;
631
632         if (! rec->dram_opened) {
633                 int err, i, ch;
634
635                 snd_emux_terminate_all(rec->emu->emu);
636                 if ((err = emu8k_open_dram_for_pcm(rec->emu, rec->voices)) != 0)
637                         return err;
638                 rec->dram_opened = 1;
639
640                 /* clear loop blanks */
641                 snd_emu8000_write_wait(rec->emu, 0);
642                 EMU8000_SMALW_WRITE(rec->emu, rec->offset);
643                 for (i = 0; i < LOOP_BLANK_SIZE; i++)
644                         EMU8000_SMLD_WRITE(rec->emu, 0);
645                 for (ch = 0; ch < rec->voices; ch++) {
646                         EMU8000_SMALW_WRITE(rec->emu, rec->loop_start[ch] + rec->buf_size);
647                         for (i = 0; i < LOOP_BLANK_SIZE; i++)
648                                 EMU8000_SMLD_WRITE(rec->emu, 0);
649                 }
650         }
651
652         setup_voice(rec, 0);
653         if (rec->voices > 1)
654                 setup_voice(rec, 1);
655         return 0;
656 }
657
658 static snd_pcm_uframes_t emu8k_pcm_pointer(struct snd_pcm_substream *subs)
659 {
660         struct snd_emu8k_pcm *rec = subs->runtime->private_data;
661         if (rec->running)
662                 return emu8k_get_curpos(rec, 0);
663         return 0;
664 }
665
666
667 static struct snd_pcm_ops emu8k_pcm_ops = {
668         .open =         emu8k_pcm_open,
669         .close =        emu8k_pcm_close,
670         .ioctl =        snd_pcm_lib_ioctl,
671         .hw_params =    emu8k_pcm_hw_params,
672         .hw_free =      emu8k_pcm_hw_free,
673         .prepare =      emu8k_pcm_prepare,
674         .trigger =      emu8k_pcm_trigger,
675         .pointer =      emu8k_pcm_pointer,
676         .copy =         emu8k_pcm_copy,
677         .silence =      emu8k_pcm_silence,
678 };
679
680
681 static void snd_emu8000_pcm_free(struct snd_pcm *pcm)
682 {
683         struct snd_emu8000 *emu = pcm->private_data;
684         emu->pcm = NULL;
685 }
686
687 int snd_emu8000_pcm_new(struct snd_card *card, struct snd_emu8000 *emu, int index)
688 {
689         struct snd_pcm *pcm;
690         int err;
691
692         if ((err = snd_pcm_new(card, "Emu8000 PCM", index, 1, 0, &pcm)) < 0)
693                 return err;
694         pcm->private_data = emu;
695         pcm->private_free = snd_emu8000_pcm_free;
696         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &emu8k_pcm_ops);
697         emu->pcm = pcm;
698
699         snd_device_register(card, pcm);
700
701         return 0;
702 }