aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt82
-rw-r--r--include/sound/pcm.h1
-rw-r--r--sound/core/pcm_lib.c14
-rw-r--r--sound/core/pcm_native.c2
-rw-r--r--sound/drivers/Kconfig19
-rw-r--r--sound/drivers/Makefile2
-rw-r--r--sound/drivers/aloop.c1055
-rw-r--r--sound/isa/Kconfig36
-rw-r--r--sound/isa/Makefile4
-rw-r--r--sound/isa/galaxy/Makefile10
-rw-r--r--sound/isa/galaxy/azt1605.c91
-rw-r--r--sound/isa/galaxy/azt2316.c111
-rw-r--r--sound/isa/galaxy/galaxy.c652
-rw-r--r--sound/isa/sgalaxy.c369
-rw-r--r--sound/pci/ice1712/delta.c10
-rw-r--r--sound/pci/ice1712/delta.h4
-rw-r--r--sound/usb/card.c31
-rw-r--r--sound/usb/endpoint.c2
-rw-r--r--sound/usb/helper.c17
-rw-r--r--sound/usb/midi.c9
-rw-r--r--sound/usb/pcm.c4
-rw-r--r--sound/usb/proc.c2
-rw-r--r--sound/usb/quirks-table.h161
-rw-r--r--sound/usb/urb.c2
24 files changed, 2260 insertions, 430 deletions
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 7f4dcebda9c6..d0eb696d32e8 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -300,6 +300,74 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
300 control correctly. If you have problems regarding this, try 300 control correctly. If you have problems regarding this, try
301 another ALSA compliant mixer (alsamixer works). 301 another ALSA compliant mixer (alsamixer works).
302 302
303 Module snd-azt1605
304 ------------------
305
306 Module for Aztech Sound Galaxy soundcards based on the Aztech AZT1605
307 chipset.
308
309 port - port # for BASE (0x220,0x240,0x260,0x280)
310 wss_port - port # for WSS (0x530,0x604,0xe80,0xf40)
311 irq - IRQ # for WSS (7,9,10,11)
312 dma1 - DMA # for WSS playback (0,1,3)
313 dma2 - DMA # for WSS capture (0,1), -1 = disabled (default)
314 mpu_port - port # for MPU-401 UART (0x300,0x330), -1 = disabled (default)
315 mpu_irq - IRQ # for MPU-401 UART (3,5,7,9), -1 = disabled (default)
316 fm_port - port # for OPL3 (0x388), -1 = disabled (default)
317
318 This module supports multiple cards. It does not support autoprobe: port,
319 wss_port, irq and dma1 have to be specified. The other values are
320 optional.
321
322 "port" needs to match the BASE ADDRESS jumper on the card (0x220 or 0x240)
323 or the value stored in the card's EEPROM for cards that have an EEPROM and
324 their "CONFIG MODE" jumper set to "EEPROM SETTING". The other values can
325 be choosen freely from the options enumerated above.
326
327 If dma2 is specified and different from dma1, the card will operate in
328 full-duplex mode. When dma1=3, only dma2=0 is valid and the only way to
329 enable capture since only channels 0 and 1 are available for capture.
330
331 Generic settings are "port=0x220 wss_port=0x530 irq=10 dma1=1 dma2=0
332 mpu_port=0x330 mpu_irq=9 fm_port=0x388".
333
334 Whatever IRQ and DMA channels you pick, be sure to reserve them for
335 legacy ISA in your BIOS.
336
337 Module snd-azt2316
338 ------------------
339
340 Module for Aztech Sound Galaxy soundcards based on the Aztech AZT2316
341 chipset.
342
343 port - port # for BASE (0x220,0x240,0x260,0x280)
344 wss_port - port # for WSS (0x530,0x604,0xe80,0xf40)
345 irq - IRQ # for WSS (7,9,10,11)
346 dma1 - DMA # for WSS playback (0,1,3)
347 dma2 - DMA # for WSS capture (0,1), -1 = disabled (default)
348 mpu_port - port # for MPU-401 UART (0x300,0x330), -1 = disabled (default)
349 mpu_irq - IRQ # for MPU-401 UART (5,7,9,10), -1 = disabled (default)
350 fm_port - port # for OPL3 (0x388), -1 = disabled (default)
351
352 This module supports multiple cards. It does not support autoprobe: port,
353 wss_port, irq and dma1 have to be specified. The other values are
354 optional.
355
356 "port" needs to match the BASE ADDRESS jumper on the card (0x220 or 0x240)
357 or the value stored in the card's EEPROM for cards that have an EEPROM and
358 their "CONFIG MODE" jumper set to "EEPROM SETTING". The other values can
359 be choosen freely from the options enumerated above.
360
361 If dma2 is specified and different from dma1, the card will operate in
362 full-duplex mode. When dma1=3, only dma2=0 is valid and the only way to
363 enable capture since only channels 0 and 1 are available for capture.
364
365 Generic settings are "port=0x220 wss_port=0x530 irq=10 dma1=1 dma2=0
366 mpu_port=0x330 mpu_irq=9 fm_port=0x388".
367
368 Whatever IRQ and DMA channels you pick, be sure to reserve them for
369 legacy ISA in your BIOS.
370
303 Module snd-aw2 371 Module snd-aw2
304 -------------- 372 --------------
305 373
@@ -1641,20 +1709,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
1641 1709
1642 This card is also known as Audio Excel DSP 16 or Zoltrix AV302. 1710 This card is also known as Audio Excel DSP 16 or Zoltrix AV302.
1643 1711
1644 Module snd-sgalaxy
1645 ------------------
1646
1647 Module for Aztech Sound Galaxy sound card.
1648
1649 sbport - Port # for SB16 interface (0x220,0x240)
1650 wssport - Port # for WSS interface (0x530,0xe80,0xf40,0x604)
1651 irq - IRQ # (7,9,10,11)
1652 dma1 - DMA #
1653
1654 This module supports multiple cards.
1655
1656 The power-management is supported.
1657
1658 Module snd-sscape 1712 Module snd-sscape
1659 ----------------- 1713 -----------------
1660 1714
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 85f1c6bf8566..dfd9b76b1853 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -278,6 +278,7 @@ struct snd_pcm_runtime {
278 snd_pcm_uframes_t hw_ptr_base; /* Position at buffer restart */ 278 snd_pcm_uframes_t hw_ptr_base; /* Position at buffer restart */
279 snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time */ 279 snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time */
280 unsigned long hw_ptr_jiffies; /* Time when hw_ptr is updated */ 280 unsigned long hw_ptr_jiffies; /* Time when hw_ptr is updated */
281 unsigned long hw_ptr_buffer_jiffies; /* buffer time in jiffies */
281 snd_pcm_sframes_t delay; /* extra delay; typically FIFO size */ 282 snd_pcm_sframes_t delay; /* extra delay; typically FIFO size */
282 283
283 /* -- HW params -- */ 284 /* -- HW params -- */
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index e23e0e7ab26f..a1707cca9c66 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -334,11 +334,15 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
334 /* delta = "expected next hw_ptr" for in_interrupt != 0 */ 334 /* delta = "expected next hw_ptr" for in_interrupt != 0 */
335 delta = runtime->hw_ptr_interrupt + runtime->period_size; 335 delta = runtime->hw_ptr_interrupt + runtime->period_size;
336 if (delta > new_hw_ptr) { 336 if (delta > new_hw_ptr) {
337 hw_base += runtime->buffer_size; 337 /* check for double acknowledged interrupts */
338 if (hw_base >= runtime->boundary) 338 hdelta = jiffies - runtime->hw_ptr_jiffies;
339 hw_base = 0; 339 if (hdelta > runtime->hw_ptr_buffer_jiffies/2) {
340 new_hw_ptr = hw_base + pos; 340 hw_base += runtime->buffer_size;
341 goto __delta; 341 if (hw_base >= runtime->boundary)
342 hw_base = 0;
343 new_hw_ptr = hw_base + pos;
344 goto __delta;
345 }
342 } 346 }
343 } 347 }
344 /* new_hw_ptr might be lower than old_hw_ptr in case when */ 348 /* new_hw_ptr might be lower than old_hw_ptr in case when */
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 134fc6c2e08d..e2e73895db12 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -864,6 +864,8 @@ static void snd_pcm_post_start(struct snd_pcm_substream *substream, int state)
864 struct snd_pcm_runtime *runtime = substream->runtime; 864 struct snd_pcm_runtime *runtime = substream->runtime;
865 snd_pcm_trigger_tstamp(substream); 865 snd_pcm_trigger_tstamp(substream);
866 runtime->hw_ptr_jiffies = jiffies; 866 runtime->hw_ptr_jiffies = jiffies;
867 runtime->hw_ptr_buffer_jiffies = (runtime->buffer_size * HZ) /
868 runtime->rate;
867 runtime->status->state = state; 869 runtime->status->state = state;
868 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && 870 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
869 runtime->silence_size > 0) 871 runtime->silence_size > 0)
diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig
index 480c38623da8..c8961165277c 100644
--- a/sound/drivers/Kconfig
+++ b/sound/drivers/Kconfig
@@ -74,6 +74,25 @@ config SND_DUMMY
74 To compile this driver as a module, choose M here: the module 74 To compile this driver as a module, choose M here: the module
75 will be called snd-dummy. 75 will be called snd-dummy.
76 76
77config SND_ALOOP
78 tristate "Generic loopback driver (PCM)"
79 select SND_PCM
80 help
81 Say 'Y' or 'M' to include support for the PCM loopback device.
82 This module returns played samples back to the user space using
83 the standard ALSA PCM device. The devices are routed 0->1 and
84 1->0, where first number is the playback PCM device and second
85 number is the capture device. Module creates two PCM devices and
86 configured number of substreams (see the pcm_substreams module
87 parameter).
88
89 The looback device allow time sychronization with an external
90 timing source using the time shift universal control (+-20%
91 of system time).
92
93 To compile this driver as a module, choose M here: the module
94 will be called snd-aloop.
95
77config SND_VIRMIDI 96config SND_VIRMIDI
78 tristate "Virtual MIDI soundcard" 97 tristate "Virtual MIDI soundcard"
79 depends on SND_SEQUENCER 98 depends on SND_SEQUENCER
diff --git a/sound/drivers/Makefile b/sound/drivers/Makefile
index d4a07f9ff2c7..1a8440c8b138 100644
--- a/sound/drivers/Makefile
+++ b/sound/drivers/Makefile
@@ -4,6 +4,7 @@
4# 4#
5 5
6snd-dummy-objs := dummy.o 6snd-dummy-objs := dummy.o
7snd-aloop-objs := aloop.o
7snd-mtpav-objs := mtpav.o 8snd-mtpav-objs := mtpav.o
8snd-mts64-objs := mts64.o 9snd-mts64-objs := mts64.o
9snd-portman2x4-objs := portman2x4.o 10snd-portman2x4-objs := portman2x4.o
@@ -13,6 +14,7 @@ snd-ml403-ac97cr-objs := ml403-ac97cr.o pcm-indirect2.o
13 14
14# Toplevel Module Dependency 15# Toplevel Module Dependency
15obj-$(CONFIG_SND_DUMMY) += snd-dummy.o 16obj-$(CONFIG_SND_DUMMY) += snd-dummy.o
17obj-$(CONFIG_SND_ALOOP) += snd-aloop.o
16obj-$(CONFIG_SND_VIRMIDI) += snd-virmidi.o 18obj-$(CONFIG_SND_VIRMIDI) += snd-virmidi.o
17obj-$(CONFIG_SND_SERIAL_U16550) += snd-serial-u16550.o 19obj-$(CONFIG_SND_SERIAL_U16550) += snd-serial-u16550.o
18obj-$(CONFIG_SND_MTPAV) += snd-mtpav.o 20obj-$(CONFIG_SND_MTPAV) += snd-mtpav.o
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c
new file mode 100644
index 000000000000..3123a15d23f6
--- /dev/null
+++ b/sound/drivers/aloop.c
@@ -0,0 +1,1055 @@
1/*
2 * Loopback soundcard
3 *
4 * Original code:
5 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
6 *
7 * More accurate positioning and full-duplex support:
8 * Copyright (c) Ahmet İnan <ainan at mathematik.uni-freiburg.de>
9 *
10 * Major (almost complete) rewrite:
11 * Copyright (c) by Takashi Iwai <tiwai@suse.de>
12 *
13 * A next major update in 2010 (separate timers for playback and capture):
14 * Copyright (c) Jaroslav Kysela <perex@perex.cz>
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 *
30 */
31
32#include <linux/init.h>
33#include <linux/jiffies.h>
34#include <linux/slab.h>
35#include <linux/time.h>
36#include <linux/wait.h>
37#include <linux/moduleparam.h>
38#include <linux/platform_device.h>
39#include <sound/core.h>
40#include <sound/control.h>
41#include <sound/pcm.h>
42#include <sound/initval.h>
43
44MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
45MODULE_DESCRIPTION("A loopback soundcard");
46MODULE_LICENSE("GPL");
47MODULE_SUPPORTED_DEVICE("{{ALSA,Loopback soundcard}}");
48
49#define MAX_PCM_SUBSTREAMS 8
50
51static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
52static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
53static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0};
54static int pcm_substreams[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8};
55static int pcm_notify[SNDRV_CARDS];
56
57module_param_array(index, int, NULL, 0444);
58MODULE_PARM_DESC(index, "Index value for loopback soundcard.");
59module_param_array(id, charp, NULL, 0444);
60MODULE_PARM_DESC(id, "ID string for loopback soundcard.");
61module_param_array(enable, bool, NULL, 0444);
62MODULE_PARM_DESC(enable, "Enable this loopback soundcard.");
63module_param_array(pcm_substreams, int, NULL, 0444);
64MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-8) for loopback driver.");
65module_param_array(pcm_notify, int, NULL, 0444);
66MODULE_PARM_DESC(pcm_notify, "Break capture when PCM format/rate/channels changes.");
67
68#define NO_PITCH 100000
69
70struct loopback_pcm;
71
72struct loopback_cable {
73 spinlock_t lock;
74 struct loopback_pcm *streams[2];
75 struct snd_pcm_hardware hw;
76 /* flags */
77 unsigned int valid;
78 unsigned int running;
79};
80
81struct loopback_setup {
82 unsigned int notify: 1;
83 unsigned int rate_shift;
84 unsigned int format;
85 unsigned int rate;
86 unsigned int channels;
87 struct snd_ctl_elem_id active_id;
88 struct snd_ctl_elem_id format_id;
89 struct snd_ctl_elem_id rate_id;
90 struct snd_ctl_elem_id channels_id;
91};
92
93struct loopback {
94 struct snd_card *card;
95 struct mutex cable_lock;
96 struct loopback_cable *cables[MAX_PCM_SUBSTREAMS][2];
97 struct snd_pcm *pcm[2];
98 struct loopback_setup setup[MAX_PCM_SUBSTREAMS][2];
99};
100
101struct loopback_pcm {
102 struct loopback *loopback;
103 struct snd_pcm_substream *substream;
104 struct loopback_cable *cable;
105 unsigned int pcm_buffer_size;
106 unsigned int buf_pos; /* position in buffer */
107 unsigned int silent_size;
108 /* PCM parameters */
109 unsigned int pcm_period_size;
110 unsigned int pcm_bps; /* bytes per second */
111 unsigned int pcm_salign; /* bytes per sample * channels */
112 unsigned int pcm_rate_shift; /* rate shift value */
113 /* flags */
114 unsigned int period_update_pending :1;
115 /* timer stuff */
116 unsigned int irq_pos; /* fractional IRQ position */
117 unsigned int period_size_frac;
118 unsigned long last_jiffies;
119 struct timer_list timer;
120};
121
122static struct platform_device *devices[SNDRV_CARDS];
123
124static inline unsigned int byte_pos(struct loopback_pcm *dpcm, unsigned int x)
125{
126 if (dpcm->pcm_rate_shift == NO_PITCH) {
127 x /= HZ;
128 } else {
129 x = div_u64(NO_PITCH * (unsigned long long)x,
130 HZ * (unsigned long long)dpcm->pcm_rate_shift);
131 }
132 return x - (x % dpcm->pcm_salign);
133}
134
135static inline unsigned int frac_pos(struct loopback_pcm *dpcm, unsigned int x)
136{
137 if (dpcm->pcm_rate_shift == NO_PITCH) { /* no pitch */
138 return x * HZ;
139 } else {
140 x = div_u64(dpcm->pcm_rate_shift * (unsigned long long)x * HZ,
141 NO_PITCH);
142 }
143 return x;
144}
145
146static inline struct loopback_setup *get_setup(struct loopback_pcm *dpcm)
147{
148 int device = dpcm->substream->pstr->pcm->device;
149
150 if (dpcm->substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
151 device ^= 1;
152 return &dpcm->loopback->setup[dpcm->substream->number][device];
153}
154
155static inline unsigned int get_notify(struct loopback_pcm *dpcm)
156{
157 return get_setup(dpcm)->notify;
158}
159
160static inline unsigned int get_rate_shift(struct loopback_pcm *dpcm)
161{
162 return get_setup(dpcm)->rate_shift;
163}
164
165static void loopback_timer_start(struct loopback_pcm *dpcm)
166{
167 unsigned long tick;
168 unsigned int rate_shift = get_rate_shift(dpcm);
169
170 if (rate_shift != dpcm->pcm_rate_shift) {
171 dpcm->pcm_rate_shift = rate_shift;
172 dpcm->period_size_frac = frac_pos(dpcm, dpcm->pcm_period_size);
173 }
174 tick = dpcm->period_size_frac - dpcm->irq_pos;
175 tick = (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps;
176 dpcm->timer.expires = jiffies + tick;
177 add_timer(&dpcm->timer);
178}
179
180static inline void loopback_timer_stop(struct loopback_pcm *dpcm)
181{
182 del_timer(&dpcm->timer);
183}
184
185#define CABLE_VALID_PLAYBACK (1 << SNDRV_PCM_STREAM_PLAYBACK)
186#define CABLE_VALID_CAPTURE (1 << SNDRV_PCM_STREAM_CAPTURE)
187#define CABLE_VALID_BOTH (CABLE_VALID_PLAYBACK|CABLE_VALID_CAPTURE)
188
189static int loopback_check_format(struct loopback_cable *cable, int stream)
190{
191 struct snd_pcm_runtime *runtime;
192 struct loopback_setup *setup;
193 struct snd_card *card;
194 int check;
195
196 if (cable->valid != CABLE_VALID_BOTH) {
197 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
198 goto __notify;
199 return 0;
200 }
201 runtime = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]->
202 substream->runtime;
203 check = cable->hw.formats != (1ULL << runtime->format) ||
204 cable->hw.rate_min != runtime->rate ||
205 cable->hw.rate_max != runtime->rate ||
206 cable->hw.channels_min != runtime->channels ||
207 cable->hw.channels_max != runtime->channels;
208 if (!check)
209 return 0;
210 if (stream == SNDRV_PCM_STREAM_CAPTURE) {
211 return -EIO;
212 } else {
213 snd_pcm_stop(cable->streams[SNDRV_PCM_STREAM_CAPTURE]->
214 substream, SNDRV_PCM_STATE_DRAINING);
215 __notify:
216 runtime = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]->
217 substream->runtime;
218 setup = get_setup(cable->streams[SNDRV_PCM_STREAM_PLAYBACK]);
219 card = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]->loopback->card;
220 if (setup->format != runtime->format) {
221 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
222 &setup->format_id);
223 setup->format = runtime->format;
224 }
225 if (setup->rate != runtime->rate) {
226 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
227 &setup->rate_id);
228 setup->rate = runtime->rate;
229 }
230 if (setup->channels != runtime->channels) {
231 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
232 &setup->channels_id);
233 setup->channels = runtime->channels;
234 }
235 }
236 return 0;
237}
238
239static void loopback_active_notify(struct loopback_pcm *dpcm)
240{
241 snd_ctl_notify(dpcm->loopback->card,
242 SNDRV_CTL_EVENT_MASK_VALUE,
243 &get_setup(dpcm)->active_id);
244}
245
246static int loopback_trigger(struct snd_pcm_substream *substream, int cmd)
247{
248 struct snd_pcm_runtime *runtime = substream->runtime;
249 struct loopback_pcm *dpcm = runtime->private_data;
250 struct loopback_cable *cable = dpcm->cable;
251 int err;
252
253 switch (cmd) {
254 case SNDRV_PCM_TRIGGER_START:
255 err = loopback_check_format(cable, substream->stream);
256 if (err < 0)
257 return err;
258 dpcm->last_jiffies = jiffies;
259 dpcm->pcm_rate_shift = 0;
260 loopback_timer_start(dpcm);
261 cable->running |= (1 << substream->stream);
262 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
263 loopback_active_notify(dpcm);
264 break;
265 case SNDRV_PCM_TRIGGER_STOP:
266 cable->running &= ~(1 << substream->stream);
267 loopback_timer_stop(dpcm);
268 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
269 loopback_active_notify(dpcm);
270 break;
271 default:
272 return -EINVAL;
273 }
274 return 0;
275}
276
277static int loopback_prepare(struct snd_pcm_substream *substream)
278{
279 struct snd_pcm_runtime *runtime = substream->runtime;
280 struct loopback_pcm *dpcm = runtime->private_data;
281 struct loopback_cable *cable = dpcm->cable;
282 unsigned int bps, salign;
283
284 salign = (snd_pcm_format_width(runtime->format) *
285 runtime->channels) / 8;
286 bps = salign * runtime->rate;
287 if (bps <= 0 || salign <= 0)
288 return -EINVAL;
289
290 dpcm->buf_pos = 0;
291 dpcm->pcm_buffer_size = frames_to_bytes(runtime, runtime->buffer_size);
292 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
293 /* clear capture buffer */
294 dpcm->silent_size = dpcm->pcm_buffer_size;
295 snd_pcm_format_set_silence(runtime->format, runtime->dma_area,
296 runtime->buffer_size * runtime->channels);
297 }
298
299 dpcm->irq_pos = 0;
300 dpcm->period_update_pending = 0;
301 dpcm->pcm_bps = bps;
302 dpcm->pcm_salign = salign;
303 dpcm->pcm_period_size = frames_to_bytes(runtime, runtime->period_size);
304
305 mutex_lock(&dpcm->loopback->cable_lock);
306 if (!(cable->valid & ~(1 << substream->stream))) {
307 cable->hw.formats = (1ULL << runtime->format);
308 cable->hw.rate_min = runtime->rate;
309 cable->hw.rate_max = runtime->rate;
310 cable->hw.channels_min = runtime->channels;
311 cable->hw.channels_max = runtime->channels;
312 }
313 cable->valid |= 1 << substream->stream;
314 mutex_unlock(&dpcm->loopback->cable_lock);
315
316 return 0;
317}
318
319static void clear_capture_buf(struct loopback_pcm *dpcm, unsigned int bytes)
320{
321 struct snd_pcm_runtime *runtime = dpcm->substream->runtime;
322 char *dst = runtime->dma_area;
323 unsigned int dst_off = dpcm->buf_pos;
324
325 if (dpcm->silent_size >= dpcm->pcm_buffer_size)
326 return;
327 if (dpcm->silent_size + bytes > dpcm->pcm_buffer_size)
328 bytes = dpcm->pcm_buffer_size - dpcm->silent_size;
329
330 for (;;) {
331 unsigned int size = bytes;
332 if (dst_off + size > dpcm->pcm_buffer_size)
333 size = dpcm->pcm_buffer_size - dst_off;
334 snd_pcm_format_set_silence(runtime->format, dst + dst_off,
335 bytes_to_frames(runtime, size) *
336 runtime->channels);
337 dpcm->silent_size += size;
338 bytes -= size;
339 if (!bytes)
340 break;
341 dst_off = 0;
342 }
343}
344
345static void copy_play_buf(struct loopback_pcm *play,
346 struct loopback_pcm *capt,
347 unsigned int bytes)
348{
349 struct snd_pcm_runtime *runtime = play->substream->runtime;
350 char *src = play->substream->runtime->dma_area;
351 char *dst = capt->substream->runtime->dma_area;
352 unsigned int src_off = play->buf_pos;
353 unsigned int dst_off = capt->buf_pos;
354 unsigned int clear_bytes = 0;
355
356 /* check if playback is draining, trim the capture copy size
357 * when our pointer is at the end of playback ring buffer */
358 if (runtime->status->state == SNDRV_PCM_STATE_DRAINING &&
359 snd_pcm_playback_hw_avail(runtime) < runtime->buffer_size) {
360 snd_pcm_uframes_t appl_ptr, appl_ptr1, diff;
361 appl_ptr = appl_ptr1 = runtime->control->appl_ptr;
362 appl_ptr1 -= appl_ptr1 % runtime->buffer_size;
363 appl_ptr1 += play->buf_pos / play->pcm_salign;
364 if (appl_ptr < appl_ptr1)
365 appl_ptr1 -= runtime->buffer_size;
366 diff = (appl_ptr - appl_ptr1) * play->pcm_salign;
367 if (diff < bytes) {
368 clear_bytes = bytes - diff;
369 bytes = diff;
370 }
371 }
372
373 for (;;) {
374 unsigned int size = bytes;
375 if (src_off + size > play->pcm_buffer_size)
376 size = play->pcm_buffer_size - src_off;
377 if (dst_off + size > capt->pcm_buffer_size)
378 size = capt->pcm_buffer_size - dst_off;
379 memcpy(dst + dst_off, src + src_off, size);
380 capt->silent_size = 0;
381 bytes -= size;
382 if (!bytes)
383 break;
384 src_off = (src_off + size) % play->pcm_buffer_size;
385 dst_off = (dst_off + size) % capt->pcm_buffer_size;
386 }
387
388 if (clear_bytes > 0)
389 clear_capture_buf(capt, clear_bytes);
390}
391
392#define BYTEPOS_UPDATE_POSONLY 0
393#define BYTEPOS_UPDATE_CLEAR 1
394#define BYTEPOS_UPDATE_COPY 2
395
396static void loopback_bytepos_update(struct loopback_pcm *dpcm,
397 unsigned int delta,
398 unsigned int cmd)
399{
400 unsigned int count;
401 unsigned long last_pos;
402
403 last_pos = byte_pos(dpcm, dpcm->irq_pos);
404 dpcm->irq_pos += delta * dpcm->pcm_bps;
405 count = byte_pos(dpcm, dpcm->irq_pos) - last_pos;
406 if (!count)
407 return;
408 if (cmd == BYTEPOS_UPDATE_CLEAR)
409 clear_capture_buf(dpcm, count);
410 else if (cmd == BYTEPOS_UPDATE_COPY)
411 copy_play_buf(dpcm->cable->streams[SNDRV_PCM_STREAM_PLAYBACK],
412 dpcm->cable->streams[SNDRV_PCM_STREAM_CAPTURE],
413 count);
414 dpcm->buf_pos += count;
415 dpcm->buf_pos %= dpcm->pcm_buffer_size;
416 if (dpcm->irq_pos >= dpcm->period_size_frac) {
417 dpcm->irq_pos %= dpcm->period_size_frac;
418 dpcm->period_update_pending = 1;
419 }
420}
421
422static void loopback_pos_update(struct loopback_cable *cable)
423{
424 struct loopback_pcm *dpcm_play =
425 cable->streams[SNDRV_PCM_STREAM_PLAYBACK];
426 struct loopback_pcm *dpcm_capt =
427 cable->streams[SNDRV_PCM_STREAM_CAPTURE];
428 unsigned long delta_play = 0, delta_capt = 0;
429
430 spin_lock(&cable->lock);
431 if (cable->running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) {
432 delta_play = jiffies - dpcm_play->last_jiffies;
433 dpcm_play->last_jiffies += delta_play;
434 }
435
436 if (cable->running & (1 << SNDRV_PCM_STREAM_CAPTURE)) {
437 delta_capt = jiffies - dpcm_capt->last_jiffies;
438 dpcm_capt->last_jiffies += delta_capt;
439 }
440
441 if (delta_play == 0 && delta_capt == 0) {
442 spin_unlock(&cable->lock);
443 return;
444 }
445
446 if (delta_play > delta_capt) {
447 loopback_bytepos_update(dpcm_play, delta_play - delta_capt,
448 BYTEPOS_UPDATE_POSONLY);
449 delta_play = delta_capt;
450 } else if (delta_play < delta_capt) {
451 loopback_bytepos_update(dpcm_capt, delta_capt - delta_play,
452 BYTEPOS_UPDATE_CLEAR);
453 delta_capt = delta_play;
454 }
455
456 if (delta_play == 0 && delta_capt == 0) {
457 spin_unlock(&cable->lock);
458 return;
459 }
460 /* note delta_capt == delta_play at this moment */
461 loopback_bytepos_update(dpcm_capt, delta_capt, BYTEPOS_UPDATE_COPY);
462 loopback_bytepos_update(dpcm_play, delta_play, BYTEPOS_UPDATE_POSONLY);
463 spin_unlock(&cable->lock);
464}
465
466static void loopback_timer_function(unsigned long data)
467{
468 struct loopback_pcm *dpcm = (struct loopback_pcm *)data;
469 int stream;
470
471 loopback_pos_update(dpcm->cable);
472 stream = dpcm->substream->stream;
473 if (dpcm->cable->running & (1 << stream))
474 loopback_timer_start(dpcm);
475 if (dpcm->period_update_pending) {
476 dpcm->period_update_pending = 0;
477 if (dpcm->cable->running & (1 << stream))
478 snd_pcm_period_elapsed(dpcm->substream);
479 }
480}
481
482static snd_pcm_uframes_t loopback_pointer(struct snd_pcm_substream *substream)
483{
484 struct snd_pcm_runtime *runtime = substream->runtime;
485 struct loopback_pcm *dpcm = runtime->private_data;
486
487 loopback_pos_update(dpcm->cable);
488 return bytes_to_frames(runtime, dpcm->buf_pos);
489}
490
491static struct snd_pcm_hardware loopback_pcm_hardware =
492{
493 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP |
494 SNDRV_PCM_INFO_MMAP_VALID),
495 .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
496 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE |
497 SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE),
498 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_192000,
499 .rate_min = 8000,
500 .rate_max = 192000,
501 .channels_min = 1,
502 .channels_max = 32,
503 .buffer_bytes_max = 2 * 1024 * 1024,
504 .period_bytes_min = 64,
505 .period_bytes_max = 2 * 1024 * 1024,
506 .periods_min = 1,
507 .periods_max = 1024,
508 .fifo_size = 0,
509};
510
511static void loopback_runtime_free(struct snd_pcm_runtime *runtime)
512{
513 struct loopback_pcm *dpcm = runtime->private_data;
514 kfree(dpcm);
515}
516
517static int loopback_hw_params(struct snd_pcm_substream *substream,
518 struct snd_pcm_hw_params *params)
519{
520 return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
521}
522
523static int loopback_hw_free(struct snd_pcm_substream *substream)
524{
525 struct snd_pcm_runtime *runtime = substream->runtime;
526 struct loopback_pcm *dpcm = runtime->private_data;
527 struct loopback_cable *cable = dpcm->cable;
528
529 mutex_lock(&dpcm->loopback->cable_lock);
530 cable->valid &= ~(1 << substream->stream);
531 mutex_unlock(&dpcm->loopback->cable_lock);
532 return snd_pcm_lib_free_pages(substream);
533}
534
535static unsigned int get_cable_index(struct snd_pcm_substream *substream)
536{
537 if (!substream->pcm->device)
538 return substream->stream;
539 else
540 return !substream->stream;
541}
542
543static int loopback_open(struct snd_pcm_substream *substream)
544{
545 struct snd_pcm_runtime *runtime = substream->runtime;
546 struct loopback *loopback = substream->private_data;
547 struct loopback_pcm *dpcm;
548 struct loopback_cable *cable;
549 int err = 0;
550 int dev = get_cable_index(substream);
551
552 mutex_lock(&loopback->cable_lock);
553 dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);
554 if (!dpcm) {
555 err = -ENOMEM;
556 goto unlock;
557 }
558 dpcm->loopback = loopback;
559 dpcm->substream = substream;
560 setup_timer(&dpcm->timer, loopback_timer_function,
561 (unsigned long)dpcm);
562
563 cable = loopback->cables[substream->number][dev];
564 if (!cable) {
565 cable = kzalloc(sizeof(*cable), GFP_KERNEL);
566 if (!cable) {
567 kfree(dpcm);
568 err = -ENOMEM;
569 goto unlock;
570 }
571 spin_lock_init(&cable->lock);
572 cable->hw = loopback_pcm_hardware;
573 loopback->cables[substream->number][dev] = cable;
574 }
575 dpcm->cable = cable;
576 cable->streams[substream->stream] = dpcm;
577
578 snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
579
580 runtime->private_data = dpcm;
581 runtime->private_free = loopback_runtime_free;
582 if (get_notify(dpcm) &&
583 substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
584 runtime->hw = loopback_pcm_hardware;
585 } else {
586 runtime->hw = cable->hw;
587 }
588 unlock:
589 mutex_unlock(&loopback->cable_lock);
590 return err;
591}
592
593static int loopback_close(struct snd_pcm_substream *substream)
594{
595 struct loopback *loopback = substream->private_data;
596 struct loopback_pcm *dpcm = substream->runtime->private_data;
597 struct loopback_cable *cable;
598 int dev = get_cable_index(substream);
599
600 loopback_timer_stop(dpcm);
601 mutex_lock(&loopback->cable_lock);
602 cable = loopback->cables[substream->number][dev];
603 if (cable->streams[!substream->stream]) {
604 /* other stream is still alive */
605 cable->streams[substream->stream] = NULL;
606 } else {
607 /* free the cable */
608 loopback->cables[substream->number][dev] = NULL;
609 kfree(cable);
610 }
611 mutex_unlock(&loopback->cable_lock);
612 return 0;
613}
614
615static struct snd_pcm_ops loopback_playback_ops = {
616 .open = loopback_open,
617 .close = loopback_close,
618 .ioctl = snd_pcm_lib_ioctl,
619 .hw_params = loopback_hw_params,
620 .hw_free = loopback_hw_free,
621 .prepare = loopback_prepare,
622 .trigger = loopback_trigger,
623 .pointer = loopback_pointer,
624};
625
626static struct snd_pcm_ops loopback_capture_ops = {
627 .open = loopback_open,
628 .close = loopback_close,
629 .ioctl = snd_pcm_lib_ioctl,
630 .hw_params = loopback_hw_params,
631 .hw_free = loopback_hw_free,
632 .prepare = loopback_prepare,
633 .trigger = loopback_trigger,
634 .pointer = loopback_pointer,
635};
636
637static int __devinit loopback_pcm_new(struct loopback *loopback,
638 int device, int substreams)
639{
640 struct snd_pcm *pcm;
641 int err;
642
643 err = snd_pcm_new(loopback->card, "Loopback PCM", device,
644 substreams, substreams, &pcm);
645 if (err < 0)
646 return err;
647 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &loopback_playback_ops);
648 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &loopback_capture_ops);
649
650 pcm->private_data = loopback;
651 pcm->info_flags = 0;
652 strcpy(pcm->name, "Loopback PCM");
653
654 loopback->pcm[device] = pcm;
655
656 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
657 snd_dma_continuous_data(GFP_KERNEL),
658 0, 2 * 1024 * 1024);
659 return 0;
660}
661
662static int loopback_rate_shift_info(struct snd_kcontrol *kcontrol,
663 struct snd_ctl_elem_info *uinfo)
664{
665 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
666 uinfo->count = 1;
667 uinfo->value.integer.min = 80000;
668 uinfo->value.integer.max = 120000;
669 uinfo->value.integer.step = 1;
670 return 0;
671}
672
673static int loopback_rate_shift_get(struct snd_kcontrol *kcontrol,
674 struct snd_ctl_elem_value *ucontrol)
675{
676 struct loopback *loopback = snd_kcontrol_chip(kcontrol);
677
678 ucontrol->value.integer.value[0] =
679 loopback->setup[kcontrol->id.subdevice]
680 [kcontrol->id.device].rate_shift;
681 return 0;
682}
683
684static int loopback_rate_shift_put(struct snd_kcontrol *kcontrol,
685 struct snd_ctl_elem_value *ucontrol)
686{
687 struct loopback *loopback = snd_kcontrol_chip(kcontrol);
688 unsigned int val;
689 int change = 0;
690
691 val = ucontrol->value.integer.value[0];
692 if (val < 80000)
693 val = 80000;
694 if (val > 120000)
695 val = 120000;
696 mutex_lock(&loopback->cable_lock);
697 if (val != loopback->setup[kcontrol->id.subdevice]
698 [kcontrol->id.device].rate_shift) {
699 loopback->setup[kcontrol->id.subdevice]
700 [kcontrol->id.device].rate_shift = val;
701 change = 1;
702 }
703 mutex_unlock(&loopback->cable_lock);
704 return change;
705}
706
707static int loopback_notify_get(struct snd_kcontrol *kcontrol,
708 struct snd_ctl_elem_value *ucontrol)
709{
710 struct loopback *loopback = snd_kcontrol_chip(kcontrol);
711
712 ucontrol->value.integer.value[0] =
713 loopback->setup[kcontrol->id.subdevice]
714 [kcontrol->id.device].notify;
715 return 0;
716}
717
718static int loopback_notify_put(struct snd_kcontrol *kcontrol,
719 struct snd_ctl_elem_value *ucontrol)
720{
721 struct loopback *loopback = snd_kcontrol_chip(kcontrol);
722 unsigned int val;
723 int change = 0;
724
725 val = ucontrol->value.integer.value[0] ? 1 : 0;
726 if (val != loopback->setup[kcontrol->id.subdevice]
727 [kcontrol->id.device].notify) {
728 loopback->setup[kcontrol->id.subdevice]
729 [kcontrol->id.device].notify = val;
730 change = 1;
731 }
732 return change;
733}
734
735static int loopback_active_get(struct snd_kcontrol *kcontrol,
736 struct snd_ctl_elem_value *ucontrol)
737{
738 struct loopback *loopback = snd_kcontrol_chip(kcontrol);
739 struct loopback_cable *cable = loopback->cables
740 [kcontrol->id.subdevice][kcontrol->id.device];
741 unsigned int val = 0;
742
743 if (cable != NULL)
744 val = (cable->running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) ?
745 1 : 0;
746 ucontrol->value.integer.value[0] = val;
747 return 0;
748}
749
750static int loopback_format_info(struct snd_kcontrol *kcontrol,
751 struct snd_ctl_elem_info *uinfo)
752{
753 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
754 uinfo->count = 1;
755 uinfo->value.integer.min = 0;
756 uinfo->value.integer.max = SNDRV_PCM_FORMAT_LAST;
757 uinfo->value.integer.step = 1;
758 return 0;
759}
760
761static int loopback_format_get(struct snd_kcontrol *kcontrol,
762 struct snd_ctl_elem_value *ucontrol)
763{
764 struct loopback *loopback = snd_kcontrol_chip(kcontrol);
765
766 ucontrol->value.integer.value[0] =
767 loopback->setup[kcontrol->id.subdevice]
768 [kcontrol->id.device].format;
769 return 0;
770}
771
772static int loopback_rate_info(struct snd_kcontrol *kcontrol,
773 struct snd_ctl_elem_info *uinfo)
774{
775 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
776 uinfo->count = 1;
777 uinfo->value.integer.min = 0;
778 uinfo->value.integer.max = 192000;
779 uinfo->value.integer.step = 1;
780 return 0;
781}
782
783static int loopback_rate_get(struct snd_kcontrol *kcontrol,
784 struct snd_ctl_elem_value *ucontrol)
785{
786 struct loopback *loopback = snd_kcontrol_chip(kcontrol);
787
788 ucontrol->value.integer.value[0] =
789 loopback->setup[kcontrol->id.subdevice]
790 [kcontrol->id.device].rate;
791 return 0;
792}
793
794static int loopback_channels_info(struct snd_kcontrol *kcontrol,
795 struct snd_ctl_elem_info *uinfo)
796{
797 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
798 uinfo->count = 1;
799 uinfo->value.integer.min = 1;
800 uinfo->value.integer.max = 1024;
801 uinfo->value.integer.step = 1;
802 return 0;
803}
804
805static int loopback_channels_get(struct snd_kcontrol *kcontrol,
806 struct snd_ctl_elem_value *ucontrol)
807{
808 struct loopback *loopback = snd_kcontrol_chip(kcontrol);
809
810 ucontrol->value.integer.value[0] =
811 loopback->setup[kcontrol->id.subdevice]
812 [kcontrol->id.device].rate;
813 return 0;
814}
815
816static struct snd_kcontrol_new loopback_controls[] __devinitdata = {
817{
818 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
819 .name = "PCM Rate Shift 100000",
820 .info = loopback_rate_shift_info,
821 .get = loopback_rate_shift_get,
822 .put = loopback_rate_shift_put,
823},
824{
825 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
826 .name = "PCM Notify",
827 .info = snd_ctl_boolean_mono_info,
828 .get = loopback_notify_get,
829 .put = loopback_notify_put,
830},
831#define ACTIVE_IDX 2
832{
833 .access = SNDRV_CTL_ELEM_ACCESS_READ,
834 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
835 .name = "PCM Slave Active",
836 .info = snd_ctl_boolean_mono_info,
837 .get = loopback_active_get,
838},
839#define FORMAT_IDX 3
840{
841 .access = SNDRV_CTL_ELEM_ACCESS_READ,
842 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
843 .name = "PCM Slave Format",
844 .info = loopback_format_info,
845 .get = loopback_format_get
846},
847#define RATE_IDX 4
848{
849 .access = SNDRV_CTL_ELEM_ACCESS_READ,
850 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
851 .name = "PCM Slave Rate",
852 .info = loopback_rate_info,
853 .get = loopback_rate_get
854},
855#define CHANNELS_IDX 5
856{
857 .access = SNDRV_CTL_ELEM_ACCESS_READ,
858 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
859 .name = "PCM Slave Channels",
860 .info = loopback_channels_info,
861 .get = loopback_channels_get
862}
863};
864
865static int __devinit loopback_mixer_new(struct loopback *loopback, int notify)
866{
867 struct snd_card *card = loopback->card;
868 struct snd_pcm *pcm;
869 struct snd_kcontrol *kctl;
870 struct loopback_setup *setup;
871 int err, dev, substr, substr_count, idx;
872
873 strcpy(card->mixername, "Loopback Mixer");
874 for (dev = 0; dev < 2; dev++) {
875 pcm = loopback->pcm[dev];
876 substr_count =
877 pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_count;
878 for (substr = 0; substr < substr_count; substr++) {
879 setup = &loopback->setup[substr][dev];
880 setup->notify = notify;
881 setup->rate_shift = NO_PITCH;
882 setup->format = SNDRV_PCM_FORMAT_S16_LE;
883 setup->rate = 48000;
884 setup->channels = 2;
885 for (idx = 0; idx < ARRAY_SIZE(loopback_controls);
886 idx++) {
887 kctl = snd_ctl_new1(&loopback_controls[idx],
888 loopback);
889 if (!kctl)
890 return -ENOMEM;
891 kctl->id.device = dev;
892 kctl->id.subdevice = substr;
893 switch (idx) {
894 case ACTIVE_IDX:
895 setup->active_id = kctl->id;
896 break;
897 case FORMAT_IDX:
898 setup->format_id = kctl->id;
899 break;
900 case RATE_IDX:
901 setup->rate_id = kctl->id;
902 break;
903 case CHANNELS_IDX:
904 setup->channels_id = kctl->id;
905 break;
906 default:
907 break;
908 }
909 err = snd_ctl_add(card, kctl);
910 if (err < 0)
911 return err;
912 }
913 }
914 }
915 return 0;
916}
917
918static int __devinit loopback_probe(struct platform_device *devptr)
919{
920 struct snd_card *card;
921 struct loopback *loopback;
922 int dev = devptr->id;
923 int err;
924
925 err = snd_card_create(index[dev], id[dev], THIS_MODULE,
926 sizeof(struct loopback), &card);
927 if (err < 0)
928 return err;
929 loopback = card->private_data;
930
931 if (pcm_substreams[dev] < 1)
932 pcm_substreams[dev] = 1;
933 if (pcm_substreams[dev] > MAX_PCM_SUBSTREAMS)
934 pcm_substreams[dev] = MAX_PCM_SUBSTREAMS;
935
936 loopback->card = card;
937 mutex_init(&loopback->cable_lock);
938
939 err = loopback_pcm_new(loopback, 0, pcm_substreams[dev]);
940 if (err < 0)
941 goto __nodev;
942 err = loopback_pcm_new(loopback, 1, pcm_substreams[dev]);
943 if (err < 0)
944 goto __nodev;
945 err = loopback_mixer_new(loopback, pcm_notify[dev] ? 1 : 0);
946 if (err < 0)
947 goto __nodev;
948 strcpy(card->driver, "Loopback");
949 strcpy(card->shortname, "Loopback");
950 sprintf(card->longname, "Loopback %i", dev + 1);
951 err = snd_card_register(card);
952 if (!err) {
953 platform_set_drvdata(devptr, card);
954 return 0;
955 }
956 __nodev:
957 snd_card_free(card);
958 return err;
959}
960
961static int __devexit loopback_remove(struct platform_device *devptr)
962{
963 snd_card_free(platform_get_drvdata(devptr));
964 platform_set_drvdata(devptr, NULL);
965 return 0;
966}
967
968#ifdef CONFIG_PM
969static int loopback_suspend(struct platform_device *pdev,
970 pm_message_t state)
971{
972 struct snd_card *card = platform_get_drvdata(pdev);
973 struct loopback *loopback = card->private_data;
974
975 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
976
977 snd_pcm_suspend_all(loopback->pcm[0]);
978 snd_pcm_suspend_all(loopback->pcm[1]);
979 return 0;
980}
981
982static int loopback_resume(struct platform_device *pdev)
983{
984 struct snd_card *card = platform_get_drvdata(pdev);
985
986 snd_power_change_state(card, SNDRV_CTL_POWER_D0);
987 return 0;
988}
989#endif
990
991#define SND_LOOPBACK_DRIVER "snd_aloop"
992
993static struct platform_driver loopback_driver = {
994 .probe = loopback_probe,
995 .remove = __devexit_p(loopback_remove),
996#ifdef CONFIG_PM
997 .suspend = loopback_suspend,
998 .resume = loopback_resume,
999#endif
1000 .driver = {
1001 .name = SND_LOOPBACK_DRIVER
1002 },
1003};
1004
1005static void loopback_unregister_all(void)
1006{
1007 int i;
1008
1009 for (i = 0; i < ARRAY_SIZE(devices); ++i)
1010 platform_device_unregister(devices[i]);
1011 platform_driver_unregister(&loopback_driver);
1012}
1013
1014static int __init alsa_card_loopback_init(void)
1015{
1016 int i, err, cards;
1017
1018 err = platform_driver_register(&loopback_driver);
1019 if (err < 0)
1020 return err;
1021
1022
1023 cards = 0;
1024 for (i = 0; i < SNDRV_CARDS; i++) {
1025 struct platform_device *device;
1026 if (!enable[i])
1027 continue;
1028 device = platform_device_register_simple(SND_LOOPBACK_DRIVER,
1029 i, NULL, 0);
1030 if (IS_ERR(device))
1031 continue;
1032 if (!platform_get_drvdata(device)) {
1033 platform_device_unregister(device);
1034 continue;
1035 }
1036 devices[i] = device;
1037 cards++;
1038 }
1039 if (!cards) {
1040#ifdef MODULE
1041 printk(KERN_ERR "aloop: No loopback enabled\n");
1042#endif
1043 loopback_unregister_all();
1044 return -ENODEV;
1045 }
1046 return 0;
1047}
1048
1049static void __exit alsa_card_loopback_exit(void)
1050{
1051 loopback_unregister_all();
1052}
1053
1054module_init(alsa_card_loopback_init)
1055module_exit(alsa_card_loopback_exit)
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index c6990c680796..52064cfa91f3 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -77,6 +77,32 @@ config SND_ALS100
77 To compile this driver as a module, choose M here: the module 77 To compile this driver as a module, choose M here: the module
78 will be called snd-als100. 78 will be called snd-als100.
79 79
80config SND_AZT1605
81 tristate "Aztech AZT1605 Driver"
82 depends on SND
83 select SND_WSS_LIB
84 select SND_MPU401_UART
85 select SND_OPL3_LIB
86 help
87 Say Y here to include support for Aztech Sound Galaxy cards
88 based on the AZT1605 chipset.
89
90 To compile this driver as a module, choose M here: the module
91 will be called snd-azt1605.
92
93config SND_AZT2316
94 tristate "Aztech AZT2316 Driver"
95 depends on SND
96 select SND_WSS_LIB
97 select SND_MPU401_UART
98 select SND_OPL3_LIB
99 help
100 Say Y here to include support for Aztech Sound Galaxy cards
101 based on the AZT2316 chipset.
102
103 To compile this driver as a module, choose M here: the module
104 will be called snd-azt2316.
105
80config SND_AZT2320 106config SND_AZT2320
81 tristate "Aztech Systems AZT2320" 107 tristate "Aztech Systems AZT2320"
82 depends on PNP 108 depends on PNP
@@ -351,16 +377,6 @@ config SND_SB16_CSP
351 coprocessor can do variable tasks like various compression and 377 coprocessor can do variable tasks like various compression and
352 decompression algorithms. 378 decompression algorithms.
353 379
354config SND_SGALAXY
355 tristate "Aztech Sound Galaxy"
356 select SND_WSS_LIB
357 help
358 Say Y here to include support for Aztech Sound Galaxy
359 soundcards.
360
361 To compile this driver as a module, choose M here: the module
362 will be called snd-sgalaxy.
363
364config SND_SSCAPE 380config SND_SSCAPE
365 tristate "Ensoniq SoundScape driver" 381 tristate "Ensoniq SoundScape driver"
366 select SND_MPU401_UART 382 select SND_MPU401_UART
diff --git a/sound/isa/Makefile b/sound/isa/Makefile
index c73d30c4f462..8d781e419e2e 100644
--- a/sound/isa/Makefile
+++ b/sound/isa/Makefile
@@ -10,7 +10,6 @@ snd-cmi8330-objs := cmi8330.o
10snd-es18xx-objs := es18xx.o 10snd-es18xx-objs := es18xx.o
11snd-opl3sa2-objs := opl3sa2.o 11snd-opl3sa2-objs := opl3sa2.o
12snd-sc6000-objs := sc6000.o 12snd-sc6000-objs := sc6000.o
13snd-sgalaxy-objs := sgalaxy.o
14snd-sscape-objs := sscape.o 13snd-sscape-objs := sscape.o
15 14
16# Toplevel Module Dependency 15# Toplevel Module Dependency
@@ -21,8 +20,7 @@ obj-$(CONFIG_SND_CMI8330) += snd-cmi8330.o
21obj-$(CONFIG_SND_ES18XX) += snd-es18xx.o 20obj-$(CONFIG_SND_ES18XX) += snd-es18xx.o
22obj-$(CONFIG_SND_OPL3SA2) += snd-opl3sa2.o 21obj-$(CONFIG_SND_OPL3SA2) += snd-opl3sa2.o
23obj-$(CONFIG_SND_SC6000) += snd-sc6000.o 22obj-$(CONFIG_SND_SC6000) += snd-sc6000.o
24obj-$(CONFIG_SND_SGALAXY) += snd-sgalaxy.o
25obj-$(CONFIG_SND_SSCAPE) += snd-sscape.o 23obj-$(CONFIG_SND_SSCAPE) += snd-sscape.o
26 24
27obj-$(CONFIG_SND) += ad1816a/ ad1848/ cs423x/ es1688/ gus/ msnd/ opti9xx/ \ 25obj-$(CONFIG_SND) += ad1816a/ ad1848/ cs423x/ es1688/ galaxy/ gus/ msnd/ opti9xx/ \
28 sb/ wavefront/ wss/ 26 sb/ wavefront/ wss/
diff --git a/sound/isa/galaxy/Makefile b/sound/isa/galaxy/Makefile
new file mode 100644
index 000000000000..e307066d4315
--- /dev/null
+++ b/sound/isa/galaxy/Makefile
@@ -0,0 +1,10 @@
1#
2# Makefile for ALSA
3# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
4#
5
6snd-azt1605-objs := azt1605.o
7snd-azt2316-objs := azt2316.o
8
9obj-$(CONFIG_SND_AZT1605) += snd-azt1605.o
10obj-$(CONFIG_SND_AZT2316) += snd-azt2316.o
diff --git a/sound/isa/galaxy/azt1605.c b/sound/isa/galaxy/azt1605.c
new file mode 100644
index 000000000000..9a97643cb713
--- /dev/null
+++ b/sound/isa/galaxy/azt1605.c
@@ -0,0 +1,91 @@
1/*
2 * Aztech AZT1605 Driver
3 * Copyright (C) 2007,2010 Rene Herman
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, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20#define AZT1605
21
22#define CRD_NAME "Aztech AZT1605"
23#define DRV_NAME "AZT1605"
24#define DEV_NAME "azt1605"
25
26#define GALAXY_DSP_MAJOR 2
27#define GALAXY_DSP_MINOR 1
28
29#define GALAXY_CONFIG_SIZE 3
30
31/*
32 * 24-bit config register
33 */
34
35#define GALAXY_CONFIG_SBA_220 (0 << 0)
36#define GALAXY_CONFIG_SBA_240 (1 << 0)
37#define GALAXY_CONFIG_SBA_260 (2 << 0)
38#define GALAXY_CONFIG_SBA_280 (3 << 0)
39#define GALAXY_CONFIG_SBA_MASK GALAXY_CONFIG_SBA_280
40
41#define GALAXY_CONFIG_MPUA_300 (0 << 2)
42#define GALAXY_CONFIG_MPUA_330 (1 << 2)
43
44#define GALAXY_CONFIG_MPU_ENABLE (1 << 3)
45
46#define GALAXY_CONFIG_GAME_ENABLE (1 << 4)
47
48#define GALAXY_CONFIG_CD_PANASONIC (1 << 5)
49#define GALAXY_CONFIG_CD_MITSUMI (1 << 6)
50#define GALAXY_CONFIG_CD_MASK (\
51 GALAXY_CONFIG_CD_PANASONIC | GALAXY_CONFIG_CD_MITSUMI)
52
53#define GALAXY_CONFIG_UNUSED (1 << 7)
54#define GALAXY_CONFIG_UNUSED_MASK GALAXY_CONFIG_UNUSED
55
56#define GALAXY_CONFIG_SBIRQ_2 (1 << 8)
57#define GALAXY_CONFIG_SBIRQ_3 (1 << 9)
58#define GALAXY_CONFIG_SBIRQ_5 (1 << 10)
59#define GALAXY_CONFIG_SBIRQ_7 (1 << 11)
60
61#define GALAXY_CONFIG_MPUIRQ_2 (1 << 12)
62#define GALAXY_CONFIG_MPUIRQ_3 (1 << 13)
63#define GALAXY_CONFIG_MPUIRQ_5 (1 << 14)
64#define GALAXY_CONFIG_MPUIRQ_7 (1 << 15)
65
66#define GALAXY_CONFIG_WSSA_530 (0 << 16)
67#define GALAXY_CONFIG_WSSA_604 (1 << 16)
68#define GALAXY_CONFIG_WSSA_E80 (2 << 16)
69#define GALAXY_CONFIG_WSSA_F40 (3 << 16)
70
71#define GALAXY_CONFIG_WSS_ENABLE (1 << 18)
72
73#define GALAXY_CONFIG_CDIRQ_11 (1 << 19)
74#define GALAXY_CONFIG_CDIRQ_12 (1 << 20)
75#define GALAXY_CONFIG_CDIRQ_15 (1 << 21)
76#define GALAXY_CONFIG_CDIRQ_MASK (\
77 GALAXY_CONFIG_CDIRQ_11 | GALAXY_CONFIG_CDIRQ_12 |\
78 GALAXY_CONFIG_CDIRQ_15)
79
80#define GALAXY_CONFIG_CDDMA_DISABLE (0 << 22)
81#define GALAXY_CONFIG_CDDMA_0 (1 << 22)
82#define GALAXY_CONFIG_CDDMA_1 (2 << 22)
83#define GALAXY_CONFIG_CDDMA_3 (3 << 22)
84#define GALAXY_CONFIG_CDDMA_MASK GALAXY_CONFIG_CDDMA_3
85
86#define GALAXY_CONFIG_MASK (\
87 GALAXY_CONFIG_SBA_MASK | GALAXY_CONFIG_CD_MASK |\
88 GALAXY_CONFIG_UNUSED_MASK | GALAXY_CONFIG_CDIRQ_MASK |\
89 GALAXY_CONFIG_CDDMA_MASK)
90
91#include "galaxy.c"
diff --git a/sound/isa/galaxy/azt2316.c b/sound/isa/galaxy/azt2316.c
new file mode 100644
index 000000000000..189441141df6
--- /dev/null
+++ b/sound/isa/galaxy/azt2316.c
@@ -0,0 +1,111 @@
1/*
2 * Aztech AZT2316 Driver
3 * Copyright (C) 2007,2010 Rene Herman
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, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20#define AZT2316
21
22#define CRD_NAME "Aztech AZT2316"
23#define DRV_NAME "AZT2316"
24#define DEV_NAME "azt2316"
25
26#define GALAXY_DSP_MAJOR 3
27#define GALAXY_DSP_MINOR 1
28
29#define GALAXY_CONFIG_SIZE 4
30
31/*
32 * 32-bit config register
33 */
34
35#define GALAXY_CONFIG_SBA_220 (0 << 0)
36#define GALAXY_CONFIG_SBA_240 (1 << 0)
37#define GALAXY_CONFIG_SBA_260 (2 << 0)
38#define GALAXY_CONFIG_SBA_280 (3 << 0)
39#define GALAXY_CONFIG_SBA_MASK GALAXY_CONFIG_SBA_280
40
41#define GALAXY_CONFIG_SBIRQ_2 (1 << 2)
42#define GALAXY_CONFIG_SBIRQ_5 (1 << 3)
43#define GALAXY_CONFIG_SBIRQ_7 (1 << 4)
44#define GALAXY_CONFIG_SBIRQ_10 (1 << 5)
45
46#define GALAXY_CONFIG_SBDMA_DISABLE (0 << 6)
47#define GALAXY_CONFIG_SBDMA_0 (1 << 6)
48#define GALAXY_CONFIG_SBDMA_1 (2 << 6)
49#define GALAXY_CONFIG_SBDMA_3 (3 << 6)
50
51#define GALAXY_CONFIG_WSSA_530 (0 << 8)
52#define GALAXY_CONFIG_WSSA_604 (1 << 8)
53#define GALAXY_CONFIG_WSSA_E80 (2 << 8)
54#define GALAXY_CONFIG_WSSA_F40 (3 << 8)
55
56#define GALAXY_CONFIG_WSS_ENABLE (1 << 10)
57
58#define GALAXY_CONFIG_GAME_ENABLE (1 << 11)
59
60#define GALAXY_CONFIG_MPUA_300 (0 << 12)
61#define GALAXY_CONFIG_MPUA_330 (1 << 12)
62
63#define GALAXY_CONFIG_MPU_ENABLE (1 << 13)
64
65#define GALAXY_CONFIG_CDA_310 (0 << 14)
66#define GALAXY_CONFIG_CDA_320 (1 << 14)
67#define GALAXY_CONFIG_CDA_340 (2 << 14)
68#define GALAXY_CONFIG_CDA_350 (3 << 14)
69#define GALAXY_CONFIG_CDA_MASK GALAXY_CONFIG_CDA_350
70
71#define GALAXY_CONFIG_CD_DISABLE (0 << 16)
72#define GALAXY_CONFIG_CD_PANASONIC (1 << 16)
73#define GALAXY_CONFIG_CD_SONY (2 << 16)
74#define GALAXY_CONFIG_CD_MITSUMI (3 << 16)
75#define GALAXY_CONFIG_CD_AZTECH (4 << 16)
76#define GALAXY_CONFIG_CD_UNUSED_5 (5 << 16)
77#define GALAXY_CONFIG_CD_UNUSED_6 (6 << 16)
78#define GALAXY_CONFIG_CD_UNUSED_7 (7 << 16)
79#define GALAXY_CONFIG_CD_MASK GALAXY_CONFIG_CD_UNUSED_7
80
81#define GALAXY_CONFIG_CDDMA8_DISABLE (0 << 20)
82#define GALAXY_CONFIG_CDDMA8_0 (1 << 20)
83#define GALAXY_CONFIG_CDDMA8_1 (2 << 20)
84#define GALAXY_CONFIG_CDDMA8_3 (3 << 20)
85#define GALAXY_CONFIG_CDDMA8_MASK GALAXY_CONFIG_CDDMA8_3
86
87#define GALAXY_CONFIG_CDDMA16_DISABLE (0 << 22)
88#define GALAXY_CONFIG_CDDMA16_5 (1 << 22)
89#define GALAXY_CONFIG_CDDMA16_6 (2 << 22)
90#define GALAXY_CONFIG_CDDMA16_7 (3 << 22)
91#define GALAXY_CONFIG_CDDMA16_MASK GALAXY_CONFIG_CDDMA16_7
92
93#define GALAXY_CONFIG_MPUIRQ_2 (1 << 24)
94#define GALAXY_CONFIG_MPUIRQ_5 (1 << 25)
95#define GALAXY_CONFIG_MPUIRQ_7 (1 << 26)
96#define GALAXY_CONFIG_MPUIRQ_10 (1 << 27)
97
98#define GALAXY_CONFIG_CDIRQ_5 (1 << 28)
99#define GALAXY_CONFIG_CDIRQ_11 (1 << 29)
100#define GALAXY_CONFIG_CDIRQ_12 (1 << 30)
101#define GALAXY_CONFIG_CDIRQ_15 (1 << 31)
102#define GALAXY_CONFIG_CDIRQ_MASK (\
103 GALAXY_CONFIG_CDIRQ_5 | GALAXY_CONFIG_CDIRQ_11 |\
104 GALAXY_CONFIG_CDIRQ_12 | GALAXY_CONFIG_CDIRQ_15)
105
106#define GALAXY_CONFIG_MASK (\
107 GALAXY_CONFIG_SBA_MASK | GALAXY_CONFIG_CDA_MASK |\
108 GALAXY_CONFIG_CD_MASK | GALAXY_CONFIG_CDDMA16_MASK |\
109 GALAXY_CONFIG_CDDMA8_MASK | GALAXY_CONFIG_CDIRQ_MASK)
110
111#include "galaxy.c"
diff --git a/sound/isa/galaxy/galaxy.c b/sound/isa/galaxy/galaxy.c
new file mode 100644
index 000000000000..ee54df082b9c
--- /dev/null
+++ b/sound/isa/galaxy/galaxy.c
@@ -0,0 +1,652 @@
1/*
2 * Aztech AZT1605/AZT2316 Driver
3 * Copyright (C) 2007,2010 Rene Herman
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, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/isa.h>
23#include <linux/delay.h>
24#include <linux/io.h>
25#include <asm/processor.h>
26#include <sound/core.h>
27#include <sound/initval.h>
28#include <sound/wss.h>
29#include <sound/mpu401.h>
30#include <sound/opl3.h>
31
32MODULE_DESCRIPTION(CRD_NAME);
33MODULE_AUTHOR("Rene Herman");
34MODULE_LICENSE("GPL");
35
36static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
37static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
38static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;
39
40module_param_array(index, int, NULL, 0444);
41MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard.");
42module_param_array(id, charp, NULL, 0444);
43MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
44module_param_array(enable, bool, NULL, 0444);
45MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
46
47static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
48static long wss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
49static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
50static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
51static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
52static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
53static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
54static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
55
56module_param_array(port, long, NULL, 0444);
57MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
58module_param_array(wss_port, long, NULL, 0444);
59MODULE_PARM_DESC(wss_port, "WSS port # for " CRD_NAME " driver.");
60module_param_array(mpu_port, long, NULL, 0444);
61MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver.");
62module_param_array(fm_port, long, NULL, 0444);
63MODULE_PARM_DESC(fm_port, "FM port # for " CRD_NAME " driver.");
64module_param_array(irq, int, NULL, 0444);
65MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver.");
66module_param_array(mpu_irq, int, NULL, 0444);
67MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver.");
68module_param_array(dma1, int, NULL, 0444);
69MODULE_PARM_DESC(dma1, "Playback DMA # for " CRD_NAME " driver.");
70module_param_array(dma2, int, NULL, 0444);
71MODULE_PARM_DESC(dma2, "Capture DMA # for " CRD_NAME " driver.");
72
73/*
74 * Generic SB DSP support routines
75 */
76
77#define DSP_PORT_RESET 0x6
78#define DSP_PORT_READ 0xa
79#define DSP_PORT_COMMAND 0xc
80#define DSP_PORT_STATUS 0xc
81#define DSP_PORT_DATA_AVAIL 0xe
82
83#define DSP_SIGNATURE 0xaa
84
85#define DSP_COMMAND_GET_VERSION 0xe1
86
87static int __devinit dsp_get_byte(void __iomem *port, u8 *val)
88{
89 int loops = 1000;
90
91 while (!(ioread8(port + DSP_PORT_DATA_AVAIL) & 0x80)) {
92 if (!loops--)
93 return -EIO;
94 cpu_relax();
95 }
96 *val = ioread8(port + DSP_PORT_READ);
97 return 0;
98}
99
100static int __devinit dsp_reset(void __iomem *port)
101{
102 u8 val;
103
104 iowrite8(1, port + DSP_PORT_RESET);
105 udelay(10);
106 iowrite8(0, port + DSP_PORT_RESET);
107
108 if (dsp_get_byte(port, &val) < 0 || val != DSP_SIGNATURE)
109 return -ENODEV;
110
111 return 0;
112}
113
114static int __devinit dsp_command(void __iomem *port, u8 cmd)
115{
116 int loops = 1000;
117
118 while (ioread8(port + DSP_PORT_STATUS) & 0x80) {
119 if (!loops--)
120 return -EIO;
121 cpu_relax();
122 }
123 iowrite8(cmd, port + DSP_PORT_COMMAND);
124 return 0;
125}
126
127static int __devinit dsp_get_version(void __iomem *port, u8 *major, u8 *minor)
128{
129 int err;
130
131 err = dsp_command(port, DSP_COMMAND_GET_VERSION);
132 if (err < 0)
133 return err;
134
135 err = dsp_get_byte(port, major);
136 if (err < 0)
137 return err;
138
139 err = dsp_get_byte(port, minor);
140 if (err < 0)
141 return err;
142
143 return 0;
144}
145
146/*
147 * Generic WSS support routines
148 */
149
150#define WSS_CONFIG_DMA_0 (1 << 0)
151#define WSS_CONFIG_DMA_1 (2 << 0)
152#define WSS_CONFIG_DMA_3 (3 << 0)
153#define WSS_CONFIG_DUPLEX (1 << 2)
154#define WSS_CONFIG_IRQ_7 (1 << 3)
155#define WSS_CONFIG_IRQ_9 (2 << 3)
156#define WSS_CONFIG_IRQ_10 (3 << 3)
157#define WSS_CONFIG_IRQ_11 (4 << 3)
158
159#define WSS_PORT_CONFIG 0
160#define WSS_PORT_SIGNATURE 3
161
162#define WSS_SIGNATURE 4
163
164static int __devinit wss_detect(void __iomem *wss_port)
165{
166 if ((ioread8(wss_port + WSS_PORT_SIGNATURE) & 0x3f) != WSS_SIGNATURE)
167 return -ENODEV;
168
169 return 0;
170}
171
172static void wss_set_config(void __iomem *wss_port, u8 wss_config)
173{
174 iowrite8(wss_config, wss_port + WSS_PORT_CONFIG);
175}
176
177/*
178 * Aztech Sound Galaxy specifics
179 */
180
181#define GALAXY_PORT_CONFIG 1024
182#define CONFIG_PORT_SET 4
183
184#define DSP_COMMAND_GALAXY_8 8
185#define GALAXY_COMMAND_GET_TYPE 5
186
187#define DSP_COMMAND_GALAXY_9 9
188#define GALAXY_COMMAND_WSSMODE 0
189#define GALAXY_COMMAND_SB8MODE 1
190
191#define GALAXY_MODE_WSS GALAXY_COMMAND_WSSMODE
192#define GALAXY_MODE_SB8 GALAXY_COMMAND_SB8MODE
193
194struct snd_galaxy {
195 void __iomem *port;
196 void __iomem *config_port;
197 void __iomem *wss_port;
198 u32 config;
199 struct resource *res_port;
200 struct resource *res_config_port;
201 struct resource *res_wss_port;
202};
203
204static u32 config[SNDRV_CARDS];
205static u8 wss_config[SNDRV_CARDS];
206
207static int __devinit snd_galaxy_match(struct device *dev, unsigned int n)
208{
209 if (!enable[n])
210 return 0;
211
212 switch (port[n]) {
213 case SNDRV_AUTO_PORT:
214 dev_err(dev, "please specify port\n");
215 return 0;
216 case 0x220:
217 config[n] |= GALAXY_CONFIG_SBA_220;
218 break;
219 case 0x240:
220 config[n] |= GALAXY_CONFIG_SBA_240;
221 break;
222 case 0x260:
223 config[n] |= GALAXY_CONFIG_SBA_260;
224 break;
225 case 0x280:
226 config[n] |= GALAXY_CONFIG_SBA_280;
227 break;
228 default:
229 dev_err(dev, "invalid port %#lx\n", port[n]);
230 return 0;
231 }
232
233 switch (wss_port[n]) {
234 case SNDRV_AUTO_PORT:
235 dev_err(dev, "please specify wss_port\n");
236 return 0;
237 case 0x530:
238 config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_530;
239 break;
240 case 0x604:
241 config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_604;
242 break;
243 case 0xe80:
244 config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_E80;
245 break;
246 case 0xf40:
247 config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_F40;
248 break;
249 default:
250 dev_err(dev, "invalid WSS port %#lx\n", wss_port[n]);
251 return 0;
252 }
253
254 switch (irq[n]) {
255 case SNDRV_AUTO_IRQ:
256 dev_err(dev, "please specify irq\n");
257 return 0;
258 case 7:
259 wss_config[n] |= WSS_CONFIG_IRQ_7;
260 break;
261 case 2:
262 irq[n] = 9;
263 case 9:
264 wss_config[n] |= WSS_CONFIG_IRQ_9;
265 break;
266 case 10:
267 wss_config[n] |= WSS_CONFIG_IRQ_10;
268 break;
269 case 11:
270 wss_config[n] |= WSS_CONFIG_IRQ_11;
271 break;
272 default:
273 dev_err(dev, "invalid IRQ %d\n", irq[n]);
274 return 0;
275 }
276
277 switch (dma1[n]) {
278 case SNDRV_AUTO_DMA:
279 dev_err(dev, "please specify dma1\n");
280 return 0;
281 case 0:
282 wss_config[n] |= WSS_CONFIG_DMA_0;
283 break;
284 case 1:
285 wss_config[n] |= WSS_CONFIG_DMA_1;
286 break;
287 case 3:
288 wss_config[n] |= WSS_CONFIG_DMA_3;
289 break;
290 default:
291 dev_err(dev, "invalid playback DMA %d\n", dma1[n]);
292 return 0;
293 }
294
295 if (dma2[n] == SNDRV_AUTO_DMA || dma2[n] == dma1[n]) {
296 dma2[n] = -1;
297 goto mpu;
298 }
299
300 wss_config[n] |= WSS_CONFIG_DUPLEX;
301 switch (dma2[n]) {
302 case 0:
303 break;
304 case 1:
305 if (dma1[n] == 0)
306 break;
307 default:
308 dev_err(dev, "invalid capture DMA %d\n", dma2[n]);
309 return 0;
310 }
311
312mpu:
313 switch (mpu_port[n]) {
314 case SNDRV_AUTO_PORT:
315 dev_warn(dev, "mpu_port not specified; not using MPU-401\n");
316 mpu_port[n] = -1;
317 goto fm;
318 case 0x300:
319 config[n] |= GALAXY_CONFIG_MPU_ENABLE | GALAXY_CONFIG_MPUA_300;
320 break;
321 case 0x330:
322 config[n] |= GALAXY_CONFIG_MPU_ENABLE | GALAXY_CONFIG_MPUA_330;
323 break;
324 default:
325 dev_err(dev, "invalid MPU port %#lx\n", mpu_port[n]);
326 return 0;
327 }
328
329 switch (mpu_irq[n]) {
330 case SNDRV_AUTO_IRQ:
331 dev_warn(dev, "mpu_irq not specified: using polling mode\n");
332 mpu_irq[n] = -1;
333 break;
334 case 2:
335 mpu_irq[n] = 9;
336 case 9:
337 config[n] |= GALAXY_CONFIG_MPUIRQ_2;
338 break;
339#ifdef AZT1605
340 case 3:
341 config[n] |= GALAXY_CONFIG_MPUIRQ_3;
342 break;
343#endif
344 case 5:
345 config[n] |= GALAXY_CONFIG_MPUIRQ_5;
346 break;
347 case 7:
348 config[n] |= GALAXY_CONFIG_MPUIRQ_7;
349 break;
350#ifdef AZT2316
351 case 10:
352 config[n] |= GALAXY_CONFIG_MPUIRQ_10;
353 break;
354#endif
355 default:
356 dev_err(dev, "invalid MPU IRQ %d\n", mpu_irq[n]);
357 return 0;
358 }
359
360 if (mpu_irq[n] == irq[n]) {
361 dev_err(dev, "cannot share IRQ between WSS and MPU-401\n");
362 return 0;
363 }
364
365fm:
366 switch (fm_port[n]) {
367 case SNDRV_AUTO_PORT:
368 dev_warn(dev, "fm_port not specified: not using OPL3\n");
369 fm_port[n] = -1;
370 break;
371 case 0x388:
372 break;
373 default:
374 dev_err(dev, "illegal FM port %#lx\n", fm_port[n]);
375 return 0;
376 }
377
378 config[n] |= GALAXY_CONFIG_GAME_ENABLE;
379 return 1;
380}
381
382static int __devinit galaxy_init(struct snd_galaxy *galaxy, u8 *type)
383{
384 u8 major;
385 u8 minor;
386 int err;
387
388 err = dsp_reset(galaxy->port);
389 if (err < 0)
390 return err;
391
392 err = dsp_get_version(galaxy->port, &major, &minor);
393 if (err < 0)
394 return err;
395
396 if (major != GALAXY_DSP_MAJOR || minor != GALAXY_DSP_MINOR)
397 return -ENODEV;
398
399 err = dsp_command(galaxy->port, DSP_COMMAND_GALAXY_8);
400 if (err < 0)
401 return err;
402
403 err = dsp_command(galaxy->port, GALAXY_COMMAND_GET_TYPE);
404 if (err < 0)
405 return err;
406
407 err = dsp_get_byte(galaxy->port, type);
408 if (err < 0)
409 return err;
410
411 return 0;
412}
413
414static int __devinit galaxy_set_mode(struct snd_galaxy *galaxy, u8 mode)
415{
416 int err;
417
418 err = dsp_command(galaxy->port, DSP_COMMAND_GALAXY_9);
419 if (err < 0)
420 return err;
421
422 err = dsp_command(galaxy->port, mode);
423 if (err < 0)
424 return err;
425
426#ifdef AZT1605
427 /*
428 * Needed for MPU IRQ on AZT1605, but AZT2316 loses WSS again
429 */
430 err = dsp_reset(galaxy->port);
431 if (err < 0)
432 return err;
433#endif
434
435 return 0;
436}
437
438static void galaxy_set_config(struct snd_galaxy *galaxy, u32 config)
439{
440 u8 tmp = ioread8(galaxy->config_port + CONFIG_PORT_SET);
441 int i;
442
443 iowrite8(tmp | 0x80, galaxy->config_port + CONFIG_PORT_SET);
444 for (i = 0; i < GALAXY_CONFIG_SIZE; i++) {
445 iowrite8(config, galaxy->config_port + i);
446 config >>= 8;
447 }
448 iowrite8(tmp & 0x7f, galaxy->config_port + CONFIG_PORT_SET);
449 msleep(10);
450}
451
452static void __devinit galaxy_config(struct snd_galaxy *galaxy, u32 config)
453{
454 int i;
455
456 for (i = GALAXY_CONFIG_SIZE; i; i--) {
457 u8 tmp = ioread8(galaxy->config_port + i - 1);
458 galaxy->config = (galaxy->config << 8) | tmp;
459 }
460 config |= galaxy->config & GALAXY_CONFIG_MASK;
461 galaxy_set_config(galaxy, config);
462}
463
464static int __devinit galaxy_wss_config(struct snd_galaxy *galaxy, u8 wss_config)
465{
466 int err;
467
468 err = wss_detect(galaxy->wss_port);
469 if (err < 0)
470 return err;
471
472 wss_set_config(galaxy->wss_port, wss_config);
473
474 err = galaxy_set_mode(galaxy, GALAXY_MODE_WSS);
475 if (err < 0)
476 return err;
477
478 return 0;
479}
480
481static void snd_galaxy_free(struct snd_card *card)
482{
483 struct snd_galaxy *galaxy = card->private_data;
484
485 if (galaxy->wss_port) {
486 wss_set_config(galaxy->wss_port, 0);
487 ioport_unmap(galaxy->wss_port);
488 release_and_free_resource(galaxy->res_wss_port);
489 }
490 if (galaxy->config_port) {
491 galaxy_set_config(galaxy, galaxy->config);
492 ioport_unmap(galaxy->config_port);
493 release_and_free_resource(galaxy->res_config_port);
494 }
495 if (galaxy->port) {
496 ioport_unmap(galaxy->port);
497 release_and_free_resource(galaxy->res_port);
498 }
499}
500
501static int __devinit snd_galaxy_probe(struct device *dev, unsigned int n)
502{
503 struct snd_galaxy *galaxy;
504 struct snd_wss *chip;
505 struct snd_card *card;
506 u8 type;
507 int err;
508
509 err = snd_card_create(index[n], id[n], THIS_MODULE, sizeof *galaxy,
510 &card);
511 if (err < 0)
512 return err;
513
514 snd_card_set_dev(card, dev);
515
516 card->private_free = snd_galaxy_free;
517 galaxy = card->private_data;
518
519 galaxy->res_port = request_region(port[n], 16, DRV_NAME);
520 if (!galaxy->res_port) {
521 dev_err(dev, "could not grab ports %#lx-%#lx\n", port[n],
522 port[n] + 15);
523 err = -EBUSY;
524 goto error;
525 }
526 galaxy->port = ioport_map(port[n], 16);
527
528 err = galaxy_init(galaxy, &type);
529 if (err < 0) {
530 dev_err(dev, "did not find a Sound Galaxy at %#lx\n", port[n]);
531 goto error;
532 }
533 dev_info(dev, "Sound Galaxy (type %d) found at %#lx\n", type, port[n]);
534
535 galaxy->res_config_port = request_region(port[n] + GALAXY_PORT_CONFIG,
536 16, DRV_NAME);
537 if (!galaxy->res_config_port) {
538 dev_err(dev, "could not grab ports %#lx-%#lx\n",
539 port[n] + GALAXY_PORT_CONFIG,
540 port[n] + GALAXY_PORT_CONFIG + 15);
541 err = -EBUSY;
542 goto error;
543 }
544 galaxy->config_port = ioport_map(port[n] + GALAXY_PORT_CONFIG, 16);
545
546 galaxy_config(galaxy, config[n]);
547
548 galaxy->res_wss_port = request_region(wss_port[n], 4, DRV_NAME);
549 if (!galaxy->res_wss_port) {
550 dev_err(dev, "could not grab ports %#lx-%#lx\n", wss_port[n],
551 wss_port[n] + 3);
552 err = -EBUSY;
553 goto error;
554 }
555 galaxy->wss_port = ioport_map(wss_port[n], 4);
556
557 err = galaxy_wss_config(galaxy, wss_config[n]);
558 if (err < 0) {
559 dev_err(dev, "could not configure WSS\n");
560 goto error;
561 }
562
563 strcpy(card->driver, DRV_NAME);
564 strcpy(card->shortname, DRV_NAME);
565 sprintf(card->longname, "%s at %#lx/%#lx, irq %d, dma %d/%d",
566 card->shortname, port[n], wss_port[n], irq[n], dma1[n],
567 dma2[n]);
568
569 err = snd_wss_create(card, wss_port[n] + 4, -1, irq[n], dma1[n],
570 dma2[n], WSS_HW_DETECT, 0, &chip);
571 if (err < 0)
572 goto error;
573
574 err = snd_wss_pcm(chip, 0, NULL);
575 if (err < 0)
576 goto error;
577
578 err = snd_wss_mixer(chip);
579 if (err < 0)
580 goto error;
581
582 err = snd_wss_timer(chip, 0, NULL);
583 if (err < 0)
584 goto error;
585
586 if (mpu_port[n] >= 0) {
587 err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
588 mpu_port[n], 0, mpu_irq[n],
589 IRQF_DISABLED, NULL);
590 if (err < 0)
591 goto error;
592 }
593
594 if (fm_port[n] >= 0) {
595 struct snd_opl3 *opl3;
596
597 err = snd_opl3_create(card, fm_port[n], fm_port[n] + 2,
598 OPL3_HW_AUTO, 0, &opl3);
599 if (err < 0) {
600 dev_err(dev, "no OPL device at %#lx\n", fm_port[n]);
601 goto error;
602 }
603 err = snd_opl3_timer_new(opl3, 1, 2);
604 if (err < 0)
605 goto error;
606
607 err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
608 if (err < 0)
609 goto error;
610 }
611
612 err = snd_card_register(card);
613 if (err < 0)
614 goto error;
615
616 dev_set_drvdata(dev, card);
617 return 0;
618
619error:
620 snd_card_free(card);
621 return err;
622}
623
624static int __devexit snd_galaxy_remove(struct device *dev, unsigned int n)
625{
626 snd_card_free(dev_get_drvdata(dev));
627 dev_set_drvdata(dev, NULL);
628 return 0;
629}
630
631static struct isa_driver snd_galaxy_driver = {
632 .match = snd_galaxy_match,
633 .probe = snd_galaxy_probe,
634 .remove = __devexit_p(snd_galaxy_remove),
635
636 .driver = {
637 .name = DEV_NAME
638 }
639};
640
641static int __init alsa_card_galaxy_init(void)
642{
643 return isa_register_driver(&snd_galaxy_driver, SNDRV_CARDS);
644}
645
646static void __exit alsa_card_galaxy_exit(void)
647{
648 isa_unregister_driver(&snd_galaxy_driver);
649}
650
651module_init(alsa_card_galaxy_init);
652module_exit(alsa_card_galaxy_exit);
diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c
deleted file mode 100644
index 6fe27b9d9440..000000000000
--- a/sound/isa/sgalaxy.c
+++ /dev/null
@@ -1,369 +0,0 @@
1/*
2 * Driver for Aztech Sound Galaxy cards
3 * Copyright (c) by Christopher Butler <chrisb@sandy.force9.co.uk.
4 *
5 * I don't have documentation for this card, I based this driver on the
6 * driver for OSS/Free included in the kernel source (drivers/sound/sgalaxy.c)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
24#include <linux/init.h>
25#include <linux/err.h>
26#include <linux/isa.h>
27#include <linux/delay.h>
28#include <linux/time.h>
29#include <linux/interrupt.h>
30#include <linux/moduleparam.h>
31#include <asm/dma.h>
32#include <sound/core.h>
33#include <sound/sb.h>
34#include <sound/wss.h>
35#include <sound/control.h>
36#define SNDRV_LEGACY_FIND_FREE_IRQ
37#define SNDRV_LEGACY_FIND_FREE_DMA
38#include <sound/initval.h>
39
40MODULE_AUTHOR("Christopher Butler <chrisb@sandy.force9.co.uk>");
41MODULE_DESCRIPTION("Aztech Sound Galaxy");
42MODULE_LICENSE("GPL");
43MODULE_SUPPORTED_DEVICE("{{Aztech Systems,Sound Galaxy}}");
44
45static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
46static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
47static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
48static long sbport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240 */
49static long wssport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x530,0xe80,0xf40,0x604 */
50static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 7,9,10,11 */
51static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */
52
53module_param_array(index, int, NULL, 0444);
54MODULE_PARM_DESC(index, "Index value for Sound Galaxy soundcard.");
55module_param_array(id, charp, NULL, 0444);
56MODULE_PARM_DESC(id, "ID string for Sound Galaxy soundcard.");
57module_param_array(sbport, long, NULL, 0444);
58MODULE_PARM_DESC(sbport, "Port # for Sound Galaxy SB driver.");
59module_param_array(wssport, long, NULL, 0444);
60MODULE_PARM_DESC(wssport, "Port # for Sound Galaxy WSS driver.");
61module_param_array(irq, int, NULL, 0444);
62MODULE_PARM_DESC(irq, "IRQ # for Sound Galaxy driver.");
63module_param_array(dma1, int, NULL, 0444);
64MODULE_PARM_DESC(dma1, "DMA1 # for Sound Galaxy driver.");
65
66#define SGALAXY_AUXC_LEFT 18
67#define SGALAXY_AUXC_RIGHT 19
68
69#define PFX "sgalaxy: "
70
71/*
72
73 */
74
75#define AD1848P1( port, x ) ( port + c_d_c_AD1848##x )
76
77/* from lowlevel/sb/sb.c - to avoid having to allocate a struct snd_sb for the */
78/* short time we actually need it.. */
79
80static int snd_sgalaxy_sbdsp_reset(unsigned long port)
81{
82 int i;
83
84 outb(1, SBP1(port, RESET));
85 udelay(10);
86 outb(0, SBP1(port, RESET));
87 udelay(30);
88 for (i = 0; i < 1000 && !(inb(SBP1(port, DATA_AVAIL)) & 0x80); i++);
89 if (inb(SBP1(port, READ)) != 0xaa) {
90 snd_printd("sb_reset: failed at 0x%lx!!!\n", port);
91 return -ENODEV;
92 }
93 return 0;
94}
95
96static int __devinit snd_sgalaxy_sbdsp_command(unsigned long port,
97 unsigned char val)
98{
99 int i;
100
101 for (i = 10000; i; i--)
102 if ((inb(SBP1(port, STATUS)) & 0x80) == 0) {
103 outb(val, SBP1(port, COMMAND));
104 return 1;
105 }
106
107 return 0;
108}
109
110static irqreturn_t snd_sgalaxy_dummy_interrupt(int irq, void *dev_id)
111{
112 return IRQ_NONE;
113}
114
115static int __devinit snd_sgalaxy_setup_wss(unsigned long port, int irq, int dma)
116{
117 static int interrupt_bits[] = {-1, -1, -1, -1, -1, -1, -1, 0x08, -1,
118 0x10, 0x18, 0x20, -1, -1, -1, -1};
119 static int dma_bits[] = {1, 2, 0, 3};
120 int tmp, tmp1;
121
122 if ((tmp = inb(port + 3)) == 0xff)
123 {
124 snd_printdd("I/O address dead (0x%lx)\n", port);
125 return 0;
126 }
127#if 0
128 snd_printdd("WSS signature = 0x%x\n", tmp);
129#endif
130
131 if ((tmp & 0x3f) != 0x04 &&
132 (tmp & 0x3f) != 0x0f &&
133 (tmp & 0x3f) != 0x00) {
134 snd_printdd("No WSS signature detected on port 0x%lx\n",
135 port + 3);
136 return 0;
137 }
138
139#if 0
140 snd_printdd(PFX "setting up IRQ/DMA for WSS\n");
141#endif
142
143 /* initialize IRQ for WSS codec */
144 tmp = interrupt_bits[irq % 16];
145 if (tmp < 0)
146 return -EINVAL;
147
148 if (request_irq(irq, snd_sgalaxy_dummy_interrupt, IRQF_DISABLED, "sgalaxy", NULL)) {
149 snd_printk(KERN_ERR "sgalaxy: can't grab irq %d\n", irq);
150 return -EIO;
151 }
152
153 outb(tmp | 0x40, port);
154 tmp1 = dma_bits[dma % 4];
155 outb(tmp | tmp1, port);
156
157 free_irq(irq, NULL);
158
159 return 0;
160}
161
162static int __devinit snd_sgalaxy_detect(int dev, int irq, int dma)
163{
164#if 0
165 snd_printdd(PFX "switching to WSS mode\n");
166#endif
167
168 /* switch to WSS mode */
169 snd_sgalaxy_sbdsp_reset(sbport[dev]);
170
171 snd_sgalaxy_sbdsp_command(sbport[dev], 9);
172 snd_sgalaxy_sbdsp_command(sbport[dev], 0);
173
174 udelay(400);
175 return snd_sgalaxy_setup_wss(wssport[dev], irq, dma);
176}
177
178static struct snd_kcontrol_new snd_sgalaxy_controls[] = {
179WSS_DOUBLE("Aux Playback Switch", 0,
180 SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 7, 7, 1, 1),
181WSS_DOUBLE("Aux Playback Volume", 0,
182 SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 0, 0, 31, 0)
183};
184
185static int __devinit snd_sgalaxy_mixer(struct snd_wss *chip)
186{
187 struct snd_card *card = chip->card;
188 struct snd_ctl_elem_id id1, id2;
189 unsigned int idx;
190 int err;
191
192 memset(&id1, 0, sizeof(id1));
193 memset(&id2, 0, sizeof(id2));
194 id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
195 /* reassign AUX0 to LINE */
196 strcpy(id1.name, "Aux Playback Switch");
197 strcpy(id2.name, "Line Playback Switch");
198 if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
199 return err;
200 strcpy(id1.name, "Aux Playback Volume");
201 strcpy(id2.name, "Line Playback Volume");
202 if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
203 return err;
204 /* reassign AUX1 to FM */
205 strcpy(id1.name, "Aux Playback Switch"); id1.index = 1;
206 strcpy(id2.name, "FM Playback Switch");
207 if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
208 return err;
209 strcpy(id1.name, "Aux Playback Volume");
210 strcpy(id2.name, "FM Playback Volume");
211 if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
212 return err;
213 /* build AUX2 input */
214 for (idx = 0; idx < ARRAY_SIZE(snd_sgalaxy_controls); idx++) {
215 err = snd_ctl_add(card,
216 snd_ctl_new1(&snd_sgalaxy_controls[idx], chip));
217 if (err < 0)
218 return err;
219 }
220 return 0;
221}
222
223static int __devinit snd_sgalaxy_match(struct device *devptr, unsigned int dev)
224{
225 if (!enable[dev])
226 return 0;
227 if (sbport[dev] == SNDRV_AUTO_PORT) {
228 snd_printk(KERN_ERR PFX "specify SB port\n");
229 return 0;
230 }
231 if (wssport[dev] == SNDRV_AUTO_PORT) {
232 snd_printk(KERN_ERR PFX "specify WSS port\n");
233 return 0;
234 }
235 return 1;
236}
237
238static int __devinit snd_sgalaxy_probe(struct device *devptr, unsigned int dev)
239{
240 static int possible_irqs[] = {7, 9, 10, 11, -1};
241 static int possible_dmas[] = {1, 3, 0, -1};
242 int err, xirq, xdma1;
243 struct snd_card *card;
244 struct snd_wss *chip;
245
246 err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
247 if (err < 0)
248 return err;
249
250 xirq = irq[dev];
251 if (xirq == SNDRV_AUTO_IRQ) {
252 if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
253 snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
254 err = -EBUSY;
255 goto _err;
256 }
257 }
258 xdma1 = dma1[dev];
259 if (xdma1 == SNDRV_AUTO_DMA) {
260 if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
261 snd_printk(KERN_ERR PFX "unable to find a free DMA\n");
262 err = -EBUSY;
263 goto _err;
264 }
265 }
266
267 if ((err = snd_sgalaxy_detect(dev, xirq, xdma1)) < 0)
268 goto _err;
269
270 err = snd_wss_create(card, wssport[dev] + 4, -1,
271 xirq, xdma1, -1,
272 WSS_HW_DETECT, 0, &chip);
273 if (err < 0)
274 goto _err;
275 card->private_data = chip;
276
277 err = snd_wss_pcm(chip, 0, NULL);
278 if (err < 0) {
279 snd_printdd(PFX "error creating new WSS PCM device\n");
280 goto _err;
281 }
282 err = snd_wss_mixer(chip);
283 if (err < 0) {
284 snd_printdd(PFX "error creating new WSS mixer\n");
285 goto _err;
286 }
287 if ((err = snd_sgalaxy_mixer(chip)) < 0) {
288 snd_printdd(PFX "the mixer rewrite failed\n");
289 goto _err;
290 }
291
292 strcpy(card->driver, "Sound Galaxy");
293 strcpy(card->shortname, "Sound Galaxy");
294 sprintf(card->longname, "Sound Galaxy at 0x%lx, irq %d, dma %d",
295 wssport[dev], xirq, xdma1);
296
297 snd_card_set_dev(card, devptr);
298
299 if ((err = snd_card_register(card)) < 0)
300 goto _err;
301
302 dev_set_drvdata(devptr, card);
303 return 0;
304
305 _err:
306 snd_card_free(card);
307 return err;
308}
309
310static int __devexit snd_sgalaxy_remove(struct device *devptr, unsigned int dev)
311{
312 snd_card_free(dev_get_drvdata(devptr));
313 dev_set_drvdata(devptr, NULL);
314 return 0;
315}
316
317#ifdef CONFIG_PM
318static int snd_sgalaxy_suspend(struct device *pdev, unsigned int n,
319 pm_message_t state)
320{
321 struct snd_card *card = dev_get_drvdata(pdev);
322 struct snd_wss *chip = card->private_data;
323
324 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
325 chip->suspend(chip);
326 return 0;
327}
328
329static int snd_sgalaxy_resume(struct device *pdev, unsigned int n)
330{
331 struct snd_card *card = dev_get_drvdata(pdev);
332 struct snd_wss *chip = card->private_data;
333
334 chip->resume(chip);
335 snd_wss_out(chip, SGALAXY_AUXC_LEFT, chip->image[SGALAXY_AUXC_LEFT]);
336 snd_wss_out(chip, SGALAXY_AUXC_RIGHT, chip->image[SGALAXY_AUXC_RIGHT]);
337
338 snd_power_change_state(card, SNDRV_CTL_POWER_D0);
339 return 0;
340}
341#endif
342
343#define DEV_NAME "sgalaxy"
344
345static struct isa_driver snd_sgalaxy_driver = {
346 .match = snd_sgalaxy_match,
347 .probe = snd_sgalaxy_probe,
348 .remove = __devexit_p(snd_sgalaxy_remove),
349#ifdef CONFIG_PM
350 .suspend = snd_sgalaxy_suspend,
351 .resume = snd_sgalaxy_resume,
352#endif
353 .driver = {
354 .name = DEV_NAME
355 },
356};
357
358static int __init alsa_card_sgalaxy_init(void)
359{
360 return isa_register_driver(&snd_sgalaxy_driver, SNDRV_CARDS);
361}
362
363static void __exit alsa_card_sgalaxy_exit(void)
364{
365 isa_unregister_driver(&snd_sgalaxy_driver);
366}
367
368module_init(alsa_card_sgalaxy_init)
369module_exit(alsa_card_sgalaxy_exit)
diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c
index d216362626d0..712c1710f9a2 100644
--- a/sound/pci/ice1712/delta.c
+++ b/sound/pci/ice1712/delta.c
@@ -563,6 +563,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
563 case ICE1712_SUBDEVICE_DELTA1010E: 563 case ICE1712_SUBDEVICE_DELTA1010E:
564 case ICE1712_SUBDEVICE_DELTA1010LT: 564 case ICE1712_SUBDEVICE_DELTA1010LT:
565 case ICE1712_SUBDEVICE_MEDIASTATION: 565 case ICE1712_SUBDEVICE_MEDIASTATION:
566 case ICE1712_SUBDEVICE_EDIROLDA2496:
566 ice->num_total_dacs = 8; 567 ice->num_total_dacs = 8;
567 ice->num_total_adcs = 8; 568 ice->num_total_adcs = 8;
568 break; 569 break;
@@ -635,6 +636,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
635 err = snd_ice1712_akm4xxx_init(ak, &akm_delta410, &akm_delta410_priv, ice); 636 err = snd_ice1712_akm4xxx_init(ak, &akm_delta410, &akm_delta410_priv, ice);
636 break; 637 break;
637 case ICE1712_SUBDEVICE_DELTA1010LT: 638 case ICE1712_SUBDEVICE_DELTA1010LT:
639 case ICE1712_SUBDEVICE_EDIROLDA2496:
638 err = snd_ice1712_akm4xxx_init(ak, &akm_delta1010lt, &akm_delta1010lt_priv, ice); 640 err = snd_ice1712_akm4xxx_init(ak, &akm_delta1010lt, &akm_delta1010lt_priv, ice);
639 break; 641 break;
640 case ICE1712_SUBDEVICE_DELTA66: 642 case ICE1712_SUBDEVICE_DELTA66:
@@ -734,6 +736,7 @@ static int __devinit snd_ice1712_delta_add_controls(struct snd_ice1712 *ice)
734 case ICE1712_SUBDEVICE_DELTA66: 736 case ICE1712_SUBDEVICE_DELTA66:
735 case ICE1712_SUBDEVICE_VX442: 737 case ICE1712_SUBDEVICE_VX442:
736 case ICE1712_SUBDEVICE_DELTA66E: 738 case ICE1712_SUBDEVICE_DELTA66E:
739 case ICE1712_SUBDEVICE_EDIROLDA2496:
737 err = snd_ice1712_akm4xxx_build_controls(ice); 740 err = snd_ice1712_akm4xxx_build_controls(ice);
738 if (err < 0) 741 if (err < 0)
739 return err; 742 return err;
@@ -813,5 +816,12 @@ struct snd_ice1712_card_info snd_ice1712_delta_cards[] __devinitdata = {
813 .chip_init = snd_ice1712_delta_init, 816 .chip_init = snd_ice1712_delta_init,
814 .build_controls = snd_ice1712_delta_add_controls, 817 .build_controls = snd_ice1712_delta_add_controls,
815 }, 818 },
819 {
820 .subvendor = ICE1712_SUBDEVICE_EDIROLDA2496,
821 .name = "Edirol DA2496",
822 .model = "da2496",
823 .chip_init = snd_ice1712_delta_init,
824 .build_controls = snd_ice1712_delta_add_controls,
825 },
816 { } /* terminator */ 826 { } /* terminator */
817}; 827};
diff --git a/sound/pci/ice1712/delta.h b/sound/pci/ice1712/delta.h
index f7f14df81f26..1a0ac6cd6501 100644
--- a/sound/pci/ice1712/delta.h
+++ b/sound/pci/ice1712/delta.h
@@ -34,7 +34,8 @@
34 "{MidiMan M Audio,Delta 410},"\ 34 "{MidiMan M Audio,Delta 410},"\
35 "{MidiMan M Audio,Audiophile 24/96},"\ 35 "{MidiMan M Audio,Audiophile 24/96},"\
36 "{Digigram,VX442},"\ 36 "{Digigram,VX442},"\
37 "{Lionstracs,Mediastation}," 37 "{Lionstracs,Mediastation},"\
38 "{Edirol,DA2496},"
38 39
39#define ICE1712_SUBDEVICE_DELTA1010 0x121430d6 40#define ICE1712_SUBDEVICE_DELTA1010 0x121430d6
40#define ICE1712_SUBDEVICE_DELTA1010E 0xff1430d6 41#define ICE1712_SUBDEVICE_DELTA1010E 0xff1430d6
@@ -47,6 +48,7 @@
47#define ICE1712_SUBDEVICE_DELTA1010LT 0x12143bd6 48#define ICE1712_SUBDEVICE_DELTA1010LT 0x12143bd6
48#define ICE1712_SUBDEVICE_VX442 0x12143cd6 49#define ICE1712_SUBDEVICE_VX442 0x12143cd6
49#define ICE1712_SUBDEVICE_MEDIASTATION 0x694c0100 50#define ICE1712_SUBDEVICE_MEDIASTATION 0x694c0100
51#define ICE1712_SUBDEVICE_EDIROLDA2496 0xce164010
50 52
51/* entry point */ 53/* entry point */
52extern struct snd_ice1712_card_info snd_ice1712_delta_cards[]; 54extern struct snd_ice1712_card_info snd_ice1712_delta_cards[];
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 32e4be8a187c..4aa4678e0a01 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -300,9 +300,13 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
300 300
301 *rchip = NULL; 301 *rchip = NULL;
302 302
303 if (snd_usb_get_speed(dev) != USB_SPEED_LOW && 303 switch (snd_usb_get_speed(dev)) {
304 snd_usb_get_speed(dev) != USB_SPEED_FULL && 304 case USB_SPEED_LOW:
305 snd_usb_get_speed(dev) != USB_SPEED_HIGH) { 305 case USB_SPEED_FULL:
306 case USB_SPEED_HIGH:
307 case USB_SPEED_SUPER:
308 break;
309 default:
306 snd_printk(KERN_ERR "unknown device speed %d\n", snd_usb_get_speed(dev)); 310 snd_printk(KERN_ERR "unknown device speed %d\n", snd_usb_get_speed(dev));
307 return -ENXIO; 311 return -ENXIO;
308 } 312 }
@@ -378,11 +382,22 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
378 if (len < sizeof(card->longname)) 382 if (len < sizeof(card->longname))
379 usb_make_path(dev, card->longname + len, sizeof(card->longname) - len); 383 usb_make_path(dev, card->longname + len, sizeof(card->longname) - len);
380 384
381 strlcat(card->longname, 385 switch (snd_usb_get_speed(dev)) {
382 snd_usb_get_speed(dev) == USB_SPEED_LOW ? ", low speed" : 386 case USB_SPEED_LOW:
383 snd_usb_get_speed(dev) == USB_SPEED_FULL ? ", full speed" : 387 strlcat(card->longname, ", low speed", sizeof(card->longname));
384 ", high speed", 388 break;
385 sizeof(card->longname)); 389 case USB_SPEED_FULL:
390 strlcat(card->longname, ", full speed", sizeof(card->longname));
391 break;
392 case USB_SPEED_HIGH:
393 strlcat(card->longname, ", high speed", sizeof(card->longname));
394 break;
395 case USB_SPEED_SUPER:
396 strlcat(card->longname, ", super speed", sizeof(card->longname));
397 break;
398 default:
399 break;
400 }
386 401
387 snd_usb_audio_create_proc(chip); 402 snd_usb_audio_create_proc(chip);
388 403
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index ef0a07e34844..b0ef9f501896 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -405,8 +405,6 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
405 break; 405 break;
406 case USB_ID(0x041e, 0x3020): /* Creative SB Audigy 2 NX */ 406 case USB_ID(0x041e, 0x3020): /* Creative SB Audigy 2 NX */
407 case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */ 407 case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
408 case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra 8 */
409 case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */
410 /* doesn't set the sample rate attribute, but supports it */ 408 /* doesn't set the sample rate attribute, but supports it */
411 fp->attributes |= UAC_EP_CS_ATTR_SAMPLE_RATE; 409 fp->attributes |= UAC_EP_CS_ATTR_SAMPLE_RATE;
412 break; 410 break;
diff --git a/sound/usb/helper.c b/sound/usb/helper.c
index d48d6f8f6ac9..f280c1903c25 100644
--- a/sound/usb/helper.c
+++ b/sound/usb/helper.c
@@ -103,11 +103,16 @@ int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request,
103unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip, 103unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip,
104 struct usb_host_interface *alts) 104 struct usb_host_interface *alts)
105{ 105{
106 if (snd_usb_get_speed(chip->dev) == USB_SPEED_HIGH && 106 switch (snd_usb_get_speed(chip->dev)) {
107 get_endpoint(alts, 0)->bInterval >= 1 && 107 case USB_SPEED_HIGH:
108 get_endpoint(alts, 0)->bInterval <= 4) 108 case USB_SPEED_SUPER:
109 return get_endpoint(alts, 0)->bInterval - 1; 109 if (get_endpoint(alts, 0)->bInterval >= 1 &&
110 else 110 get_endpoint(alts, 0)->bInterval <= 4)
111 return 0; 111 return get_endpoint(alts, 0)->bInterval - 1;
112 break;
113 default:
114 break;
115 }
116 return 0;
112} 117}
113 118
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index b9c2bc65f51a..156cd0716c42 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -834,7 +834,14 @@ static void snd_usbmidi_us122l_output(struct snd_usb_midi_out_endpoint *ep,
834 834
835 if (!ep->ports[0].active) 835 if (!ep->ports[0].active)
836 return; 836 return;
837 count = snd_usb_get_speed(ep->umidi->dev) == USB_SPEED_HIGH ? 1 : 2; 837 switch (snd_usb_get_speed(ep->umidi->dev)) {
838 case USB_SPEED_HIGH:
839 case USB_SPEED_SUPER:
840 count = 1;
841 break;
842 default:
843 count = 2;
844 }
838 count = snd_rawmidi_transmit(ep->ports[0].substream, 845 count = snd_rawmidi_transmit(ep->ports[0].substream,
839 urb->transfer_buffer, 846 urb->transfer_buffer,
840 count); 847 count);
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 3b5135c93062..f49756c1b837 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -466,7 +466,7 @@ static int hw_check_valid_format(struct snd_usb_substream *subs,
466 return 0; 466 return 0;
467 } 467 }
468 /* check whether the period time is >= the data packet interval */ 468 /* check whether the period time is >= the data packet interval */
469 if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH) { 469 if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) {
470 ptime = 125 * (1 << fp->datainterval); 470 ptime = 125 * (1 << fp->datainterval);
471 if (ptime > pt->max || (ptime == pt->max && pt->openmax)) { 471 if (ptime > pt->max || (ptime == pt->max && pt->openmax)) {
472 hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max); 472 hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max);
@@ -734,7 +734,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
734 } 734 }
735 735
736 param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; 736 param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME;
737 if (snd_usb_get_speed(subs->dev) != USB_SPEED_HIGH) 737 if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
738 /* full speed devices have fixed data packet interval */ 738 /* full speed devices have fixed data packet interval */
739 ptmin = 1000; 739 ptmin = 1000;
740 if (ptmin == 1000) 740 if (ptmin == 1000)
diff --git a/sound/usb/proc.c b/sound/usb/proc.c
index f5e3f356b95f..3c650ab3c91d 100644
--- a/sound/usb/proc.c
+++ b/sound/usb/proc.c
@@ -107,7 +107,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s
107 } 107 }
108 snd_iprintf(buffer, "\n"); 108 snd_iprintf(buffer, "\n");
109 } 109 }
110 if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH) 110 if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL)
111 snd_iprintf(buffer, " Data packet interval: %d us\n", 111 snd_iprintf(buffer, " Data packet interval: %d us\n",
112 125 * (1 << fp->datainterval)); 112 125 * (1 << fp->datainterval));
113 // snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize); 113 // snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize);
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 2e8003f98fca..c86c613e0b96 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -1136,11 +1136,34 @@ YAMAHA_DEVICE(0x7010, "UB99"),
1136 } 1136 }
1137}, 1137},
1138{ 1138{
1139 /* has ID 0x0066 when not in "Advanced Driver" mode */
1140 USB_DEVICE(0x0582, 0x0064),
1141 .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
1142 /* .vendor_name = "EDIROL", */
1143 /* .product_name = "PCR-1", */
1144 .ifnum = QUIRK_ANY_INTERFACE,
1145 .type = QUIRK_COMPOSITE,
1146 .data = (const struct snd_usb_audio_quirk[]) {
1147 {
1148 .ifnum = 1,
1149 .type = QUIRK_AUDIO_STANDARD_INTERFACE
1150 },
1151 {
1152 .ifnum = 2,
1153 .type = QUIRK_AUDIO_STANDARD_INTERFACE
1154 },
1155 {
1156 .ifnum = -1
1157 }
1158 }
1159 }
1160},
1161{
1139 /* has ID 0x0067 when not in "Advanced Driver" mode */ 1162 /* has ID 0x0067 when not in "Advanced Driver" mode */
1140 USB_DEVICE(0x0582, 0x0065), 1163 USB_DEVICE(0x0582, 0x0065),
1141 .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { 1164 .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
1142 .vendor_name = "EDIROL", 1165 /* .vendor_name = "EDIROL", */
1143 .product_name = "PCR-1", 1166 /* .product_name = "PCR-1", */
1144 .ifnum = 0, 1167 .ifnum = 0,
1145 .type = QUIRK_MIDI_FIXED_ENDPOINT, 1168 .type = QUIRK_MIDI_FIXED_ENDPOINT,
1146 .data = & (const struct snd_usb_midi_endpoint_info) { 1169 .data = & (const struct snd_usb_midi_endpoint_info) {
@@ -1525,6 +1548,50 @@ YAMAHA_DEVICE(0x7010, "UB99"),
1525 } 1548 }
1526 } 1549 }
1527}, 1550},
1551{
1552 /* has ID 0x0110 when not in Advanced Driver mode */
1553 USB_DEVICE_VENDOR_SPEC(0x0582, 0x010f),
1554 .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
1555 /* .vendor_name = "Roland", */
1556 /* .product_name = "A-PRO", */
1557 .ifnum = 1,
1558 .type = QUIRK_MIDI_FIXED_ENDPOINT,
1559 .data = & (const struct snd_usb_midi_endpoint_info) {
1560 .out_cables = 0x0003,
1561 .in_cables = 0x0007
1562 }
1563 }
1564},
1565{
1566 USB_DEVICE(0x0582, 0x0113),
1567 .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
1568 /* .vendor_name = "BOSS", */
1569 /* .product_name = "ME-25", */
1570 .ifnum = QUIRK_ANY_INTERFACE,
1571 .type = QUIRK_COMPOSITE,
1572 .data = (const struct snd_usb_audio_quirk[]) {
1573 {
1574 .ifnum = 0,
1575 .type = QUIRK_AUDIO_STANDARD_INTERFACE
1576 },
1577 {
1578 .ifnum = 1,
1579 .type = QUIRK_AUDIO_STANDARD_INTERFACE
1580 },
1581 {
1582 .ifnum = 2,
1583 .type = QUIRK_MIDI_FIXED_ENDPOINT,
1584 .data = & (const struct snd_usb_midi_endpoint_info) {
1585 .out_cables = 0x0001,
1586 .in_cables = 0x0001
1587 }
1588 },
1589 {
1590 .ifnum = -1
1591 }
1592 }
1593 }
1594},
1528 1595
1529/* Guillemot devices */ 1596/* Guillemot devices */
1530{ 1597{
@@ -1830,7 +1897,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
1830 USB_DEVICE(0x0763, 0x2080), 1897 USB_DEVICE(0x0763, 0x2080),
1831 .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { 1898 .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
1832 /* .vendor_name = "M-Audio", */ 1899 /* .vendor_name = "M-Audio", */
1833 /* .product_name = "Fast Track Ultra 8", */ 1900 /* .product_name = "Fast Track Ultra", */
1834 .ifnum = QUIRK_ANY_INTERFACE, 1901 .ifnum = QUIRK_ANY_INTERFACE,
1835 .type = QUIRK_COMPOSITE, 1902 .type = QUIRK_COMPOSITE,
1836 .data = & (const struct snd_usb_audio_quirk[]) { 1903 .data = & (const struct snd_usb_audio_quirk[]) {
@@ -1840,11 +1907,51 @@ YAMAHA_DEVICE(0x7010, "UB99"),
1840 }, 1907 },
1841 { 1908 {
1842 .ifnum = 1, 1909 .ifnum = 1,
1843 .type = QUIRK_AUDIO_STANDARD_INTERFACE 1910 .type = QUIRK_AUDIO_FIXED_ENDPOINT,
1911 .data = & (const struct audioformat) {
1912 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
1913 .channels = 8,
1914 .iface = 1,
1915 .altsetting = 1,
1916 .altset_idx = 1,
1917 .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
1918 .endpoint = 0x01,
1919 .ep_attr = 0x09,
1920 .rates = SNDRV_PCM_RATE_44100 |
1921 SNDRV_PCM_RATE_48000 |
1922 SNDRV_PCM_RATE_88200 |
1923 SNDRV_PCM_RATE_96000,
1924 .rate_min = 44100,
1925 .rate_max = 96000,
1926 .nr_rates = 4,
1927 .rate_table = (unsigned int[]) {
1928 44100, 48000, 88200, 96000
1929 }
1930 }
1844 }, 1931 },
1845 { 1932 {
1846 .ifnum = 2, 1933 .ifnum = 2,
1847 .type = QUIRK_AUDIO_STANDARD_INTERFACE 1934 .type = QUIRK_AUDIO_FIXED_ENDPOINT,
1935 .data = & (const struct audioformat) {
1936 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
1937 .channels = 8,
1938 .iface = 2,
1939 .altsetting = 1,
1940 .altset_idx = 1,
1941 .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
1942 .endpoint = 0x81,
1943 .ep_attr = 0x05,
1944 .rates = SNDRV_PCM_RATE_44100 |
1945 SNDRV_PCM_RATE_48000 |
1946 SNDRV_PCM_RATE_88200 |
1947 SNDRV_PCM_RATE_96000,
1948 .rate_min = 44100,
1949 .rate_max = 96000,
1950 .nr_rates = 4,
1951 .rate_table = (unsigned int[]) {
1952 44100, 48000, 88200, 96000
1953 }
1954 }
1848 }, 1955 },
1849 /* interface 3 (MIDI) is standard compliant */ 1956 /* interface 3 (MIDI) is standard compliant */
1850 { 1957 {
@@ -1867,11 +1974,51 @@ YAMAHA_DEVICE(0x7010, "UB99"),
1867 }, 1974 },
1868 { 1975 {
1869 .ifnum = 1, 1976 .ifnum = 1,
1870 .type = QUIRK_AUDIO_STANDARD_INTERFACE 1977 .type = QUIRK_AUDIO_FIXED_ENDPOINT,
1978 .data = & (const struct audioformat) {
1979 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
1980 .channels = 8,
1981 .iface = 1,
1982 .altsetting = 1,
1983 .altset_idx = 1,
1984 .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
1985 .endpoint = 0x01,
1986 .ep_attr = 0x09,
1987 .rates = SNDRV_PCM_RATE_44100 |
1988 SNDRV_PCM_RATE_48000 |
1989 SNDRV_PCM_RATE_88200 |
1990 SNDRV_PCM_RATE_96000,
1991 .rate_min = 44100,
1992 .rate_max = 96000,
1993 .nr_rates = 4,
1994 .rate_table = (unsigned int[]) {
1995 44100, 48000, 88200, 96000
1996 }
1997 }
1871 }, 1998 },
1872 { 1999 {
1873 .ifnum = 2, 2000 .ifnum = 2,
1874 .type = QUIRK_AUDIO_STANDARD_INTERFACE 2001 .type = QUIRK_AUDIO_FIXED_ENDPOINT,
2002 .data = & (const struct audioformat) {
2003 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
2004 .channels = 8,
2005 .iface = 2,
2006 .altsetting = 1,
2007 .altset_idx = 1,
2008 .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
2009 .endpoint = 0x81,
2010 .ep_attr = 0x05,
2011 .rates = SNDRV_PCM_RATE_44100 |
2012 SNDRV_PCM_RATE_48000 |
2013 SNDRV_PCM_RATE_88200 |
2014 SNDRV_PCM_RATE_96000,
2015 .rate_min = 44100,
2016 .rate_max = 96000,
2017 .nr_rates = 4,
2018 .rate_table = (unsigned int[]) {
2019 44100, 48000, 88200, 96000
2020 }
2021 }
1875 }, 2022 },
1876 /* interface 3 (MIDI) is standard compliant */ 2023 /* interface 3 (MIDI) is standard compliant */
1877 { 2024 {
diff --git a/sound/usb/urb.c b/sound/usb/urb.c
index de607d4411ac..8deeaad10f10 100644
--- a/sound/usb/urb.c
+++ b/sound/usb/urb.c
@@ -244,7 +244,7 @@ int snd_usb_init_substream_urbs(struct snd_usb_substream *subs,
244 else 244 else
245 subs->curpacksize = maxsize; 245 subs->curpacksize = maxsize;
246 246
247 if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH) 247 if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL)
248 packs_per_ms = 8 >> subs->datainterval; 248 packs_per_ms = 8 >> subs->datainterval;
249 else 249 else
250 packs_per_ms = 1; 250 packs_per_ms = 1;