diff options
| -rw-r--r-- | sound/drivers/dummy.c | 290 |
1 files changed, 180 insertions, 110 deletions
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index 252e04ce602f..7f41990ed68b 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c | |||
| @@ -45,109 +45,23 @@ MODULE_SUPPORTED_DEVICE("{{ALSA,Dummy soundcard}}"); | |||
| 45 | #define MAX_PCM_SUBSTREAMS 128 | 45 | #define MAX_PCM_SUBSTREAMS 128 |
| 46 | #define MAX_MIDI_DEVICES 2 | 46 | #define MAX_MIDI_DEVICES 2 |
| 47 | 47 | ||
| 48 | #if 0 /* emu10k1 emulation */ | ||
| 49 | #define MAX_BUFFER_SIZE (128 * 1024) | ||
| 50 | static int emu10k1_playback_constraints(struct snd_pcm_runtime *runtime) | ||
| 51 | { | ||
| 52 | int err; | ||
| 53 | err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); | ||
| 54 | if (err < 0) | ||
| 55 | return err; | ||
| 56 | err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX); | ||
| 57 | if (err < 0) | ||
| 58 | return err; | ||
| 59 | return 0; | ||
| 60 | } | ||
| 61 | #define add_playback_constraints emu10k1_playback_constraints | ||
| 62 | #endif | ||
| 63 | |||
| 64 | #if 0 /* RME9652 emulation */ | ||
| 65 | #define MAX_BUFFER_SIZE (26 * 64 * 1024) | ||
| 66 | #define USE_FORMATS SNDRV_PCM_FMTBIT_S32_LE | ||
| 67 | #define USE_CHANNELS_MIN 26 | ||
| 68 | #define USE_CHANNELS_MAX 26 | ||
| 69 | #define USE_PERIODS_MIN 2 | ||
| 70 | #define USE_PERIODS_MAX 2 | ||
| 71 | #endif | ||
| 72 | |||
| 73 | #if 0 /* ICE1712 emulation */ | ||
| 74 | #define MAX_BUFFER_SIZE (256 * 1024) | ||
| 75 | #define USE_FORMATS SNDRV_PCM_FMTBIT_S32_LE | ||
| 76 | #define USE_CHANNELS_MIN 10 | ||
| 77 | #define USE_CHANNELS_MAX 10 | ||
| 78 | #define USE_PERIODS_MIN 1 | ||
| 79 | #define USE_PERIODS_MAX 1024 | ||
| 80 | #endif | ||
| 81 | |||
| 82 | #if 0 /* UDA1341 emulation */ | ||
| 83 | #define MAX_BUFFER_SIZE (16380) | ||
| 84 | #define USE_FORMATS SNDRV_PCM_FMTBIT_S16_LE | ||
| 85 | #define USE_CHANNELS_MIN 2 | ||
| 86 | #define USE_CHANNELS_MAX 2 | ||
| 87 | #define USE_PERIODS_MIN 2 | ||
| 88 | #define USE_PERIODS_MAX 255 | ||
| 89 | #endif | ||
| 90 | |||
| 91 | #if 0 /* simple AC97 bridge (intel8x0) with 48kHz AC97 only codec */ | ||
| 92 | #define USE_FORMATS SNDRV_PCM_FMTBIT_S16_LE | ||
| 93 | #define USE_CHANNELS_MIN 2 | ||
| 94 | #define USE_CHANNELS_MAX 2 | ||
| 95 | #define USE_RATE SNDRV_PCM_RATE_48000 | ||
| 96 | #define USE_RATE_MIN 48000 | ||
| 97 | #define USE_RATE_MAX 48000 | ||
| 98 | #endif | ||
| 99 | |||
| 100 | #if 0 /* CA0106 */ | ||
| 101 | #define USE_FORMATS SNDRV_PCM_FMTBIT_S16_LE | ||
| 102 | #define USE_CHANNELS_MIN 2 | ||
| 103 | #define USE_CHANNELS_MAX 2 | ||
| 104 | #define USE_RATE (SNDRV_PCM_RATE_48000|SNDRV_PCM_RATE_96000|SNDRV_PCM_RATE_192000) | ||
| 105 | #define USE_RATE_MIN 48000 | ||
| 106 | #define USE_RATE_MAX 192000 | ||
| 107 | #define MAX_BUFFER_SIZE ((65536-64)*8) | ||
| 108 | #define MAX_PERIOD_SIZE (65536-64) | ||
| 109 | #define USE_PERIODS_MIN 2 | ||
| 110 | #define USE_PERIODS_MAX 8 | ||
| 111 | #endif | ||
| 112 | |||
| 113 | |||
| 114 | /* defaults */ | 48 | /* defaults */ |
| 115 | #ifndef MAX_BUFFER_SIZE | ||
| 116 | #define MAX_BUFFER_SIZE (64*1024) | 49 | #define MAX_BUFFER_SIZE (64*1024) |
| 117 | #endif | 50 | #define MIN_PERIOD_SIZE 64 |
| 118 | #ifndef MAX_PERIOD_SIZE | ||
| 119 | #define MAX_PERIOD_SIZE MAX_BUFFER_SIZE | 51 | #define MAX_PERIOD_SIZE MAX_BUFFER_SIZE |
| 120 | #endif | ||
| 121 | #ifndef USE_FORMATS | ||
| 122 | #define USE_FORMATS (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE) | 52 | #define USE_FORMATS (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE) |
| 123 | #endif | ||
| 124 | #ifndef USE_RATE | ||
| 125 | #define USE_RATE SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000 | 53 | #define USE_RATE SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000 |
| 126 | #define USE_RATE_MIN 5500 | 54 | #define USE_RATE_MIN 5500 |
| 127 | #define USE_RATE_MAX 48000 | 55 | #define USE_RATE_MAX 48000 |
| 128 | #endif | ||
| 129 | #ifndef USE_CHANNELS_MIN | ||
| 130 | #define USE_CHANNELS_MIN 1 | 56 | #define USE_CHANNELS_MIN 1 |
| 131 | #endif | ||
| 132 | #ifndef USE_CHANNELS_MAX | ||
| 133 | #define USE_CHANNELS_MAX 2 | 57 | #define USE_CHANNELS_MAX 2 |
| 134 | #endif | ||
| 135 | #ifndef USE_PERIODS_MIN | ||
| 136 | #define USE_PERIODS_MIN 1 | 58 | #define USE_PERIODS_MIN 1 |
| 137 | #endif | ||
| 138 | #ifndef USE_PERIODS_MAX | ||
| 139 | #define USE_PERIODS_MAX 1024 | 59 | #define USE_PERIODS_MAX 1024 |
| 140 | #endif | ||
| 141 | #ifndef add_playback_constraints | ||
| 142 | #define add_playback_constraints(x) 0 | ||
| 143 | #endif | ||
| 144 | #ifndef add_capture_constraints | ||
| 145 | #define add_capture_constraints(x) 0 | ||
| 146 | #endif | ||
| 147 | 60 | ||
| 148 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | 61 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ |
| 149 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | 62 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ |
| 150 | static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0}; | 63 | static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0}; |
| 64 | static char *model[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = NULL}; | ||
| 151 | static int pcm_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; | 65 | static int pcm_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; |
| 152 | static int pcm_substreams[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8}; | 66 | static int pcm_substreams[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8}; |
| 153 | //static int midi_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; | 67 | //static int midi_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; |
| @@ -162,6 +76,8 @@ module_param_array(id, charp, NULL, 0444); | |||
| 162 | MODULE_PARM_DESC(id, "ID string for dummy soundcard."); | 76 | MODULE_PARM_DESC(id, "ID string for dummy soundcard."); |
| 163 | module_param_array(enable, bool, NULL, 0444); | 77 | module_param_array(enable, bool, NULL, 0444); |
| 164 | MODULE_PARM_DESC(enable, "Enable this dummy soundcard."); | 78 | MODULE_PARM_DESC(enable, "Enable this dummy soundcard."); |
| 79 | module_param_array(model, charp, NULL, 0444); | ||
| 80 | MODULE_PARM_DESC(model, "Soundcard model."); | ||
| 165 | module_param_array(pcm_devs, int, NULL, 0444); | 81 | module_param_array(pcm_devs, int, NULL, 0444); |
| 166 | MODULE_PARM_DESC(pcm_devs, "PCM devices # (0-4) for dummy driver."); | 82 | MODULE_PARM_DESC(pcm_devs, "PCM devices # (0-4) for dummy driver."); |
| 167 | module_param_array(pcm_substreams, int, NULL, 0444); | 83 | module_param_array(pcm_substreams, int, NULL, 0444); |
| @@ -193,9 +109,28 @@ struct dummy_timer_ops { | |||
| 193 | snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *); | 109 | snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *); |
| 194 | }; | 110 | }; |
| 195 | 111 | ||
| 112 | struct dummy_model { | ||
| 113 | const char *name; | ||
| 114 | int (*playback_constraints)(struct snd_pcm_runtime *runtime); | ||
| 115 | int (*capture_constraints)(struct snd_pcm_runtime *runtime); | ||
| 116 | u64 formats; | ||
| 117 | size_t buffer_bytes_max; | ||
| 118 | size_t period_bytes_min; | ||
| 119 | size_t period_bytes_max; | ||
| 120 | unsigned int periods_min; | ||
| 121 | unsigned int periods_max; | ||
| 122 | unsigned int rates; | ||
| 123 | unsigned int rate_min; | ||
| 124 | unsigned int rate_max; | ||
| 125 | unsigned int channels_min; | ||
| 126 | unsigned int channels_max; | ||
| 127 | }; | ||
| 128 | |||
| 196 | struct snd_dummy { | 129 | struct snd_dummy { |
| 197 | struct snd_card *card; | 130 | struct snd_card *card; |
| 131 | struct dummy_model *model; | ||
| 198 | struct snd_pcm *pcm; | 132 | struct snd_pcm *pcm; |
| 133 | struct snd_pcm_hardware pcm_hw; | ||
| 199 | spinlock_t mixer_lock; | 134 | spinlock_t mixer_lock; |
| 200 | int mixer_volume[MIXER_ADDR_LAST+1][2]; | 135 | int mixer_volume[MIXER_ADDR_LAST+1][2]; |
| 201 | int capture_source[MIXER_ADDR_LAST+1][2]; | 136 | int capture_source[MIXER_ADDR_LAST+1][2]; |
| @@ -203,6 +138,92 @@ struct snd_dummy { | |||
| 203 | }; | 138 | }; |
| 204 | 139 | ||
| 205 | /* | 140 | /* |
| 141 | * card models | ||
| 142 | */ | ||
| 143 | |||
| 144 | static int emu10k1_playback_constraints(struct snd_pcm_runtime *runtime) | ||
| 145 | { | ||
| 146 | int err; | ||
| 147 | err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); | ||
| 148 | if (err < 0) | ||
| 149 | return err; | ||
| 150 | err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX); | ||
| 151 | if (err < 0) | ||
| 152 | return err; | ||
| 153 | return 0; | ||
| 154 | } | ||
| 155 | |||
| 156 | struct dummy_model model_emu10k1 = { | ||
| 157 | .name = "emu10k1", | ||
| 158 | .playback_constraints = emu10k1_playback_constraints, | ||
| 159 | .buffer_bytes_max = 128 * 1024, | ||
| 160 | }; | ||
| 161 | |||
| 162 | struct dummy_model model_rme9652 = { | ||
| 163 | .name = "rme9652", | ||
| 164 | .buffer_bytes_max = 26 * 64 * 1024, | ||
| 165 | .formats = SNDRV_PCM_FMTBIT_S32_LE, | ||
| 166 | .channels_min = 26, | ||
| 167 | .channels_max = 26, | ||
| 168 | .periods_min = 2, | ||
| 169 | .periods_max = 2, | ||
| 170 | }; | ||
| 171 | |||
| 172 | struct dummy_model model_ice1712 = { | ||
| 173 | .name = "ice1712", | ||
| 174 | .buffer_bytes_max = 256 * 1024, | ||
| 175 | .formats = SNDRV_PCM_FMTBIT_S32_LE, | ||
| 176 | .channels_min = 10, | ||
| 177 | .channels_max = 10, | ||
| 178 | .periods_min = 1, | ||
| 179 | .periods_max = 1024, | ||
| 180 | }; | ||
| 181 | |||
| 182 | struct dummy_model model_uda1341 = { | ||
| 183 | .name = "uda1341", | ||
| 184 | .buffer_bytes_max = 16380, | ||
| 185 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
| 186 | .channels_min = 2, | ||
| 187 | .channels_max = 2, | ||
| 188 | .periods_min = 2, | ||
| 189 | .periods_max = 255, | ||
| 190 | }; | ||
| 191 | |||
| 192 | struct dummy_model model_ac97 = { | ||
| 193 | .name = "ac97", | ||
| 194 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
| 195 | .channels_min = 2, | ||
| 196 | .channels_max = 2, | ||
| 197 | .rates = SNDRV_PCM_RATE_48000, | ||
| 198 | .rate_min = 48000, | ||
| 199 | .rate_max = 48000, | ||
| 200 | }; | ||
| 201 | |||
| 202 | struct dummy_model model_ca0106 = { | ||
| 203 | .name = "ca0106", | ||
| 204 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
| 205 | .buffer_bytes_max = ((65536-64)*8), | ||
| 206 | .period_bytes_max = (65536-64), | ||
| 207 | .periods_min = 2, | ||
| 208 | .periods_max = 8, | ||
| 209 | .channels_min = 2, | ||
| 210 | .channels_max = 2, | ||
| 211 | .rates = SNDRV_PCM_RATE_48000|SNDRV_PCM_RATE_96000|SNDRV_PCM_RATE_192000, | ||
| 212 | .rate_min = 48000, | ||
| 213 | .rate_max = 192000, | ||
| 214 | }; | ||
| 215 | |||
| 216 | struct dummy_model *dummy_models[] = { | ||
| 217 | &model_emu10k1, | ||
| 218 | &model_rme9652, | ||
| 219 | &model_ice1712, | ||
| 220 | &model_uda1341, | ||
| 221 | &model_ac97, | ||
| 222 | &model_ca0106, | ||
| 223 | NULL | ||
| 224 | }; | ||
| 225 | |||
| 226 | /* | ||
| 206 | * system timer interface | 227 | * system timer interface |
| 207 | */ | 228 | */ |
| 208 | 229 | ||
| @@ -509,7 +530,7 @@ static struct snd_pcm_hardware dummy_pcm_hardware = { | |||
| 509 | .channels_min = USE_CHANNELS_MIN, | 530 | .channels_min = USE_CHANNELS_MIN, |
| 510 | .channels_max = USE_CHANNELS_MAX, | 531 | .channels_max = USE_CHANNELS_MAX, |
| 511 | .buffer_bytes_max = MAX_BUFFER_SIZE, | 532 | .buffer_bytes_max = MAX_BUFFER_SIZE, |
| 512 | .period_bytes_min = 64, | 533 | .period_bytes_min = MIN_PERIOD_SIZE, |
| 513 | .period_bytes_max = MAX_PERIOD_SIZE, | 534 | .period_bytes_max = MAX_PERIOD_SIZE, |
| 514 | .periods_min = USE_PERIODS_MIN, | 535 | .periods_min = USE_PERIODS_MIN, |
| 515 | .periods_max = USE_PERIODS_MAX, | 536 | .periods_max = USE_PERIODS_MAX, |
| @@ -538,6 +559,7 @@ static int dummy_pcm_hw_free(struct snd_pcm_substream *substream) | |||
| 538 | static int dummy_pcm_open(struct snd_pcm_substream *substream) | 559 | static int dummy_pcm_open(struct snd_pcm_substream *substream) |
| 539 | { | 560 | { |
| 540 | struct snd_dummy *dummy = snd_pcm_substream_chip(substream); | 561 | struct snd_dummy *dummy = snd_pcm_substream_chip(substream); |
| 562 | struct dummy_model *model = dummy->model; | ||
| 541 | struct snd_pcm_runtime *runtime = substream->runtime; | 563 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 542 | int err; | 564 | int err; |
| 543 | 565 | ||
| @@ -551,7 +573,7 @@ static int dummy_pcm_open(struct snd_pcm_substream *substream) | |||
| 551 | if (err < 0) | 573 | if (err < 0) |
| 552 | return err; | 574 | return err; |
| 553 | 575 | ||
| 554 | runtime->hw = dummy_pcm_hardware; | 576 | runtime->hw = dummy->pcm_hw; |
| 555 | if (substream->pcm->device & 1) { | 577 | if (substream->pcm->device & 1) { |
| 556 | runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED; | 578 | runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED; |
| 557 | runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED; | 579 | runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED; |
| @@ -560,10 +582,16 @@ static int dummy_pcm_open(struct snd_pcm_substream *substream) | |||
| 560 | runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP | | 582 | runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP | |
| 561 | SNDRV_PCM_INFO_MMAP_VALID); | 583 | SNDRV_PCM_INFO_MMAP_VALID); |
| 562 | 584 | ||
| 563 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 585 | if (model == NULL) |
| 564 | err = add_playback_constraints(substream->runtime); | 586 | return 0; |
| 565 | else | 587 | |
| 566 | err = add_capture_constraints(substream->runtime); | 588 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
| 589 | if (model->playback_constraints) | ||
| 590 | err = model->playback_constraints(substream->runtime); | ||
| 591 | } else { | ||
| 592 | if (model->capture_constraints) | ||
| 593 | err = model->capture_constraints(substream->runtime); | ||
| 594 | } | ||
| 567 | if (err < 0) { | 595 | if (err < 0) { |
| 568 | dummy->timer_ops->free(substream); | 596 | dummy->timer_ops->free(substream); |
| 569 | return err; | 597 | return err; |
| @@ -823,17 +851,19 @@ static int __devinit snd_card_dummy_new_mixer(struct snd_dummy *dummy) | |||
| 823 | /* | 851 | /* |
| 824 | * proc interface | 852 | * proc interface |
| 825 | */ | 853 | */ |
| 826 | static void print_formats(struct snd_info_buffer *buffer) | 854 | static void print_formats(struct snd_dummy *dummy, |
| 855 | struct snd_info_buffer *buffer) | ||
| 827 | { | 856 | { |
| 828 | int i; | 857 | int i; |
| 829 | 858 | ||
| 830 | for (i = 0; i < SNDRV_PCM_FORMAT_LAST; i++) { | 859 | for (i = 0; i < SNDRV_PCM_FORMAT_LAST; i++) { |
| 831 | if (dummy_pcm_hardware.formats & (1ULL << i)) | 860 | if (dummy->pcm_hw.formats & (1ULL << i)) |
| 832 | snd_iprintf(buffer, " %s", snd_pcm_format_name(i)); | 861 | snd_iprintf(buffer, " %s", snd_pcm_format_name(i)); |
| 833 | } | 862 | } |
| 834 | } | 863 | } |
| 835 | 864 | ||
| 836 | static void print_rates(struct snd_info_buffer *buffer) | 865 | static void print_rates(struct snd_dummy *dummy, |
| 866 | struct snd_info_buffer *buffer) | ||
| 837 | { | 867 | { |
| 838 | static int rates[] = { | 868 | static int rates[] = { |
| 839 | 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, | 869 | 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, |
| @@ -841,19 +871,19 @@ static void print_rates(struct snd_info_buffer *buffer) | |||
| 841 | }; | 871 | }; |
| 842 | int i; | 872 | int i; |
| 843 | 873 | ||
| 844 | if (dummy_pcm_hardware.rates & SNDRV_PCM_RATE_CONTINUOUS) | 874 | if (dummy->pcm_hw.rates & SNDRV_PCM_RATE_CONTINUOUS) |
| 845 | snd_iprintf(buffer, " continuous"); | 875 | snd_iprintf(buffer, " continuous"); |
| 846 | if (dummy_pcm_hardware.rates & SNDRV_PCM_RATE_KNOT) | 876 | if (dummy->pcm_hw.rates & SNDRV_PCM_RATE_KNOT) |
| 847 | snd_iprintf(buffer, " knot"); | 877 | snd_iprintf(buffer, " knot"); |
| 848 | for (i = 0; i < ARRAY_SIZE(rates); i++) | 878 | for (i = 0; i < ARRAY_SIZE(rates); i++) |
| 849 | if (dummy_pcm_hardware.rates & (1 << i)) | 879 | if (dummy->pcm_hw.rates & (1 << i)) |
| 850 | snd_iprintf(buffer, " %d", rates[i]); | 880 | snd_iprintf(buffer, " %d", rates[i]); |
| 851 | } | 881 | } |
| 852 | 882 | ||
| 853 | #define get_dummy_int_ptr(ofs) \ | 883 | #define get_dummy_int_ptr(dummy, ofs) \ |
| 854 | (unsigned int *)((char *)&dummy_pcm_hardware + (ofs)) | 884 | (unsigned int *)((char *)&((dummy)->pcm_hw) + (ofs)) |
| 855 | #define get_dummy_ll_ptr(ofs) \ | 885 | #define get_dummy_ll_ptr(dummy, ofs) \ |
| 856 | (unsigned long long *)((char *)&dummy_pcm_hardware + (ofs)) | 886 | (unsigned long long *)((char *)&((dummy)->pcm_hw) + (ofs)) |
| 857 | 887 | ||
| 858 | struct dummy_hw_field { | 888 | struct dummy_hw_field { |
| 859 | const char *name; | 889 | const char *name; |
| @@ -884,20 +914,21 @@ static struct dummy_hw_field fields[] = { | |||
| 884 | static void dummy_proc_read(struct snd_info_entry *entry, | 914 | static void dummy_proc_read(struct snd_info_entry *entry, |
| 885 | struct snd_info_buffer *buffer) | 915 | struct snd_info_buffer *buffer) |
| 886 | { | 916 | { |
| 917 | struct snd_dummy *dummy = entry->private_data; | ||
| 887 | int i; | 918 | int i; |
| 888 | 919 | ||
| 889 | for (i = 0; i < ARRAY_SIZE(fields); i++) { | 920 | for (i = 0; i < ARRAY_SIZE(fields); i++) { |
| 890 | snd_iprintf(buffer, "%s ", fields[i].name); | 921 | snd_iprintf(buffer, "%s ", fields[i].name); |
| 891 | if (fields[i].size == sizeof(int)) | 922 | if (fields[i].size == sizeof(int)) |
| 892 | snd_iprintf(buffer, fields[i].format, | 923 | snd_iprintf(buffer, fields[i].format, |
| 893 | *get_dummy_int_ptr(fields[i].offset)); | 924 | *get_dummy_int_ptr(dummy, fields[i].offset)); |
| 894 | else | 925 | else |
| 895 | snd_iprintf(buffer, fields[i].format, | 926 | snd_iprintf(buffer, fields[i].format, |
| 896 | *get_dummy_ll_ptr(fields[i].offset)); | 927 | *get_dummy_ll_ptr(dummy, fields[i].offset)); |
| 897 | if (!strcmp(fields[i].name, "formats")) | 928 | if (!strcmp(fields[i].name, "formats")) |
| 898 | print_formats(buffer); | 929 | print_formats(dummy, buffer); |
| 899 | else if (!strcmp(fields[i].name, "rates")) | 930 | else if (!strcmp(fields[i].name, "rates")) |
| 900 | print_rates(buffer); | 931 | print_rates(dummy, buffer); |
| 901 | snd_iprintf(buffer, "\n"); | 932 | snd_iprintf(buffer, "\n"); |
| 902 | } | 933 | } |
| 903 | } | 934 | } |
| @@ -905,6 +936,7 @@ static void dummy_proc_read(struct snd_info_entry *entry, | |||
| 905 | static void dummy_proc_write(struct snd_info_entry *entry, | 936 | static void dummy_proc_write(struct snd_info_entry *entry, |
| 906 | struct snd_info_buffer *buffer) | 937 | struct snd_info_buffer *buffer) |
| 907 | { | 938 | { |
| 939 | struct snd_dummy *dummy = entry->private_data; | ||
| 908 | char line[64]; | 940 | char line[64]; |
| 909 | 941 | ||
| 910 | while (!snd_info_get_line(buffer, line, sizeof(line))) { | 942 | while (!snd_info_get_line(buffer, line, sizeof(line))) { |
| @@ -924,9 +956,9 @@ static void dummy_proc_write(struct snd_info_entry *entry, | |||
| 924 | if (strict_strtoull(item, 0, &val)) | 956 | if (strict_strtoull(item, 0, &val)) |
| 925 | continue; | 957 | continue; |
| 926 | if (fields[i].size == sizeof(int)) | 958 | if (fields[i].size == sizeof(int)) |
| 927 | *get_dummy_int_ptr(fields[i].offset) = val; | 959 | *get_dummy_int_ptr(dummy, fields[i].offset) = val; |
| 928 | else | 960 | else |
| 929 | *get_dummy_ll_ptr(fields[i].offset) = val; | 961 | *get_dummy_ll_ptr(dummy, fields[i].offset) = val; |
| 930 | } | 962 | } |
| 931 | } | 963 | } |
| 932 | 964 | ||
| @@ -938,6 +970,7 @@ static void __devinit dummy_proc_init(struct snd_dummy *chip) | |||
| 938 | snd_info_set_text_ops(entry, chip, dummy_proc_read); | 970 | snd_info_set_text_ops(entry, chip, dummy_proc_read); |
| 939 | entry->c.text.write = dummy_proc_write; | 971 | entry->c.text.write = dummy_proc_write; |
| 940 | entry->mode |= S_IWUSR; | 972 | entry->mode |= S_IWUSR; |
| 973 | entry->private_data = chip; | ||
| 941 | } | 974 | } |
| 942 | } | 975 | } |
| 943 | #else | 976 | #else |
| @@ -948,6 +981,7 @@ static int __devinit snd_dummy_probe(struct platform_device *devptr) | |||
| 948 | { | 981 | { |
| 949 | struct snd_card *card; | 982 | struct snd_card *card; |
| 950 | struct snd_dummy *dummy; | 983 | struct snd_dummy *dummy; |
| 984 | struct dummy_model *m = NULL, **mdl; | ||
| 951 | int idx, err; | 985 | int idx, err; |
| 952 | int dev = devptr->id; | 986 | int dev = devptr->id; |
| 953 | 987 | ||
| @@ -957,6 +991,15 @@ static int __devinit snd_dummy_probe(struct platform_device *devptr) | |||
| 957 | return err; | 991 | return err; |
| 958 | dummy = card->private_data; | 992 | dummy = card->private_data; |
| 959 | dummy->card = card; | 993 | dummy->card = card; |
| 994 | for (mdl = dummy_models; *mdl && model[dev]; mdl++) { | ||
| 995 | if (strcmp(model[dev], (*mdl)->name) == 0) { | ||
| 996 | printk(KERN_INFO | ||
| 997 | "snd-dummy: Using model '%s' for card %i\n", | ||
| 998 | (*mdl)->name, card->number); | ||
| 999 | m = dummy->model = *mdl; | ||
| 1000 | break; | ||
| 1001 | } | ||
| 1002 | } | ||
| 960 | for (idx = 0; idx < MAX_PCM_DEVICES && idx < pcm_devs[dev]; idx++) { | 1003 | for (idx = 0; idx < MAX_PCM_DEVICES && idx < pcm_devs[dev]; idx++) { |
| 961 | if (pcm_substreams[dev] < 1) | 1004 | if (pcm_substreams[dev] < 1) |
| 962 | pcm_substreams[dev] = 1; | 1005 | pcm_substreams[dev] = 1; |
| @@ -966,6 +1009,33 @@ static int __devinit snd_dummy_probe(struct platform_device *devptr) | |||
| 966 | if (err < 0) | 1009 | if (err < 0) |
| 967 | goto __nodev; | 1010 | goto __nodev; |
| 968 | } | 1011 | } |
| 1012 | |||
| 1013 | dummy->pcm_hw = dummy_pcm_hardware; | ||
| 1014 | if (m) { | ||
| 1015 | if (m->formats) | ||
| 1016 | dummy->pcm_hw.formats = m->formats; | ||
| 1017 | if (m->buffer_bytes_max) | ||
| 1018 | dummy->pcm_hw.buffer_bytes_max = m->buffer_bytes_max; | ||
| 1019 | if (m->period_bytes_min) | ||
| 1020 | dummy->pcm_hw.period_bytes_min = m->period_bytes_min; | ||
| 1021 | if (m->period_bytes_max) | ||
| 1022 | dummy->pcm_hw.period_bytes_max = m->period_bytes_max; | ||
| 1023 | if (m->periods_min) | ||
| 1024 | dummy->pcm_hw.periods_min = m->periods_min; | ||
| 1025 | if (m->periods_max) | ||
| 1026 | dummy->pcm_hw.periods_max = m->periods_max; | ||
| 1027 | if (m->rates) | ||
| 1028 | dummy->pcm_hw.rates = m->rates; | ||
| 1029 | if (m->rate_min) | ||
| 1030 | dummy->pcm_hw.rate_min = m->rate_min; | ||
| 1031 | if (m->rate_max) | ||
| 1032 | dummy->pcm_hw.rate_max = m->rate_max; | ||
| 1033 | if (m->channels_min) | ||
| 1034 | dummy->pcm_hw.channels_min = m->channels_min; | ||
| 1035 | if (m->channels_max) | ||
| 1036 | dummy->pcm_hw.channels_max = m->channels_max; | ||
| 1037 | } | ||
| 1038 | |||
| 969 | err = snd_card_dummy_new_mixer(dummy); | 1039 | err = snd_card_dummy_new_mixer(dummy); |
| 970 | if (err < 0) | 1040 | if (err < 0) |
| 971 | goto __nodev; | 1041 | goto __nodev; |
