aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/6fire/Makefile3
-rw-r--r--sound/usb/6fire/chip.c232
-rw-r--r--sound/usb/6fire/chip.h32
-rw-r--r--sound/usb/6fire/comm.c176
-rw-r--r--sound/usb/6fire/comm.h44
-rw-r--r--sound/usb/6fire/common.h30
-rw-r--r--sound/usb/6fire/control.c275
-rw-r--r--sound/usb/6fire/control.h37
-rw-r--r--sound/usb/6fire/firmware.c426
-rw-r--r--sound/usb/6fire/firmware.h27
-rw-r--r--sound/usb/6fire/midi.c203
-rw-r--r--sound/usb/6fire/midi.h46
-rw-r--r--sound/usb/6fire/pcm.c688
-rw-r--r--sound/usb/6fire/pcm.h76
-rw-r--r--sound/usb/Kconfig17
-rw-r--r--sound/usb/Makefile2
-rw-r--r--sound/usb/caiaq/audio.c1
-rw-r--r--sound/usb/caiaq/device.c6
-rw-r--r--sound/usb/caiaq/device.h1
-rw-r--r--sound/usb/card.c64
-rw-r--r--sound/usb/midi.c8
-rw-r--r--sound/usb/mixer.c65
-rw-r--r--sound/usb/mixer.h2
-rw-r--r--sound/usb/mixer_quirks.c174
-rw-r--r--sound/usb/pcm.c20
-rw-r--r--sound/usb/power.h17
-rw-r--r--sound/usb/quirks-table.h14
-rw-r--r--sound/usb/quirks.c56
-rw-r--r--sound/usb/usbaudio.h6
29 files changed, 2704 insertions, 44 deletions
diff --git a/sound/usb/6fire/Makefile b/sound/usb/6fire/Makefile
new file mode 100644
index 000000000000..dfce6ec53513
--- /dev/null
+++ b/sound/usb/6fire/Makefile
@@ -0,0 +1,3 @@
1snd-usb-6fire-objs += chip.o comm.o midi.o control.o firmware.o pcm.o
2obj-$(CONFIG_SND_USB_6FIRE) += snd-usb-6fire.o
3
diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c
new file mode 100644
index 000000000000..c7dca7b0b9fe
--- /dev/null
+++ b/sound/usb/6fire/chip.c
@@ -0,0 +1,232 @@
1/*
2 * Linux driver for TerraTec DMX 6Fire USB
3 *
4 * Main routines and module definitions.
5 *
6 * Author: Torsten Schenk <torsten.schenk@zoho.com>
7 * Created: Jan 01, 2011
8 * Version: 0.3.0
9 * Copyright: (C) Torsten Schenk
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 */
16
17#include "chip.h"
18#include "firmware.h"
19#include "pcm.h"
20#include "control.h"
21#include "comm.h"
22#include "midi.h"
23
24#include <linux/moduleparam.h>
25#include <linux/interrupt.h>
26#include <linux/module.h>
27#include <linux/init.h>
28#include <linux/gfp.h>
29#include <sound/initval.h>
30
31MODULE_AUTHOR("Torsten Schenk <torsten.schenk@zoho.com>");
32MODULE_DESCRIPTION("TerraTec DMX 6Fire USB audio driver, version 0.3.0");
33MODULE_LICENSE("GPL v2");
34MODULE_SUPPORTED_DEVICE("{{TerraTec, DMX 6Fire USB}}");
35
36static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */
37static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for card */
38static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable card */
39static struct sfire_chip *chips[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
40static struct usb_device *devices[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
41
42module_param_array(index, int, NULL, 0444);
43MODULE_PARM_DESC(index, "Index value for the 6fire sound device");
44module_param_array(id, charp, NULL, 0444);
45MODULE_PARM_DESC(id, "ID string for the 6fire sound device.");
46module_param_array(enable, bool, NULL, 0444);
47MODULE_PARM_DESC(enable, "Enable the 6fire sound device.");
48
49static DEFINE_MUTEX(register_mutex);
50
51static void usb6fire_chip_abort(struct sfire_chip *chip)
52{
53 if (chip) {
54 if (chip->pcm)
55 usb6fire_pcm_abort(chip);
56 if (chip->midi)
57 usb6fire_midi_abort(chip);
58 if (chip->comm)
59 usb6fire_comm_abort(chip);
60 if (chip->control)
61 usb6fire_control_abort(chip);
62 if (chip->card) {
63 snd_card_disconnect(chip->card);
64 snd_card_free_when_closed(chip->card);
65 chip->card = NULL;
66 }
67 }
68}
69
70static void usb6fire_chip_destroy(struct sfire_chip *chip)
71{
72 if (chip) {
73 if (chip->pcm)
74 usb6fire_pcm_destroy(chip);
75 if (chip->midi)
76 usb6fire_midi_destroy(chip);
77 if (chip->comm)
78 usb6fire_comm_destroy(chip);
79 if (chip->control)
80 usb6fire_control_destroy(chip);
81 if (chip->card)
82 snd_card_free(chip->card);
83 }
84}
85
86static int __devinit usb6fire_chip_probe(struct usb_interface *intf,
87 const struct usb_device_id *usb_id)
88{
89 int ret;
90 int i;
91 struct sfire_chip *chip = NULL;
92 struct usb_device *device = interface_to_usbdev(intf);
93 int regidx = -1; /* index in module parameter array */
94 struct snd_card *card = NULL;
95
96 /* look if we already serve this card and return if so */
97 mutex_lock(&register_mutex);
98 for (i = 0; i < SNDRV_CARDS; i++) {
99 if (devices[i] == device) {
100 if (chips[i])
101 chips[i]->intf_count++;
102 usb_set_intfdata(intf, chips[i]);
103 mutex_unlock(&register_mutex);
104 return 0;
105 } else if (regidx < 0)
106 regidx = i;
107 }
108 if (regidx < 0) {
109 mutex_unlock(&register_mutex);
110 snd_printk(KERN_ERR PREFIX "too many cards registered.\n");
111 return -ENODEV;
112 }
113 devices[regidx] = device;
114 mutex_unlock(&register_mutex);
115
116 /* check, if firmware is present on device, upload it if not */
117 ret = usb6fire_fw_init(intf);
118 if (ret < 0)
119 return ret;
120 else if (ret == FW_NOT_READY) /* firmware update performed */
121 return 0;
122
123 /* if we are here, card can be registered in alsa. */
124 if (usb_set_interface(device, 0, 0) != 0) {
125 snd_printk(KERN_ERR PREFIX "can't set first interface.\n");
126 return -EIO;
127 }
128 ret = snd_card_create(index[regidx], id[regidx], THIS_MODULE,
129 sizeof(struct sfire_chip), &card);
130 if (ret < 0) {
131 snd_printk(KERN_ERR PREFIX "cannot create alsa card.\n");
132 return ret;
133 }
134 strcpy(card->driver, "6FireUSB");
135 strcpy(card->shortname, "TerraTec DMX6FireUSB");
136 sprintf(card->longname, "%s at %d:%d", card->shortname,
137 device->bus->busnum, device->devnum);
138 snd_card_set_dev(card, &intf->dev);
139
140 chip = card->private_data;
141 chips[regidx] = chip;
142 chip->dev = device;
143 chip->regidx = regidx;
144 chip->intf_count = 1;
145 chip->card = card;
146
147 ret = usb6fire_comm_init(chip);
148 if (ret < 0) {
149 usb6fire_chip_destroy(chip);
150 return ret;
151 }
152
153 ret = usb6fire_midi_init(chip);
154 if (ret < 0) {
155 usb6fire_chip_destroy(chip);
156 return ret;
157 }
158
159 ret = usb6fire_pcm_init(chip);
160 if (ret < 0) {
161 usb6fire_chip_destroy(chip);
162 return ret;
163 }
164
165 ret = usb6fire_control_init(chip);
166 if (ret < 0) {
167 usb6fire_chip_destroy(chip);
168 return ret;
169 }
170
171 ret = snd_card_register(card);
172 if (ret < 0) {
173 snd_printk(KERN_ERR PREFIX "cannot register card.");
174 usb6fire_chip_destroy(chip);
175 return ret;
176 }
177 usb_set_intfdata(intf, chip);
178 return 0;
179}
180
181static void usb6fire_chip_disconnect(struct usb_interface *intf)
182{
183 struct sfire_chip *chip;
184 struct snd_card *card;
185
186 chip = usb_get_intfdata(intf);
187 if (chip) { /* if !chip, fw upload has been performed */
188 card = chip->card;
189 chip->intf_count--;
190 if (!chip->intf_count) {
191 mutex_lock(&register_mutex);
192 devices[chip->regidx] = NULL;
193 chips[chip->regidx] = NULL;
194 mutex_unlock(&register_mutex);
195
196 chip->shutdown = true;
197 usb6fire_chip_abort(chip);
198 usb6fire_chip_destroy(chip);
199 }
200 }
201}
202
203static struct usb_device_id device_table[] = {
204 {
205 .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
206 .idVendor = 0x0ccd,
207 .idProduct = 0x0080
208 },
209 {}
210};
211
212MODULE_DEVICE_TABLE(usb, device_table);
213
214static struct usb_driver driver = {
215 .name = "snd-usb-6fire",
216 .probe = usb6fire_chip_probe,
217 .disconnect = usb6fire_chip_disconnect,
218 .id_table = device_table,
219};
220
221static int __init usb6fire_chip_init(void)
222{
223 return usb_register(&driver);
224}
225
226static void __exit usb6fire_chip_cleanup(void)
227{
228 usb_deregister(&driver);
229}
230
231module_init(usb6fire_chip_init);
232module_exit(usb6fire_chip_cleanup);
diff --git a/sound/usb/6fire/chip.h b/sound/usb/6fire/chip.h
new file mode 100644
index 000000000000..d11e5cb520f0
--- /dev/null
+++ b/sound/usb/6fire/chip.h
@@ -0,0 +1,32 @@
1/*
2 * Linux driver for TerraTec DMX 6Fire USB
3 *
4 * Author: Torsten Schenk <torsten.schenk@zoho.com>
5 * Created: Jan 01, 2011
6 * Version: 0.3.0
7 * Copyright: (C) Torsten Schenk
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 */
14#ifndef USB6FIRE_CHIP_H
15#define USB6FIRE_CHIP_H
16
17#include "common.h"
18
19struct sfire_chip {
20 struct usb_device *dev;
21 struct snd_card *card;
22 int intf_count; /* number of registered interfaces */
23 int regidx; /* index in module parameter arrays */
24 bool shutdown;
25
26 struct midi_runtime *midi;
27 struct pcm_runtime *pcm;
28 struct control_runtime *control;
29 struct comm_runtime *comm;
30};
31#endif /* USB6FIRE_CHIP_H */
32
diff --git a/sound/usb/6fire/comm.c b/sound/usb/6fire/comm.c
new file mode 100644
index 000000000000..c994daa57af2
--- /dev/null
+++ b/sound/usb/6fire/comm.c
@@ -0,0 +1,176 @@
1/*
2 * Linux driver for TerraTec DMX 6Fire USB
3 *
4 * Device communications
5 *
6 * Author: Torsten Schenk <torsten.schenk@zoho.com>
7 * Created: Jan 01, 2011
8 * Version: 0.3.0
9 * Copyright: (C) Torsten Schenk
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 */
16
17#include "comm.h"
18#include "chip.h"
19#include "midi.h"
20
21enum {
22 COMM_EP = 1,
23 COMM_FPGA_EP = 2
24};
25
26static void usb6fire_comm_init_urb(struct comm_runtime *rt, struct urb *urb,
27 u8 *buffer, void *context, void(*handler)(struct urb *urb))
28{
29 usb_init_urb(urb);
30 urb->transfer_buffer = buffer;
31 urb->pipe = usb_sndintpipe(rt->chip->dev, COMM_EP);
32 urb->complete = handler;
33 urb->context = context;
34 urb->interval = 1;
35 urb->dev = rt->chip->dev;
36}
37
38static void usb6fire_comm_receiver_handler(struct urb *urb)
39{
40 struct comm_runtime *rt = urb->context;
41 struct midi_runtime *midi_rt = rt->chip->midi;
42
43 if (!urb->status) {
44 if (rt->receiver_buffer[0] == 0x10) /* midi in event */
45 if (midi_rt)
46 midi_rt->in_received(midi_rt,
47 rt->receiver_buffer + 2,
48 rt->receiver_buffer[1]);
49 }
50
51 if (!rt->chip->shutdown) {
52 urb->status = 0;
53 urb->actual_length = 0;
54 if (usb_submit_urb(urb, GFP_ATOMIC) < 0)
55 snd_printk(KERN_WARNING PREFIX
56 "comm data receiver aborted.\n");
57 }
58}
59
60static void usb6fire_comm_init_buffer(u8 *buffer, u8 id, u8 request,
61 u8 reg, u8 vl, u8 vh)
62{
63 buffer[0] = 0x01;
64 buffer[2] = request;
65 buffer[3] = id;
66 switch (request) {
67 case 0x02:
68 buffer[1] = 0x05; /* length (starting at buffer[2]) */
69 buffer[4] = reg;
70 buffer[5] = vl;
71 buffer[6] = vh;
72 break;
73
74 case 0x12:
75 buffer[1] = 0x0b; /* length (starting at buffer[2]) */
76 buffer[4] = 0x00;
77 buffer[5] = 0x18;
78 buffer[6] = 0x05;
79 buffer[7] = 0x00;
80 buffer[8] = 0x01;
81 buffer[9] = 0x00;
82 buffer[10] = 0x9e;
83 buffer[11] = reg;
84 buffer[12] = vl;
85 break;
86
87 case 0x20:
88 case 0x21:
89 case 0x22:
90 buffer[1] = 0x04;
91 buffer[4] = reg;
92 buffer[5] = vl;
93 break;
94 }
95}
96
97static int usb6fire_comm_send_buffer(u8 *buffer, struct usb_device *dev)
98{
99 int ret;
100 int actual_len;
101
102 ret = usb_interrupt_msg(dev, usb_sndintpipe(dev, COMM_EP),
103 buffer, buffer[1] + 2, &actual_len, HZ);
104 if (ret < 0)
105 return ret;
106 else if (actual_len != buffer[1] + 2)
107 return -EIO;
108 return 0;
109}
110
111static int usb6fire_comm_write8(struct comm_runtime *rt, u8 request,
112 u8 reg, u8 value)
113{
114 u8 buffer[13]; /* 13: maximum length of message */
115
116 usb6fire_comm_init_buffer(buffer, 0x00, request, reg, value, 0x00);
117 return usb6fire_comm_send_buffer(buffer, rt->chip->dev);
118}
119
120static int usb6fire_comm_write16(struct comm_runtime *rt, u8 request,
121 u8 reg, u8 vl, u8 vh)
122{
123 u8 buffer[13]; /* 13: maximum length of message */
124
125 usb6fire_comm_init_buffer(buffer, 0x00, request, reg, vl, vh);
126 return usb6fire_comm_send_buffer(buffer, rt->chip->dev);
127}
128
129int __devinit usb6fire_comm_init(struct sfire_chip *chip)
130{
131 struct comm_runtime *rt = kzalloc(sizeof(struct comm_runtime),
132 GFP_KERNEL);
133 struct urb *urb = &rt->receiver;
134 int ret;
135
136 if (!rt)
137 return -ENOMEM;
138
139 rt->serial = 1;
140 rt->chip = chip;
141 usb_init_urb(urb);
142 rt->init_urb = usb6fire_comm_init_urb;
143 rt->write8 = usb6fire_comm_write8;
144 rt->write16 = usb6fire_comm_write16;
145
146 /* submit an urb that receives communication data from device */
147 urb->transfer_buffer = rt->receiver_buffer;
148 urb->transfer_buffer_length = COMM_RECEIVER_BUFSIZE;
149 urb->pipe = usb_rcvintpipe(chip->dev, COMM_EP);
150 urb->dev = chip->dev;
151 urb->complete = usb6fire_comm_receiver_handler;
152 urb->context = rt;
153 urb->interval = 1;
154 ret = usb_submit_urb(urb, GFP_KERNEL);
155 if (ret < 0) {
156 kfree(rt);
157 snd_printk(KERN_ERR PREFIX "cannot create comm data receiver.");
158 return ret;
159 }
160 chip->comm = rt;
161 return 0;
162}
163
164void usb6fire_comm_abort(struct sfire_chip *chip)
165{
166 struct comm_runtime *rt = chip->comm;
167
168 if (rt)
169 usb_poison_urb(&rt->receiver);
170}
171
172void usb6fire_comm_destroy(struct sfire_chip *chip)
173{
174 kfree(chip->comm);
175 chip->comm = NULL;
176}
diff --git a/sound/usb/6fire/comm.h b/sound/usb/6fire/comm.h
new file mode 100644
index 000000000000..edc5dc84b888
--- /dev/null
+++ b/sound/usb/6fire/comm.h
@@ -0,0 +1,44 @@
1/*
2 * Linux driver for TerraTec DMX 6Fire USB
3 *
4 * Author: Torsten Schenk <torsten.schenk@zoho.com>
5 * Created: Jan 01, 2011
6 * Version: 0.3.0
7 * Copyright: (C) Torsten Schenk
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 */
14#ifndef USB6FIRE_COMM_H
15#define USB6FIRE_COMM_H
16
17#include "common.h"
18
19enum /* settings for comm */
20{
21 COMM_RECEIVER_BUFSIZE = 64,
22};
23
24struct comm_runtime {
25 struct sfire_chip *chip;
26
27 struct urb receiver;
28 u8 receiver_buffer[COMM_RECEIVER_BUFSIZE];
29
30 u8 serial; /* urb serial */
31
32 void (*init_urb)(struct comm_runtime *rt, struct urb *urb, u8 *buffer,
33 void *context, void(*handler)(struct urb *urb));
34 /* writes control data to the device */
35 int (*write8)(struct comm_runtime *rt, u8 request, u8 reg, u8 value);
36 int (*write16)(struct comm_runtime *rt, u8 request, u8 reg,
37 u8 vh, u8 vl);
38};
39
40int __devinit usb6fire_comm_init(struct sfire_chip *chip);
41void usb6fire_comm_abort(struct sfire_chip *chip);
42void usb6fire_comm_destroy(struct sfire_chip *chip);
43#endif /* USB6FIRE_COMM_H */
44
diff --git a/sound/usb/6fire/common.h b/sound/usb/6fire/common.h
new file mode 100644
index 000000000000..7dbeb4a37831
--- /dev/null
+++ b/sound/usb/6fire/common.h
@@ -0,0 +1,30 @@
1/*
2 * Linux driver for TerraTec DMX 6Fire USB
3 *
4 * Author: Torsten Schenk <torsten.schenk@zoho.com>
5 * Created: Jan 01, 2011
6 * Version: 0.3.0
7 * Copyright: (C) Torsten Schenk
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 */
14
15#ifndef USB6FIRE_COMMON_H
16#define USB6FIRE_COMMON_H
17
18#include <linux/slab.h>
19#include <linux/usb.h>
20#include <sound/core.h>
21
22#define PREFIX "6fire: "
23
24struct sfire_chip;
25struct midi_runtime;
26struct pcm_runtime;
27struct control_runtime;
28struct comm_runtime;
29#endif /* USB6FIRE_COMMON_H */
30
diff --git a/sound/usb/6fire/control.c b/sound/usb/6fire/control.c
new file mode 100644
index 000000000000..248463511186
--- /dev/null
+++ b/sound/usb/6fire/control.c
@@ -0,0 +1,275 @@
1/*
2 * Linux driver for TerraTec DMX 6Fire USB
3 *
4 * Mixer control
5 *
6 * Author: Torsten Schenk <torsten.schenk@zoho.com>
7 * Created: Jan 01, 2011
8 * Version: 0.3.0
9 * Copyright: (C) Torsten Schenk
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 */
16
17#include <linux/interrupt.h>
18#include <sound/control.h>
19
20#include "control.h"
21#include "comm.h"
22#include "chip.h"
23
24static char *opt_coax_texts[2] = { "Optical", "Coax" };
25static char *line_phono_texts[2] = { "Line", "Phono" };
26
27/*
28 * calculated with $value\[i\] = 128 \cdot sqrt[3]{\frac{i}{128}}$
29 * this is done because the linear values cause rapid degredation
30 * of volume in the uppermost region.
31 */
32static const u8 log_volume_table[128] = {
33 0x00, 0x19, 0x20, 0x24, 0x28, 0x2b, 0x2e, 0x30, 0x32, 0x34,
34 0x36, 0x38, 0x3a, 0x3b, 0x3d, 0x3e, 0x40, 0x41, 0x42, 0x43,
35 0x44, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e,
36 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x53, 0x54, 0x55, 0x56,
37 0x56, 0x57, 0x58, 0x58, 0x59, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c,
38 0x5d, 0x5e, 0x5e, 0x5f, 0x60, 0x60, 0x61, 0x61, 0x62, 0x62,
39 0x63, 0x63, 0x64, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67, 0x68,
40 0x68, 0x69, 0x69, 0x6a, 0x6a, 0x6b, 0x6b, 0x6c, 0x6c, 0x6c,
41 0x6d, 0x6d, 0x6e, 0x6e, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x71,
42 0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x74, 0x75, 0x75,
43 0x75, 0x76, 0x76, 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79,
44 0x79, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c,
45 0x7d, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f };
46
47/*
48 * data that needs to be sent to device. sets up card internal stuff.
49 * values dumped from windows driver and filtered by trial'n'error.
50 */
51static const struct {
52 u8 type;
53 u8 reg;
54 u8 value;
55}
56init_data[] = {
57 { 0x22, 0x00, 0x00 }, { 0x20, 0x00, 0x08 }, { 0x22, 0x01, 0x01 },
58 { 0x20, 0x01, 0x08 }, { 0x22, 0x02, 0x00 }, { 0x20, 0x02, 0x08 },
59 { 0x22, 0x03, 0x00 }, { 0x20, 0x03, 0x08 }, { 0x22, 0x04, 0x00 },
60 { 0x20, 0x04, 0x08 }, { 0x22, 0x05, 0x01 }, { 0x20, 0x05, 0x08 },
61 { 0x22, 0x04, 0x01 }, { 0x12, 0x04, 0x00 }, { 0x12, 0x05, 0x00 },
62 { 0x12, 0x0d, 0x78 }, { 0x12, 0x21, 0x82 }, { 0x12, 0x22, 0x80 },
63 { 0x12, 0x23, 0x00 }, { 0x12, 0x06, 0x02 }, { 0x12, 0x03, 0x00 },
64 { 0x12, 0x02, 0x00 }, { 0x22, 0x03, 0x01 },
65 { 0 } /* TERMINATING ENTRY */
66};
67
68static void usb6fire_control_master_vol_update(struct control_runtime *rt)
69{
70 struct comm_runtime *comm_rt = rt->chip->comm;
71 if (comm_rt) {
72 /* set volume */
73 comm_rt->write8(comm_rt, 0x12, 0x0f, 0x7f -
74 log_volume_table[rt->master_vol]);
75 /* unmute */
76 comm_rt->write8(comm_rt, 0x12, 0x0e, 0x00);
77 }
78}
79
80static void usb6fire_control_line_phono_update(struct control_runtime *rt)
81{
82 struct comm_runtime *comm_rt = rt->chip->comm;
83 if (comm_rt) {
84 comm_rt->write8(comm_rt, 0x22, 0x02, rt->line_phono_switch);
85 comm_rt->write8(comm_rt, 0x21, 0x02, rt->line_phono_switch);
86 }
87}
88
89static void usb6fire_control_opt_coax_update(struct control_runtime *rt)
90{
91 struct comm_runtime *comm_rt = rt->chip->comm;
92 if (comm_rt) {
93 comm_rt->write8(comm_rt, 0x22, 0x00, rt->opt_coax_switch);
94 comm_rt->write8(comm_rt, 0x21, 0x00, rt->opt_coax_switch);
95 }
96}
97
98static int usb6fire_control_master_vol_info(struct snd_kcontrol *kcontrol,
99 struct snd_ctl_elem_info *uinfo)
100{
101 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
102 uinfo->count = 1;
103 uinfo->value.integer.min = 0;
104 uinfo->value.integer.max = 127;
105 return 0;
106}
107
108static int usb6fire_control_master_vol_put(struct snd_kcontrol *kcontrol,
109 struct snd_ctl_elem_value *ucontrol)
110{
111 struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
112 int changed = 0;
113 if (rt->master_vol != ucontrol->value.integer.value[0]) {
114 rt->master_vol = ucontrol->value.integer.value[0];
115 usb6fire_control_master_vol_update(rt);
116 changed = 1;
117 }
118 return changed;
119}
120
121static int usb6fire_control_master_vol_get(struct snd_kcontrol *kcontrol,
122 struct snd_ctl_elem_value *ucontrol)
123{
124 struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
125 ucontrol->value.integer.value[0] = rt->master_vol;
126 return 0;
127}
128
129static int usb6fire_control_line_phono_info(struct snd_kcontrol *kcontrol,
130 struct snd_ctl_elem_info *uinfo)
131{
132 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
133 uinfo->count = 1;
134 uinfo->value.enumerated.items = 2;
135 if (uinfo->value.enumerated.item > 1)
136 uinfo->value.enumerated.item = 1;
137 strcpy(uinfo->value.enumerated.name,
138 line_phono_texts[uinfo->value.enumerated.item]);
139 return 0;
140}
141
142static int usb6fire_control_line_phono_put(struct snd_kcontrol *kcontrol,
143 struct snd_ctl_elem_value *ucontrol)
144{
145 struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
146 int changed = 0;
147 if (rt->line_phono_switch != ucontrol->value.integer.value[0]) {
148 rt->line_phono_switch = ucontrol->value.integer.value[0];
149 usb6fire_control_line_phono_update(rt);
150 changed = 1;
151 }
152 return changed;
153}
154
155static int usb6fire_control_line_phono_get(struct snd_kcontrol *kcontrol,
156 struct snd_ctl_elem_value *ucontrol)
157{
158 struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
159 ucontrol->value.integer.value[0] = rt->line_phono_switch;
160 return 0;
161}
162
163static int usb6fire_control_opt_coax_info(struct snd_kcontrol *kcontrol,
164 struct snd_ctl_elem_info *uinfo)
165{
166 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
167 uinfo->count = 1;
168 uinfo->value.enumerated.items = 2;
169 if (uinfo->value.enumerated.item > 1)
170 uinfo->value.enumerated.item = 1;
171 strcpy(uinfo->value.enumerated.name,
172 opt_coax_texts[uinfo->value.enumerated.item]);
173 return 0;
174}
175
176static int usb6fire_control_opt_coax_put(struct snd_kcontrol *kcontrol,
177 struct snd_ctl_elem_value *ucontrol)
178{
179 struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
180 int changed = 0;
181
182 if (rt->opt_coax_switch != ucontrol->value.enumerated.item[0]) {
183 rt->opt_coax_switch = ucontrol->value.enumerated.item[0];
184 usb6fire_control_opt_coax_update(rt);
185 changed = 1;
186 }
187 return changed;
188}
189
190static int usb6fire_control_opt_coax_get(struct snd_kcontrol *kcontrol,
191 struct snd_ctl_elem_value *ucontrol)
192{
193 struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
194 ucontrol->value.enumerated.item[0] = rt->opt_coax_switch;
195 return 0;
196}
197
198static struct __devinitdata snd_kcontrol_new elements[] = {
199 {
200 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
201 .name = "Master Playback Volume",
202 .index = 0,
203 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
204 .info = usb6fire_control_master_vol_info,
205 .get = usb6fire_control_master_vol_get,
206 .put = usb6fire_control_master_vol_put
207 },
208 {
209 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
210 .name = "Line/Phono Capture Route",
211 .index = 0,
212 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
213 .info = usb6fire_control_line_phono_info,
214 .get = usb6fire_control_line_phono_get,
215 .put = usb6fire_control_line_phono_put
216 },
217 {
218 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
219 .name = "Opt/Coax Capture Route",
220 .index = 0,
221 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
222 .info = usb6fire_control_opt_coax_info,
223 .get = usb6fire_control_opt_coax_get,
224 .put = usb6fire_control_opt_coax_put
225 },
226 {}
227};
228
229int __devinit usb6fire_control_init(struct sfire_chip *chip)
230{
231 int i;
232 int ret;
233 struct control_runtime *rt = kzalloc(sizeof(struct control_runtime),
234 GFP_KERNEL);
235 struct comm_runtime *comm_rt = chip->comm;
236
237 if (!rt)
238 return -ENOMEM;
239
240 rt->chip = chip;
241
242 i = 0;
243 while (init_data[i].type) {
244 comm_rt->write8(comm_rt, init_data[i].type, init_data[i].reg,
245 init_data[i].value);
246 i++;
247 }
248
249 usb6fire_control_opt_coax_update(rt);
250 usb6fire_control_line_phono_update(rt);
251 usb6fire_control_master_vol_update(rt);
252
253 i = 0;
254 while (elements[i].name) {
255 ret = snd_ctl_add(chip->card, snd_ctl_new1(&elements[i], rt));
256 if (ret < 0) {
257 kfree(rt);
258 snd_printk(KERN_ERR PREFIX "cannot add control.\n");
259 return ret;
260 }
261 i++;
262 }
263
264 chip->control = rt;
265 return 0;
266}
267
268void usb6fire_control_abort(struct sfire_chip *chip)
269{}
270
271void usb6fire_control_destroy(struct sfire_chip *chip)
272{
273 kfree(chip->control);
274 chip->control = NULL;
275}
diff --git a/sound/usb/6fire/control.h b/sound/usb/6fire/control.h
new file mode 100644
index 000000000000..b534c777ab02
--- /dev/null
+++ b/sound/usb/6fire/control.h
@@ -0,0 +1,37 @@
1/*
2 * Linux driver for TerraTec DMX 6Fire USB
3 *
4 * Author: Torsten Schenk <torsten.schenk@zoho.com>
5 * Created: Jan 01, 2011
6 * Version: 0.3.0
7 * Copyright: (C) Torsten Schenk
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 */
14
15#ifndef USB6FIRE_CONTROL_H
16#define USB6FIRE_CONTROL_H
17
18#include "common.h"
19
20enum {
21 CONTROL_MAX_ELEMENTS = 32
22};
23
24struct control_runtime {
25 struct sfire_chip *chip;
26
27 struct snd_kcontrol *element[CONTROL_MAX_ELEMENTS];
28 bool opt_coax_switch;
29 bool line_phono_switch;
30 u8 master_vol;
31};
32
33int __devinit usb6fire_control_init(struct sfire_chip *chip);
34void usb6fire_control_abort(struct sfire_chip *chip);
35void usb6fire_control_destroy(struct sfire_chip *chip);
36#endif /* USB6FIRE_CONTROL_H */
37
diff --git a/sound/usb/6fire/firmware.c b/sound/usb/6fire/firmware.c
new file mode 100644
index 000000000000..9081a54a9c6c
--- /dev/null
+++ b/sound/usb/6fire/firmware.c
@@ -0,0 +1,426 @@
1/*
2 * Linux driver for TerraTec DMX 6Fire USB
3 *
4 * Firmware loader
5 *
6 * Currently not working for all devices. To be able to use the device
7 * in linux, it is also possible to let the windows driver upload the firmware.
8 * For that, start the computer in windows and reboot.
9 * As long as the device is connected to the power supply, no firmware reload
10 * needs to be performed.
11 *
12 * Author: Torsten Schenk <torsten.schenk@zoho.com>
13 * Created: Jan 01, 2011
14 * Version: 0.3.0
15 * Copyright: (C) Torsten Schenk
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
21 */
22
23#include <linux/firmware.h>
24
25#include "firmware.h"
26#include "chip.h"
27
28MODULE_FIRMWARE("6fire/dmx6firel2.ihx");
29MODULE_FIRMWARE("6fire/dmx6fireap.ihx");
30MODULE_FIRMWARE("6fire/dmx6firecf.bin");
31
32enum {
33 FPGA_BUFSIZE = 512, FPGA_EP = 2
34};
35
36static const u8 BIT_REVERSE_TABLE[256] = {
37 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50,
38 0xd0, 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8,
39 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04,
40 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4,
41 0x34, 0xb4, 0x74, 0xf4, 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c,
42 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82,
43 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32,
44 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
45 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 0x06, 0x86, 0x46,
46 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6,
47 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e,
48 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1,
49 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71,
50 0xf1, 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99,
51 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25,
52 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
53 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d,
54 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3,
55 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 0x0b,
56 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb,
57 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67,
58 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 0x0f, 0x8f,
59 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f,
60 0xbf, 0x7f, 0xff };
61
62/*
63 * wMaxPacketSize of pcm endpoints.
64 * keep synced with rates_in_packet_size and rates_out_packet_size in pcm.c
65 * fpp: frames per isopacket
66 *
67 * CAUTION: keep sizeof <= buffer[] in usb6fire_fw_init
68 */
69static const u8 ep_w_max_packet_size[] = {
70 0xe4, 0x00, 0xe4, 0x00, /* alt 1: 228 EP2 and EP6 (7 fpp) */
71 0xa4, 0x01, 0xa4, 0x01, /* alt 2: 420 EP2 and EP6 (13 fpp)*/
72 0x94, 0x01, 0x5c, 0x02 /* alt 3: 404 EP2 and 604 EP6 (25 fpp) */
73};
74
75struct ihex_record {
76 u16 address;
77 u8 len;
78 u8 data[256];
79 char error; /* true if an error occured parsing this record */
80
81 u8 max_len; /* maximum record length in whole ihex */
82
83 /* private */
84 const char *txt_data;
85 unsigned int txt_length;
86 unsigned int txt_offset; /* current position in txt_data */
87};
88
89static u8 usb6fire_fw_ihex_nibble(const u8 n)
90{
91 if (n >= '0' && n <= '9')
92 return n - '0';
93 else if (n >= 'A' && n <= 'F')
94 return n - ('A' - 10);
95 else if (n >= 'a' && n <= 'f')
96 return n - ('a' - 10);
97 return 0;
98}
99
100static u8 usb6fire_fw_ihex_hex(const u8 *data, u8 *crc)
101{
102 u8 val = (usb6fire_fw_ihex_nibble(data[0]) << 4) |
103 usb6fire_fw_ihex_nibble(data[1]);
104 *crc += val;
105 return val;
106}
107
108/*
109 * returns true if record is available, false otherwise.
110 * iff an error occured, false will be returned and record->error will be true.
111 */
112static bool usb6fire_fw_ihex_next_record(struct ihex_record *record)
113{
114 u8 crc = 0;
115 u8 type;
116 int i;
117
118 record->error = false;
119
120 /* find begin of record (marked by a colon) */
121 while (record->txt_offset < record->txt_length
122 && record->txt_data[record->txt_offset] != ':')
123 record->txt_offset++;
124 if (record->txt_offset == record->txt_length)
125 return false;
126
127 /* number of characters needed for len, addr and type entries */
128 record->txt_offset++;
129 if (record->txt_offset + 8 > record->txt_length) {
130 record->error = true;
131 return false;
132 }
133
134 record->len = usb6fire_fw_ihex_hex(record->txt_data +
135 record->txt_offset, &crc);
136 record->txt_offset += 2;
137 record->address = usb6fire_fw_ihex_hex(record->txt_data +
138 record->txt_offset, &crc) << 8;
139 record->txt_offset += 2;
140 record->address |= usb6fire_fw_ihex_hex(record->txt_data +
141 record->txt_offset, &crc);
142 record->txt_offset += 2;
143 type = usb6fire_fw_ihex_hex(record->txt_data +
144 record->txt_offset, &crc);
145 record->txt_offset += 2;
146
147 /* number of characters needed for data and crc entries */
148 if (record->txt_offset + 2 * (record->len + 1) > record->txt_length) {
149 record->error = true;
150 return false;
151 }
152 for (i = 0; i < record->len; i++) {
153 record->data[i] = usb6fire_fw_ihex_hex(record->txt_data
154 + record->txt_offset, &crc);
155 record->txt_offset += 2;
156 }
157 usb6fire_fw_ihex_hex(record->txt_data + record->txt_offset, &crc);
158 if (crc) {
159 record->error = true;
160 return false;
161 }
162
163 if (type == 1 || !record->len) /* eof */
164 return false;
165 else if (type == 0)
166 return true;
167 else {
168 record->error = true;
169 return false;
170 }
171}
172
173static int usb6fire_fw_ihex_init(const struct firmware *fw,
174 struct ihex_record *record)
175{
176 record->txt_data = fw->data;
177 record->txt_length = fw->size;
178 record->txt_offset = 0;
179 record->max_len = 0;
180 /* read all records, if loop ends, record->error indicates,
181 * whether ihex is valid. */
182 while (usb6fire_fw_ihex_next_record(record))
183 record->max_len = max(record->len, record->max_len);
184 if (record->error)
185 return -EINVAL;
186 record->txt_offset = 0;
187 return 0;
188}
189
190static int usb6fire_fw_ezusb_write(struct usb_device *device,
191 int type, int value, char *data, int len)
192{
193 int ret;
194
195 ret = usb_control_msg(device, usb_sndctrlpipe(device, 0), type,
196 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
197 value, 0, data, len, HZ);
198 if (ret < 0)
199 return ret;
200 else if (ret != len)
201 return -EIO;
202 return 0;
203}
204
205static int usb6fire_fw_ezusb_read(struct usb_device *device,
206 int type, int value, char *data, int len)
207{
208 int ret = usb_control_msg(device, usb_rcvctrlpipe(device, 0), type,
209 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value,
210 0, data, len, HZ);
211 if (ret < 0)
212 return ret;
213 else if (ret != len)
214 return -EIO;
215 return 0;
216}
217
218static int usb6fire_fw_fpga_write(struct usb_device *device,
219 char *data, int len)
220{
221 int actual_len;
222 int ret;
223
224 ret = usb_bulk_msg(device, usb_sndbulkpipe(device, FPGA_EP), data, len,
225 &actual_len, HZ);
226 if (ret < 0)
227 return ret;
228 else if (actual_len != len)
229 return -EIO;
230 return 0;
231}
232
233static int usb6fire_fw_ezusb_upload(
234 struct usb_interface *intf, const char *fwname,
235 unsigned int postaddr, u8 *postdata, unsigned int postlen)
236{
237 int ret;
238 u8 data;
239 struct usb_device *device = interface_to_usbdev(intf);
240 const struct firmware *fw = 0;
241 struct ihex_record *rec = kmalloc(sizeof(struct ihex_record),
242 GFP_KERNEL);
243
244 if (!rec)
245 return -ENOMEM;
246
247 ret = request_firmware(&fw, fwname, &device->dev);
248 if (ret < 0) {
249 kfree(rec);
250 snd_printk(KERN_ERR PREFIX "error requesting ezusb "
251 "firmware %s.\n", fwname);
252 return ret;
253 }
254 ret = usb6fire_fw_ihex_init(fw, rec);
255 if (ret < 0) {
256 kfree(rec);
257 snd_printk(KERN_ERR PREFIX "error validating ezusb "
258 "firmware %s.\n", fwname);
259 return ret;
260 }
261 /* upload firmware image */
262 data = 0x01; /* stop ezusb cpu */
263 ret = usb6fire_fw_ezusb_write(device, 0xa0, 0xe600, &data, 1);
264 if (ret < 0) {
265 kfree(rec);
266 release_firmware(fw);
267 snd_printk(KERN_ERR PREFIX "unable to upload ezusb "
268 "firmware %s: begin message.\n", fwname);
269 return ret;
270 }
271
272 while (usb6fire_fw_ihex_next_record(rec)) { /* write firmware */
273 ret = usb6fire_fw_ezusb_write(device, 0xa0, rec->address,
274 rec->data, rec->len);
275 if (ret < 0) {
276 kfree(rec);
277 release_firmware(fw);
278 snd_printk(KERN_ERR PREFIX "unable to upload ezusb "
279 "firmware %s: data urb.\n", fwname);
280 return ret;
281 }
282 }
283
284 release_firmware(fw);
285 kfree(rec);
286 if (postdata) { /* write data after firmware has been uploaded */
287 ret = usb6fire_fw_ezusb_write(device, 0xa0, postaddr,
288 postdata, postlen);
289 if (ret < 0) {
290 snd_printk(KERN_ERR PREFIX "unable to upload ezusb "
291 "firmware %s: post urb.\n", fwname);
292 return ret;
293 }
294 }
295
296 data = 0x00; /* resume ezusb cpu */
297 ret = usb6fire_fw_ezusb_write(device, 0xa0, 0xe600, &data, 1);
298 if (ret < 0) {
299 release_firmware(fw);
300 snd_printk(KERN_ERR PREFIX "unable to upload ezusb "
301 "firmware %s: end message.\n", fwname);
302 return ret;
303 }
304 return 0;
305}
306
307static int usb6fire_fw_fpga_upload(
308 struct usb_interface *intf, const char *fwname)
309{
310 int ret;
311 int i;
312 struct usb_device *device = interface_to_usbdev(intf);
313 u8 *buffer = kmalloc(FPGA_BUFSIZE, GFP_KERNEL);
314 const char *c;
315 const char *end;
316 const struct firmware *fw;
317
318 if (!buffer)
319 return -ENOMEM;
320
321 ret = request_firmware(&fw, fwname, &device->dev);
322 if (ret < 0) {
323 snd_printk(KERN_ERR PREFIX "unable to get fpga firmware %s.\n",
324 fwname);
325 kfree(buffer);
326 return -EIO;
327 }
328
329 c = fw->data;
330 end = fw->data + fw->size;
331
332 ret = usb6fire_fw_ezusb_write(device, 8, 0, NULL, 0);
333 if (ret < 0) {
334 kfree(buffer);
335 release_firmware(fw);
336 snd_printk(KERN_ERR PREFIX "unable to upload fpga firmware: "
337 "begin urb.\n");
338 return ret;
339 }
340
341 while (c != end) {
342 for (i = 0; c != end && i < FPGA_BUFSIZE; i++, c++)
343 buffer[i] = BIT_REVERSE_TABLE[(u8) *c];
344
345 ret = usb6fire_fw_fpga_write(device, buffer, i);
346 if (ret < 0) {
347 release_firmware(fw);
348 kfree(buffer);
349 snd_printk(KERN_ERR PREFIX "unable to upload fpga "
350 "firmware: fw urb.\n");
351 return ret;
352 }
353 }
354 release_firmware(fw);
355 kfree(buffer);
356
357 ret = usb6fire_fw_ezusb_write(device, 9, 0, NULL, 0);
358 if (ret < 0) {
359 snd_printk(KERN_ERR PREFIX "unable to upload fpga firmware: "
360 "end urb.\n");
361 return ret;
362 }
363 return 0;
364}
365
366int usb6fire_fw_init(struct usb_interface *intf)
367{
368 int i;
369 int ret;
370 struct usb_device *device = interface_to_usbdev(intf);
371 /* buffer: 8 receiving bytes from device and
372 * sizeof(EP_W_MAX_PACKET_SIZE) bytes for non-const copy */
373 u8 buffer[12];
374
375 ret = usb6fire_fw_ezusb_read(device, 1, 0, buffer, 8);
376 if (ret < 0) {
377 snd_printk(KERN_ERR PREFIX "unable to receive device "
378 "firmware state.\n");
379 return ret;
380 }
381 if (buffer[0] != 0xeb || buffer[1] != 0xaa || buffer[2] != 0x55
382 || buffer[4] != 0x03 || buffer[5] != 0x01 || buffer[7]
383 != 0x00) {
384 snd_printk(KERN_ERR PREFIX "unknown device firmware state "
385 "received from device: ");
386 for (i = 0; i < 8; i++)
387 snd_printk("%02x ", buffer[i]);
388 snd_printk("\n");
389 return -EIO;
390 }
391 /* do we need fpga loader ezusb firmware? */
392 if (buffer[3] == 0x01 && buffer[6] == 0x19) {
393 ret = usb6fire_fw_ezusb_upload(intf,
394 "6fire/dmx6firel2.ihx", 0, NULL, 0);
395 if (ret < 0)
396 return ret;
397 return FW_NOT_READY;
398 }
399 /* do we need fpga firmware and application ezusb firmware? */
400 else if (buffer[3] == 0x02 && buffer[6] == 0x0b) {
401 ret = usb6fire_fw_fpga_upload(intf, "6fire/dmx6firecf.bin");
402 if (ret < 0)
403 return ret;
404 memcpy(buffer, ep_w_max_packet_size,
405 sizeof(ep_w_max_packet_size));
406 ret = usb6fire_fw_ezusb_upload(intf, "6fire/dmx6fireap.ihx",
407 0x0003, buffer, sizeof(ep_w_max_packet_size));
408 if (ret < 0)
409 return ret;
410 return FW_NOT_READY;
411 }
412 /* all fw loaded? */
413 else if (buffer[3] == 0x03 && buffer[6] == 0x0b)
414 return 0;
415 /* unknown data? */
416 else {
417 snd_printk(KERN_ERR PREFIX "unknown device firmware state "
418 "received from device: ");
419 for (i = 0; i < 8; i++)
420 snd_printk("%02x ", buffer[i]);
421 snd_printk("\n");
422 return -EIO;
423 }
424 return 0;
425}
426
diff --git a/sound/usb/6fire/firmware.h b/sound/usb/6fire/firmware.h
new file mode 100644
index 000000000000..008569895381
--- /dev/null
+++ b/sound/usb/6fire/firmware.h
@@ -0,0 +1,27 @@
1/*
2 * Linux driver for TerraTec DMX 6Fire USB
3 *
4 * Author: Torsten Schenk
5 * Created: Jan 01, 2011
6 * Copyright: (C) Torsten Schenk
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
14#ifndef USB6FIRE_FIRMWARE_H
15#define USB6FIRE_FIRMWARE_H
16
17#include "common.h"
18
19enum /* firmware state of device */
20{
21 FW_READY = 0,
22 FW_NOT_READY = 1
23};
24
25int __devinit usb6fire_fw_init(struct usb_interface *intf);
26#endif /* USB6FIRE_FIRMWARE_H */
27
diff --git a/sound/usb/6fire/midi.c b/sound/usb/6fire/midi.c
new file mode 100644
index 000000000000..13f4509dce2b
--- /dev/null
+++ b/sound/usb/6fire/midi.c
@@ -0,0 +1,203 @@
1/*
2 * Linux driver for TerraTec DMX 6Fire USB
3 *
4 * Rawmidi driver
5 *
6 * Author: Torsten Schenk <torsten.schenk@zoho.com>
7 * Created: Jan 01, 2011
8 * Version: 0.3.0
9 * Copyright: (C) Torsten Schenk
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 */
16
17#include <sound/rawmidi.h>
18
19#include "midi.h"
20#include "chip.h"
21#include "comm.h"
22
23static void usb6fire_midi_out_handler(struct urb *urb)
24{
25 struct midi_runtime *rt = urb->context;
26 int ret;
27 unsigned long flags;
28
29 spin_lock_irqsave(&rt->out_lock, flags);
30
31 if (rt->out) {
32 ret = snd_rawmidi_transmit(rt->out, rt->out_buffer + 4,
33 MIDI_BUFSIZE - 4);
34 if (ret > 0) { /* more data available, send next packet */
35 rt->out_buffer[1] = ret + 2;
36 rt->out_buffer[3] = rt->out_serial++;
37 urb->transfer_buffer_length = ret + 4;
38
39 ret = usb_submit_urb(urb, GFP_ATOMIC);
40 if (ret < 0)
41 snd_printk(KERN_ERR PREFIX "midi out urb "
42 "submit failed: %d\n", ret);
43 } else /* no more data to transmit */
44 rt->out = NULL;
45 }
46 spin_unlock_irqrestore(&rt->out_lock, flags);
47}
48
49static void usb6fire_midi_in_received(
50 struct midi_runtime *rt, u8 *data, int length)
51{
52 unsigned long flags;
53
54 spin_lock_irqsave(&rt->in_lock, flags);
55 if (rt->in)
56 snd_rawmidi_receive(rt->in, data, length);
57 spin_unlock_irqrestore(&rt->in_lock, flags);
58}
59
60static int usb6fire_midi_out_open(struct snd_rawmidi_substream *alsa_sub)
61{
62 return 0;
63}
64
65static int usb6fire_midi_out_close(struct snd_rawmidi_substream *alsa_sub)
66{
67 return 0;
68}
69
70static void usb6fire_midi_out_trigger(
71 struct snd_rawmidi_substream *alsa_sub, int up)
72{
73 struct midi_runtime *rt = alsa_sub->rmidi->private_data;
74 struct urb *urb = &rt->out_urb;
75 __s8 ret;
76 unsigned long flags;
77
78 spin_lock_irqsave(&rt->out_lock, flags);
79 if (up) { /* start transfer */
80 if (rt->out) { /* we are already transmitting so just return */
81 spin_unlock_irqrestore(&rt->out_lock, flags);
82 return;
83 }
84
85 ret = snd_rawmidi_transmit(alsa_sub, rt->out_buffer + 4,
86 MIDI_BUFSIZE - 4);
87 if (ret > 0) {
88 rt->out_buffer[1] = ret + 2;
89 rt->out_buffer[3] = rt->out_serial++;
90 urb->transfer_buffer_length = ret + 4;
91
92 ret = usb_submit_urb(urb, GFP_ATOMIC);
93 if (ret < 0)
94 snd_printk(KERN_ERR PREFIX "midi out urb "
95 "submit failed: %d\n", ret);
96 else
97 rt->out = alsa_sub;
98 }
99 } else if (rt->out == alsa_sub)
100 rt->out = NULL;
101 spin_unlock_irqrestore(&rt->out_lock, flags);
102}
103
104static void usb6fire_midi_out_drain(struct snd_rawmidi_substream *alsa_sub)
105{
106 struct midi_runtime *rt = alsa_sub->rmidi->private_data;
107 int retry = 0;
108
109 while (rt->out && retry++ < 100)
110 msleep(10);
111}
112
113static int usb6fire_midi_in_open(struct snd_rawmidi_substream *alsa_sub)
114{
115 return 0;
116}
117
118static int usb6fire_midi_in_close(struct snd_rawmidi_substream *alsa_sub)
119{
120 return 0;
121}
122
123static void usb6fire_midi_in_trigger(
124 struct snd_rawmidi_substream *alsa_sub, int up)
125{
126 struct midi_runtime *rt = alsa_sub->rmidi->private_data;
127 unsigned long flags;
128
129 spin_lock_irqsave(&rt->in_lock, flags);
130 if (up)
131 rt->in = alsa_sub;
132 else
133 rt->in = NULL;
134 spin_unlock_irqrestore(&rt->in_lock, flags);
135}
136
137static struct snd_rawmidi_ops out_ops = {
138 .open = usb6fire_midi_out_open,
139 .close = usb6fire_midi_out_close,
140 .trigger = usb6fire_midi_out_trigger,
141 .drain = usb6fire_midi_out_drain
142};
143
144static struct snd_rawmidi_ops in_ops = {
145 .open = usb6fire_midi_in_open,
146 .close = usb6fire_midi_in_close,
147 .trigger = usb6fire_midi_in_trigger
148};
149
150int __devinit usb6fire_midi_init(struct sfire_chip *chip)
151{
152 int ret;
153 struct midi_runtime *rt = kzalloc(sizeof(struct midi_runtime),
154 GFP_KERNEL);
155 struct comm_runtime *comm_rt = chip->comm;
156
157 if (!rt)
158 return -ENOMEM;
159
160 rt->chip = chip;
161 rt->in_received = usb6fire_midi_in_received;
162 rt->out_buffer[0] = 0x80; /* 'send midi' command */
163 rt->out_buffer[1] = 0x00; /* size of data */
164 rt->out_buffer[2] = 0x00; /* always 0 */
165 spin_lock_init(&rt->in_lock);
166 spin_lock_init(&rt->out_lock);
167
168 comm_rt->init_urb(comm_rt, &rt->out_urb, rt->out_buffer, rt,
169 usb6fire_midi_out_handler);
170
171 ret = snd_rawmidi_new(chip->card, "6FireUSB", 0, 1, 1, &rt->instance);
172 if (ret < 0) {
173 kfree(rt);
174 snd_printk(KERN_ERR PREFIX "unable to create midi.\n");
175 return ret;
176 }
177 rt->instance->private_data = rt;
178 strcpy(rt->instance->name, "DMX6FireUSB MIDI");
179 rt->instance->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
180 SNDRV_RAWMIDI_INFO_INPUT |
181 SNDRV_RAWMIDI_INFO_DUPLEX;
182 snd_rawmidi_set_ops(rt->instance, SNDRV_RAWMIDI_STREAM_OUTPUT,
183 &out_ops);
184 snd_rawmidi_set_ops(rt->instance, SNDRV_RAWMIDI_STREAM_INPUT,
185 &in_ops);
186
187 chip->midi = rt;
188 return 0;
189}
190
191void usb6fire_midi_abort(struct sfire_chip *chip)
192{
193 struct midi_runtime *rt = chip->midi;
194
195 if (rt)
196 usb_poison_urb(&rt->out_urb);
197}
198
199void usb6fire_midi_destroy(struct sfire_chip *chip)
200{
201 kfree(chip->midi);
202 chip->midi = NULL;
203}
diff --git a/sound/usb/6fire/midi.h b/sound/usb/6fire/midi.h
new file mode 100644
index 000000000000..97a7bf669135
--- /dev/null
+++ b/sound/usb/6fire/midi.h
@@ -0,0 +1,46 @@
1/*
2 * Linux driver for TerraTec DMX 6Fire USB
3 *
4 * Author: Torsten Schenk <torsten.schenk@zoho.com>
5 * Created: Jan 01, 2011
6 * Version: 0.3.0
7 * Copyright: (C) Torsten Schenk
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 */
14
15#ifndef USB6FIRE_MIDI_H
16#define USB6FIRE_MIDI_H
17
18#include "common.h"
19
20enum {
21 MIDI_BUFSIZE = 64
22};
23
24struct midi_runtime {
25 struct sfire_chip *chip;
26 struct snd_rawmidi *instance;
27
28 struct snd_rawmidi_substream *in;
29 char in_active;
30
31 spinlock_t in_lock;
32 spinlock_t out_lock;
33 struct snd_rawmidi_substream *out;
34 struct urb out_urb;
35 u8 out_serial; /* serial number of out packet */
36 u8 out_buffer[MIDI_BUFSIZE];
37 int buffer_offset;
38
39 void (*in_received)(struct midi_runtime *rt, u8 *data, int length);
40};
41
42int __devinit usb6fire_midi_init(struct sfire_chip *chip);
43void usb6fire_midi_abort(struct sfire_chip *chip);
44void usb6fire_midi_destroy(struct sfire_chip *chip);
45#endif /* USB6FIRE_MIDI_H */
46
diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c
new file mode 100644
index 000000000000..ba62c7468ba8
--- /dev/null
+++ b/sound/usb/6fire/pcm.c
@@ -0,0 +1,688 @@
1/*
2 * Linux driver for TerraTec DMX 6Fire USB
3 *
4 * PCM driver
5 *
6 * Author: Torsten Schenk <torsten.schenk@zoho.com>
7 * Created: Jan 01, 2011
8 * Version: 0.3.0
9 * Copyright: (C) Torsten Schenk
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 */
16
17#include "pcm.h"
18#include "chip.h"
19#include "comm.h"
20
21enum {
22 OUT_N_CHANNELS = 6, IN_N_CHANNELS = 4
23};
24
25/* keep next two synced with
26 * FW_EP_W_MAX_PACKET_SIZE[] and RATES_MAX_PACKET_SIZE */
27static const int rates_in_packet_size[] = { 228, 228, 420, 420, 404, 404 };
28static const int rates_out_packet_size[] = { 228, 228, 420, 420, 604, 604 };
29static const int rates[] = { 44100, 48000, 88200, 96000, 176400, 192000 };
30static const int rates_altsetting[] = { 1, 1, 2, 2, 3, 3 };
31static const int rates_alsaid[] = {
32 SNDRV_PCM_RATE_44100, SNDRV_PCM_RATE_48000,
33 SNDRV_PCM_RATE_88200, SNDRV_PCM_RATE_96000,
34 SNDRV_PCM_RATE_176400, SNDRV_PCM_RATE_192000 };
35
36/* values to write to soundcard register for all samplerates */
37static const u16 rates_6fire_vl[] = {0x00, 0x01, 0x00, 0x01, 0x00, 0x01};
38static const u16 rates_6fire_vh[] = {0x11, 0x11, 0x10, 0x10, 0x00, 0x00};
39
40enum { /* settings for pcm */
41 OUT_EP = 6, IN_EP = 2, MAX_BUFSIZE = 128 * 1024
42};
43
44enum { /* pcm streaming states */
45 STREAM_DISABLED, /* no pcm streaming */
46 STREAM_STARTING, /* pcm streaming requested, waiting to become ready */
47 STREAM_RUNNING, /* pcm streaming running */
48 STREAM_STOPPING
49};
50
51enum { /* pcm sample rates (also index into RATES_XXX[]) */
52 RATE_44KHZ,
53 RATE_48KHZ,
54 RATE_88KHZ,
55 RATE_96KHZ,
56 RATE_176KHZ,
57 RATE_192KHZ
58};
59
60static const struct snd_pcm_hardware pcm_hw = {
61 .info = SNDRV_PCM_INFO_MMAP |
62 SNDRV_PCM_INFO_INTERLEAVED |
63 SNDRV_PCM_INFO_BLOCK_TRANSFER |
64 SNDRV_PCM_INFO_MMAP_VALID |
65 SNDRV_PCM_INFO_BATCH,
66
67 .formats = SNDRV_PCM_FMTBIT_S24_LE,
68
69 .rates = SNDRV_PCM_RATE_44100 |
70 SNDRV_PCM_RATE_48000 |
71 SNDRV_PCM_RATE_88200 |
72 SNDRV_PCM_RATE_96000 |
73 SNDRV_PCM_RATE_176400 |
74 SNDRV_PCM_RATE_192000,
75
76 .rate_min = 44100,
77 .rate_max = 192000,
78 .channels_min = 1,
79 .channels_max = 0, /* set in pcm_open, depending on capture/playback */
80 .buffer_bytes_max = MAX_BUFSIZE,
81 .period_bytes_min = PCM_N_PACKETS_PER_URB * (PCM_MAX_PACKET_SIZE - 4),
82 .period_bytes_max = MAX_BUFSIZE,
83 .periods_min = 2,
84 .periods_max = 1024
85};
86
87static int usb6fire_pcm_set_rate(struct pcm_runtime *rt)
88{
89 int ret;
90 struct usb_device *device = rt->chip->dev;
91 struct comm_runtime *comm_rt = rt->chip->comm;
92
93 if (rt->rate >= ARRAY_SIZE(rates))
94 return -EINVAL;
95 /* disable streaming */
96 ret = comm_rt->write16(comm_rt, 0x02, 0x00, 0x00, 0x00);
97 if (ret < 0) {
98 snd_printk(KERN_ERR PREFIX "error stopping streaming while "
99 "setting samplerate %d.\n", rates[rt->rate]);
100 return ret;
101 }
102
103 ret = usb_set_interface(device, 1, rates_altsetting[rt->rate]);
104 if (ret < 0) {
105 snd_printk(KERN_ERR PREFIX "error setting interface "
106 "altsetting %d for samplerate %d.\n",
107 rates_altsetting[rt->rate], rates[rt->rate]);
108 return ret;
109 }
110
111 /* set soundcard clock */
112 ret = comm_rt->write16(comm_rt, 0x02, 0x01, rates_6fire_vl[rt->rate],
113 rates_6fire_vh[rt->rate]);
114 if (ret < 0) {
115 snd_printk(KERN_ERR PREFIX "error setting samplerate %d.\n",
116 rates[rt->rate]);
117 return ret;
118 }
119
120 /* enable analog inputs and outputs
121 * (one bit per stereo-channel) */
122 ret = comm_rt->write16(comm_rt, 0x02, 0x02,
123 (1 << (OUT_N_CHANNELS / 2)) - 1,
124 (1 << (IN_N_CHANNELS / 2)) - 1);
125 if (ret < 0) {
126 snd_printk(KERN_ERR PREFIX "error initializing analog channels "
127 "while setting samplerate %d.\n",
128 rates[rt->rate]);
129 return ret;
130 }
131 /* disable digital inputs and outputs */
132 ret = comm_rt->write16(comm_rt, 0x02, 0x03, 0x00, 0x00);
133 if (ret < 0) {
134 snd_printk(KERN_ERR PREFIX "error initializing digital "
135 "channels while setting samplerate %d.\n",
136 rates[rt->rate]);
137 return ret;
138 }
139
140 ret = comm_rt->write16(comm_rt, 0x02, 0x00, 0x00, 0x01);
141 if (ret < 0) {
142 snd_printk(KERN_ERR PREFIX "error starting streaming while "
143 "setting samplerate %d.\n", rates[rt->rate]);
144 return ret;
145 }
146
147 rt->in_n_analog = IN_N_CHANNELS;
148 rt->out_n_analog = OUT_N_CHANNELS;
149 rt->in_packet_size = rates_in_packet_size[rt->rate];
150 rt->out_packet_size = rates_out_packet_size[rt->rate];
151 return 0;
152}
153
154static struct pcm_substream *usb6fire_pcm_get_substream(
155 struct snd_pcm_substream *alsa_sub)
156{
157 struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
158
159 if (alsa_sub->stream == SNDRV_PCM_STREAM_PLAYBACK)
160 return &rt->playback;
161 else if (alsa_sub->stream == SNDRV_PCM_STREAM_CAPTURE)
162 return &rt->capture;
163 snd_printk(KERN_ERR PREFIX "error getting pcm substream slot.\n");
164 return NULL;
165}
166
167/* call with stream_mutex locked */
168static void usb6fire_pcm_stream_stop(struct pcm_runtime *rt)
169{
170 int i;
171
172 if (rt->stream_state != STREAM_DISABLED) {
173 for (i = 0; i < PCM_N_URBS; i++) {
174 usb_kill_urb(&rt->in_urbs[i].instance);
175 usb_kill_urb(&rt->out_urbs[i].instance);
176 }
177 rt->stream_state = STREAM_DISABLED;
178 }
179}
180
181/* call with stream_mutex locked */
182static int usb6fire_pcm_stream_start(struct pcm_runtime *rt)
183{
184 int ret;
185 int i;
186 int k;
187 struct usb_iso_packet_descriptor *packet;
188
189 if (rt->stream_state == STREAM_DISABLED) {
190 /* submit our in urbs */
191 rt->stream_wait_cond = false;
192 rt->stream_state = STREAM_STARTING;
193 for (i = 0; i < PCM_N_URBS; i++) {
194 for (k = 0; k < PCM_N_PACKETS_PER_URB; k++) {
195 packet = &rt->in_urbs[i].packets[k];
196 packet->offset = k * rt->in_packet_size;
197 packet->length = rt->in_packet_size;
198 packet->actual_length = 0;
199 packet->status = 0;
200 }
201 ret = usb_submit_urb(&rt->in_urbs[i].instance,
202 GFP_ATOMIC);
203 if (ret) {
204 usb6fire_pcm_stream_stop(rt);
205 return ret;
206 }
207 }
208
209 /* wait for first out urb to return (sent in in urb handler) */
210 wait_event_timeout(rt->stream_wait_queue, rt->stream_wait_cond,
211 HZ);
212 if (rt->stream_wait_cond)
213 rt->stream_state = STREAM_RUNNING;
214 else {
215 usb6fire_pcm_stream_stop(rt);
216 return -EIO;
217 }
218 }
219 return 0;
220}
221
222/* call with substream locked */
223static void usb6fire_pcm_capture(struct pcm_substream *sub, struct pcm_urb *urb)
224{
225 int i;
226 int frame;
227 int frame_count;
228 unsigned int total_length = 0;
229 struct pcm_runtime *rt = snd_pcm_substream_chip(sub->instance);
230 struct snd_pcm_runtime *alsa_rt = sub->instance->runtime;
231 u32 *src = (u32 *) urb->buffer;
232 u32 *dest = (u32 *) (alsa_rt->dma_area + sub->dma_off
233 * (alsa_rt->frame_bits >> 3));
234 u32 *dest_end = (u32 *) (alsa_rt->dma_area + alsa_rt->buffer_size
235 * (alsa_rt->frame_bits >> 3));
236 int bytes_per_frame = alsa_rt->channels << 2;
237
238 for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) {
239 /* at least 4 header bytes for valid packet.
240 * after that: 32 bits per sample for analog channels */
241 if (urb->packets[i].actual_length > 4)
242 frame_count = (urb->packets[i].actual_length - 4)
243 / (rt->in_n_analog << 2);
244 else
245 frame_count = 0;
246
247 src = (u32 *) (urb->buffer + total_length);
248 src++; /* skip leading 4 bytes of every packet */
249 total_length += urb->packets[i].length;
250 for (frame = 0; frame < frame_count; frame++) {
251 memcpy(dest, src, bytes_per_frame);
252 dest += alsa_rt->channels;
253 src += rt->in_n_analog;
254 sub->dma_off++;
255 sub->period_off++;
256 if (dest == dest_end) {
257 sub->dma_off = 0;
258 dest = (u32 *) alsa_rt->dma_area;
259 }
260 }
261 }
262}
263
264/* call with substream locked */
265static void usb6fire_pcm_playback(struct pcm_substream *sub,
266 struct pcm_urb *urb)
267{
268 int i;
269 int frame;
270 int frame_count;
271 struct pcm_runtime *rt = snd_pcm_substream_chip(sub->instance);
272 struct snd_pcm_runtime *alsa_rt = sub->instance->runtime;
273 u32 *src = (u32 *) (alsa_rt->dma_area + sub->dma_off
274 * (alsa_rt->frame_bits >> 3));
275 u32 *src_end = (u32 *) (alsa_rt->dma_area + alsa_rt->buffer_size
276 * (alsa_rt->frame_bits >> 3));
277 u32 *dest = (u32 *) urb->buffer;
278 int bytes_per_frame = alsa_rt->channels << 2;
279
280 for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) {
281 /* at least 4 header bytes for valid packet.
282 * after that: 32 bits per sample for analog channels */
283 if (urb->packets[i].length > 4)
284 frame_count = (urb->packets[i].length - 4)
285 / (rt->out_n_analog << 2);
286 else
287 frame_count = 0;
288 dest++; /* skip leading 4 bytes of every frame */
289 for (frame = 0; frame < frame_count; frame++) {
290 memcpy(dest, src, bytes_per_frame);
291 src += alsa_rt->channels;
292 dest += rt->out_n_analog;
293 sub->dma_off++;
294 sub->period_off++;
295 if (src == src_end) {
296 src = (u32 *) alsa_rt->dma_area;
297 sub->dma_off = 0;
298 }
299 }
300 }
301}
302
303static void usb6fire_pcm_in_urb_handler(struct urb *usb_urb)
304{
305 struct pcm_urb *in_urb = usb_urb->context;
306 struct pcm_urb *out_urb = in_urb->peer;
307 struct pcm_runtime *rt = in_urb->chip->pcm;
308 struct pcm_substream *sub;
309 unsigned long flags;
310 int total_length = 0;
311 int frame_count;
312 int frame;
313 int channel;
314 int i;
315 u8 *dest;
316
317 if (usb_urb->status || rt->panic || rt->stream_state == STREAM_STOPPING)
318 return;
319 for (i = 0; i < PCM_N_PACKETS_PER_URB; i++)
320 if (in_urb->packets[i].status) {
321 rt->panic = true;
322 return;
323 }
324
325 if (rt->stream_state == STREAM_DISABLED) {
326 snd_printk(KERN_ERR PREFIX "internal error: "
327 "stream disabled in in-urb handler.\n");
328 return;
329 }
330
331 /* receive our capture data */
332 sub = &rt->capture;
333 spin_lock_irqsave(&sub->lock, flags);
334 if (sub->active) {
335 usb6fire_pcm_capture(sub, in_urb);
336 if (sub->period_off >= sub->instance->runtime->period_size) {
337 sub->period_off %= sub->instance->runtime->period_size;
338 spin_unlock_irqrestore(&sub->lock, flags);
339 snd_pcm_period_elapsed(sub->instance);
340 } else
341 spin_unlock_irqrestore(&sub->lock, flags);
342 } else
343 spin_unlock_irqrestore(&sub->lock, flags);
344
345 /* setup out urb structure */
346 for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) {
347 out_urb->packets[i].offset = total_length;
348 out_urb->packets[i].length = (in_urb->packets[i].actual_length
349 - 4) / (rt->in_n_analog << 2)
350 * (rt->out_n_analog << 2) + 4;
351 out_urb->packets[i].status = 0;
352 total_length += out_urb->packets[i].length;
353 }
354 memset(out_urb->buffer, 0, total_length);
355
356 /* now send our playback data (if a free out urb was found) */
357 sub = &rt->playback;
358 spin_lock_irqsave(&sub->lock, flags);
359 if (sub->active) {
360 usb6fire_pcm_playback(sub, out_urb);
361 if (sub->period_off >= sub->instance->runtime->period_size) {
362 sub->period_off %= sub->instance->runtime->period_size;
363 spin_unlock_irqrestore(&sub->lock, flags);
364 snd_pcm_period_elapsed(sub->instance);
365 } else
366 spin_unlock_irqrestore(&sub->lock, flags);
367 } else
368 spin_unlock_irqrestore(&sub->lock, flags);
369
370 /* setup the 4th byte of each sample (0x40 for analog channels) */
371 dest = out_urb->buffer;
372 for (i = 0; i < PCM_N_PACKETS_PER_URB; i++)
373 if (out_urb->packets[i].length >= 4) {
374 frame_count = (out_urb->packets[i].length - 4)
375 / (rt->out_n_analog << 2);
376 *(dest++) = 0xaa;
377 *(dest++) = 0xaa;
378 *(dest++) = frame_count;
379 *(dest++) = 0x00;
380 for (frame = 0; frame < frame_count; frame++)
381 for (channel = 0;
382 channel < rt->out_n_analog;
383 channel++) {
384 dest += 3; /* skip sample data */
385 *(dest++) = 0x40;
386 }
387 }
388 usb_submit_urb(&out_urb->instance, GFP_ATOMIC);
389 usb_submit_urb(&in_urb->instance, GFP_ATOMIC);
390}
391
392static void usb6fire_pcm_out_urb_handler(struct urb *usb_urb)
393{
394 struct pcm_urb *urb = usb_urb->context;
395 struct pcm_runtime *rt = urb->chip->pcm;
396
397 if (rt->stream_state == STREAM_STARTING) {
398 rt->stream_wait_cond = true;
399 wake_up(&rt->stream_wait_queue);
400 }
401}
402
403static int usb6fire_pcm_open(struct snd_pcm_substream *alsa_sub)
404{
405 struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
406 struct pcm_substream *sub = NULL;
407 struct snd_pcm_runtime *alsa_rt = alsa_sub->runtime;
408
409 if (rt->panic)
410 return -EPIPE;
411
412 mutex_lock(&rt->stream_mutex);
413 alsa_rt->hw = pcm_hw;
414
415 if (alsa_sub->stream == SNDRV_PCM_STREAM_PLAYBACK) {
416 if (rt->rate >= 0)
417 alsa_rt->hw.rates = rates_alsaid[rt->rate];
418 alsa_rt->hw.channels_max = OUT_N_CHANNELS;
419 sub = &rt->playback;
420 } else if (alsa_sub->stream == SNDRV_PCM_STREAM_CAPTURE) {
421 if (rt->rate >= 0)
422 alsa_rt->hw.rates = rates_alsaid[rt->rate];
423 alsa_rt->hw.channels_max = IN_N_CHANNELS;
424 sub = &rt->capture;
425 }
426
427 if (!sub) {
428 mutex_unlock(&rt->stream_mutex);
429 snd_printk(KERN_ERR PREFIX "invalid stream type.\n");
430 return -EINVAL;
431 }
432
433 sub->instance = alsa_sub;
434 sub->active = false;
435 mutex_unlock(&rt->stream_mutex);
436 return 0;
437}
438
439static int usb6fire_pcm_close(struct snd_pcm_substream *alsa_sub)
440{
441 struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
442 struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub);
443 unsigned long flags;
444
445 if (rt->panic)
446 return 0;
447
448 mutex_lock(&rt->stream_mutex);
449 if (sub) {
450 /* deactivate substream */
451 spin_lock_irqsave(&sub->lock, flags);
452 sub->instance = NULL;
453 sub->active = false;
454 spin_unlock_irqrestore(&sub->lock, flags);
455
456 /* all substreams closed? if so, stop streaming */
457 if (!rt->playback.instance && !rt->capture.instance) {
458 usb6fire_pcm_stream_stop(rt);
459 rt->rate = -1;
460 }
461 }
462 mutex_unlock(&rt->stream_mutex);
463 return 0;
464}
465
466static int usb6fire_pcm_hw_params(struct snd_pcm_substream *alsa_sub,
467 struct snd_pcm_hw_params *hw_params)
468{
469 return snd_pcm_lib_malloc_pages(alsa_sub,
470 params_buffer_bytes(hw_params));
471}
472
473static int usb6fire_pcm_hw_free(struct snd_pcm_substream *alsa_sub)
474{
475 return snd_pcm_lib_free_pages(alsa_sub);
476}
477
478static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub)
479{
480 struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
481 struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub);
482 struct snd_pcm_runtime *alsa_rt = alsa_sub->runtime;
483 int i;
484 int ret;
485
486 if (rt->panic)
487 return -EPIPE;
488 if (!sub)
489 return -ENODEV;
490
491 mutex_lock(&rt->stream_mutex);
492 sub->dma_off = 0;
493 sub->period_off = 0;
494
495 if (rt->stream_state == STREAM_DISABLED) {
496 for (i = 0; i < ARRAY_SIZE(rates); i++)
497 if (alsa_rt->rate == rates[i]) {
498 rt->rate = i;
499 break;
500 }
501 if (i == ARRAY_SIZE(rates)) {
502 mutex_unlock(&rt->stream_mutex);
503 snd_printk("invalid rate %d in prepare.\n",
504 alsa_rt->rate);
505 return -EINVAL;
506 }
507
508 ret = usb6fire_pcm_set_rate(rt);
509 if (ret) {
510 mutex_unlock(&rt->stream_mutex);
511 return ret;
512 }
513 ret = usb6fire_pcm_stream_start(rt);
514 if (ret) {
515 mutex_unlock(&rt->stream_mutex);
516 snd_printk(KERN_ERR PREFIX
517 "could not start pcm stream.\n");
518 return ret;
519 }
520 }
521 mutex_unlock(&rt->stream_mutex);
522 return 0;
523}
524
525static int usb6fire_pcm_trigger(struct snd_pcm_substream *alsa_sub, int cmd)
526{
527 struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub);
528 struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
529 unsigned long flags;
530
531 if (rt->panic)
532 return -EPIPE;
533 if (!sub)
534 return -ENODEV;
535
536 switch (cmd) {
537 case SNDRV_PCM_TRIGGER_START:
538 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
539 spin_lock_irqsave(&sub->lock, flags);
540 sub->active = true;
541 spin_unlock_irqrestore(&sub->lock, flags);
542 return 0;
543
544 case SNDRV_PCM_TRIGGER_STOP:
545 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
546 spin_lock_irqsave(&sub->lock, flags);
547 sub->active = false;
548 spin_unlock_irqrestore(&sub->lock, flags);
549 return 0;
550
551 default:
552 return -EINVAL;
553 }
554}
555
556static snd_pcm_uframes_t usb6fire_pcm_pointer(
557 struct snd_pcm_substream *alsa_sub)
558{
559 struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub);
560 struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
561 unsigned long flags;
562 snd_pcm_uframes_t ret;
563
564 if (rt->panic || !sub)
565 return SNDRV_PCM_STATE_XRUN;
566
567 spin_lock_irqsave(&sub->lock, flags);
568 ret = sub->dma_off;
569 spin_unlock_irqrestore(&sub->lock, flags);
570 return ret;
571}
572
573static struct snd_pcm_ops pcm_ops = {
574 .open = usb6fire_pcm_open,
575 .close = usb6fire_pcm_close,
576 .ioctl = snd_pcm_lib_ioctl,
577 .hw_params = usb6fire_pcm_hw_params,
578 .hw_free = usb6fire_pcm_hw_free,
579 .prepare = usb6fire_pcm_prepare,
580 .trigger = usb6fire_pcm_trigger,
581 .pointer = usb6fire_pcm_pointer,
582};
583
584static void __devinit usb6fire_pcm_init_urb(struct pcm_urb *urb,
585 struct sfire_chip *chip, bool in, int ep,
586 void (*handler)(struct urb *))
587{
588 urb->chip = chip;
589 usb_init_urb(&urb->instance);
590 urb->instance.transfer_buffer = urb->buffer;
591 urb->instance.transfer_buffer_length =
592 PCM_N_PACKETS_PER_URB * PCM_MAX_PACKET_SIZE;
593 urb->instance.dev = chip->dev;
594 urb->instance.pipe = in ? usb_rcvisocpipe(chip->dev, ep)
595 : usb_sndisocpipe(chip->dev, ep);
596 urb->instance.interval = 1;
597 urb->instance.transfer_flags = URB_ISO_ASAP;
598 urb->instance.complete = handler;
599 urb->instance.context = urb;
600 urb->instance.number_of_packets = PCM_N_PACKETS_PER_URB;
601}
602
603int __devinit usb6fire_pcm_init(struct sfire_chip *chip)
604{
605 int i;
606 int ret;
607 struct snd_pcm *pcm;
608 struct pcm_runtime *rt =
609 kzalloc(sizeof(struct pcm_runtime), GFP_KERNEL);
610
611 if (!rt)
612 return -ENOMEM;
613
614 rt->chip = chip;
615 rt->stream_state = STREAM_DISABLED;
616 rt->rate = -1;
617 init_waitqueue_head(&rt->stream_wait_queue);
618 mutex_init(&rt->stream_mutex);
619
620 spin_lock_init(&rt->playback.lock);
621 spin_lock_init(&rt->capture.lock);
622
623 for (i = 0; i < PCM_N_URBS; i++) {
624 usb6fire_pcm_init_urb(&rt->in_urbs[i], chip, true, IN_EP,
625 usb6fire_pcm_in_urb_handler);
626 usb6fire_pcm_init_urb(&rt->out_urbs[i], chip, false, OUT_EP,
627 usb6fire_pcm_out_urb_handler);
628
629 rt->in_urbs[i].peer = &rt->out_urbs[i];
630 rt->out_urbs[i].peer = &rt->in_urbs[i];
631 }
632
633 ret = snd_pcm_new(chip->card, "DMX6FireUSB", 0, 1, 1, &pcm);
634 if (ret < 0) {
635 kfree(rt);
636 snd_printk(KERN_ERR PREFIX "cannot create pcm instance.\n");
637 return ret;
638 }
639
640 pcm->private_data = rt;
641 strcpy(pcm->name, "DMX 6Fire USB");
642 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_ops);
643 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_ops);
644
645 ret = snd_pcm_lib_preallocate_pages_for_all(pcm,
646 SNDRV_DMA_TYPE_CONTINUOUS,
647 snd_dma_continuous_data(GFP_KERNEL),
648 MAX_BUFSIZE, MAX_BUFSIZE);
649 if (ret) {
650 kfree(rt);
651 snd_printk(KERN_ERR PREFIX
652 "error preallocating pcm buffers.\n");
653 return ret;
654 }
655 rt->instance = pcm;
656
657 chip->pcm = rt;
658 return 0;
659}
660
661void usb6fire_pcm_abort(struct sfire_chip *chip)
662{
663 struct pcm_runtime *rt = chip->pcm;
664 int i;
665
666 if (rt) {
667 rt->panic = true;
668
669 if (rt->playback.instance)
670 snd_pcm_stop(rt->playback.instance,
671 SNDRV_PCM_STATE_XRUN);
672 if (rt->capture.instance)
673 snd_pcm_stop(rt->capture.instance,
674 SNDRV_PCM_STATE_XRUN);
675
676 for (i = 0; i < PCM_N_URBS; i++) {
677 usb_poison_urb(&rt->in_urbs[i].instance);
678 usb_poison_urb(&rt->out_urbs[i].instance);
679 }
680
681 }
682}
683
684void usb6fire_pcm_destroy(struct sfire_chip *chip)
685{
686 kfree(chip->pcm);
687 chip->pcm = NULL;
688}
diff --git a/sound/usb/6fire/pcm.h b/sound/usb/6fire/pcm.h
new file mode 100644
index 000000000000..2bee81374002
--- /dev/null
+++ b/sound/usb/6fire/pcm.h
@@ -0,0 +1,76 @@
1/*
2 * Linux driver for TerraTec DMX 6Fire USB
3 *
4 * Author: Torsten Schenk <torsten.schenk@zoho.com>
5 * Created: Jan 01, 2011
6 * Version: 0.3.0
7 * Copyright: (C) Torsten Schenk
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 */
14
15#ifndef USB6FIRE_PCM_H
16#define USB6FIRE_PCM_H
17
18#include <sound/pcm.h>
19#include <linux/mutex.h>
20
21#include "common.h"
22
23enum /* settings for pcm */
24{
25 /* maximum of EP_W_MAX_PACKET_SIZE[] (see firmware.c) */
26 PCM_N_URBS = 16, PCM_N_PACKETS_PER_URB = 8, PCM_MAX_PACKET_SIZE = 604
27};
28
29struct pcm_urb {
30 struct sfire_chip *chip;
31
32 /* BEGIN DO NOT SEPARATE */
33 struct urb instance;
34 struct usb_iso_packet_descriptor packets[PCM_N_PACKETS_PER_URB];
35 /* END DO NOT SEPARATE */
36 u8 buffer[PCM_N_PACKETS_PER_URB * PCM_MAX_PACKET_SIZE];
37
38 struct pcm_urb *peer;
39};
40
41struct pcm_substream {
42 spinlock_t lock;
43 struct snd_pcm_substream *instance;
44
45 bool active;
46
47 snd_pcm_uframes_t dma_off; /* current position in alsa dma_area */
48 snd_pcm_uframes_t period_off; /* current position in current period */
49};
50
51struct pcm_runtime {
52 struct sfire_chip *chip;
53 struct snd_pcm *instance;
54
55 struct pcm_substream playback;
56 struct pcm_substream capture;
57 bool panic; /* if set driver won't do anymore pcm on device */
58
59 struct pcm_urb in_urbs[PCM_N_URBS];
60 struct pcm_urb out_urbs[PCM_N_URBS];
61 int in_packet_size;
62 int out_packet_size;
63 int in_n_analog; /* number of analog channels soundcard sends */
64 int out_n_analog; /* number of analog channels soundcard receives */
65
66 struct mutex stream_mutex;
67 u8 stream_state; /* one of STREAM_XXX (pcm.c) */
68 u8 rate; /* one of PCM_RATE_XXX */
69 wait_queue_head_t stream_wait_queue;
70 bool stream_wait_cond;
71};
72
73int __devinit usb6fire_pcm_init(struct sfire_chip *chip);
74void usb6fire_pcm_abort(struct sfire_chip *chip);
75void usb6fire_pcm_destroy(struct sfire_chip *chip);
76#endif /* USB6FIRE_PCM_H */
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig
index 112984f4080f..97724d8fa9f6 100644
--- a/sound/usb/Kconfig
+++ b/sound/usb/Kconfig
@@ -62,6 +62,7 @@ config SND_USB_CAIAQ
62 * Native Instruments Audio 2 DJ 62 * Native Instruments Audio 2 DJ
63 * Native Instruments Audio 4 DJ 63 * Native Instruments Audio 4 DJ
64 * Native Instruments Audio 8 DJ 64 * Native Instruments Audio 8 DJ
65 * Native Instruments Traktor Audio 2
65 * Native Instruments Guitar Rig Session I/O 66 * Native Instruments Guitar Rig Session I/O
66 * Native Instruments Guitar Rig mobile 67 * Native Instruments Guitar Rig mobile
67 * Native Instruments Traktor Kontrol X1 68 * Native Instruments Traktor Kontrol X1
@@ -97,5 +98,21 @@ config SND_USB_US122L
97 To compile this driver as a module, choose M here: the module 98 To compile this driver as a module, choose M here: the module
98 will be called snd-usb-us122l. 99 will be called snd-usb-us122l.
99 100
101config SND_USB_6FIRE
102 tristate "TerraTec DMX 6Fire USB"
103 depends on EXPERIMENTAL
104 select FW_LOADER
105 select SND_RAWMIDI
106 select SND_PCM
107 help
108 Say Y here to include support for TerraTec 6fire DMX USB interface.
109
110 You will need firmware files in order to be able to use the device
111 after it has been coldstarted. This driver currently does not support
112 firmware loading for all devices. If you own such a device,
113 you could start windows and let the windows driver upload
114 the firmware. As long as you do not unplug your device from power,
115 it should be usable.
116
100endif # SND_USB 117endif # SND_USB
101 118
diff --git a/sound/usb/Makefile b/sound/usb/Makefile
index 1e362bf8834f..cf9ed66445fa 100644
--- a/sound/usb/Makefile
+++ b/sound/usb/Makefile
@@ -23,4 +23,4 @@ obj-$(CONFIG_SND_USB_UA101) += snd-usbmidi-lib.o
23obj-$(CONFIG_SND_USB_USX2Y) += snd-usbmidi-lib.o 23obj-$(CONFIG_SND_USB_USX2Y) += snd-usbmidi-lib.o
24obj-$(CONFIG_SND_USB_US122L) += snd-usbmidi-lib.o 24obj-$(CONFIG_SND_USB_US122L) += snd-usbmidi-lib.o
25 25
26obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/ 26obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/ 6fire/
diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c
index 66eabafb1c24..d0d493ca28ae 100644
--- a/sound/usb/caiaq/audio.c
+++ b/sound/usb/caiaq/audio.c
@@ -805,6 +805,7 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev)
805 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO2DJ): 805 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO2DJ):
806 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): 806 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ):
807 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ): 807 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ):
808 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORAUDIO2):
808 dev->samplerates |= SNDRV_PCM_RATE_88200; 809 dev->samplerates |= SNDRV_PCM_RATE_88200;
809 break; 810 break;
810 } 811 }
diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c
index 6480c3283c05..45bc4a2dc6f0 100644
--- a/sound/usb/caiaq/device.c
+++ b/sound/usb/caiaq/device.c
@@ -46,6 +46,7 @@ MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
46 "{Native Instruments, Audio 2 DJ}," 46 "{Native Instruments, Audio 2 DJ},"
47 "{Native Instruments, Audio 4 DJ}," 47 "{Native Instruments, Audio 4 DJ},"
48 "{Native Instruments, Audio 8 DJ}," 48 "{Native Instruments, Audio 8 DJ},"
49 "{Native Instruments, Traktor Audio 2},"
49 "{Native Instruments, Session I/O}," 50 "{Native Instruments, Session I/O},"
50 "{Native Instruments, GuitarRig mobile}" 51 "{Native Instruments, GuitarRig mobile}"
51 "{Native Instruments, Traktor Kontrol X1}" 52 "{Native Instruments, Traktor Kontrol X1}"
@@ -140,6 +141,11 @@ static struct usb_device_id snd_usb_id_table[] = {
140 .idVendor = USB_VID_NATIVEINSTRUMENTS, 141 .idVendor = USB_VID_NATIVEINSTRUMENTS,
141 .idProduct = USB_PID_TRAKTORKONTROLS4 142 .idProduct = USB_PID_TRAKTORKONTROLS4
142 }, 143 },
144 {
145 .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
146 .idVendor = USB_VID_NATIVEINSTRUMENTS,
147 .idProduct = USB_PID_TRAKTORAUDIO2
148 },
143 { /* terminator */ } 149 { /* terminator */ }
144}; 150};
145 151
diff --git a/sound/usb/caiaq/device.h b/sound/usb/caiaq/device.h
index e3d8a3efb35b..b2b310194ffa 100644
--- a/sound/usb/caiaq/device.h
+++ b/sound/usb/caiaq/device.h
@@ -17,6 +17,7 @@
17#define USB_PID_GUITARRIGMOBILE 0x0d8d 17#define USB_PID_GUITARRIGMOBILE 0x0d8d
18#define USB_PID_TRAKTORKONTROLX1 0x2305 18#define USB_PID_TRAKTORKONTROLX1 0x2305
19#define USB_PID_TRAKTORKONTROLS4 0xbaff 19#define USB_PID_TRAKTORKONTROLS4 0xbaff
20#define USB_PID_TRAKTORAUDIO2 0x041d
20 21
21#define EP1_BUFSIZE 64 22#define EP1_BUFSIZE 64
22#define EP4_BUFSIZE 512 23#define EP4_BUFSIZE 512
diff --git a/sound/usb/card.c b/sound/usb/card.c
index c0f8270bc199..40722f8711ad 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -65,6 +65,7 @@
65#include "pcm.h" 65#include "pcm.h"
66#include "urb.h" 66#include "urb.h"
67#include "format.h" 67#include "format.h"
68#include "power.h"
68 69
69MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); 70MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
70MODULE_DESCRIPTION("USB Audio"); 71MODULE_DESCRIPTION("USB Audio");
@@ -330,6 +331,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
330 chip->setup = device_setup[idx]; 331 chip->setup = device_setup[idx];
331 chip->nrpacks = nrpacks; 332 chip->nrpacks = nrpacks;
332 chip->async_unlink = async_unlink; 333 chip->async_unlink = async_unlink;
334 chip->probing = 1;
333 335
334 chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor), 336 chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
335 le16_to_cpu(dev->descriptor.idProduct)); 337 le16_to_cpu(dev->descriptor.idProduct));
@@ -451,6 +453,7 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
451 goto __error; 453 goto __error;
452 } 454 }
453 chip = usb_chip[i]; 455 chip = usb_chip[i];
456 chip->probing = 1;
454 break; 457 break;
455 } 458 }
456 } 459 }
@@ -466,6 +469,7 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
466 goto __error; 469 goto __error;
467 } 470 }
468 snd_card_set_dev(chip->card, &intf->dev); 471 snd_card_set_dev(chip->card, &intf->dev);
472 chip->pm_intf = intf;
469 break; 473 break;
470 } 474 }
471 if (!chip) { 475 if (!chip) {
@@ -505,6 +509,7 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
505 509
506 usb_chip[chip->index] = chip; 510 usb_chip[chip->index] = chip;
507 chip->num_interfaces++; 511 chip->num_interfaces++;
512 chip->probing = 0;
508 mutex_unlock(&register_mutex); 513 mutex_unlock(&register_mutex);
509 return chip; 514 return chip;
510 515
@@ -581,29 +586,61 @@ static void usb_audio_disconnect(struct usb_interface *intf)
581} 586}
582 587
583#ifdef CONFIG_PM 588#ifdef CONFIG_PM
589
590int snd_usb_autoresume(struct snd_usb_audio *chip)
591{
592 int err = -ENODEV;
593
594 if (!chip->shutdown && !chip->probing)
595 err = usb_autopm_get_interface(chip->pm_intf);
596
597 return err;
598}
599
600void snd_usb_autosuspend(struct snd_usb_audio *chip)
601{
602 if (!chip->shutdown && !chip->probing)
603 usb_autopm_put_interface(chip->pm_intf);
604}
605
584static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) 606static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
585{ 607{
586 struct snd_usb_audio *chip = usb_get_intfdata(intf); 608 struct snd_usb_audio *chip = usb_get_intfdata(intf);
587 struct list_head *p; 609 struct list_head *p;
588 struct snd_usb_stream *as; 610 struct snd_usb_stream *as;
611 struct usb_mixer_interface *mixer;
589 612
590 if (chip == (void *)-1L) 613 if (chip == (void *)-1L)
591 return 0; 614 return 0;
592 615
593 snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot); 616 if (!(message.event & PM_EVENT_AUTO)) {
594 if (!chip->num_suspended_intf++) { 617 snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot);
595 list_for_each(p, &chip->pcm_list) { 618 if (!chip->num_suspended_intf++) {
596 as = list_entry(p, struct snd_usb_stream, list); 619 list_for_each(p, &chip->pcm_list) {
597 snd_pcm_suspend_all(as->pcm); 620 as = list_entry(p, struct snd_usb_stream, list);
598 } 621 snd_pcm_suspend_all(as->pcm);
622 }
623 }
624 } else {
625 /*
626 * otherwise we keep the rest of the system in the dark
627 * to keep this transparent
628 */
629 if (!chip->num_suspended_intf++)
630 chip->autosuspended = 1;
599 } 631 }
600 632
633 list_for_each_entry(mixer, &chip->mixer_list, list)
634 snd_usb_mixer_inactivate(mixer);
635
601 return 0; 636 return 0;
602} 637}
603 638
604static int usb_audio_resume(struct usb_interface *intf) 639static int usb_audio_resume(struct usb_interface *intf)
605{ 640{
606 struct snd_usb_audio *chip = usb_get_intfdata(intf); 641 struct snd_usb_audio *chip = usb_get_intfdata(intf);
642 struct usb_mixer_interface *mixer;
643 int err = 0;
607 644
608 if (chip == (void *)-1L) 645 if (chip == (void *)-1L)
609 return 0; 646 return 0;
@@ -611,12 +648,20 @@ static int usb_audio_resume(struct usb_interface *intf)
611 return 0; 648 return 0;
612 /* 649 /*
613 * ALSA leaves material resumption to user space 650 * ALSA leaves material resumption to user space
614 * we just notify 651 * we just notify and restart the mixers
615 */ 652 */
653 list_for_each_entry(mixer, &chip->mixer_list, list) {
654 err = snd_usb_mixer_activate(mixer);
655 if (err < 0)
656 goto err_out;
657 }
616 658
617 snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0); 659 if (!chip->autosuspended)
660 snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0);
661 chip->autosuspended = 0;
618 662
619 return 0; 663err_out:
664 return err;
620} 665}
621#else 666#else
622#define usb_audio_suspend NULL 667#define usb_audio_suspend NULL
@@ -644,6 +689,7 @@ static struct usb_driver usb_audio_driver = {
644 .suspend = usb_audio_suspend, 689 .suspend = usb_audio_suspend,
645 .resume = usb_audio_resume, 690 .resume = usb_audio_resume,
646 .id_table = usb_audio_ids, 691 .id_table = usb_audio_ids,
692 .supports_autosuspend = 1,
647}; 693};
648 694
649static int __init snd_usb_audio_init(void) 695static int __init snd_usb_audio_init(void)
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index db2dc5ffe6dd..b4b39c0b6c9e 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -54,6 +54,7 @@
54#include <sound/asequencer.h> 54#include <sound/asequencer.h>
55#include "usbaudio.h" 55#include "usbaudio.h"
56#include "midi.h" 56#include "midi.h"
57#include "power.h"
57#include "helper.h" 58#include "helper.h"
58 59
59/* 60/*
@@ -1044,6 +1045,7 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
1044 struct snd_usb_midi* umidi = substream->rmidi->private_data; 1045 struct snd_usb_midi* umidi = substream->rmidi->private_data;
1045 struct usbmidi_out_port* port = NULL; 1046 struct usbmidi_out_port* port = NULL;
1046 int i, j; 1047 int i, j;
1048 int err;
1047 1049
1048 for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) 1050 for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
1049 if (umidi->endpoints[i].out) 1051 if (umidi->endpoints[i].out)
@@ -1056,6 +1058,9 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
1056 snd_BUG(); 1058 snd_BUG();
1057 return -ENXIO; 1059 return -ENXIO;
1058 } 1060 }
1061 err = usb_autopm_get_interface(umidi->iface);
1062 if (err < 0)
1063 return -EIO;
1059 substream->runtime->private_data = port; 1064 substream->runtime->private_data = port;
1060 port->state = STATE_UNKNOWN; 1065 port->state = STATE_UNKNOWN;
1061 substream_open(substream, 1); 1066 substream_open(substream, 1);
@@ -1064,7 +1069,10 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
1064 1069
1065static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream) 1070static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream)
1066{ 1071{
1072 struct snd_usb_midi* umidi = substream->rmidi->private_data;
1073
1067 substream_open(substream, 0); 1074 substream_open(substream, 0);
1075 usb_autopm_put_interface(umidi->iface);
1068 return 0; 1076 return 0;
1069} 1077}
1070 1078
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 85af6051b52d..5e4775716607 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -61,6 +61,7 @@
61#include "mixer.h" 61#include "mixer.h"
62#include "helper.h" 62#include "helper.h"
63#include "mixer_quirks.h" 63#include "mixer_quirks.h"
64#include "power.h"
64 65
65#define MAX_ID_ELEMS 256 66#define MAX_ID_ELEMS 256
66 67
@@ -295,16 +296,22 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v
295 unsigned char buf[2]; 296 unsigned char buf[2];
296 int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; 297 int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
297 int timeout = 10; 298 int timeout = 10;
299 int err;
298 300
301 err = snd_usb_autoresume(cval->mixer->chip);
302 if (err < 0)
303 return -EIO;
299 while (timeout-- > 0) { 304 while (timeout-- > 0) {
300 if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, 305 if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request,
301 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, 306 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
302 validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), 307 validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
303 buf, val_len, 100) >= val_len) { 308 buf, val_len, 100) >= val_len) {
304 *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); 309 *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len));
310 snd_usb_autosuspend(cval->mixer->chip);
305 return 0; 311 return 0;
306 } 312 }
307 } 313 }
314 snd_usb_autosuspend(cval->mixer->chip);
308 snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", 315 snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
309 request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); 316 request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type);
310 return -EINVAL; 317 return -EINVAL;
@@ -328,12 +335,18 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
328 335
329 memset(buf, 0, sizeof(buf)); 336 memset(buf, 0, sizeof(buf));
330 337
338 ret = snd_usb_autoresume(chip) ? -EIO : 0;
339 if (ret)
340 goto error;
341
331 ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, 342 ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest,
332 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, 343 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
333 validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), 344 validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
334 buf, size, 1000); 345 buf, size, 1000);
346 snd_usb_autosuspend(chip);
335 347
336 if (ret < 0) { 348 if (ret < 0) {
349error:
337 snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", 350 snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
338 request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); 351 request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type);
339 return ret; 352 return ret;
@@ -413,7 +426,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
413{ 426{
414 struct snd_usb_audio *chip = cval->mixer->chip; 427 struct snd_usb_audio *chip = cval->mixer->chip;
415 unsigned char buf[2]; 428 unsigned char buf[2];
416 int val_len, timeout = 10; 429 int val_len, err, timeout = 10;
417 430
418 if (cval->mixer->protocol == UAC_VERSION_1) { 431 if (cval->mixer->protocol == UAC_VERSION_1) {
419 val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; 432 val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
@@ -433,13 +446,19 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
433 value_set = convert_bytes_value(cval, value_set); 446 value_set = convert_bytes_value(cval, value_set);
434 buf[0] = value_set & 0xff; 447 buf[0] = value_set & 0xff;
435 buf[1] = (value_set >> 8) & 0xff; 448 buf[1] = (value_set >> 8) & 0xff;
449 err = snd_usb_autoresume(chip);
450 if (err < 0)
451 return -EIO;
436 while (timeout-- > 0) 452 while (timeout-- > 0)
437 if (snd_usb_ctl_msg(chip->dev, 453 if (snd_usb_ctl_msg(chip->dev,
438 usb_sndctrlpipe(chip->dev, 0), request, 454 usb_sndctrlpipe(chip->dev, 0), request,
439 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, 455 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
440 validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), 456 validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
441 buf, val_len, 100) >= 0) 457 buf, val_len, 100) >= 0) {
458 snd_usb_autosuspend(chip);
442 return 0; 459 return 0;
460 }
461 snd_usb_autosuspend(chip);
443 snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", 462 snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n",
444 request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]); 463 request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]);
445 return -EINVAL; 464 return -EINVAL;
@@ -987,6 +1006,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
987 struct snd_kcontrol *kctl; 1006 struct snd_kcontrol *kctl;
988 struct usb_mixer_elem_info *cval; 1007 struct usb_mixer_elem_info *cval;
989 const struct usbmix_name_map *map; 1008 const struct usbmix_name_map *map;
1009 unsigned int range;
990 1010
991 control++; /* change from zero-based to 1-based value */ 1011 control++; /* change from zero-based to 1-based value */
992 1012
@@ -1121,6 +1141,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
1121 } 1141 }
1122 break; 1142 break;
1123 1143
1144 case USB_ID(0x046d, 0x0808):
1124 case USB_ID(0x046d, 0x0809): 1145 case USB_ID(0x046d, 0x0809):
1125 case USB_ID(0x046d, 0x0991): 1146 case USB_ID(0x046d, 0x0991):
1126 /* Most audio usb devices lie about volume resolution. 1147 /* Most audio usb devices lie about volume resolution.
@@ -1136,6 +1157,21 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
1136 1157
1137 } 1158 }
1138 1159
1160 range = (cval->max - cval->min) / cval->res;
1161 /* Are there devices with volume range more than 255? I use a bit more
1162 * to be sure. 384 is a resolution magic number found on Logitech
1163 * devices. It will definitively catch all buggy Logitech devices.
1164 */
1165 if (range > 384) {
1166 snd_printk(KERN_WARNING "usb_audio: Warning! Unlikely big "
1167 "volume range (=%u), cval->res is probably wrong.",
1168 range);
1169 snd_printk(KERN_WARNING "usb_audio: [%d] FU [%s] ch = %d, "
1170 "val = %d/%d/%d", cval->id,
1171 kctl->id.name, cval->channels,
1172 cval->min, cval->max, cval->res);
1173 }
1174
1139 snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", 1175 snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",
1140 cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res); 1176 cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res);
1141 add_control_to_empty(state, kctl); 1177 add_control_to_empty(state, kctl);
@@ -2058,8 +2094,9 @@ static void snd_usb_mixer_interrupt(struct urb *urb)
2058{ 2094{
2059 struct usb_mixer_interface *mixer = urb->context; 2095 struct usb_mixer_interface *mixer = urb->context;
2060 int len = urb->actual_length; 2096 int len = urb->actual_length;
2097 int ustatus = urb->status;
2061 2098
2062 if (urb->status != 0) 2099 if (ustatus != 0)
2063 goto requeue; 2100 goto requeue;
2064 2101
2065 if (mixer->protocol == UAC_VERSION_1) { 2102 if (mixer->protocol == UAC_VERSION_1) {
@@ -2100,12 +2137,32 @@ static void snd_usb_mixer_interrupt(struct urb *urb)
2100 } 2137 }
2101 2138
2102requeue: 2139requeue:
2103 if (urb->status != -ENOENT && urb->status != -ECONNRESET) { 2140 if (ustatus != -ENOENT && ustatus != -ECONNRESET && ustatus != -ESHUTDOWN) {
2104 urb->dev = mixer->chip->dev; 2141 urb->dev = mixer->chip->dev;
2105 usb_submit_urb(urb, GFP_ATOMIC); 2142 usb_submit_urb(urb, GFP_ATOMIC);
2106 } 2143 }
2107} 2144}
2108 2145
2146/* stop any bus activity of a mixer */
2147void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer)
2148{
2149 usb_kill_urb(mixer->urb);
2150 usb_kill_urb(mixer->rc_urb);
2151}
2152
2153int snd_usb_mixer_activate(struct usb_mixer_interface *mixer)
2154{
2155 int err;
2156
2157 if (mixer->urb) {
2158 err = usb_submit_urb(mixer->urb, GFP_NOIO);
2159 if (err < 0)
2160 return err;
2161 }
2162
2163 return 0;
2164}
2165
2109/* create the handler for the optional status interrupt endpoint */ 2166/* create the handler for the optional status interrupt endpoint */
2110static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer) 2167static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer)
2111{ 2168{
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
index 26c636c5c93a..b4a2c8165e4b 100644
--- a/sound/usb/mixer.h
+++ b/sound/usb/mixer.h
@@ -52,5 +52,7 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid);
52 52
53int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, 53int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
54 int request, int validx, int value_set); 54 int request, int validx, int value_set);
55void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer);
56int snd_usb_mixer_activate(struct usb_mixer_interface *mixer);
55 57
56#endif /* __USBMIXER_H */ 58#endif /* __USBMIXER_H */
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index 782f741cd00a..73dcc8256bc0 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -346,6 +346,141 @@ static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer)
346 return 0; 346 return 0;
347} 347}
348 348
349/* Native Instruments device quirks */
350
351#define _MAKE_NI_CONTROL(bRequest,wIndex) ((bRequest) << 16 | (wIndex))
352
353static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol,
354 struct snd_ctl_elem_value *ucontrol)
355{
356 struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
357 struct usb_device *dev = mixer->chip->dev;
358 u8 bRequest = (kcontrol->private_value >> 16) & 0xff;
359 u16 wIndex = kcontrol->private_value & 0xffff;
360 u8 tmp;
361
362 int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest,
363 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
364 0, cpu_to_le16(wIndex),
365 &tmp, sizeof(tmp), 1000);
366
367 if (ret < 0) {
368 snd_printk(KERN_ERR
369 "unable to issue vendor read request (ret = %d)", ret);
370 return ret;
371 }
372
373 ucontrol->value.integer.value[0] = tmp;
374
375 return 0;
376}
377
378static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol,
379 struct snd_ctl_elem_value *ucontrol)
380{
381 struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
382 struct usb_device *dev = mixer->chip->dev;
383 u8 bRequest = (kcontrol->private_value >> 16) & 0xff;
384 u16 wIndex = kcontrol->private_value & 0xffff;
385 u16 wValue = ucontrol->value.integer.value[0];
386
387 int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest,
388 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
389 cpu_to_le16(wValue), cpu_to_le16(wIndex),
390 NULL, 0, 1000);
391
392 if (ret < 0) {
393 snd_printk(KERN_ERR
394 "unable to issue vendor write request (ret = %d)", ret);
395 return ret;
396 }
397
398 return 0;
399}
400
401static struct snd_kcontrol_new snd_nativeinstruments_ta6_mixers[] = {
402 {
403 .name = "Direct Thru Channel A",
404 .private_value = _MAKE_NI_CONTROL(0x01, 0x03),
405 },
406 {
407 .name = "Direct Thru Channel B",
408 .private_value = _MAKE_NI_CONTROL(0x01, 0x05),
409 },
410 {
411 .name = "Phono Input Channel A",
412 .private_value = _MAKE_NI_CONTROL(0x02, 0x03),
413 },
414 {
415 .name = "Phono Input Channel B",
416 .private_value = _MAKE_NI_CONTROL(0x02, 0x05),
417 },
418};
419
420static struct snd_kcontrol_new snd_nativeinstruments_ta10_mixers[] = {
421 {
422 .name = "Direct Thru Channel A",
423 .private_value = _MAKE_NI_CONTROL(0x01, 0x03),
424 },
425 {
426 .name = "Direct Thru Channel B",
427 .private_value = _MAKE_NI_CONTROL(0x01, 0x05),
428 },
429 {
430 .name = "Direct Thru Channel C",
431 .private_value = _MAKE_NI_CONTROL(0x01, 0x07),
432 },
433 {
434 .name = "Direct Thru Channel D",
435 .private_value = _MAKE_NI_CONTROL(0x01, 0x09),
436 },
437 {
438 .name = "Phono Input Channel A",
439 .private_value = _MAKE_NI_CONTROL(0x02, 0x03),
440 },
441 {
442 .name = "Phono Input Channel B",
443 .private_value = _MAKE_NI_CONTROL(0x02, 0x05),
444 },
445 {
446 .name = "Phono Input Channel C",
447 .private_value = _MAKE_NI_CONTROL(0x02, 0x07),
448 },
449 {
450 .name = "Phono Input Channel D",
451 .private_value = _MAKE_NI_CONTROL(0x02, 0x09),
452 },
453};
454
455static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer,
456 const struct snd_kcontrol_new *kc,
457 unsigned int count)
458{
459 int i, err = 0;
460 struct snd_kcontrol_new template = {
461 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
462 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
463 .get = snd_nativeinstruments_control_get,
464 .put = snd_nativeinstruments_control_put,
465 .info = snd_ctl_boolean_mono_info,
466 };
467
468 for (i = 0; i < count; i++) {
469 struct snd_kcontrol *c;
470
471 template.name = kc[i].name;
472 template.private_value = kc[i].private_value;
473
474 c = snd_ctl_new1(&template, mixer);
475 err = snd_ctl_add(mixer->chip->card, c);
476
477 if (err < 0)
478 break;
479 }
480
481 return err;
482}
483
349void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, 484void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
350 unsigned char samplerate_id) 485 unsigned char samplerate_id)
351{ 486{
@@ -367,31 +502,44 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
367 502
368int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) 503int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
369{ 504{
370 int err; 505 int err = 0;
371 struct snd_info_entry *entry; 506 struct snd_info_entry *entry;
372 507
373 if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0) 508 if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0)
374 return err; 509 return err;
375 510
376 if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020) || 511 switch (mixer->chip->usb_id) {
377 mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || 512 case USB_ID(0x041e, 0x3020):
378 mixer->chip->usb_id == USB_ID(0x041e, 0x3042) || 513 case USB_ID(0x041e, 0x3040):
379 mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) { 514 case USB_ID(0x041e, 0x3042):
380 if ((err = snd_audigy2nx_controls_create(mixer)) < 0) 515 case USB_ID(0x041e, 0x3048):
381 return err; 516 err = snd_audigy2nx_controls_create(mixer);
517 if (err < 0)
518 break;
382 if (!snd_card_proc_new(mixer->chip->card, "audigy2nx", &entry)) 519 if (!snd_card_proc_new(mixer->chip->card, "audigy2nx", &entry))
383 snd_info_set_text_ops(entry, mixer, 520 snd_info_set_text_ops(entry, mixer,
384 snd_audigy2nx_proc_read); 521 snd_audigy2nx_proc_read);
385 } 522 break;
386 523
387 if (mixer->chip->usb_id == USB_ID(0x0b05, 0x1739) || 524 case USB_ID(0x0b05, 0x1739):
388 mixer->chip->usb_id == USB_ID(0x0b05, 0x1743)) { 525 case USB_ID(0x0b05, 0x1743):
389 err = snd_xonar_u1_controls_create(mixer); 526 err = snd_xonar_u1_controls_create(mixer);
390 if (err < 0) 527 break;
391 return err; 528
529 case USB_ID(0x17cc, 0x1011): /* Traktor Audio 6 */
530 err = snd_nativeinstruments_create_mixer(mixer,
531 snd_nativeinstruments_ta6_mixers,
532 ARRAY_SIZE(snd_nativeinstruments_ta6_mixers));
533 break;
534
535 case USB_ID(0x17cc, 0x1021): /* Traktor Audio 10 */
536 err = snd_nativeinstruments_create_mixer(mixer,
537 snd_nativeinstruments_ta10_mixers,
538 ARRAY_SIZE(snd_nativeinstruments_ta10_mixers));
539 break;
392 } 540 }
393 541
394 return 0; 542 return err;
395} 543}
396 544
397void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer, 545void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer,
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index e3f680526cb5..b8dcbf407bbb 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -32,6 +32,7 @@
32#include "helper.h" 32#include "helper.h"
33#include "pcm.h" 33#include "pcm.h"
34#include "clock.h" 34#include "clock.h"
35#include "power.h"
35 36
36/* 37/*
37 * return the current pcm pointer. just based on the hwptr_done value. 38 * return the current pcm pointer. just based on the hwptr_done value.
@@ -739,6 +740,9 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
739 pt = 125 * (1 << fp->datainterval); 740 pt = 125 * (1 << fp->datainterval);
740 ptmin = min(ptmin, pt); 741 ptmin = min(ptmin, pt);
741 } 742 }
743 err = snd_usb_autoresume(subs->stream->chip);
744 if (err < 0)
745 return err;
742 746
743 param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; 747 param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME;
744 if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) 748 if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
@@ -756,21 +760,21 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
756 SNDRV_PCM_HW_PARAM_CHANNELS, 760 SNDRV_PCM_HW_PARAM_CHANNELS,
757 param_period_time_if_needed, 761 param_period_time_if_needed,
758 -1)) < 0) 762 -1)) < 0)
759 return err; 763 goto rep_err;
760 if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 764 if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
761 hw_rule_channels, subs, 765 hw_rule_channels, subs,
762 SNDRV_PCM_HW_PARAM_FORMAT, 766 SNDRV_PCM_HW_PARAM_FORMAT,
763 SNDRV_PCM_HW_PARAM_RATE, 767 SNDRV_PCM_HW_PARAM_RATE,
764 param_period_time_if_needed, 768 param_period_time_if_needed,
765 -1)) < 0) 769 -1)) < 0)
766 return err; 770 goto rep_err;
767 if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, 771 if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
768 hw_rule_format, subs, 772 hw_rule_format, subs,
769 SNDRV_PCM_HW_PARAM_RATE, 773 SNDRV_PCM_HW_PARAM_RATE,
770 SNDRV_PCM_HW_PARAM_CHANNELS, 774 SNDRV_PCM_HW_PARAM_CHANNELS,
771 param_period_time_if_needed, 775 param_period_time_if_needed,
772 -1)) < 0) 776 -1)) < 0)
773 return err; 777 goto rep_err;
774 if (param_period_time_if_needed >= 0) { 778 if (param_period_time_if_needed >= 0) {
775 err = snd_pcm_hw_rule_add(runtime, 0, 779 err = snd_pcm_hw_rule_add(runtime, 0,
776 SNDRV_PCM_HW_PARAM_PERIOD_TIME, 780 SNDRV_PCM_HW_PARAM_PERIOD_TIME,
@@ -780,11 +784,15 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
780 SNDRV_PCM_HW_PARAM_RATE, 784 SNDRV_PCM_HW_PARAM_RATE,
781 -1); 785 -1);
782 if (err < 0) 786 if (err < 0)
783 return err; 787 goto rep_err;
784 } 788 }
785 if ((err = snd_usb_pcm_check_knot(runtime, subs)) < 0) 789 if ((err = snd_usb_pcm_check_knot(runtime, subs)) < 0)
786 return err; 790 goto rep_err;
787 return 0; 791 return 0;
792
793rep_err:
794 snd_usb_autosuspend(subs->stream->chip);
795 return err;
788} 796}
789 797
790static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction) 798static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
@@ -798,6 +806,7 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
798 runtime->hw = snd_usb_hardware; 806 runtime->hw = snd_usb_hardware;
799 runtime->private_data = subs; 807 runtime->private_data = subs;
800 subs->pcm_substream = substream; 808 subs->pcm_substream = substream;
809 /* runtime PM is also done there */
801 return setup_hw_info(runtime, subs); 810 return setup_hw_info(runtime, subs);
802} 811}
803 812
@@ -811,6 +820,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
811 subs->interface = -1; 820 subs->interface = -1;
812 } 821 }
813 subs->pcm_substream = NULL; 822 subs->pcm_substream = NULL;
823 snd_usb_autosuspend(subs->stream->chip);
814 return 0; 824 return 0;
815} 825}
816 826
diff --git a/sound/usb/power.h b/sound/usb/power.h
new file mode 100644
index 000000000000..48ee51dcb71e
--- /dev/null
+++ b/sound/usb/power.h
@@ -0,0 +1,17 @@
1#ifndef __USBAUDIO_POWER_H
2#define __USBAUDIO_POWER_H
3
4#ifdef CONFIG_PM
5int snd_usb_autoresume(struct snd_usb_audio *chip);
6void snd_usb_autosuspend(struct snd_usb_audio *chip);
7#else
8static inline int snd_usb_autoresume(struct snd_usb_audio *chip)
9{
10 return 0;
11}
12static inline void snd_usb_autosuspend(struct snd_usb_audio *chip)
13{
14}
15#endif
16
17#endif /* __USBAUDIO_POWER_H */
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 921a86fd9884..c0dcfca9b5b5 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -2290,6 +2290,20 @@ YAMAHA_DEVICE(0x7010, "UB99"),
2290 } 2290 }
2291}, 2291},
2292 2292
2293/* Native Instruments MK2 series */
2294{
2295 /* Traktor Audio 6 */
2296 .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
2297 .idVendor = 0x17cc,
2298 .idProduct = 0x1010,
2299},
2300{
2301 /* Traktor Audio 10 */
2302 .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
2303 .idVendor = 0x17cc,
2304 .idProduct = 0x1020,
2305},
2306
2293/* Miditech devices */ 2307/* Miditech devices */
2294{ 2308{
2295 USB_DEVICE(0x4752, 0x0011), 2309 USB_DEVICE(0x4752, 0x0011),
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index e314cdb85003..355759bad581 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -425,6 +425,34 @@ static int snd_usb_accessmusic_boot_quirk(struct usb_device *dev)
425} 425}
426 426
427/* 427/*
428 * Some sound cards from Native Instruments are in fact compliant to the USB
429 * audio standard of version 2 and other approved USB standards, even though
430 * they come up as vendor-specific device when first connected.
431 *
432 * However, they can be told to come up with a new set of descriptors
433 * upon their next enumeration, and the interfaces announced by the new
434 * descriptors will then be handled by the kernel's class drivers. As the
435 * product ID will also change, no further checks are required.
436 */
437
438static int snd_usb_nativeinstruments_boot_quirk(struct usb_device *dev)
439{
440 int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
441 0xaf, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
442 cpu_to_le16(1), 0, NULL, 0, 1000);
443
444 if (ret < 0)
445 return ret;
446
447 usb_reset_device(dev);
448
449 /* return -EAGAIN, so the creation of an audio interface for this
450 * temporary device is aborted. The device will reconnect with a
451 * new product ID */
452 return -EAGAIN;
453}
454
455/*
428 * Setup quirks 456 * Setup quirks
429 */ 457 */
430#define AUDIOPHILE_SET 0x01 /* if set, parse device_setup */ 458#define AUDIOPHILE_SET 0x01 /* if set, parse device_setup */
@@ -489,27 +517,33 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
489 u32 id = USB_ID(le16_to_cpu(dev->descriptor.idVendor), 517 u32 id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
490 le16_to_cpu(dev->descriptor.idProduct)); 518 le16_to_cpu(dev->descriptor.idProduct));
491 519
492 /* SB Extigy needs special boot-up sequence */ 520 switch (id) {
493 /* if more models come, this will go to the quirk list. */ 521 case USB_ID(0x041e, 0x3000):
494 if (id == USB_ID(0x041e, 0x3000)) 522 /* SB Extigy needs special boot-up sequence */
523 /* if more models come, this will go to the quirk list. */
495 return snd_usb_extigy_boot_quirk(dev, intf); 524 return snd_usb_extigy_boot_quirk(dev, intf);
496 525
497 /* SB Audigy 2 NX needs its own boot-up magic, too */ 526 case USB_ID(0x041e, 0x3020):
498 if (id == USB_ID(0x041e, 0x3020)) 527 /* SB Audigy 2 NX needs its own boot-up magic, too */
499 return snd_usb_audigy2nx_boot_quirk(dev); 528 return snd_usb_audigy2nx_boot_quirk(dev);
500 529
501 /* C-Media CM106 / Turtle Beach Audio Advantage Roadie */ 530 case USB_ID(0x10f5, 0x0200):
502 if (id == USB_ID(0x10f5, 0x0200)) 531 /* C-Media CM106 / Turtle Beach Audio Advantage Roadie */
503 return snd_usb_cm106_boot_quirk(dev); 532 return snd_usb_cm106_boot_quirk(dev);
504 533
505 /* C-Media CM6206 / CM106-Like Sound Device */ 534 case USB_ID(0x0d8c, 0x0102):
506 if (id == USB_ID(0x0d8c, 0x0102)) 535 /* C-Media CM6206 / CM106-Like Sound Device */
507 return snd_usb_cm6206_boot_quirk(dev); 536 return snd_usb_cm6206_boot_quirk(dev);
508 537
509 /* Access Music VirusTI Desktop */ 538 case USB_ID(0x133e, 0x0815):
510 if (id == USB_ID(0x133e, 0x0815)) 539 /* Access Music VirusTI Desktop */
511 return snd_usb_accessmusic_boot_quirk(dev); 540 return snd_usb_accessmusic_boot_quirk(dev);
512 541
542 case USB_ID(0x17cc, 0x1010): /* Traktor Audio 6 */
543 case USB_ID(0x17cc, 0x1020): /* Traktor Audio 10 */
544 return snd_usb_nativeinstruments_boot_quirk(dev);
545 }
546
513 return 0; 547 return 0;
514} 548}
515 549
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 6e66fffe87f5..32f2a97f2f14 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -34,10 +34,14 @@ struct snd_usb_audio {
34 int index; 34 int index;
35 struct usb_device *dev; 35 struct usb_device *dev;
36 struct snd_card *card; 36 struct snd_card *card;
37 struct usb_interface *pm_intf;
37 u32 usb_id; 38 u32 usb_id;
38 int shutdown;
39 struct mutex shutdown_mutex; 39 struct mutex shutdown_mutex;
40 unsigned int shutdown:1;
41 unsigned int probing:1;
42 unsigned int autosuspended:1;
40 unsigned int txfr_quirk:1; /* Subframe boundaries on transfers */ 43 unsigned int txfr_quirk:1; /* Subframe boundaries on transfers */
44
41 int num_interfaces; 45 int num_interfaces;
42 int num_suspended_intf; 46 int num_suspended_intf;
43 47