ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / sound / drivers / dummy.c
1 /*
2  *  Dummy soundcard
3  *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
4  *
5  *   This program is free software; you can redistribute it and/or modify
6  *   it under the terms of the GNU General Public License as published by
7  *   the Free Software Foundation; either version 2 of the License, or
8  *   (at your option) any later version.
9  *
10  *   This program is distributed in the hope that it will be useful,
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *   GNU General Public License for more details.
14  *
15  *   You should have received a copy of the GNU General Public License
16  *   along with this program; if not, write to the Free Software
17  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18  *
19  */
20
21 #include <sound/driver.h>
22 #include <linux/init.h>
23 #include <linux/jiffies.h>
24 #include <linux/slab.h>
25 #include <linux/time.h>
26 #include <linux/wait.h>
27 #include <sound/core.h>
28 #include <sound/control.h>
29 #include <sound/pcm.h>
30 #include <sound/rawmidi.h>
31 #define SNDRV_GET_ID
32 #include <sound/initval.h>
33
34 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
35 MODULE_DESCRIPTION("Dummy soundcard (/dev/null)");
36 MODULE_LICENSE("GPL");
37 MODULE_CLASSES("{sound}");
38 MODULE_DEVICES("{{ALSA,Dummy soundcard}}");
39
40 #define MAX_PCM_DEVICES         4
41 #define MAX_PCM_SUBSTREAMS      16
42 #define MAX_MIDI_DEVICES        2
43
44 #if 0 /* emu10k1 emulation */
45 #define MAX_BUFFER_SIZE         (128 * 1024)
46 static int emu10k1_playback_constraints(snd_pcm_runtime_t *runtime)
47 {
48         int err;
49         if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
50                 return err;
51         if ((err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX)) < 0)
52                 return err;
53         return 0;
54 }
55 #define add_playback_constraints emu10k1_playback_constraints
56 #endif
57
58 #if 0 /* RME9652 emulation */
59 #define MAX_BUFFER_SIZE         (26 * 64 * 1024)
60 #define USE_FORMATS             SNDRV_PCM_FMTBIT_S32_LE
61 #define USE_CHANNELS_MIN        26
62 #define USE_CHANNELS_MAX        26
63 #define USE_PERIODS_MIN         2
64 #define USE_PERIODS_MAX         2
65 #endif
66
67 #if 0 /* ICE1712 emulation */
68 #define MAX_BUFFER_SIZE         (256 * 1024)
69 #define USE_FORMATS             SNDRV_PCM_FMTBIT_S32_LE
70 #define USE_CHANNELS_MIN        10
71 #define USE_CHANNELS_MAX        10
72 #define USE_PERIODS_MIN         1
73 #define USE_PERIODS_MAX         1024
74 #endif
75
76 #if 0 /* UDA1341 emulation */
77 #define MAX_BUFFER_SIZE         (16380)
78 #define USE_FORMATS             SNDRV_PCM_FMTBIT_S16_LE
79 #define USE_CHANNELS_MIN        2
80 #define USE_CHANNELS_MAX        2
81 #define USE_PERIODS_MIN         2
82 #define USE_PERIODS_MAX         255
83 #endif
84
85 #if 0 /* simple AC97 bridge (intel8x0) with 48kHz AC97 only codec */
86 #define USE_FORMATS             SNDRV_PCM_FMTBIT_S16_LE
87 #define USE_CHANNELS_MIN        2
88 #define USE_CHANNELS_MAX        2
89 #define USE_RATE                SNDRV_PCM_RATE_48000
90 #define USE_RATE_MIN            48000
91 #define USE_RATE_MAX            48000
92 #endif
93
94
95 /* defaults */
96 #ifndef MAX_BUFFER_SIZE
97 #define MAX_BUFFER_SIZE         (64*1024)
98 #endif
99 #ifndef USE_FORMATS
100 #define USE_FORMATS             (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE)
101 #endif
102 #ifndef USE_RATE
103 #define USE_RATE                SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000
104 #define USE_RATE_MIN            5500
105 #define USE_RATE_MAX            48000
106 #endif
107 #ifndef USE_CHANNELS_MIN
108 #define USE_CHANNELS_MIN        1
109 #endif
110 #ifndef USE_CHANNELS_MAX
111 #define USE_CHANNELS_MAX        2
112 #endif
113 #ifndef USE_PERIODS_MIN
114 #define USE_PERIODS_MIN         1
115 #endif
116 #ifndef USE_PERIODS_MAX
117 #define USE_PERIODS_MAX         1024
118 #endif
119 #ifndef add_playback_constraints
120 #define add_playback_constraints(x) 0
121 #endif
122 #ifndef add_capture_constraints
123 #define add_capture_constraints(x) 0
124 #endif
125
126 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;      /* Index 0-MAX */
127 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;       /* ID for this card */
128 static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0};
129 static int pcm_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
130 static int pcm_substreams[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8};
131 //static int midi_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
132
133 MODULE_PARM(index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
134 MODULE_PARM_DESC(index, "Index value for dummy soundcard.");
135 MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
136 MODULE_PARM(id, "1-" __MODULE_STRING(SNDRV_CARDS) "s");
137 MODULE_PARM_DESC(id, "ID string for dummy soundcard.");
138 MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
139 MODULE_PARM(enable, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
140 MODULE_PARM_DESC(enable, "Enable this dummy soundcard.");
141 MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
142 MODULE_PARM(pcm_devs, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
143 MODULE_PARM_DESC(pcm_devs, "PCM devices # (0-4) for dummy driver.");
144 MODULE_PARM_SYNTAX(pcm_devs, SNDRV_ENABLED ",allows:{{0,4}},default:1,dialog:list");
145 MODULE_PARM(pcm_substreams, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
146 MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-16) for dummy driver.");
147 MODULE_PARM_SYNTAX(pcm_substreams, SNDRV_ENABLED ",allows:{{1,16}},default:8,dialog:list");
148 //MODULE_PARM(midi_devs, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
149 //MODULE_PARM_DESC(midi_devs, "MIDI devices # (0-2) for dummy driver.");
150 //MODULE_PARM_SYNTAX(midi_devs, SNDRV_ENABLED ",allows:{{0,2}},default:8,dialog:list");
151
152 #define MIXER_ADDR_MASTER       0
153 #define MIXER_ADDR_LINE         1
154 #define MIXER_ADDR_MIC          2
155 #define MIXER_ADDR_SYNTH        3
156 #define MIXER_ADDR_CD           4
157 #define MIXER_ADDR_LAST         4
158
159 typedef struct snd_card_dummy {
160         snd_card_t *card;
161         spinlock_t mixer_lock;
162         int mixer_volume[MIXER_ADDR_LAST+1][2];
163         int capture_source[MIXER_ADDR_LAST+1][2];
164 } snd_card_dummy_t;
165
166 typedef struct snd_card_dummy_pcm {
167         snd_card_dummy_t *dummy;
168         spinlock_t lock;
169         struct timer_list timer;
170         unsigned int pcm_size;
171         unsigned int pcm_count;
172         unsigned int pcm_bps;           /* bytes per second */
173         unsigned int pcm_jiffie;        /* bytes per one jiffie */
174         unsigned int pcm_irq_pos;       /* IRQ position */
175         unsigned int pcm_buf_pos;       /* position in buffer */
176         snd_pcm_substream_t *substream;
177 } snd_card_dummy_pcm_t;
178
179 static snd_card_t *snd_dummy_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
180
181
182 static int snd_card_dummy_playback_ioctl(snd_pcm_substream_t * substream,
183                                          unsigned int cmd,
184                                          void *arg)
185 {
186         return snd_pcm_lib_ioctl(substream, cmd, arg);
187 }
188
189 static int snd_card_dummy_capture_ioctl(snd_pcm_substream_t * substream,
190                                         unsigned int cmd,
191                                         void *arg)
192 {
193         return snd_pcm_lib_ioctl(substream, cmd, arg);
194 }
195
196 static void snd_card_dummy_pcm_timer_start(snd_pcm_substream_t * substream)
197 {
198         snd_pcm_runtime_t *runtime = substream->runtime;
199         snd_card_dummy_pcm_t *dpcm = snd_magic_cast(snd_card_dummy_pcm_t, runtime->private_data, return);
200
201         dpcm->timer.expires = 1 + jiffies;
202         add_timer(&dpcm->timer);
203 }
204
205 static void snd_card_dummy_pcm_timer_stop(snd_pcm_substream_t * substream)
206 {
207         snd_pcm_runtime_t *runtime = substream->runtime;
208         snd_card_dummy_pcm_t *dpcm = snd_magic_cast(snd_card_dummy_pcm_t, runtime->private_data, return);
209
210         del_timer(&dpcm->timer);
211 }
212
213 static int snd_card_dummy_playback_trigger(snd_pcm_substream_t * substream,
214                                            int cmd)
215 {
216         if (cmd == SNDRV_PCM_TRIGGER_START) {
217                 snd_card_dummy_pcm_timer_start(substream);
218         } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
219                 snd_card_dummy_pcm_timer_stop(substream);
220         } else {
221                 return -EINVAL;
222         }
223         return 0;
224 }
225
226 static int snd_card_dummy_capture_trigger(snd_pcm_substream_t * substream,
227                                           int cmd)
228 {
229         if (cmd == SNDRV_PCM_TRIGGER_START) {
230                 snd_card_dummy_pcm_timer_start(substream);
231         } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
232                 snd_card_dummy_pcm_timer_stop(substream);
233         } else {
234                 return -EINVAL;
235         }
236         return 0;
237 }
238
239 static int snd_card_dummy_pcm_prepare(snd_pcm_substream_t * substream)
240 {
241         snd_pcm_runtime_t *runtime = substream->runtime;
242         snd_card_dummy_pcm_t *dpcm = snd_magic_cast(snd_card_dummy_pcm_t, runtime->private_data, return -ENXIO);
243         unsigned int bps;
244
245         bps = runtime->rate * runtime->channels;
246         bps *= snd_pcm_format_width(runtime->format);
247         bps /= 8;
248         if (bps <= 0)
249                 return -EINVAL;
250         dpcm->pcm_bps = bps;
251         dpcm->pcm_jiffie = bps / HZ;
252         dpcm->pcm_size = snd_pcm_lib_buffer_bytes(substream);
253         dpcm->pcm_count = snd_pcm_lib_period_bytes(substream);
254         dpcm->pcm_irq_pos = 0;
255         dpcm->pcm_buf_pos = 0;
256         return 0;
257 }
258
259 static int snd_card_dummy_playback_prepare(snd_pcm_substream_t * substream)
260 {
261         return snd_card_dummy_pcm_prepare(substream);
262 }
263
264 static int snd_card_dummy_capture_prepare(snd_pcm_substream_t * substream)
265 {
266         return snd_card_dummy_pcm_prepare(substream);
267 }
268
269 static void snd_card_dummy_pcm_timer_function(unsigned long data)
270 {
271         snd_card_dummy_pcm_t *dpcm = snd_magic_cast(snd_card_dummy_pcm_t, (void *)data, return);
272         
273         dpcm->timer.expires = 1 + jiffies;
274         add_timer(&dpcm->timer);
275         spin_lock_irq(&dpcm->lock);
276         dpcm->pcm_irq_pos += dpcm->pcm_jiffie;
277         dpcm->pcm_buf_pos += dpcm->pcm_jiffie;
278         dpcm->pcm_buf_pos %= dpcm->pcm_size;
279         if (dpcm->pcm_irq_pos >= dpcm->pcm_count) {
280                 dpcm->pcm_irq_pos %= dpcm->pcm_count;
281                 snd_pcm_period_elapsed(dpcm->substream);
282         }
283         spin_unlock_irq(&dpcm->lock);   
284 }
285
286 static snd_pcm_uframes_t snd_card_dummy_playback_pointer(snd_pcm_substream_t * substream)
287 {
288         snd_pcm_runtime_t *runtime = substream->runtime;
289         snd_card_dummy_pcm_t *dpcm = snd_magic_cast(snd_card_dummy_pcm_t, runtime->private_data, return -ENXIO);
290
291         return bytes_to_frames(runtime, dpcm->pcm_buf_pos);
292 }
293
294 static snd_pcm_uframes_t snd_card_dummy_capture_pointer(snd_pcm_substream_t * substream)
295 {
296         snd_pcm_runtime_t *runtime = substream->runtime;
297         snd_card_dummy_pcm_t *dpcm = snd_magic_cast(snd_card_dummy_pcm_t, runtime->private_data, return -ENXIO);
298
299         return bytes_to_frames(runtime, dpcm->pcm_buf_pos);
300 }
301
302 static snd_pcm_hardware_t snd_card_dummy_playback =
303 {
304         .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
305                                  SNDRV_PCM_INFO_MMAP_VALID),
306         .formats =              USE_FORMATS,
307         .rates =                USE_RATE,
308         .rate_min =             USE_RATE_MIN,
309         .rate_max =             USE_RATE_MAX,
310         .channels_min =         USE_CHANNELS_MIN,
311         .channels_max =         USE_CHANNELS_MAX,
312         .buffer_bytes_max =     MAX_BUFFER_SIZE,
313         .period_bytes_min =     64,
314         .period_bytes_max =     MAX_BUFFER_SIZE,
315         .periods_min =          USE_PERIODS_MIN,
316         .periods_max =          USE_PERIODS_MAX,
317         .fifo_size =            0,
318 };
319
320 static snd_pcm_hardware_t snd_card_dummy_capture =
321 {
322         .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
323                                  SNDRV_PCM_INFO_MMAP_VALID),
324         .formats =              USE_FORMATS,
325         .rates =                USE_RATE,
326         .rate_min =             USE_RATE_MIN,
327         .rate_max =             USE_RATE_MAX,
328         .channels_min =         USE_CHANNELS_MIN,
329         .channels_max =         USE_CHANNELS_MAX,
330         .buffer_bytes_max =     MAX_BUFFER_SIZE,
331         .period_bytes_min =     64,
332         .period_bytes_max =     MAX_BUFFER_SIZE,
333         .periods_min =          USE_PERIODS_MIN,
334         .periods_max =          USE_PERIODS_MAX,
335         .fifo_size =            0,
336 };
337
338 static void snd_card_dummy_runtime_free(snd_pcm_runtime_t *runtime)
339 {
340         snd_card_dummy_pcm_t *dpcm = snd_magic_cast(snd_card_dummy_pcm_t, runtime->private_data, return);
341         snd_magic_kfree(dpcm);
342 }
343
344 static int snd_card_dummy_playback_open(snd_pcm_substream_t * substream)
345 {
346         snd_pcm_runtime_t *runtime = substream->runtime;
347         snd_card_dummy_pcm_t *dpcm;
348         int err;
349
350         dpcm = snd_magic_kcalloc(snd_card_dummy_pcm_t, 0, GFP_KERNEL);
351         if (dpcm == NULL)
352                 return -ENOMEM;
353         if ((runtime->dma_area = snd_malloc_pages_fallback(MAX_BUFFER_SIZE, GFP_KERNEL, &runtime->dma_bytes)) == NULL) {
354                 snd_magic_kfree(dpcm);
355                 return -ENOMEM;
356         }
357         init_timer(&dpcm->timer);
358         dpcm->timer.data = (unsigned long) dpcm;
359         dpcm->timer.function = snd_card_dummy_pcm_timer_function;
360         spin_lock_init(&dpcm->lock);
361         dpcm->substream = substream;
362         runtime->private_data = dpcm;
363         runtime->private_free = snd_card_dummy_runtime_free;
364         runtime->hw = snd_card_dummy_playback;
365         if (substream->pcm->device & 1) {
366                 runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED;
367                 runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED;
368         }
369         if (substream->pcm->device & 2)
370                 runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID);
371         if ((err = add_playback_constraints(runtime)) < 0) {
372                 snd_magic_kfree(dpcm);
373                 return err;
374         }
375
376         return 0;
377 }
378
379 static int snd_card_dummy_capture_open(snd_pcm_substream_t * substream)
380 {
381         snd_pcm_runtime_t *runtime = substream->runtime;
382         snd_card_dummy_pcm_t *dpcm;
383         int err;
384
385         dpcm = snd_magic_kcalloc(snd_card_dummy_pcm_t, 0, GFP_KERNEL);
386         if (dpcm == NULL)
387                 return -ENOMEM;
388         if ((runtime->dma_area = snd_malloc_pages_fallback(MAX_BUFFER_SIZE, GFP_KERNEL, &runtime->dma_bytes)) == NULL) {
389                 snd_magic_kfree(dpcm);
390                 return -ENOMEM;
391         }
392         memset(runtime->dma_area, 0, runtime->dma_bytes);
393         init_timer(&dpcm->timer);
394         dpcm->timer.data = (unsigned long) dpcm;
395         dpcm->timer.function = snd_card_dummy_pcm_timer_function;
396         spin_lock_init(&dpcm->lock);
397         dpcm->substream = substream;
398         runtime->private_data = dpcm;
399         runtime->private_free = snd_card_dummy_runtime_free;
400         runtime->hw = snd_card_dummy_capture;
401         if (substream->pcm->device == 1) {
402                 runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED;
403                 runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED;
404         }
405         if (substream->pcm->device & 2)
406                 runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID);
407         if ((err = add_capture_constraints(runtime)) < 0) {
408                 snd_magic_kfree(dpcm);
409                 return err;
410         }
411
412         return 0;
413 }
414
415 static int snd_card_dummy_playback_close(snd_pcm_substream_t * substream)
416 {
417         snd_pcm_runtime_t *runtime = substream->runtime;
418
419         snd_free_pages(runtime->dma_area, runtime->dma_bytes);
420         return 0;
421 }
422
423 static int snd_card_dummy_capture_close(snd_pcm_substream_t * substream)
424 {
425         snd_pcm_runtime_t *runtime = substream->runtime;
426
427         snd_free_pages(runtime->dma_area, runtime->dma_bytes);
428         return 0;
429 }
430
431 static snd_pcm_ops_t snd_card_dummy_playback_ops = {
432         .open =                 snd_card_dummy_playback_open,
433         .close =                snd_card_dummy_playback_close,
434         .ioctl =                snd_card_dummy_playback_ioctl,
435         .prepare =              snd_card_dummy_playback_prepare,
436         .trigger =              snd_card_dummy_playback_trigger,
437         .pointer =              snd_card_dummy_playback_pointer,
438 };
439
440 static snd_pcm_ops_t snd_card_dummy_capture_ops = {
441         .open =                 snd_card_dummy_capture_open,
442         .close =                snd_card_dummy_capture_close,
443         .ioctl =                snd_card_dummy_capture_ioctl,
444         .prepare =              snd_card_dummy_capture_prepare,
445         .trigger =              snd_card_dummy_capture_trigger,
446         .pointer =              snd_card_dummy_capture_pointer,
447 };
448
449 static int __init snd_card_dummy_pcm(snd_card_dummy_t *dummy, int device, int substreams)
450 {
451         snd_pcm_t *pcm;
452         int err;
453
454         if ((err = snd_pcm_new(dummy->card, "Dummy PCM", device, substreams, substreams, &pcm)) < 0)
455                 return err;
456         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_card_dummy_playback_ops);
457         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_dummy_capture_ops);
458         pcm->private_data = dummy;
459         pcm->info_flags = 0;
460         strcpy(pcm->name, "Dummy PCM");
461         return 0;
462 }
463
464 #define DUMMY_VOLUME(xname, xindex, addr) \
465 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
466   .info = snd_dummy_volume_info, \
467   .get = snd_dummy_volume_get, .put = snd_dummy_volume_put, \
468   .private_value = addr }
469
470 static int snd_dummy_volume_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
471 {
472         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
473         uinfo->count = 2;
474         uinfo->value.integer.min = -50;
475         uinfo->value.integer.max = 100;
476         return 0;
477 }
478  
479 static int snd_dummy_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
480 {
481         snd_card_dummy_t *dummy = _snd_kcontrol_chip(kcontrol);
482         unsigned long flags;
483         int addr = kcontrol->private_value;
484
485         spin_lock_irqsave(&dummy->mixer_lock, flags);
486         ucontrol->value.integer.value[0] = dummy->mixer_volume[addr][0];
487         ucontrol->value.integer.value[1] = dummy->mixer_volume[addr][1];
488         spin_unlock_irqrestore(&dummy->mixer_lock, flags);
489         return 0;
490 }                                                                                                                                                                                                                                                                                                            
491
492 static int snd_dummy_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
493 {
494         snd_card_dummy_t *dummy = _snd_kcontrol_chip(kcontrol);
495         unsigned long flags;
496         int change, addr = kcontrol->private_value;
497         int left, right;
498
499         left = ucontrol->value.integer.value[0];
500         if (left < -50)
501                 left = -50;
502         if (left > 100)
503                 left = 100;
504         right = ucontrol->value.integer.value[1];
505         if (right < -50)
506                 right = -50;
507         if (right > 100)
508                 right = 100;
509         spin_lock_irqsave(&dummy->mixer_lock, flags);
510         change = dummy->mixer_volume[addr][0] != left ||
511                  dummy->mixer_volume[addr][1] != right;
512         dummy->mixer_volume[addr][0] = left;
513         dummy->mixer_volume[addr][1] = right;
514         spin_unlock_irqrestore(&dummy->mixer_lock, flags);
515         return change;
516 }                                                                                                                                                                                                                                                                                                            
517
518 #define DUMMY_CAPSRC(xname, xindex, addr) \
519 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
520   .info = snd_dummy_capsrc_info, \
521   .get = snd_dummy_capsrc_get, .put = snd_dummy_capsrc_put, \
522   .private_value = addr }
523
524 static int snd_dummy_capsrc_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
525 {
526         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
527         uinfo->count = 2;
528         uinfo->value.integer.min = 0;
529         uinfo->value.integer.max = 1;
530         return 0;
531 }
532  
533 static int snd_dummy_capsrc_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
534 {
535         snd_card_dummy_t *dummy = _snd_kcontrol_chip(kcontrol);
536         unsigned long flags;
537         int addr = kcontrol->private_value;
538
539         spin_lock_irqsave(&dummy->mixer_lock, flags);
540         ucontrol->value.integer.value[0] = dummy->capture_source[addr][0];
541         ucontrol->value.integer.value[1] = dummy->capture_source[addr][1];
542         spin_unlock_irqrestore(&dummy->mixer_lock, flags);
543         return 0;
544 }
545
546 static int snd_dummy_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
547 {
548         snd_card_dummy_t *dummy = _snd_kcontrol_chip(kcontrol);
549         unsigned long flags;
550         int change, addr = kcontrol->private_value;
551         int left, right;
552
553         left = ucontrol->value.integer.value[0] & 1;
554         right = ucontrol->value.integer.value[1] & 1;
555         spin_lock_irqsave(&dummy->mixer_lock, flags);
556         change = dummy->capture_source[addr][0] != left &&
557                  dummy->capture_source[addr][1] != right;
558         dummy->capture_source[addr][0] = left;
559         dummy->capture_source[addr][1] = right;
560         spin_unlock_irqrestore(&dummy->mixer_lock, flags);
561         return change;
562 }                                                                                                                                                                                                                                                                                                            
563
564 #define DUMMY_CONTROLS (sizeof(snd_dummy_controls)/sizeof(snd_kcontrol_new_t))
565
566 static snd_kcontrol_new_t snd_dummy_controls[] = {
567 DUMMY_VOLUME("Master Volume", 0, MIXER_ADDR_MASTER),
568 DUMMY_CAPSRC("Master Capture Switch", 0, MIXER_ADDR_MASTER),
569 DUMMY_VOLUME("Synth Volume", 0, MIXER_ADDR_SYNTH),
570 DUMMY_CAPSRC("Synth Capture Switch", 0, MIXER_ADDR_MASTER),
571 DUMMY_VOLUME("Line Volume", 0, MIXER_ADDR_LINE),
572 DUMMY_CAPSRC("Line Capture Switch", 0, MIXER_ADDR_MASTER),
573 DUMMY_VOLUME("Mic Volume", 0, MIXER_ADDR_MIC),
574 DUMMY_CAPSRC("Mic Capture Switch", 0, MIXER_ADDR_MASTER),
575 DUMMY_VOLUME("CD Volume", 0, MIXER_ADDR_CD),
576 DUMMY_CAPSRC("CD Capture Switch", 0, MIXER_ADDR_MASTER)
577 };
578
579 int __init snd_card_dummy_new_mixer(snd_card_dummy_t * dummy)
580 {
581         snd_card_t *card = dummy->card;
582         unsigned int idx;
583         int err;
584
585         snd_assert(dummy != NULL, return -EINVAL);
586         spin_lock_init(&dummy->mixer_lock);
587         strcpy(card->mixername, "Dummy Mixer");
588
589         for (idx = 0; idx < DUMMY_CONTROLS; idx++) {
590                 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_dummy_controls[idx], dummy))) < 0)
591                         return err;
592         }
593         return 0;
594 }
595
596 static int __init snd_card_dummy_probe(int dev)
597 {
598         snd_card_t *card;
599         struct snd_card_dummy *dummy;
600         int idx, err;
601
602         if (!enable[dev])
603                 return -ENODEV;
604         card = snd_card_new(index[dev], id[dev], THIS_MODULE,
605                             sizeof(struct snd_card_dummy));
606         if (card == NULL)
607                 return -ENOMEM;
608         dummy = (struct snd_card_dummy *)card->private_data;
609         dummy->card = card;
610         for (idx = 0; idx < MAX_PCM_DEVICES && idx < pcm_devs[dev]; idx++) {
611                 if (pcm_substreams[dev] < 1)
612                         pcm_substreams[dev] = 1;
613                 if (pcm_substreams[dev] > MAX_PCM_SUBSTREAMS)
614                         pcm_substreams[dev] = MAX_PCM_SUBSTREAMS;
615                 if ((err = snd_card_dummy_pcm(dummy, idx, pcm_substreams[dev])) < 0)
616                         goto __nodev;
617         }
618         if ((err = snd_card_dummy_new_mixer(dummy)) < 0)
619                 goto __nodev;
620         strcpy(card->driver, "Dummy");
621         strcpy(card->shortname, "Dummy");
622         sprintf(card->longname, "Dummy %i", dev + 1);
623         if ((err = snd_card_register(card)) == 0) {
624                 snd_dummy_cards[dev] = card;
625                 return 0;
626         }
627       __nodev:
628         snd_card_free(card);
629         return err;
630 }
631
632 static int __init alsa_card_dummy_init(void)
633 {
634         int dev, cards;
635
636         for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev]; dev++) {
637                 if (snd_card_dummy_probe(dev) < 0) {
638 #ifdef MODULE
639                         printk(KERN_ERR "Dummy soundcard #%i not found or device busy\n", dev + 1);
640 #endif
641                         break;
642                 }
643                 cards++;
644         }
645         if (!cards) {
646 #ifdef MODULE
647                 printk(KERN_ERR "Dummy soundcard not found or device busy\n");
648 #endif
649                 return -ENODEV;
650         }
651         return 0;
652 }
653
654 static void __exit alsa_card_dummy_exit(void)
655 {
656         int idx;
657
658         for (idx = 0; idx < SNDRV_CARDS; idx++)
659                 snd_card_free(snd_dummy_cards[idx]);
660 }
661
662 module_init(alsa_card_dummy_init)
663 module_exit(alsa_card_dummy_exit)
664
665 #ifndef MODULE
666
667 /* format is: snd-dummy=enable,index,id,
668                         pcm_devs,pcm_substreams */
669
670 static int __init alsa_card_dummy_setup(char *str)
671 {
672         static unsigned __initdata nr_dev = 0;
673
674         if (nr_dev >= SNDRV_CARDS)
675                 return 0;
676         (void)(get_option(&str,&enable[nr_dev]) == 2 &&
677                get_option(&str,&index[nr_dev]) == 2 &&
678                get_id(&str,&id[nr_dev]) == 2 &&
679                get_option(&str,&pcm_devs[nr_dev]) == 2 &&
680                get_option(&str,&pcm_substreams[nr_dev]) == 2);
681         nr_dev++;
682         return 1;
683 }
684
685 __setup("snd-dummy=", alsa_card_dummy_setup);
686
687 #endif /* ifndef MODULE */