1185 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Dummy soundcard4 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>5 */6 7#include <linux/init.h>8#include <linux/err.h>9#include <linux/platform_device.h>10#include <linux/jiffies.h>11#include <linux/slab.h>12#include <linux/time.h>13#include <linux/wait.h>14#include <linux/hrtimer.h>15#include <linux/math64.h>16#include <linux/module.h>17#include <sound/core.h>18#include <sound/control.h>19#include <sound/tlv.h>20#include <sound/pcm.h>21#include <sound/rawmidi.h>22#include <sound/info.h>23#include <sound/initval.h>24 25MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");26MODULE_DESCRIPTION("Dummy soundcard (/dev/null)");27MODULE_LICENSE("GPL");28 29#define MAX_PCM_DEVICES 430#define MAX_PCM_SUBSTREAMS 12831#define MAX_MIDI_DEVICES 232 33/* defaults */34#define MAX_BUFFER_SIZE (64*1024)35#define MIN_PERIOD_SIZE 6436#define MAX_PERIOD_SIZE MAX_BUFFER_SIZE37#define USE_FORMATS (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE)38#define USE_RATE SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_4800039#define USE_RATE_MIN 550040#define USE_RATE_MAX 4800041#define USE_CHANNELS_MIN 142#define USE_CHANNELS_MAX 243#define USE_PERIODS_MIN 144#define USE_PERIODS_MAX 102445#define USE_MIXER_VOLUME_LEVEL_MIN -5046#define USE_MIXER_VOLUME_LEVEL_MAX 10047 48static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */49static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */50static bool enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0};51static char *model[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = NULL};52static int pcm_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};53static int pcm_substreams[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8};54//static int midi_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};55static int mixer_volume_level_min = USE_MIXER_VOLUME_LEVEL_MIN;56static int mixer_volume_level_max = USE_MIXER_VOLUME_LEVEL_MAX;57#ifdef CONFIG_HIGH_RES_TIMERS58static bool hrtimer = 1;59#endif60static bool fake_buffer = 1;61 62module_param_array(index, int, NULL, 0444);63MODULE_PARM_DESC(index, "Index value for dummy soundcard.");64module_param_array(id, charp, NULL, 0444);65MODULE_PARM_DESC(id, "ID string for dummy soundcard.");66module_param_array(enable, bool, NULL, 0444);67MODULE_PARM_DESC(enable, "Enable this dummy soundcard.");68module_param_array(model, charp, NULL, 0444);69MODULE_PARM_DESC(model, "Soundcard model.");70module_param_array(pcm_devs, int, NULL, 0444);71MODULE_PARM_DESC(pcm_devs, "PCM devices # (0-4) for dummy driver.");72module_param_array(pcm_substreams, int, NULL, 0444);73MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-128) for dummy driver.");74//module_param_array(midi_devs, int, NULL, 0444);75//MODULE_PARM_DESC(midi_devs, "MIDI devices # (0-2) for dummy driver.");76module_param(mixer_volume_level_min, int, 0444);77MODULE_PARM_DESC(mixer_volume_level_min, "Minimum mixer volume level for dummy driver. Default: -50");78module_param(mixer_volume_level_max, int, 0444);79MODULE_PARM_DESC(mixer_volume_level_max, "Maximum mixer volume level for dummy driver. Default: 100");80module_param(fake_buffer, bool, 0444);81MODULE_PARM_DESC(fake_buffer, "Fake buffer allocations.");82#ifdef CONFIG_HIGH_RES_TIMERS83module_param(hrtimer, bool, 0644);84MODULE_PARM_DESC(hrtimer, "Use hrtimer as the timer source.");85#endif86 87static struct platform_device *devices[SNDRV_CARDS];88 89#define MIXER_ADDR_MASTER 090#define MIXER_ADDR_LINE 191#define MIXER_ADDR_MIC 292#define MIXER_ADDR_SYNTH 393#define MIXER_ADDR_CD 494#define MIXER_ADDR_LAST 495 96struct dummy_timer_ops {97 int (*create)(struct snd_pcm_substream *);98 void (*free)(struct snd_pcm_substream *);99 int (*prepare)(struct snd_pcm_substream *);100 int (*start)(struct snd_pcm_substream *);101 int (*stop)(struct snd_pcm_substream *);102 snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *);103};104 105#define get_dummy_ops(substream) \106 (*(const struct dummy_timer_ops **)(substream)->runtime->private_data)107 108struct dummy_model {109 const char *name;110 int (*playback_constraints)(struct snd_pcm_runtime *runtime);111 int (*capture_constraints)(struct snd_pcm_runtime *runtime);112 u64 formats;113 size_t buffer_bytes_max;114 size_t period_bytes_min;115 size_t period_bytes_max;116 unsigned int periods_min;117 unsigned int periods_max;118 unsigned int rates;119 unsigned int rate_min;120 unsigned int rate_max;121 unsigned int channels_min;122 unsigned int channels_max;123};124 125struct snd_dummy {126 struct snd_card *card;127 const struct dummy_model *model;128 struct snd_pcm *pcm;129 struct snd_pcm_hardware pcm_hw;130 spinlock_t mixer_lock;131 int mixer_volume[MIXER_ADDR_LAST+1][2];132 int capture_source[MIXER_ADDR_LAST+1][2];133 int iobox;134 struct snd_kcontrol *cd_volume_ctl;135 struct snd_kcontrol *cd_switch_ctl;136};137 138/*139 * card models140 */141 142static int emu10k1_playback_constraints(struct snd_pcm_runtime *runtime)143{144 int err;145 err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);146 if (err < 0)147 return err;148 err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX);149 if (err < 0)150 return err;151 return 0;152}153 154static const struct dummy_model model_emu10k1 = {155 .name = "emu10k1",156 .playback_constraints = emu10k1_playback_constraints,157 .buffer_bytes_max = 128 * 1024,158};159 160static const struct dummy_model model_rme9652 = {161 .name = "rme9652",162 .buffer_bytes_max = 26 * 64 * 1024,163 .formats = SNDRV_PCM_FMTBIT_S32_LE,164 .channels_min = 26,165 .channels_max = 26,166 .periods_min = 2,167 .periods_max = 2,168};169 170static const struct dummy_model model_ice1712 = {171 .name = "ice1712",172 .buffer_bytes_max = 256 * 1024,173 .formats = SNDRV_PCM_FMTBIT_S32_LE,174 .channels_min = 10,175 .channels_max = 10,176 .periods_min = 1,177 .periods_max = 1024,178};179 180static const struct dummy_model model_uda1341 = {181 .name = "uda1341",182 .buffer_bytes_max = 16380,183 .formats = SNDRV_PCM_FMTBIT_S16_LE,184 .channels_min = 2,185 .channels_max = 2,186 .periods_min = 2,187 .periods_max = 255,188};189 190static const struct dummy_model model_ac97 = {191 .name = "ac97",192 .formats = SNDRV_PCM_FMTBIT_S16_LE,193 .channels_min = 2,194 .channels_max = 2,195 .rates = SNDRV_PCM_RATE_48000,196 .rate_min = 48000,197 .rate_max = 48000,198};199 200static const struct dummy_model model_ca0106 = {201 .name = "ca0106",202 .formats = SNDRV_PCM_FMTBIT_S16_LE,203 .buffer_bytes_max = ((65536-64)*8),204 .period_bytes_max = (65536-64),205 .periods_min = 2,206 .periods_max = 8,207 .channels_min = 2,208 .channels_max = 2,209 .rates = SNDRV_PCM_RATE_48000|SNDRV_PCM_RATE_96000|SNDRV_PCM_RATE_192000,210 .rate_min = 48000,211 .rate_max = 192000,212};213 214static const struct dummy_model *dummy_models[] = {215 &model_emu10k1,216 &model_rme9652,217 &model_ice1712,218 &model_uda1341,219 &model_ac97,220 &model_ca0106,221 NULL222};223 224/*225 * system timer interface226 */227 228struct dummy_systimer_pcm {229 /* ops must be the first item */230 const struct dummy_timer_ops *timer_ops;231 spinlock_t lock;232 struct timer_list timer;233 unsigned long base_time;234 unsigned int frac_pos; /* fractional sample position (based HZ) */235 unsigned int frac_period_rest;236 unsigned int frac_buffer_size; /* buffer_size * HZ */237 unsigned int frac_period_size; /* period_size * HZ */238 unsigned int rate;239 int elapsed;240 struct snd_pcm_substream *substream;241};242 243static void dummy_systimer_rearm(struct dummy_systimer_pcm *dpcm)244{245 mod_timer(&dpcm->timer, jiffies +246 DIV_ROUND_UP(dpcm->frac_period_rest, dpcm->rate));247}248 249static void dummy_systimer_update(struct dummy_systimer_pcm *dpcm)250{251 unsigned long delta;252 253 delta = jiffies - dpcm->base_time;254 if (!delta)255 return;256 dpcm->base_time += delta;257 delta *= dpcm->rate;258 dpcm->frac_pos += delta;259 while (dpcm->frac_pos >= dpcm->frac_buffer_size)260 dpcm->frac_pos -= dpcm->frac_buffer_size;261 while (dpcm->frac_period_rest <= delta) {262 dpcm->elapsed++;263 dpcm->frac_period_rest += dpcm->frac_period_size;264 }265 dpcm->frac_period_rest -= delta;266}267 268static int dummy_systimer_start(struct snd_pcm_substream *substream)269{270 struct dummy_systimer_pcm *dpcm = substream->runtime->private_data;271 spin_lock(&dpcm->lock);272 dpcm->base_time = jiffies;273 dummy_systimer_rearm(dpcm);274 spin_unlock(&dpcm->lock);275 return 0;276}277 278static int dummy_systimer_stop(struct snd_pcm_substream *substream)279{280 struct dummy_systimer_pcm *dpcm = substream->runtime->private_data;281 spin_lock(&dpcm->lock);282 del_timer(&dpcm->timer);283 spin_unlock(&dpcm->lock);284 return 0;285}286 287static int dummy_systimer_prepare(struct snd_pcm_substream *substream)288{289 struct snd_pcm_runtime *runtime = substream->runtime;290 struct dummy_systimer_pcm *dpcm = runtime->private_data;291 292 dpcm->frac_pos = 0;293 dpcm->rate = runtime->rate;294 dpcm->frac_buffer_size = runtime->buffer_size * HZ;295 dpcm->frac_period_size = runtime->period_size * HZ;296 dpcm->frac_period_rest = dpcm->frac_period_size;297 dpcm->elapsed = 0;298 299 return 0;300}301 302static void dummy_systimer_callback(struct timer_list *t)303{304 struct dummy_systimer_pcm *dpcm = from_timer(dpcm, t, timer);305 unsigned long flags;306 int elapsed = 0;307 308 spin_lock_irqsave(&dpcm->lock, flags);309 dummy_systimer_update(dpcm);310 dummy_systimer_rearm(dpcm);311 elapsed = dpcm->elapsed;312 dpcm->elapsed = 0;313 spin_unlock_irqrestore(&dpcm->lock, flags);314 if (elapsed)315 snd_pcm_period_elapsed(dpcm->substream);316}317 318static snd_pcm_uframes_t319dummy_systimer_pointer(struct snd_pcm_substream *substream)320{321 struct dummy_systimer_pcm *dpcm = substream->runtime->private_data;322 snd_pcm_uframes_t pos;323 324 spin_lock(&dpcm->lock);325 dummy_systimer_update(dpcm);326 pos = dpcm->frac_pos / HZ;327 spin_unlock(&dpcm->lock);328 return pos;329}330 331static int dummy_systimer_create(struct snd_pcm_substream *substream)332{333 struct dummy_systimer_pcm *dpcm;334 335 dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);336 if (!dpcm)337 return -ENOMEM;338 substream->runtime->private_data = dpcm;339 timer_setup(&dpcm->timer, dummy_systimer_callback, 0);340 spin_lock_init(&dpcm->lock);341 dpcm->substream = substream;342 return 0;343}344 345static void dummy_systimer_free(struct snd_pcm_substream *substream)346{347 kfree(substream->runtime->private_data);348}349 350static const struct dummy_timer_ops dummy_systimer_ops = {351 .create = dummy_systimer_create,352 .free = dummy_systimer_free,353 .prepare = dummy_systimer_prepare,354 .start = dummy_systimer_start,355 .stop = dummy_systimer_stop,356 .pointer = dummy_systimer_pointer,357};358 359#ifdef CONFIG_HIGH_RES_TIMERS360/*361 * hrtimer interface362 */363 364struct dummy_hrtimer_pcm {365 /* ops must be the first item */366 const struct dummy_timer_ops *timer_ops;367 ktime_t base_time;368 ktime_t period_time;369 atomic_t running;370 struct hrtimer timer;371 struct snd_pcm_substream *substream;372};373 374static enum hrtimer_restart dummy_hrtimer_callback(struct hrtimer *timer)375{376 struct dummy_hrtimer_pcm *dpcm;377 378 dpcm = container_of(timer, struct dummy_hrtimer_pcm, timer);379 if (!atomic_read(&dpcm->running))380 return HRTIMER_NORESTART;381 /*382 * In cases of XRUN and draining, this calls .trigger to stop PCM383 * substream.384 */385 snd_pcm_period_elapsed(dpcm->substream);386 if (!atomic_read(&dpcm->running))387 return HRTIMER_NORESTART;388 389 hrtimer_forward_now(timer, dpcm->period_time);390 return HRTIMER_RESTART;391}392 393static int dummy_hrtimer_start(struct snd_pcm_substream *substream)394{395 struct dummy_hrtimer_pcm *dpcm = substream->runtime->private_data;396 397 dpcm->base_time = hrtimer_cb_get_time(&dpcm->timer);398 hrtimer_start(&dpcm->timer, dpcm->period_time, HRTIMER_MODE_REL_SOFT);399 atomic_set(&dpcm->running, 1);400 return 0;401}402 403static int dummy_hrtimer_stop(struct snd_pcm_substream *substream)404{405 struct dummy_hrtimer_pcm *dpcm = substream->runtime->private_data;406 407 atomic_set(&dpcm->running, 0);408 if (!hrtimer_callback_running(&dpcm->timer))409 hrtimer_cancel(&dpcm->timer);410 return 0;411}412 413static inline void dummy_hrtimer_sync(struct dummy_hrtimer_pcm *dpcm)414{415 hrtimer_cancel(&dpcm->timer);416}417 418static snd_pcm_uframes_t419dummy_hrtimer_pointer(struct snd_pcm_substream *substream)420{421 struct snd_pcm_runtime *runtime = substream->runtime;422 struct dummy_hrtimer_pcm *dpcm = runtime->private_data;423 u64 delta;424 u32 pos;425 426 delta = ktime_us_delta(hrtimer_cb_get_time(&dpcm->timer),427 dpcm->base_time);428 delta = div_u64(delta * runtime->rate + 999999, 1000000);429 div_u64_rem(delta, runtime->buffer_size, &pos);430 return pos;431}432 433static int dummy_hrtimer_prepare(struct snd_pcm_substream *substream)434{435 struct snd_pcm_runtime *runtime = substream->runtime;436 struct dummy_hrtimer_pcm *dpcm = runtime->private_data;437 unsigned int period, rate;438 long sec;439 unsigned long nsecs;440 441 dummy_hrtimer_sync(dpcm);442 period = runtime->period_size;443 rate = runtime->rate;444 sec = period / rate;445 period %= rate;446 nsecs = div_u64((u64)period * 1000000000UL + rate - 1, rate);447 dpcm->period_time = ktime_set(sec, nsecs);448 449 return 0;450}451 452static int dummy_hrtimer_create(struct snd_pcm_substream *substream)453{454 struct dummy_hrtimer_pcm *dpcm;455 456 dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);457 if (!dpcm)458 return -ENOMEM;459 substream->runtime->private_data = dpcm;460 hrtimer_init(&dpcm->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT);461 dpcm->timer.function = dummy_hrtimer_callback;462 dpcm->substream = substream;463 atomic_set(&dpcm->running, 0);464 return 0;465}466 467static void dummy_hrtimer_free(struct snd_pcm_substream *substream)468{469 struct dummy_hrtimer_pcm *dpcm = substream->runtime->private_data;470 dummy_hrtimer_sync(dpcm);471 kfree(dpcm);472}473 474static const struct dummy_timer_ops dummy_hrtimer_ops = {475 .create = dummy_hrtimer_create,476 .free = dummy_hrtimer_free,477 .prepare = dummy_hrtimer_prepare,478 .start = dummy_hrtimer_start,479 .stop = dummy_hrtimer_stop,480 .pointer = dummy_hrtimer_pointer,481};482 483#endif /* CONFIG_HIGH_RES_TIMERS */484 485/*486 * PCM interface487 */488 489static int dummy_pcm_trigger(struct snd_pcm_substream *substream, int cmd)490{491 switch (cmd) {492 case SNDRV_PCM_TRIGGER_START:493 case SNDRV_PCM_TRIGGER_RESUME:494 return get_dummy_ops(substream)->start(substream);495 case SNDRV_PCM_TRIGGER_STOP:496 case SNDRV_PCM_TRIGGER_SUSPEND:497 return get_dummy_ops(substream)->stop(substream);498 }499 return -EINVAL;500}501 502static int dummy_pcm_prepare(struct snd_pcm_substream *substream)503{504 return get_dummy_ops(substream)->prepare(substream);505}506 507static snd_pcm_uframes_t dummy_pcm_pointer(struct snd_pcm_substream *substream)508{509 return get_dummy_ops(substream)->pointer(substream);510}511 512static const struct snd_pcm_hardware dummy_pcm_hardware = {513 .info = (SNDRV_PCM_INFO_MMAP |514 SNDRV_PCM_INFO_INTERLEAVED |515 SNDRV_PCM_INFO_RESUME |516 SNDRV_PCM_INFO_MMAP_VALID),517 .formats = USE_FORMATS,518 .rates = USE_RATE,519 .rate_min = USE_RATE_MIN,520 .rate_max = USE_RATE_MAX,521 .channels_min = USE_CHANNELS_MIN,522 .channels_max = USE_CHANNELS_MAX,523 .buffer_bytes_max = MAX_BUFFER_SIZE,524 .period_bytes_min = MIN_PERIOD_SIZE,525 .period_bytes_max = MAX_PERIOD_SIZE,526 .periods_min = USE_PERIODS_MIN,527 .periods_max = USE_PERIODS_MAX,528 .fifo_size = 0,529};530 531static int dummy_pcm_hw_params(struct snd_pcm_substream *substream,532 struct snd_pcm_hw_params *hw_params)533{534 if (fake_buffer) {535 /* runtime->dma_bytes has to be set manually to allow mmap */536 substream->runtime->dma_bytes = params_buffer_bytes(hw_params);537 return 0;538 }539 return 0;540}541 542static int dummy_pcm_open(struct snd_pcm_substream *substream)543{544 struct snd_dummy *dummy = snd_pcm_substream_chip(substream);545 const struct dummy_model *model = dummy->model;546 struct snd_pcm_runtime *runtime = substream->runtime;547 const struct dummy_timer_ops *ops;548 int err;549 550 ops = &dummy_systimer_ops;551#ifdef CONFIG_HIGH_RES_TIMERS552 if (hrtimer)553 ops = &dummy_hrtimer_ops;554#endif555 556 err = ops->create(substream);557 if (err < 0)558 return err;559 get_dummy_ops(substream) = ops;560 561 runtime->hw = dummy->pcm_hw;562 if (substream->pcm->device & 1) {563 runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED;564 runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED;565 }566 if (substream->pcm->device & 2)567 runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP |568 SNDRV_PCM_INFO_MMAP_VALID);569 570 if (model == NULL)571 return 0;572 573 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {574 if (model->playback_constraints)575 err = model->playback_constraints(substream->runtime);576 } else {577 if (model->capture_constraints)578 err = model->capture_constraints(substream->runtime);579 }580 if (err < 0) {581 get_dummy_ops(substream)->free(substream);582 return err;583 }584 return 0;585}586 587static int dummy_pcm_close(struct snd_pcm_substream *substream)588{589 get_dummy_ops(substream)->free(substream);590 return 0;591}592 593/*594 * dummy buffer handling595 */596 597static void *dummy_page[2];598 599static void free_fake_buffer(void)600{601 if (fake_buffer) {602 int i;603 for (i = 0; i < 2; i++)604 if (dummy_page[i]) {605 free_page((unsigned long)dummy_page[i]);606 dummy_page[i] = NULL;607 }608 }609}610 611static int alloc_fake_buffer(void)612{613 int i;614 615 if (!fake_buffer)616 return 0;617 for (i = 0; i < 2; i++) {618 dummy_page[i] = (void *)get_zeroed_page(GFP_KERNEL);619 if (!dummy_page[i]) {620 free_fake_buffer();621 return -ENOMEM;622 }623 }624 return 0;625}626 627static int dummy_pcm_copy(struct snd_pcm_substream *substream,628 int channel, unsigned long pos,629 struct iov_iter *iter, unsigned long bytes)630{631 return 0; /* do nothing */632}633 634static int dummy_pcm_silence(struct snd_pcm_substream *substream,635 int channel, unsigned long pos,636 unsigned long bytes)637{638 return 0; /* do nothing */639}640 641static struct page *dummy_pcm_page(struct snd_pcm_substream *substream,642 unsigned long offset)643{644 return virt_to_page(dummy_page[substream->stream]); /* the same page */645}646 647static const struct snd_pcm_ops dummy_pcm_ops = {648 .open = dummy_pcm_open,649 .close = dummy_pcm_close,650 .hw_params = dummy_pcm_hw_params,651 .prepare = dummy_pcm_prepare,652 .trigger = dummy_pcm_trigger,653 .pointer = dummy_pcm_pointer,654};655 656static const struct snd_pcm_ops dummy_pcm_ops_no_buf = {657 .open = dummy_pcm_open,658 .close = dummy_pcm_close,659 .hw_params = dummy_pcm_hw_params,660 .prepare = dummy_pcm_prepare,661 .trigger = dummy_pcm_trigger,662 .pointer = dummy_pcm_pointer,663 .copy = dummy_pcm_copy,664 .fill_silence = dummy_pcm_silence,665 .page = dummy_pcm_page,666};667 668static int snd_card_dummy_pcm(struct snd_dummy *dummy, int device,669 int substreams)670{671 struct snd_pcm *pcm;672 const struct snd_pcm_ops *ops;673 int err;674 675 err = snd_pcm_new(dummy->card, "Dummy PCM", device,676 substreams, substreams, &pcm);677 if (err < 0)678 return err;679 dummy->pcm = pcm;680 if (fake_buffer)681 ops = &dummy_pcm_ops_no_buf;682 else683 ops = &dummy_pcm_ops;684 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, ops);685 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, ops);686 pcm->private_data = dummy;687 pcm->info_flags = 0;688 strcpy(pcm->name, "Dummy PCM");689 if (!fake_buffer) {690 snd_pcm_set_managed_buffer_all(pcm,691 SNDRV_DMA_TYPE_CONTINUOUS,692 NULL,693 0, 64*1024);694 }695 return 0;696}697 698/*699 * mixer interface700 */701 702#define DUMMY_VOLUME(xname, xindex, addr) \703{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \704 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \705 .name = xname, .index = xindex, \706 .info = snd_dummy_volume_info, \707 .get = snd_dummy_volume_get, .put = snd_dummy_volume_put, \708 .private_value = addr, \709 .tlv = { .p = db_scale_dummy } }710 711static int snd_dummy_volume_info(struct snd_kcontrol *kcontrol,712 struct snd_ctl_elem_info *uinfo)713{714 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;715 uinfo->count = 2;716 uinfo->value.integer.min = mixer_volume_level_min;717 uinfo->value.integer.max = mixer_volume_level_max;718 return 0;719}720 721static int snd_dummy_volume_get(struct snd_kcontrol *kcontrol,722 struct snd_ctl_elem_value *ucontrol)723{724 struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol);725 int addr = kcontrol->private_value;726 727 spin_lock_irq(&dummy->mixer_lock);728 ucontrol->value.integer.value[0] = dummy->mixer_volume[addr][0];729 ucontrol->value.integer.value[1] = dummy->mixer_volume[addr][1];730 spin_unlock_irq(&dummy->mixer_lock);731 return 0;732}733 734static int snd_dummy_volume_put(struct snd_kcontrol *kcontrol,735 struct snd_ctl_elem_value *ucontrol)736{737 struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol);738 int change, addr = kcontrol->private_value;739 int left, right;740 741 left = ucontrol->value.integer.value[0];742 if (left < mixer_volume_level_min)743 left = mixer_volume_level_min;744 if (left > mixer_volume_level_max)745 left = mixer_volume_level_max;746 right = ucontrol->value.integer.value[1];747 if (right < mixer_volume_level_min)748 right = mixer_volume_level_min;749 if (right > mixer_volume_level_max)750 right = mixer_volume_level_max;751 spin_lock_irq(&dummy->mixer_lock);752 change = dummy->mixer_volume[addr][0] != left ||753 dummy->mixer_volume[addr][1] != right;754 dummy->mixer_volume[addr][0] = left;755 dummy->mixer_volume[addr][1] = right;756 spin_unlock_irq(&dummy->mixer_lock);757 return change;758}759 760static const DECLARE_TLV_DB_SCALE(db_scale_dummy, -4500, 30, 0);761 762#define DUMMY_CAPSRC(xname, xindex, addr) \763{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \764 .info = snd_dummy_capsrc_info, \765 .get = snd_dummy_capsrc_get, .put = snd_dummy_capsrc_put, \766 .private_value = addr }767 768#define snd_dummy_capsrc_info snd_ctl_boolean_stereo_info769 770static int snd_dummy_capsrc_get(struct snd_kcontrol *kcontrol,771 struct snd_ctl_elem_value *ucontrol)772{773 struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol);774 int addr = kcontrol->private_value;775 776 spin_lock_irq(&dummy->mixer_lock);777 ucontrol->value.integer.value[0] = dummy->capture_source[addr][0];778 ucontrol->value.integer.value[1] = dummy->capture_source[addr][1];779 spin_unlock_irq(&dummy->mixer_lock);780 return 0;781}782 783static int snd_dummy_capsrc_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)784{785 struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol);786 int change, addr = kcontrol->private_value;787 int left, right;788 789 left = ucontrol->value.integer.value[0] & 1;790 right = ucontrol->value.integer.value[1] & 1;791 spin_lock_irq(&dummy->mixer_lock);792 change = dummy->capture_source[addr][0] != left &&793 dummy->capture_source[addr][1] != right;794 dummy->capture_source[addr][0] = left;795 dummy->capture_source[addr][1] = right;796 spin_unlock_irq(&dummy->mixer_lock);797 return change;798}799 800static int snd_dummy_iobox_info(struct snd_kcontrol *kcontrol,801 struct snd_ctl_elem_info *info)802{803 static const char *const names[] = { "None", "CD Player" };804 805 return snd_ctl_enum_info(info, 1, 2, names);806}807 808static int snd_dummy_iobox_get(struct snd_kcontrol *kcontrol,809 struct snd_ctl_elem_value *value)810{811 struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol);812 813 value->value.enumerated.item[0] = dummy->iobox;814 return 0;815}816 817static int snd_dummy_iobox_put(struct snd_kcontrol *kcontrol,818 struct snd_ctl_elem_value *value)819{820 struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol);821 int changed;822 823 if (value->value.enumerated.item[0] > 1)824 return -EINVAL;825 826 changed = value->value.enumerated.item[0] != dummy->iobox;827 if (changed) {828 dummy->iobox = value->value.enumerated.item[0];829 830 if (dummy->iobox) {831 dummy->cd_volume_ctl->vd[0].access &=832 ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;833 dummy->cd_switch_ctl->vd[0].access &=834 ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;835 } else {836 dummy->cd_volume_ctl->vd[0].access |=837 SNDRV_CTL_ELEM_ACCESS_INACTIVE;838 dummy->cd_switch_ctl->vd[0].access |=839 SNDRV_CTL_ELEM_ACCESS_INACTIVE;840 }841 842 snd_ctl_notify(dummy->card, SNDRV_CTL_EVENT_MASK_INFO,843 &dummy->cd_volume_ctl->id);844 snd_ctl_notify(dummy->card, SNDRV_CTL_EVENT_MASK_INFO,845 &dummy->cd_switch_ctl->id);846 }847 848 return changed;849}850 851static const struct snd_kcontrol_new snd_dummy_controls[] = {852DUMMY_VOLUME("Master Volume", 0, MIXER_ADDR_MASTER),853DUMMY_CAPSRC("Master Capture Switch", 0, MIXER_ADDR_MASTER),854DUMMY_VOLUME("Synth Volume", 0, MIXER_ADDR_SYNTH),855DUMMY_CAPSRC("Synth Capture Switch", 0, MIXER_ADDR_SYNTH),856DUMMY_VOLUME("Line Volume", 0, MIXER_ADDR_LINE),857DUMMY_CAPSRC("Line Capture Switch", 0, MIXER_ADDR_LINE),858DUMMY_VOLUME("Mic Volume", 0, MIXER_ADDR_MIC),859DUMMY_CAPSRC("Mic Capture Switch", 0, MIXER_ADDR_MIC),860DUMMY_VOLUME("CD Volume", 0, MIXER_ADDR_CD),861DUMMY_CAPSRC("CD Capture Switch", 0, MIXER_ADDR_CD),862{863 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,864 .name = "External I/O Box",865 .info = snd_dummy_iobox_info,866 .get = snd_dummy_iobox_get,867 .put = snd_dummy_iobox_put,868},869};870 871static int snd_card_dummy_new_mixer(struct snd_dummy *dummy)872{873 struct snd_card *card = dummy->card;874 struct snd_kcontrol *kcontrol;875 unsigned int idx;876 int err;877 878 spin_lock_init(&dummy->mixer_lock);879 strcpy(card->mixername, "Dummy Mixer");880 dummy->iobox = 1;881 882 for (idx = 0; idx < ARRAY_SIZE(snd_dummy_controls); idx++) {883 kcontrol = snd_ctl_new1(&snd_dummy_controls[idx], dummy);884 err = snd_ctl_add(card, kcontrol);885 if (err < 0)886 return err;887 if (!strcmp(kcontrol->id.name, "CD Volume"))888 dummy->cd_volume_ctl = kcontrol;889 else if (!strcmp(kcontrol->id.name, "CD Capture Switch"))890 dummy->cd_switch_ctl = kcontrol;891 892 }893 return 0;894}895 896#if defined(CONFIG_SND_DEBUG) && defined(CONFIG_SND_PROC_FS)897/*898 * proc interface899 */900static void print_formats(struct snd_dummy *dummy,901 struct snd_info_buffer *buffer)902{903 snd_pcm_format_t i;904 905 pcm_for_each_format(i) {906 if (dummy->pcm_hw.formats & pcm_format_to_bits(i))907 snd_iprintf(buffer, " %s", snd_pcm_format_name(i));908 }909}910 911static void print_rates(struct snd_dummy *dummy,912 struct snd_info_buffer *buffer)913{914 static const int rates[] = {915 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000,916 64000, 88200, 96000, 176400, 192000,917 };918 int i;919 920 if (dummy->pcm_hw.rates & SNDRV_PCM_RATE_CONTINUOUS)921 snd_iprintf(buffer, " continuous");922 if (dummy->pcm_hw.rates & SNDRV_PCM_RATE_KNOT)923 snd_iprintf(buffer, " knot");924 for (i = 0; i < ARRAY_SIZE(rates); i++)925 if (dummy->pcm_hw.rates & (1 << i))926 snd_iprintf(buffer, " %d", rates[i]);927}928 929#define get_dummy_int_ptr(dummy, ofs) \930 (unsigned int *)((char *)&((dummy)->pcm_hw) + (ofs))931#define get_dummy_ll_ptr(dummy, ofs) \932 (unsigned long long *)((char *)&((dummy)->pcm_hw) + (ofs))933 934struct dummy_hw_field {935 const char *name;936 const char *format;937 unsigned int offset;938 unsigned int size;939};940#define FIELD_ENTRY(item, fmt) { \941 .name = #item, \942 .format = fmt, \943 .offset = offsetof(struct snd_pcm_hardware, item), \944 .size = sizeof(dummy_pcm_hardware.item) }945 946static const struct dummy_hw_field fields[] = {947 FIELD_ENTRY(formats, "%#llx"),948 FIELD_ENTRY(rates, "%#x"),949 FIELD_ENTRY(rate_min, "%d"),950 FIELD_ENTRY(rate_max, "%d"),951 FIELD_ENTRY(channels_min, "%d"),952 FIELD_ENTRY(channels_max, "%d"),953 FIELD_ENTRY(buffer_bytes_max, "%ld"),954 FIELD_ENTRY(period_bytes_min, "%ld"),955 FIELD_ENTRY(period_bytes_max, "%ld"),956 FIELD_ENTRY(periods_min, "%d"),957 FIELD_ENTRY(periods_max, "%d"),958};959 960static void dummy_proc_read(struct snd_info_entry *entry,961 struct snd_info_buffer *buffer)962{963 struct snd_dummy *dummy = entry->private_data;964 int i;965 966 for (i = 0; i < ARRAY_SIZE(fields); i++) {967 snd_iprintf(buffer, "%s ", fields[i].name);968 if (fields[i].size == sizeof(int))969 snd_iprintf(buffer, fields[i].format,970 *get_dummy_int_ptr(dummy, fields[i].offset));971 else972 snd_iprintf(buffer, fields[i].format,973 *get_dummy_ll_ptr(dummy, fields[i].offset));974 if (!strcmp(fields[i].name, "formats"))975 print_formats(dummy, buffer);976 else if (!strcmp(fields[i].name, "rates"))977 print_rates(dummy, buffer);978 snd_iprintf(buffer, "\n");979 }980}981 982static void dummy_proc_write(struct snd_info_entry *entry,983 struct snd_info_buffer *buffer)984{985 struct snd_dummy *dummy = entry->private_data;986 char line[64];987 988 while (!snd_info_get_line(buffer, line, sizeof(line))) {989 char item[20];990 const char *ptr;991 unsigned long long val;992 int i;993 994 ptr = snd_info_get_str(item, line, sizeof(item));995 for (i = 0; i < ARRAY_SIZE(fields); i++) {996 if (!strcmp(item, fields[i].name))997 break;998 }999 if (i >= ARRAY_SIZE(fields))1000 continue;1001 snd_info_get_str(item, ptr, sizeof(item));1002 if (kstrtoull(item, 0, &val))1003 continue;1004 if (fields[i].size == sizeof(int))1005 *get_dummy_int_ptr(dummy, fields[i].offset) = val;1006 else1007 *get_dummy_ll_ptr(dummy, fields[i].offset) = val;1008 }1009}1010 1011static void dummy_proc_init(struct snd_dummy *chip)1012{1013 snd_card_rw_proc_new(chip->card, "dummy_pcm", chip,1014 dummy_proc_read, dummy_proc_write);1015}1016#else1017#define dummy_proc_init(x)1018#endif /* CONFIG_SND_DEBUG && CONFIG_SND_PROC_FS */1019 1020static int snd_dummy_probe(struct platform_device *devptr)1021{1022 struct snd_card *card;1023 struct snd_dummy *dummy;1024 const struct dummy_model *m = NULL, **mdl;1025 int idx, err;1026 int dev = devptr->id;1027 1028 err = snd_devm_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE,1029 sizeof(struct snd_dummy), &card);1030 if (err < 0)1031 return err;1032 dummy = card->private_data;1033 dummy->card = card;1034 for (mdl = dummy_models; *mdl && model[dev]; mdl++) {1035 if (strcmp(model[dev], (*mdl)->name) == 0) {1036 pr_info("snd-dummy: Using model '%s' for card %i\n",1037 (*mdl)->name, card->number);1038 m = dummy->model = *mdl;1039 break;1040 }1041 }1042 for (idx = 0; idx < MAX_PCM_DEVICES && idx < pcm_devs[dev]; idx++) {1043 if (pcm_substreams[dev] < 1)1044 pcm_substreams[dev] = 1;1045 if (pcm_substreams[dev] > MAX_PCM_SUBSTREAMS)1046 pcm_substreams[dev] = MAX_PCM_SUBSTREAMS;1047 err = snd_card_dummy_pcm(dummy, idx, pcm_substreams[dev]);1048 if (err < 0)1049 return err;1050 }1051 1052 dummy->pcm_hw = dummy_pcm_hardware;1053 if (m) {1054 if (m->formats)1055 dummy->pcm_hw.formats = m->formats;1056 if (m->buffer_bytes_max)1057 dummy->pcm_hw.buffer_bytes_max = m->buffer_bytes_max;1058 if (m->period_bytes_min)1059 dummy->pcm_hw.period_bytes_min = m->period_bytes_min;1060 if (m->period_bytes_max)1061 dummy->pcm_hw.period_bytes_max = m->period_bytes_max;1062 if (m->periods_min)1063 dummy->pcm_hw.periods_min = m->periods_min;1064 if (m->periods_max)1065 dummy->pcm_hw.periods_max = m->periods_max;1066 if (m->rates)1067 dummy->pcm_hw.rates = m->rates;1068 if (m->rate_min)1069 dummy->pcm_hw.rate_min = m->rate_min;1070 if (m->rate_max)1071 dummy->pcm_hw.rate_max = m->rate_max;1072 if (m->channels_min)1073 dummy->pcm_hw.channels_min = m->channels_min;1074 if (m->channels_max)1075 dummy->pcm_hw.channels_max = m->channels_max;1076 }1077 1078 if (mixer_volume_level_min > mixer_volume_level_max) {1079 pr_warn("snd-dummy: Invalid mixer volume level: min=%d, max=%d. Fall back to default value.\n",1080 mixer_volume_level_min, mixer_volume_level_max);1081 mixer_volume_level_min = USE_MIXER_VOLUME_LEVEL_MIN;1082 mixer_volume_level_max = USE_MIXER_VOLUME_LEVEL_MAX;1083 }1084 err = snd_card_dummy_new_mixer(dummy);1085 if (err < 0)1086 return err;1087 strcpy(card->driver, "Dummy");1088 strcpy(card->shortname, "Dummy");1089 sprintf(card->longname, "Dummy %i", dev + 1);1090 1091 dummy_proc_init(dummy);1092 1093 err = snd_card_register(card);1094 if (err < 0)1095 return err;1096 platform_set_drvdata(devptr, card);1097 return 0;1098}1099 1100static int snd_dummy_suspend(struct device *pdev)1101{1102 struct snd_card *card = dev_get_drvdata(pdev);1103 1104 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);1105 return 0;1106}1107 1108static int snd_dummy_resume(struct device *pdev)1109{1110 struct snd_card *card = dev_get_drvdata(pdev);1111 1112 snd_power_change_state(card, SNDRV_CTL_POWER_D0);1113 return 0;1114}1115 1116static DEFINE_SIMPLE_DEV_PM_OPS(snd_dummy_pm, snd_dummy_suspend, snd_dummy_resume);1117 1118#define SND_DUMMY_DRIVER "snd_dummy"1119 1120static struct platform_driver snd_dummy_driver = {1121 .probe = snd_dummy_probe,1122 .driver = {1123 .name = SND_DUMMY_DRIVER,1124 .pm = &snd_dummy_pm,1125 },1126};1127 1128static void snd_dummy_unregister_all(void)1129{1130 int i;1131 1132 for (i = 0; i < ARRAY_SIZE(devices); ++i)1133 platform_device_unregister(devices[i]);1134 platform_driver_unregister(&snd_dummy_driver);1135 free_fake_buffer();1136}1137 1138static int __init alsa_card_dummy_init(void)1139{1140 int i, cards, err;1141 1142 err = platform_driver_register(&snd_dummy_driver);1143 if (err < 0)1144 return err;1145 1146 err = alloc_fake_buffer();1147 if (err < 0) {1148 platform_driver_unregister(&snd_dummy_driver);1149 return err;1150 }1151 1152 cards = 0;1153 for (i = 0; i < SNDRV_CARDS; i++) {1154 struct platform_device *device;1155 if (! enable[i])1156 continue;1157 device = platform_device_register_simple(SND_DUMMY_DRIVER,1158 i, NULL, 0);1159 if (IS_ERR(device))1160 continue;1161 if (!platform_get_drvdata(device)) {1162 platform_device_unregister(device);1163 continue;1164 }1165 devices[i] = device;1166 cards++;1167 }1168 if (!cards) {1169#ifdef MODULE1170 pr_err("Dummy soundcard not found or device busy\n");1171#endif1172 snd_dummy_unregister_all();1173 return -ENODEV;1174 }1175 return 0;1176}1177 1178static void __exit alsa_card_dummy_exit(void)1179{1180 snd_dummy_unregister_all();1181}1182 1183module_init(alsa_card_dummy_init)1184module_exit(alsa_card_dummy_exit)1185