diff options
Diffstat (limited to 'sound/drivers')
-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; |