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/err.h> 24 #include <linux/platform_device.h> 25 #include <linux/jiffies.h> 26 #include <linux/slab.h> 27 #include <linux/time.h> 28 #include <linux/wait.h> 29 #include <linux/moduleparam.h> 30 #include <sound/core.h> 31 #include <sound/control.h> 32 #include <sound/tlv.h> 33 #include <sound/pcm.h> 34 #include <sound/rawmidi.h> 35 #include <sound/initval.h> 36 37 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); 38 MODULE_DESCRIPTION("Dummy soundcard (/dev/null)"); 39 MODULE_LICENSE("GPL"); 40 MODULE_SUPPORTED_DEVICE("{{ALSA,Dummy soundcard}}"); 41 42 #define MAX_PCM_DEVICES 4 43 #define MAX_PCM_SUBSTREAMS 16 44 #define MAX_MIDI_DEVICES 2 45 46 #if 0 /* emu10k1 emulation */ 47 #define MAX_BUFFER_SIZE (128 * 1024) 48 static int emu10k1_playback_constraints(struct snd_pcm_runtime *runtime) 49 { 50 int err; 51 if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) 52 return err; 53 if ((err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX)) < 0) 54 return err; 55 return 0; 56 } 57 #define add_playback_constraints emu10k1_playback_constraints 58 #endif 59 60 #if 0 /* RME9652 emulation */ 61 #define MAX_BUFFER_SIZE (26 * 64 * 1024) 62 #define USE_FORMATS SNDRV_PCM_FMTBIT_S32_LE 63 #define USE_CHANNELS_MIN 26 64 #define USE_CHANNELS_MAX 26 65 #define USE_PERIODS_MIN 2 66 #define USE_PERIODS_MAX 2 67 #endif 68 69 #if 0 /* ICE1712 emulation */ 70 #define MAX_BUFFER_SIZE (256 * 1024) 71 #define USE_FORMATS SNDRV_PCM_FMTBIT_S32_LE 72 #define USE_CHANNELS_MIN 10 73 #define USE_CHANNELS_MAX 10 74 #define USE_PERIODS_MIN 1 75 #define USE_PERIODS_MAX 1024 76 #endif 77 78 #if 0 /* UDA1341 emulation */ 79 #define MAX_BUFFER_SIZE (16380) 80 #define USE_FORMATS SNDRV_PCM_FMTBIT_S16_LE 81 #define USE_CHANNELS_MIN 2 82 #define USE_CHANNELS_MAX 2 83 #define USE_PERIODS_MIN 2 84 #define USE_PERIODS_MAX 255 85 #endif 86 87 #if 0 /* simple AC97 bridge (intel8x0) with 48kHz AC97 only codec */ 88 #define USE_FORMATS SNDRV_PCM_FMTBIT_S16_LE 89 #define USE_CHANNELS_MIN 2 90 #define USE_CHANNELS_MAX 2 91 #define USE_RATE SNDRV_PCM_RATE_48000 92 #define USE_RATE_MIN 48000 93 #define USE_RATE_MAX 48000 94 #endif 95 96 #if 0 /* CA0106 */ 97 #define USE_FORMATS SNDRV_PCM_FMTBIT_S16_LE 98 #define USE_CHANNELS_MIN 2 99 #define USE_CHANNELS_MAX 2 100 #define USE_RATE (SNDRV_PCM_RATE_48000|SNDRV_PCM_RATE_96000|SNDRV_PCM_RATE_192000) 101 #define USE_RATE_MIN 48000 102 #define USE_RATE_MAX 192000 103 #define MAX_BUFFER_SIZE ((65536-64)*8) 104 #define MAX_PERIOD_SIZE (65536-64) 105 #define USE_PERIODS_MIN 2 106 #define USE_PERIODS_MAX 8 107 #endif 108 109 110 /* defaults */ 111 #ifndef MAX_BUFFER_SIZE 112 #define MAX_BUFFER_SIZE (64*1024) 113 #endif 114 #ifndef MAX_PERIOD_SIZE 115 #define MAX_PERIOD_SIZE MAX_BUFFER_SIZE 116 #endif 117 #ifndef USE_FORMATS 118 #define USE_FORMATS (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE) 119 #endif 120 #ifndef USE_RATE 121 #define USE_RATE SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000 122 #define USE_RATE_MIN 5500 123 #define USE_RATE_MAX 48000 124 #endif 125 #ifndef USE_CHANNELS_MIN 126 #define USE_CHANNELS_MIN 1 127 #endif 128 #ifndef USE_CHANNELS_MAX 129 #define USE_CHANNELS_MAX 2 130 #endif 131 #ifndef USE_PERIODS_MIN 132 #define USE_PERIODS_MIN 1 133 #endif 134 #ifndef USE_PERIODS_MAX 135 #define USE_PERIODS_MAX 1024 136 #endif 137 #ifndef add_playback_constraints 138 #define add_playback_constraints(x) 0 139 #endif 140 #ifndef add_capture_constraints 141 #define add_capture_constraints(x) 0 142 #endif 143 144 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ 145 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 146 static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0}; 147 static int pcm_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; 148 static int pcm_substreams[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8}; 149 //static int midi_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; 150 151 module_param_array(index, int, NULL, 0444); 152 MODULE_PARM_DESC(index, "Index value for dummy soundcard."); 153 module_param_array(id, charp, NULL, 0444); 154 MODULE_PARM_DESC(id, "ID string for dummy soundcard."); 155 module_param_array(enable, bool, NULL, 0444); 156 MODULE_PARM_DESC(enable, "Enable this dummy soundcard."); 157 module_param_array(pcm_devs, int, NULL, 0444); 158 MODULE_PARM_DESC(pcm_devs, "PCM devices # (0-4) for dummy driver."); 159 module_param_array(pcm_substreams, int, NULL, 0444); 160 MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-16) for dummy driver."); 161 //module_param_array(midi_devs, int, NULL, 0444); 162 //MODULE_PARM_DESC(midi_devs, "MIDI devices # (0-2) for dummy driver."); 163 164 static struct platform_device *devices[SNDRV_CARDS]; 165 166 #define MIXER_ADDR_MASTER 0 167 #define MIXER_ADDR_LINE 1 168 #define MIXER_ADDR_MIC 2 169 #define MIXER_ADDR_SYNTH 3 170 #define MIXER_ADDR_CD 4 171 #define MIXER_ADDR_LAST 4 172 173 struct snd_dummy { 174 struct snd_card *card; 175 struct snd_pcm *pcm; 176 spinlock_t mixer_lock; 177 int mixer_volume[MIXER_ADDR_LAST+1][2]; 178 int capture_source[MIXER_ADDR_LAST+1][2]; 179 }; 180 181 struct snd_dummy_pcm { 182 struct snd_dummy *dummy; 183 spinlock_t lock; 184 struct timer_list timer; 185 unsigned int pcm_size; 186 unsigned int pcm_count; 187 unsigned int pcm_bps; /* bytes per second */ 188 unsigned int pcm_jiffie; /* bytes per one jiffie */ 189 unsigned int pcm_irq_pos; /* IRQ position */ 190 unsigned int pcm_buf_pos; /* position in buffer */ 191 struct snd_pcm_substream *substream; 192 }; 193 194 195 static inline void snd_card_dummy_pcm_timer_start(struct snd_dummy_pcm *dpcm) 196 { 197 dpcm->timer.expires = 1 + jiffies; 198 add_timer(&dpcm->timer); 199 } 200 201 static inline void snd_card_dummy_pcm_timer_stop(struct snd_dummy_pcm *dpcm) 202 { 203 del_timer(&dpcm->timer); 204 } 205 206 static int snd_card_dummy_pcm_trigger(struct snd_pcm_substream *substream, int cmd) 207 { 208 struct snd_pcm_runtime *runtime = substream->runtime; 209 struct snd_dummy_pcm *dpcm = runtime->private_data; 210 int err = 0; 211 212 spin_lock(&dpcm->lock); 213 switch (cmd) { 214 case SNDRV_PCM_TRIGGER_START: 215 case SNDRV_PCM_TRIGGER_RESUME: 216 snd_card_dummy_pcm_timer_start(dpcm); 217 break; 218 case SNDRV_PCM_TRIGGER_STOP: 219 case SNDRV_PCM_TRIGGER_SUSPEND: 220 snd_card_dummy_pcm_timer_stop(dpcm); 221 break; 222 default: 223 err = -EINVAL; 224 break; 225 } 226 spin_unlock(&dpcm->lock); 227 return 0; 228 } 229 230 static int snd_card_dummy_pcm_prepare(struct snd_pcm_substream *substream) 231 { 232 struct snd_pcm_runtime *runtime = substream->runtime; 233 struct snd_dummy_pcm *dpcm = runtime->private_data; 234 unsigned int bps; 235 236 bps = runtime->rate * runtime->channels; 237 bps *= snd_pcm_format_width(runtime->format); 238 bps /= 8; 239 if (bps <= 0) 240 return -EINVAL; 241 dpcm->pcm_bps = bps; 242 dpcm->pcm_jiffie = bps / HZ; 243 dpcm->pcm_size = snd_pcm_lib_buffer_bytes(substream); 244 dpcm->pcm_count = snd_pcm_lib_period_bytes(substream); 245 dpcm->pcm_irq_pos = 0; 246 dpcm->pcm_buf_pos = 0; 247 return 0; 248 } 249 250 static void snd_card_dummy_pcm_timer_function(unsigned long data) 251 { 252 struct snd_dummy_pcm *dpcm = (struct snd_dummy_pcm *)data; 253 unsigned long flags; 254 255 spin_lock_irqsave(&dpcm->lock, flags); 256 dpcm->timer.expires = 1 + jiffies; 257 add_timer(&dpcm->timer); 258 dpcm->pcm_irq_pos += dpcm->pcm_jiffie; 259 dpcm->pcm_buf_pos += dpcm->pcm_jiffie; 260 dpcm->pcm_buf_pos %= dpcm->pcm_size; 261 if (dpcm->pcm_irq_pos >= dpcm->pcm_count) { 262 dpcm->pcm_irq_pos %= dpcm->pcm_count; 263 spin_unlock_irqrestore(&dpcm->lock, flags); 264 snd_pcm_period_elapsed(dpcm->substream); 265 } else 266 spin_unlock_irqrestore(&dpcm->lock, flags); 267 } 268 269 static snd_pcm_uframes_t snd_card_dummy_pcm_pointer(struct snd_pcm_substream *substream) 270 { 271 struct snd_pcm_runtime *runtime = substream->runtime; 272 struct snd_dummy_pcm *dpcm = runtime->private_data; 273 274 return bytes_to_frames(runtime, dpcm->pcm_buf_pos); 275 } 276 277 static struct snd_pcm_hardware snd_card_dummy_playback = 278 { 279 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 280 SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID), 281 .formats = USE_FORMATS, 282 .rates = USE_RATE, 283 .rate_min = USE_RATE_MIN, 284 .rate_max = USE_RATE_MAX, 285 .channels_min = USE_CHANNELS_MIN, 286 .channels_max = USE_CHANNELS_MAX, 287 .buffer_bytes_max = MAX_BUFFER_SIZE, 288 .period_bytes_min = 64, 289 .period_bytes_max = MAX_PERIOD_SIZE, 290 .periods_min = USE_PERIODS_MIN, 291 .periods_max = USE_PERIODS_MAX, 292 .fifo_size = 0, 293 }; 294 295 static struct snd_pcm_hardware snd_card_dummy_capture = 296 { 297 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 298 SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID), 299 .formats = USE_FORMATS, 300 .rates = USE_RATE, 301 .rate_min = USE_RATE_MIN, 302 .rate_max = USE_RATE_MAX, 303 .channels_min = USE_CHANNELS_MIN, 304 .channels_max = USE_CHANNELS_MAX, 305 .buffer_bytes_max = MAX_BUFFER_SIZE, 306 .period_bytes_min = 64, 307 .period_bytes_max = MAX_PERIOD_SIZE, 308 .periods_min = USE_PERIODS_MIN, 309 .periods_max = USE_PERIODS_MAX, 310 .fifo_size = 0, 311 }; 312 313 static void snd_card_dummy_runtime_free(struct snd_pcm_runtime *runtime) 314 { 315 kfree(runtime->private_data); 316 } 317 318 static int snd_card_dummy_hw_params(struct snd_pcm_substream *substream, 319 struct snd_pcm_hw_params *hw_params) 320 { 321 return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); 322 } 323 324 static int snd_card_dummy_hw_free(struct snd_pcm_substream *substream) 325 { 326 return snd_pcm_lib_free_pages(substream); 327 } 328 329 static struct snd_dummy_pcm *new_pcm_stream(struct snd_pcm_substream *substream) 330 { 331 struct snd_dummy_pcm *dpcm; 332 333 dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL); 334 if (! dpcm) 335 return dpcm; 336 init_timer(&dpcm->timer); 337 dpcm->timer.data = (unsigned long) dpcm; 338 dpcm->timer.function = snd_card_dummy_pcm_timer_function; 339 spin_lock_init(&dpcm->lock); 340 dpcm->substream = substream; 341 return dpcm; 342 } 343 344 static int snd_card_dummy_playback_open(struct snd_pcm_substream *substream) 345 { 346 struct snd_pcm_runtime *runtime = substream->runtime; 347 struct snd_dummy_pcm *dpcm; 348 int err; 349 350 if ((dpcm = new_pcm_stream(substream)) == NULL) 351 return -ENOMEM; 352 runtime->private_data = dpcm; 353 runtime->private_free = snd_card_dummy_runtime_free; 354 runtime->hw = snd_card_dummy_playback; 355 if (substream->pcm->device & 1) { 356 runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED; 357 runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED; 358 } 359 if (substream->pcm->device & 2) 360 runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID); 361 if ((err = add_playback_constraints(runtime)) < 0) { 362 kfree(dpcm); 363 return err; 364 } 365 366 return 0; 367 } 368 369 static int snd_card_dummy_capture_open(struct snd_pcm_substream *substream) 370 { 371 struct snd_pcm_runtime *runtime = substream->runtime; 372 struct snd_dummy_pcm *dpcm; 373 int err; 374 375 if ((dpcm = new_pcm_stream(substream)) == NULL) 376 return -ENOMEM; 377 runtime->private_data = dpcm; 378 runtime->private_free = snd_card_dummy_runtime_free; 379 runtime->hw = snd_card_dummy_capture; 380 if (substream->pcm->device == 1) { 381 runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED; 382 runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED; 383 } 384 if (substream->pcm->device & 2) 385 runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID); 386 if ((err = add_capture_constraints(runtime)) < 0) { 387 kfree(dpcm); 388 return err; 389 } 390 391 return 0; 392 } 393 394 static int snd_card_dummy_playback_close(struct snd_pcm_substream *substream) 395 { 396 return 0; 397 } 398 399 static int snd_card_dummy_capture_close(struct snd_pcm_substream *substream) 400 { 401 return 0; 402 } 403 404 static struct snd_pcm_ops snd_card_dummy_playback_ops = { 405 .open = snd_card_dummy_playback_open, 406 .close = snd_card_dummy_playback_close, 407 .ioctl = snd_pcm_lib_ioctl, 408 .hw_params = snd_card_dummy_hw_params, 409 .hw_free = snd_card_dummy_hw_free, 410 .prepare = snd_card_dummy_pcm_prepare, 411 .trigger = snd_card_dummy_pcm_trigger, 412 .pointer = snd_card_dummy_pcm_pointer, 413 }; 414 415 static struct snd_pcm_ops snd_card_dummy_capture_ops = { 416 .open = snd_card_dummy_capture_open, 417 .close = snd_card_dummy_capture_close, 418 .ioctl = snd_pcm_lib_ioctl, 419 .hw_params = snd_card_dummy_hw_params, 420 .hw_free = snd_card_dummy_hw_free, 421 .prepare = snd_card_dummy_pcm_prepare, 422 .trigger = snd_card_dummy_pcm_trigger, 423 .pointer = snd_card_dummy_pcm_pointer, 424 }; 425 426 static int __devinit snd_card_dummy_pcm(struct snd_dummy *dummy, int device, 427 int substreams) 428 { 429 struct snd_pcm *pcm; 430 int err; 431 432 if ((err = snd_pcm_new(dummy->card, "Dummy PCM", device, 433 substreams, substreams, &pcm)) < 0) 434 return err; 435 dummy->pcm = pcm; 436 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_card_dummy_playback_ops); 437 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_dummy_capture_ops); 438 pcm->private_data = dummy; 439 pcm->info_flags = 0; 440 strcpy(pcm->name, "Dummy PCM"); 441 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, 442 snd_dma_continuous_data(GFP_KERNEL), 443 0, 64*1024); 444 return 0; 445 } 446 447 #define DUMMY_VOLUME(xname, xindex, addr) \ 448 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 449 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ 450 .name = xname, .index = xindex, \ 451 .info = snd_dummy_volume_info, \ 452 .get = snd_dummy_volume_get, .put = snd_dummy_volume_put, \ 453 .private_value = addr, \ 454 .tlv = { .p = db_scale_dummy } } 455 456 static int snd_dummy_volume_info(struct snd_kcontrol *kcontrol, 457 struct snd_ctl_elem_info *uinfo) 458 { 459 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 460 uinfo->count = 2; 461 uinfo->value.integer.min = -50; 462 uinfo->value.integer.max = 100; 463 return 0; 464 } 465 466 static int snd_dummy_volume_get(struct snd_kcontrol *kcontrol, 467 struct snd_ctl_elem_value *ucontrol) 468 { 469 struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol); 470 int addr = kcontrol->private_value; 471 472 spin_lock_irq(&dummy->mixer_lock); 473 ucontrol->value.integer.value[0] = dummy->mixer_volume[addr][0]; 474 ucontrol->value.integer.value[1] = dummy->mixer_volume[addr][1]; 475 spin_unlock_irq(&dummy->mixer_lock); 476 return 0; 477 } 478 479 static int snd_dummy_volume_put(struct snd_kcontrol *kcontrol, 480 struct snd_ctl_elem_value *ucontrol) 481 { 482 struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol); 483 int change, addr = kcontrol->private_value; 484 int left, right; 485 486 left = ucontrol->value.integer.value[0]; 487 if (left < -50) 488 left = -50; 489 if (left > 100) 490 left = 100; 491 right = ucontrol->value.integer.value[1]; 492 if (right < -50) 493 right = -50; 494 if (right > 100) 495 right = 100; 496 spin_lock_irq(&dummy->mixer_lock); 497 change = dummy->mixer_volume[addr][0] != left || 498 dummy->mixer_volume[addr][1] != right; 499 dummy->mixer_volume[addr][0] = left; 500 dummy->mixer_volume[addr][1] = right; 501 spin_unlock_irq(&dummy->mixer_lock); 502 return change; 503 } 504 505 static const DECLARE_TLV_DB_SCALE(db_scale_dummy, -4500, 30, 0); 506 507 #define DUMMY_CAPSRC(xname, xindex, addr) \ 508 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ 509 .info = snd_dummy_capsrc_info, \ 510 .get = snd_dummy_capsrc_get, .put = snd_dummy_capsrc_put, \ 511 .private_value = addr } 512 513 static int snd_dummy_capsrc_info(struct snd_kcontrol *kcontrol, 514 struct snd_ctl_elem_info *uinfo) 515 { 516 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 517 uinfo->count = 2; 518 uinfo->value.integer.min = 0; 519 uinfo->value.integer.max = 1; 520 return 0; 521 } 522 523 static int snd_dummy_capsrc_get(struct snd_kcontrol *kcontrol, 524 struct snd_ctl_elem_value *ucontrol) 525 { 526 struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol); 527 int addr = kcontrol->private_value; 528 529 spin_lock_irq(&dummy->mixer_lock); 530 ucontrol->value.integer.value[0] = dummy->capture_source[addr][0]; 531 ucontrol->value.integer.value[1] = dummy->capture_source[addr][1]; 532 spin_unlock_irq(&dummy->mixer_lock); 533 return 0; 534 } 535 536 static int snd_dummy_capsrc_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 537 { 538 struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol); 539 int change, addr = kcontrol->private_value; 540 int left, right; 541 542 left = ucontrol->value.integer.value[0] & 1; 543 right = ucontrol->value.integer.value[1] & 1; 544 spin_lock_irq(&dummy->mixer_lock); 545 change = dummy->capture_source[addr][0] != left && 546 dummy->capture_source[addr][1] != right; 547 dummy->capture_source[addr][0] = left; 548 dummy->capture_source[addr][1] = right; 549 spin_unlock_irq(&dummy->mixer_lock); 550 return change; 551 } 552 553 static struct snd_kcontrol_new snd_dummy_controls[] = { 554 DUMMY_VOLUME("Master Volume", 0, MIXER_ADDR_MASTER), 555 DUMMY_CAPSRC("Master Capture Switch", 0, MIXER_ADDR_MASTER), 556 DUMMY_VOLUME("Synth Volume", 0, MIXER_ADDR_SYNTH), 557 DUMMY_CAPSRC("Synth Capture Switch", 0, MIXER_ADDR_SYNTH), 558 DUMMY_VOLUME("Line Volume", 0, MIXER_ADDR_LINE), 559 DUMMY_CAPSRC("Line Capture Switch", 0, MIXER_ADDR_LINE), 560 DUMMY_VOLUME("Mic Volume", 0, MIXER_ADDR_MIC), 561 DUMMY_CAPSRC("Mic Capture Switch", 0, MIXER_ADDR_MIC), 562 DUMMY_VOLUME("CD Volume", 0, MIXER_ADDR_CD), 563 DUMMY_CAPSRC("CD Capture Switch", 0, MIXER_ADDR_CD) 564 }; 565 566 static int __devinit snd_card_dummy_new_mixer(struct snd_dummy *dummy) 567 { 568 struct snd_card *card = dummy->card; 569 unsigned int idx; 570 int err; 571 572 snd_assert(dummy != NULL, return -EINVAL); 573 spin_lock_init(&dummy->mixer_lock); 574 strcpy(card->mixername, "Dummy Mixer"); 575 576 for (idx = 0; idx < ARRAY_SIZE(snd_dummy_controls); idx++) { 577 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_dummy_controls[idx], dummy))) < 0) 578 return err; 579 } 580 return 0; 581 } 582 583 static int __devinit snd_dummy_probe(struct platform_device *devptr) 584 { 585 struct snd_card *card; 586 struct snd_dummy *dummy; 587 int idx, err; 588 int dev = devptr->id; 589 590 card = snd_card_new(index[dev], id[dev], THIS_MODULE, 591 sizeof(struct snd_dummy)); 592 if (card == NULL) 593 return -ENOMEM; 594 dummy = card->private_data; 595 dummy->card = card; 596 for (idx = 0; idx < MAX_PCM_DEVICES && idx < pcm_devs[dev]; idx++) { 597 if (pcm_substreams[dev] < 1) 598 pcm_substreams[dev] = 1; 599 if (pcm_substreams[dev] > MAX_PCM_SUBSTREAMS) 600 pcm_substreams[dev] = MAX_PCM_SUBSTREAMS; 601 if ((err = snd_card_dummy_pcm(dummy, idx, pcm_substreams[dev])) < 0) 602 goto __nodev; 603 } 604 if ((err = snd_card_dummy_new_mixer(dummy)) < 0) 605 goto __nodev; 606 strcpy(card->driver, "Dummy"); 607 strcpy(card->shortname, "Dummy"); 608 sprintf(card->longname, "Dummy %i", dev + 1); 609 610 snd_card_set_dev(card, &devptr->dev); 611 612 if ((err = snd_card_register(card)) == 0) { 613 platform_set_drvdata(devptr, card); 614 return 0; 615 } 616 __nodev: 617 snd_card_free(card); 618 return err; 619 } 620 621 static int __devexit snd_dummy_remove(struct platform_device *devptr) 622 { 623 snd_card_free(platform_get_drvdata(devptr)); 624 platform_set_drvdata(devptr, NULL); 625 return 0; 626 } 627 628 #ifdef CONFIG_PM 629 static int snd_dummy_suspend(struct platform_device *pdev, pm_message_t state) 630 { 631 struct snd_card *card = platform_get_drvdata(pdev); 632 struct snd_dummy *dummy = card->private_data; 633 634 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); 635 snd_pcm_suspend_all(dummy->pcm); 636 return 0; 637 } 638 639 static int snd_dummy_resume(struct platform_device *pdev) 640 { 641 struct snd_card *card = platform_get_drvdata(pdev); 642 643 snd_power_change_state(card, SNDRV_CTL_POWER_D0); 644 return 0; 645 } 646 #endif 647 648 #define SND_DUMMY_DRIVER "snd_dummy" 649 650 static struct platform_driver snd_dummy_driver = { 651 .probe = snd_dummy_probe, 652 .remove = __devexit_p(snd_dummy_remove), 653 #ifdef CONFIG_PM 654 .suspend = snd_dummy_suspend, 655 .resume = snd_dummy_resume, 656 #endif 657 .driver = { 658 .name = SND_DUMMY_DRIVER 659 }, 660 }; 661 662 static void __init_or_module snd_dummy_unregister_all(void) 663 { 664 int i; 665 666 for (i = 0; i < ARRAY_SIZE(devices); ++i) 667 platform_device_unregister(devices[i]); 668 platform_driver_unregister(&snd_dummy_driver); 669 } 670 671 static int __init alsa_card_dummy_init(void) 672 { 673 int i, cards, err; 674 675 if ((err = platform_driver_register(&snd_dummy_driver)) < 0) 676 return err; 677 678 cards = 0; 679 for (i = 0; i < SNDRV_CARDS; i++) { 680 struct platform_device *device; 681 if (! enable[i]) 682 continue; 683 device = platform_device_register_simple(SND_DUMMY_DRIVER, 684 i, NULL, 0); 685 if (IS_ERR(device)) 686 continue; 687 if (!platform_get_drvdata(device)) { 688 platform_device_unregister(device); 689 continue; 690 } 691 devices[i] = device; 692 cards++; 693 } 694 if (!cards) { 695 #ifdef MODULE 696 printk(KERN_ERR "Dummy soundcard not found or device busy\n"); 697 #endif 698 snd_dummy_unregister_all(); 699 return -ENODEV; 700 } 701 return 0; 702 } 703 704 static void __exit alsa_card_dummy_exit(void) 705 { 706 snd_dummy_unregister_all(); 707 } 708 709 module_init(alsa_card_dummy_init) 710 module_exit(alsa_card_dummy_exit) 711