diff options
author | Takashi Iwai <tiwai@suse.de> | 2011-05-22 04:01:29 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-05-22 04:01:29 -0400 |
commit | 02e5fbf622aabf68bdc02282a17a3aeed054237a (patch) | |
tree | 60f2d4e09464dbf338c832bb39f861f29779b86b /sound/usb | |
parent | b759b3ac9aee3afb01c21b603970ebb200c8048e (diff) | |
parent | bfe9fc8aebc997ce8bcf8ac0586c84a247812064 (diff) |
Merge branch 'topic/misc' into for-linus
Diffstat (limited to 'sound/usb')
-rw-r--r-- | sound/usb/6fire/control.c | 105 | ||||
-rw-r--r-- | sound/usb/6fire/control.h | 17 | ||||
-rw-r--r-- | sound/usb/6fire/firmware.c | 73 | ||||
-rw-r--r-- | sound/usb/6fire/pcm.c | 97 | ||||
-rw-r--r-- | sound/usb/Kconfig | 10 | ||||
-rw-r--r-- | sound/usb/clock.c | 11 | ||||
-rw-r--r-- | sound/usb/debug.h | 2 | ||||
-rw-r--r-- | sound/usb/format.c | 1 | ||||
-rw-r--r-- | sound/usb/mixer.c | 10 | ||||
-rw-r--r-- | sound/usb/mixer_quirks.c | 12 | ||||
-rw-r--r-- | sound/usb/quirks-table.h | 47 | ||||
-rw-r--r-- | sound/usb/quirks.c | 1 |
12 files changed, 273 insertions, 113 deletions
diff --git a/sound/usb/6fire/control.c b/sound/usb/6fire/control.c index 24846351118..ac828eff1a6 100644 --- a/sound/usb/6fire/control.c +++ b/sound/usb/6fire/control.c | |||
@@ -65,6 +65,15 @@ init_data[] = { | |||
65 | { 0 } /* TERMINATING ENTRY */ | 65 | { 0 } /* TERMINATING ENTRY */ |
66 | }; | 66 | }; |
67 | 67 | ||
68 | static const int rates_altsetting[] = { 1, 1, 2, 2, 3, 3 }; | ||
69 | /* values to write to soundcard register for all samplerates */ | ||
70 | static const u16 rates_6fire_vl[] = {0x00, 0x01, 0x00, 0x01, 0x00, 0x01}; | ||
71 | static const u16 rates_6fire_vh[] = {0x11, 0x11, 0x10, 0x10, 0x00, 0x00}; | ||
72 | |||
73 | enum { | ||
74 | DIGITAL_THRU_ONLY_SAMPLERATE = 3 | ||
75 | }; | ||
76 | |||
68 | static void usb6fire_control_master_vol_update(struct control_runtime *rt) | 77 | static void usb6fire_control_master_vol_update(struct control_runtime *rt) |
69 | { | 78 | { |
70 | struct comm_runtime *comm_rt = rt->chip->comm; | 79 | struct comm_runtime *comm_rt = rt->chip->comm; |
@@ -95,6 +104,67 @@ static void usb6fire_control_opt_coax_update(struct control_runtime *rt) | |||
95 | } | 104 | } |
96 | } | 105 | } |
97 | 106 | ||
107 | static int usb6fire_control_set_rate(struct control_runtime *rt, int rate) | ||
108 | { | ||
109 | int ret; | ||
110 | struct usb_device *device = rt->chip->dev; | ||
111 | struct comm_runtime *comm_rt = rt->chip->comm; | ||
112 | |||
113 | if (rate < 0 || rate >= CONTROL_N_RATES) | ||
114 | return -EINVAL; | ||
115 | |||
116 | ret = usb_set_interface(device, 1, rates_altsetting[rate]); | ||
117 | if (ret < 0) | ||
118 | return ret; | ||
119 | |||
120 | /* set soundcard clock */ | ||
121 | ret = comm_rt->write16(comm_rt, 0x02, 0x01, rates_6fire_vl[rate], | ||
122 | rates_6fire_vh[rate]); | ||
123 | if (ret < 0) | ||
124 | return ret; | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static int usb6fire_control_set_channels( | ||
130 | struct control_runtime *rt, int n_analog_out, | ||
131 | int n_analog_in, bool spdif_out, bool spdif_in) | ||
132 | { | ||
133 | int ret; | ||
134 | struct comm_runtime *comm_rt = rt->chip->comm; | ||
135 | |||
136 | /* enable analog inputs and outputs | ||
137 | * (one bit per stereo-channel) */ | ||
138 | ret = comm_rt->write16(comm_rt, 0x02, 0x02, | ||
139 | (1 << (n_analog_out / 2)) - 1, | ||
140 | (1 << (n_analog_in / 2)) - 1); | ||
141 | if (ret < 0) | ||
142 | return ret; | ||
143 | |||
144 | /* disable digital inputs and outputs */ | ||
145 | /* TODO: use spdif_x to enable/disable digital channels */ | ||
146 | ret = comm_rt->write16(comm_rt, 0x02, 0x03, 0x00, 0x00); | ||
147 | if (ret < 0) | ||
148 | return ret; | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static int usb6fire_control_streaming_update(struct control_runtime *rt) | ||
154 | { | ||
155 | struct comm_runtime *comm_rt = rt->chip->comm; | ||
156 | |||
157 | if (comm_rt) { | ||
158 | if (!rt->usb_streaming && rt->digital_thru_switch) | ||
159 | usb6fire_control_set_rate(rt, | ||
160 | DIGITAL_THRU_ONLY_SAMPLERATE); | ||
161 | return comm_rt->write16(comm_rt, 0x02, 0x00, 0x00, | ||
162 | (rt->usb_streaming ? 0x01 : 0x00) | | ||
163 | (rt->digital_thru_switch ? 0x08 : 0x00)); | ||
164 | } | ||
165 | return -EINVAL; | ||
166 | } | ||
167 | |||
98 | static int usb6fire_control_master_vol_info(struct snd_kcontrol *kcontrol, | 168 | static int usb6fire_control_master_vol_info(struct snd_kcontrol *kcontrol, |
99 | struct snd_ctl_elem_info *uinfo) | 169 | struct snd_ctl_elem_info *uinfo) |
100 | { | 170 | { |
@@ -195,6 +265,28 @@ static int usb6fire_control_opt_coax_get(struct snd_kcontrol *kcontrol, | |||
195 | return 0; | 265 | return 0; |
196 | } | 266 | } |
197 | 267 | ||
268 | static int usb6fire_control_digital_thru_put(struct snd_kcontrol *kcontrol, | ||
269 | struct snd_ctl_elem_value *ucontrol) | ||
270 | { | ||
271 | struct control_runtime *rt = snd_kcontrol_chip(kcontrol); | ||
272 | int changed = 0; | ||
273 | |||
274 | if (rt->digital_thru_switch != ucontrol->value.integer.value[0]) { | ||
275 | rt->digital_thru_switch = ucontrol->value.integer.value[0]; | ||
276 | usb6fire_control_streaming_update(rt); | ||
277 | changed = 1; | ||
278 | } | ||
279 | return changed; | ||
280 | } | ||
281 | |||
282 | static int usb6fire_control_digital_thru_get(struct snd_kcontrol *kcontrol, | ||
283 | struct snd_ctl_elem_value *ucontrol) | ||
284 | { | ||
285 | struct control_runtime *rt = snd_kcontrol_chip(kcontrol); | ||
286 | ucontrol->value.integer.value[0] = rt->digital_thru_switch; | ||
287 | return 0; | ||
288 | } | ||
289 | |||
198 | static struct __devinitdata snd_kcontrol_new elements[] = { | 290 | static struct __devinitdata snd_kcontrol_new elements[] = { |
199 | { | 291 | { |
200 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 292 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -223,6 +315,15 @@ static struct __devinitdata snd_kcontrol_new elements[] = { | |||
223 | .get = usb6fire_control_opt_coax_get, | 315 | .get = usb6fire_control_opt_coax_get, |
224 | .put = usb6fire_control_opt_coax_put | 316 | .put = usb6fire_control_opt_coax_put |
225 | }, | 317 | }, |
318 | { | ||
319 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
320 | .name = "Digital Thru Playback Route", | ||
321 | .index = 0, | ||
322 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
323 | .info = snd_ctl_boolean_mono_info, | ||
324 | .get = usb6fire_control_digital_thru_get, | ||
325 | .put = usb6fire_control_digital_thru_put | ||
326 | }, | ||
226 | {} | 327 | {} |
227 | }; | 328 | }; |
228 | 329 | ||
@@ -238,6 +339,9 @@ int __devinit usb6fire_control_init(struct sfire_chip *chip) | |||
238 | return -ENOMEM; | 339 | return -ENOMEM; |
239 | 340 | ||
240 | rt->chip = chip; | 341 | rt->chip = chip; |
342 | rt->update_streaming = usb6fire_control_streaming_update; | ||
343 | rt->set_rate = usb6fire_control_set_rate; | ||
344 | rt->set_channels = usb6fire_control_set_channels; | ||
241 | 345 | ||
242 | i = 0; | 346 | i = 0; |
243 | while (init_data[i].type) { | 347 | while (init_data[i].type) { |
@@ -249,6 +353,7 @@ int __devinit usb6fire_control_init(struct sfire_chip *chip) | |||
249 | usb6fire_control_opt_coax_update(rt); | 353 | usb6fire_control_opt_coax_update(rt); |
250 | usb6fire_control_line_phono_update(rt); | 354 | usb6fire_control_line_phono_update(rt); |
251 | usb6fire_control_master_vol_update(rt); | 355 | usb6fire_control_master_vol_update(rt); |
356 | usb6fire_control_streaming_update(rt); | ||
252 | 357 | ||
253 | i = 0; | 358 | i = 0; |
254 | while (elements[i].name) { | 359 | while (elements[i].name) { |
diff --git a/sound/usb/6fire/control.h b/sound/usb/6fire/control.h index b534c777ab0..8f5aeead2e3 100644 --- a/sound/usb/6fire/control.h +++ b/sound/usb/6fire/control.h | |||
@@ -21,12 +21,29 @@ enum { | |||
21 | CONTROL_MAX_ELEMENTS = 32 | 21 | CONTROL_MAX_ELEMENTS = 32 |
22 | }; | 22 | }; |
23 | 23 | ||
24 | enum { | ||
25 | CONTROL_RATE_44KHZ, | ||
26 | CONTROL_RATE_48KHZ, | ||
27 | CONTROL_RATE_88KHZ, | ||
28 | CONTROL_RATE_96KHZ, | ||
29 | CONTROL_RATE_176KHZ, | ||
30 | CONTROL_RATE_192KHZ, | ||
31 | CONTROL_N_RATES | ||
32 | }; | ||
33 | |||
24 | struct control_runtime { | 34 | struct control_runtime { |
35 | int (*update_streaming)(struct control_runtime *rt); | ||
36 | int (*set_rate)(struct control_runtime *rt, int rate); | ||
37 | int (*set_channels)(struct control_runtime *rt, int n_analog_out, | ||
38 | int n_analog_in, bool spdif_out, bool spdif_in); | ||
39 | |||
25 | struct sfire_chip *chip; | 40 | struct sfire_chip *chip; |
26 | 41 | ||
27 | struct snd_kcontrol *element[CONTROL_MAX_ELEMENTS]; | 42 | struct snd_kcontrol *element[CONTROL_MAX_ELEMENTS]; |
28 | bool opt_coax_switch; | 43 | bool opt_coax_switch; |
29 | bool line_phono_switch; | 44 | bool line_phono_switch; |
45 | bool digital_thru_switch; | ||
46 | bool usb_streaming; | ||
30 | u8 master_vol; | 47 | u8 master_vol; |
31 | }; | 48 | }; |
32 | 49 | ||
diff --git a/sound/usb/6fire/firmware.c b/sound/usb/6fire/firmware.c index 86c1a310376..d47beffedb0 100644 --- a/sound/usb/6fire/firmware.c +++ b/sound/usb/6fire/firmware.c | |||
@@ -3,12 +3,6 @@ | |||
3 | * | 3 | * |
4 | * Firmware loader | 4 | * Firmware loader |
5 | * | 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> | 6 | * Author: Torsten Schenk <torsten.schenk@zoho.com> |
13 | * Created: Jan 01, 2011 | 7 | * Created: Jan 01, 2011 |
14 | * Version: 0.3.0 | 8 | * Version: 0.3.0 |
@@ -21,6 +15,7 @@ | |||
21 | */ | 15 | */ |
22 | 16 | ||
23 | #include <linux/firmware.h> | 17 | #include <linux/firmware.h> |
18 | #include <linux/bitrev.h> | ||
24 | 19 | ||
25 | #include "firmware.h" | 20 | #include "firmware.h" |
26 | #include "chip.h" | 21 | #include "chip.h" |
@@ -33,32 +28,6 @@ enum { | |||
33 | FPGA_BUFSIZE = 512, FPGA_EP = 2 | 28 | FPGA_BUFSIZE = 512, FPGA_EP = 2 |
34 | }; | 29 | }; |
35 | 30 | ||
36 | static 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 | /* | 31 | /* |
63 | * wMaxPacketSize of pcm endpoints. | 32 | * wMaxPacketSize of pcm endpoints. |
64 | * keep synced with rates_in_packet_size and rates_out_packet_size in pcm.c | 33 | * keep synced with rates_in_packet_size and rates_out_packet_size in pcm.c |
@@ -72,6 +41,10 @@ static const u8 ep_w_max_packet_size[] = { | |||
72 | 0x94, 0x01, 0x5c, 0x02 /* alt 3: 404 EP2 and 604 EP6 (25 fpp) */ | 41 | 0x94, 0x01, 0x5c, 0x02 /* alt 3: 404 EP2 and 604 EP6 (25 fpp) */ |
73 | }; | 42 | }; |
74 | 43 | ||
44 | static const u8 known_fw_versions[][4] = { | ||
45 | { 0x03, 0x01, 0x0b, 0x00 } | ||
46 | }; | ||
47 | |||
75 | struct ihex_record { | 48 | struct ihex_record { |
76 | u16 address; | 49 | u16 address; |
77 | u8 len; | 50 | u8 len; |
@@ -340,7 +313,7 @@ static int usb6fire_fw_fpga_upload( | |||
340 | 313 | ||
341 | while (c != end) { | 314 | while (c != end) { |
342 | for (i = 0; c != end && i < FPGA_BUFSIZE; i++, c++) | 315 | for (i = 0; c != end && i < FPGA_BUFSIZE; i++, c++) |
343 | buffer[i] = BIT_REVERSE_TABLE[(u8) *c]; | 316 | buffer[i] = byte_rev_table[(u8) *c]; |
344 | 317 | ||
345 | ret = usb6fire_fw_fpga_write(device, buffer, i); | 318 | ret = usb6fire_fw_fpga_write(device, buffer, i); |
346 | if (ret < 0) { | 319 | if (ret < 0) { |
@@ -363,6 +336,25 @@ static int usb6fire_fw_fpga_upload( | |||
363 | return 0; | 336 | return 0; |
364 | } | 337 | } |
365 | 338 | ||
339 | /* check, if the firmware version the devices has currently loaded | ||
340 | * is known by this driver. 'version' needs to have 4 bytes version | ||
341 | * info data. */ | ||
342 | static int usb6fire_fw_check(u8 *version) | ||
343 | { | ||
344 | int i; | ||
345 | |||
346 | for (i = 0; i < ARRAY_SIZE(known_fw_versions); i++) | ||
347 | if (!memcmp(version, known_fw_versions + i, 4)) | ||
348 | return 0; | ||
349 | |||
350 | snd_printk(KERN_ERR PREFIX "invalid fimware version in device: " | ||
351 | "%02x %02x %02x %02x. " | ||
352 | "please reconnect to power. if this failure " | ||
353 | "still happens, check your firmware installation.", | ||
354 | version[0], version[1], version[2], version[3]); | ||
355 | return -EINVAL; | ||
356 | } | ||
357 | |||
366 | int usb6fire_fw_init(struct usb_interface *intf) | 358 | int usb6fire_fw_init(struct usb_interface *intf) |
367 | { | 359 | { |
368 | int i; | 360 | int i; |
@@ -378,9 +370,7 @@ int usb6fire_fw_init(struct usb_interface *intf) | |||
378 | "firmware state.\n"); | 370 | "firmware state.\n"); |
379 | return ret; | 371 | return ret; |
380 | } | 372 | } |
381 | if (buffer[0] != 0xeb || buffer[1] != 0xaa || buffer[2] != 0x55 | 373 | 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 " | 374 | snd_printk(KERN_ERR PREFIX "unknown device firmware state " |
385 | "received from device: "); | 375 | "received from device: "); |
386 | for (i = 0; i < 8; i++) | 376 | for (i = 0; i < 8; i++) |
@@ -389,7 +379,7 @@ int usb6fire_fw_init(struct usb_interface *intf) | |||
389 | return -EIO; | 379 | return -EIO; |
390 | } | 380 | } |
391 | /* do we need fpga loader ezusb firmware? */ | 381 | /* do we need fpga loader ezusb firmware? */ |
392 | if (buffer[3] == 0x01 && buffer[6] == 0x19) { | 382 | if (buffer[3] == 0x01) { |
393 | ret = usb6fire_fw_ezusb_upload(intf, | 383 | ret = usb6fire_fw_ezusb_upload(intf, |
394 | "6fire/dmx6firel2.ihx", 0, NULL, 0); | 384 | "6fire/dmx6firel2.ihx", 0, NULL, 0); |
395 | if (ret < 0) | 385 | if (ret < 0) |
@@ -397,7 +387,10 @@ int usb6fire_fw_init(struct usb_interface *intf) | |||
397 | return FW_NOT_READY; | 387 | return FW_NOT_READY; |
398 | } | 388 | } |
399 | /* do we need fpga firmware and application ezusb firmware? */ | 389 | /* do we need fpga firmware and application ezusb firmware? */ |
400 | else if (buffer[3] == 0x02 && buffer[6] == 0x0b) { | 390 | else if (buffer[3] == 0x02) { |
391 | ret = usb6fire_fw_check(buffer + 4); | ||
392 | if (ret < 0) | ||
393 | return ret; | ||
401 | ret = usb6fire_fw_fpga_upload(intf, "6fire/dmx6firecf.bin"); | 394 | ret = usb6fire_fw_fpga_upload(intf, "6fire/dmx6firecf.bin"); |
402 | if (ret < 0) | 395 | if (ret < 0) |
403 | return ret; | 396 | return ret; |
@@ -410,8 +403,8 @@ int usb6fire_fw_init(struct usb_interface *intf) | |||
410 | return FW_NOT_READY; | 403 | return FW_NOT_READY; |
411 | } | 404 | } |
412 | /* all fw loaded? */ | 405 | /* all fw loaded? */ |
413 | else if (buffer[3] == 0x03 && buffer[6] == 0x0b) | 406 | else if (buffer[3] == 0x03) |
414 | return 0; | 407 | return usb6fire_fw_check(buffer + 4); |
415 | /* unknown data? */ | 408 | /* unknown data? */ |
416 | else { | 409 | else { |
417 | snd_printk(KERN_ERR PREFIX "unknown device firmware state " | 410 | snd_printk(KERN_ERR PREFIX "unknown device firmware state " |
diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c index ba62c7468ba..b137b25865c 100644 --- a/sound/usb/6fire/pcm.c +++ b/sound/usb/6fire/pcm.c | |||
@@ -17,26 +17,23 @@ | |||
17 | #include "pcm.h" | 17 | #include "pcm.h" |
18 | #include "chip.h" | 18 | #include "chip.h" |
19 | #include "comm.h" | 19 | #include "comm.h" |
20 | #include "control.h" | ||
20 | 21 | ||
21 | enum { | 22 | enum { |
22 | OUT_N_CHANNELS = 6, IN_N_CHANNELS = 4 | 23 | OUT_N_CHANNELS = 6, IN_N_CHANNELS = 4 |
23 | }; | 24 | }; |
24 | 25 | ||
25 | /* keep next two synced with | 26 | /* keep next two synced with |
26 | * FW_EP_W_MAX_PACKET_SIZE[] and RATES_MAX_PACKET_SIZE */ | 27 | * FW_EP_W_MAX_PACKET_SIZE[] and RATES_MAX_PACKET_SIZE |
28 | * and CONTROL_RATE_XXX in control.h */ | ||
27 | static const int rates_in_packet_size[] = { 228, 228, 420, 420, 404, 404 }; | 29 | static const int rates_in_packet_size[] = { 228, 228, 420, 420, 404, 404 }; |
28 | static const int rates_out_packet_size[] = { 228, 228, 420, 420, 604, 604 }; | 30 | static const int rates_out_packet_size[] = { 228, 228, 420, 420, 604, 604 }; |
29 | static const int rates[] = { 44100, 48000, 88200, 96000, 176400, 192000 }; | 31 | static const int rates[] = { 44100, 48000, 88200, 96000, 176400, 192000 }; |
30 | static const int rates_altsetting[] = { 1, 1, 2, 2, 3, 3 }; | ||
31 | static const int rates_alsaid[] = { | 32 | static const int rates_alsaid[] = { |
32 | SNDRV_PCM_RATE_44100, SNDRV_PCM_RATE_48000, | 33 | SNDRV_PCM_RATE_44100, SNDRV_PCM_RATE_48000, |
33 | SNDRV_PCM_RATE_88200, SNDRV_PCM_RATE_96000, | 34 | SNDRV_PCM_RATE_88200, SNDRV_PCM_RATE_96000, |
34 | SNDRV_PCM_RATE_176400, SNDRV_PCM_RATE_192000 }; | 35 | SNDRV_PCM_RATE_176400, SNDRV_PCM_RATE_192000 }; |
35 | 36 | ||
36 | /* values to write to soundcard register for all samplerates */ | ||
37 | static const u16 rates_6fire_vl[] = {0x00, 0x01, 0x00, 0x01, 0x00, 0x01}; | ||
38 | static const u16 rates_6fire_vh[] = {0x11, 0x11, 0x10, 0x10, 0x00, 0x00}; | ||
39 | |||
40 | enum { /* settings for pcm */ | 37 | enum { /* settings for pcm */ |
41 | OUT_EP = 6, IN_EP = 2, MAX_BUFSIZE = 128 * 1024 | 38 | OUT_EP = 6, IN_EP = 2, MAX_BUFSIZE = 128 * 1024 |
42 | }; | 39 | }; |
@@ -48,15 +45,6 @@ enum { /* pcm streaming states */ | |||
48 | STREAM_STOPPING | 45 | STREAM_STOPPING |
49 | }; | 46 | }; |
50 | 47 | ||
51 | enum { /* 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 | |||
60 | static const struct snd_pcm_hardware pcm_hw = { | 48 | static const struct snd_pcm_hardware pcm_hw = { |
61 | .info = SNDRV_PCM_INFO_MMAP | | 49 | .info = SNDRV_PCM_INFO_MMAP | |
62 | SNDRV_PCM_INFO_INTERLEAVED | | 50 | SNDRV_PCM_INFO_INTERLEAVED | |
@@ -64,7 +52,7 @@ static const struct snd_pcm_hardware pcm_hw = { | |||
64 | SNDRV_PCM_INFO_MMAP_VALID | | 52 | SNDRV_PCM_INFO_MMAP_VALID | |
65 | SNDRV_PCM_INFO_BATCH, | 53 | SNDRV_PCM_INFO_BATCH, |
66 | 54 | ||
67 | .formats = SNDRV_PCM_FMTBIT_S24_LE, | 55 | .formats = SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, |
68 | 56 | ||
69 | .rates = SNDRV_PCM_RATE_44100 | | 57 | .rates = SNDRV_PCM_RATE_44100 | |
70 | SNDRV_PCM_RATE_48000 | | 58 | SNDRV_PCM_RATE_48000 | |
@@ -87,57 +75,34 @@ static const struct snd_pcm_hardware pcm_hw = { | |||
87 | static int usb6fire_pcm_set_rate(struct pcm_runtime *rt) | 75 | static int usb6fire_pcm_set_rate(struct pcm_runtime *rt) |
88 | { | 76 | { |
89 | int ret; | 77 | int ret; |
90 | struct usb_device *device = rt->chip->dev; | 78 | struct control_runtime *ctrl_rt = rt->chip->control; |
91 | struct comm_runtime *comm_rt = rt->chip->comm; | ||
92 | 79 | ||
93 | if (rt->rate >= ARRAY_SIZE(rates)) | 80 | ctrl_rt->usb_streaming = false; |
94 | return -EINVAL; | 81 | ret = ctrl_rt->update_streaming(ctrl_rt); |
95 | /* disable streaming */ | ||
96 | ret = comm_rt->write16(comm_rt, 0x02, 0x00, 0x00, 0x00); | ||
97 | if (ret < 0) { | 82 | if (ret < 0) { |
98 | snd_printk(KERN_ERR PREFIX "error stopping streaming while " | 83 | snd_printk(KERN_ERR PREFIX "error stopping streaming while " |
99 | "setting samplerate %d.\n", rates[rt->rate]); | 84 | "setting samplerate %d.\n", rates[rt->rate]); |
100 | return ret; | 85 | return ret; |
101 | } | 86 | } |
102 | 87 | ||
103 | ret = usb_set_interface(device, 1, rates_altsetting[rt->rate]); | 88 | ret = ctrl_rt->set_rate(ctrl_rt, 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) { | 89 | if (ret < 0) { |
115 | snd_printk(KERN_ERR PREFIX "error setting samplerate %d.\n", | 90 | snd_printk(KERN_ERR PREFIX "error setting samplerate %d.\n", |
116 | rates[rt->rate]); | 91 | rates[rt->rate]); |
117 | return ret; | 92 | return ret; |
118 | } | 93 | } |
119 | 94 | ||
120 | /* enable analog inputs and outputs | 95 | ret = ctrl_rt->set_channels(ctrl_rt, OUT_N_CHANNELS, IN_N_CHANNELS, |
121 | * (one bit per stereo-channel) */ | 96 | false, false); |
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) { | 97 | if (ret < 0) { |
126 | snd_printk(KERN_ERR PREFIX "error initializing analog channels " | 98 | snd_printk(KERN_ERR PREFIX "error initializing channels " |
127 | "while setting samplerate %d.\n", | 99 | "while setting samplerate %d.\n", |
128 | rates[rt->rate]); | 100 | rates[rt->rate]); |
129 | return ret; | 101 | return ret; |
130 | } | 102 | } |
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 | 103 | ||
140 | ret = comm_rt->write16(comm_rt, 0x02, 0x00, 0x00, 0x01); | 104 | ctrl_rt->usb_streaming = true; |
105 | ret = ctrl_rt->update_streaming(ctrl_rt); | ||
141 | if (ret < 0) { | 106 | if (ret < 0) { |
142 | snd_printk(KERN_ERR PREFIX "error starting streaming while " | 107 | snd_printk(KERN_ERR PREFIX "error starting streaming while " |
143 | "setting samplerate %d.\n", rates[rt->rate]); | 108 | "setting samplerate %d.\n", rates[rt->rate]); |
@@ -168,12 +133,15 @@ static struct pcm_substream *usb6fire_pcm_get_substream( | |||
168 | static void usb6fire_pcm_stream_stop(struct pcm_runtime *rt) | 133 | static void usb6fire_pcm_stream_stop(struct pcm_runtime *rt) |
169 | { | 134 | { |
170 | int i; | 135 | int i; |
136 | struct control_runtime *ctrl_rt = rt->chip->control; | ||
171 | 137 | ||
172 | if (rt->stream_state != STREAM_DISABLED) { | 138 | if (rt->stream_state != STREAM_DISABLED) { |
173 | for (i = 0; i < PCM_N_URBS; i++) { | 139 | for (i = 0; i < PCM_N_URBS; i++) { |
174 | usb_kill_urb(&rt->in_urbs[i].instance); | 140 | usb_kill_urb(&rt->in_urbs[i].instance); |
175 | usb_kill_urb(&rt->out_urbs[i].instance); | 141 | usb_kill_urb(&rt->out_urbs[i].instance); |
176 | } | 142 | } |
143 | ctrl_rt->usb_streaming = false; | ||
144 | ctrl_rt->update_streaming(ctrl_rt); | ||
177 | rt->stream_state = STREAM_DISABLED; | 145 | rt->stream_state = STREAM_DISABLED; |
178 | } | 146 | } |
179 | } | 147 | } |
@@ -228,7 +196,7 @@ static void usb6fire_pcm_capture(struct pcm_substream *sub, struct pcm_urb *urb) | |||
228 | unsigned int total_length = 0; | 196 | unsigned int total_length = 0; |
229 | struct pcm_runtime *rt = snd_pcm_substream_chip(sub->instance); | 197 | struct pcm_runtime *rt = snd_pcm_substream_chip(sub->instance); |
230 | struct snd_pcm_runtime *alsa_rt = sub->instance->runtime; | 198 | struct snd_pcm_runtime *alsa_rt = sub->instance->runtime; |
231 | u32 *src = (u32 *) urb->buffer; | 199 | u32 *src = NULL; |
232 | u32 *dest = (u32 *) (alsa_rt->dma_area + sub->dma_off | 200 | u32 *dest = (u32 *) (alsa_rt->dma_area + sub->dma_off |
233 | * (alsa_rt->frame_bits >> 3)); | 201 | * (alsa_rt->frame_bits >> 3)); |
234 | u32 *dest_end = (u32 *) (alsa_rt->dma_area + alsa_rt->buffer_size | 202 | u32 *dest_end = (u32 *) (alsa_rt->dma_area + alsa_rt->buffer_size |
@@ -244,7 +212,12 @@ static void usb6fire_pcm_capture(struct pcm_substream *sub, struct pcm_urb *urb) | |||
244 | else | 212 | else |
245 | frame_count = 0; | 213 | frame_count = 0; |
246 | 214 | ||
247 | src = (u32 *) (urb->buffer + total_length); | 215 | if (alsa_rt->format == SNDRV_PCM_FORMAT_S24_LE) |
216 | src = (u32 *) (urb->buffer + total_length); | ||
217 | else if (alsa_rt->format == SNDRV_PCM_FORMAT_S32_LE) | ||
218 | src = (u32 *) (urb->buffer - 1 + total_length); | ||
219 | else | ||
220 | return; | ||
248 | src++; /* skip leading 4 bytes of every packet */ | 221 | src++; /* skip leading 4 bytes of every packet */ |
249 | total_length += urb->packets[i].length; | 222 | total_length += urb->packets[i].length; |
250 | for (frame = 0; frame < frame_count; frame++) { | 223 | for (frame = 0; frame < frame_count; frame++) { |
@@ -274,9 +247,18 @@ static void usb6fire_pcm_playback(struct pcm_substream *sub, | |||
274 | * (alsa_rt->frame_bits >> 3)); | 247 | * (alsa_rt->frame_bits >> 3)); |
275 | u32 *src_end = (u32 *) (alsa_rt->dma_area + alsa_rt->buffer_size | 248 | u32 *src_end = (u32 *) (alsa_rt->dma_area + alsa_rt->buffer_size |
276 | * (alsa_rt->frame_bits >> 3)); | 249 | * (alsa_rt->frame_bits >> 3)); |
277 | u32 *dest = (u32 *) urb->buffer; | 250 | u32 *dest; |
278 | int bytes_per_frame = alsa_rt->channels << 2; | 251 | int bytes_per_frame = alsa_rt->channels << 2; |
279 | 252 | ||
253 | if (alsa_rt->format == SNDRV_PCM_FORMAT_S32_LE) | ||
254 | dest = (u32 *) (urb->buffer - 1); | ||
255 | else if (alsa_rt->format == SNDRV_PCM_FORMAT_S24_LE) | ||
256 | dest = (u32 *) (urb->buffer); | ||
257 | else { | ||
258 | snd_printk(KERN_ERR PREFIX "Unknown sample format."); | ||
259 | return; | ||
260 | } | ||
261 | |||
280 | for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) { | 262 | for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) { |
281 | /* at least 4 header bytes for valid packet. | 263 | /* at least 4 header bytes for valid packet. |
282 | * after that: 32 bits per sample for analog channels */ | 264 | * after that: 32 bits per sample for analog channels */ |
@@ -456,7 +438,7 @@ static int usb6fire_pcm_close(struct snd_pcm_substream *alsa_sub) | |||
456 | /* all substreams closed? if so, stop streaming */ | 438 | /* all substreams closed? if so, stop streaming */ |
457 | if (!rt->playback.instance && !rt->capture.instance) { | 439 | if (!rt->playback.instance && !rt->capture.instance) { |
458 | usb6fire_pcm_stream_stop(rt); | 440 | usb6fire_pcm_stream_stop(rt); |
459 | rt->rate = -1; | 441 | rt->rate = ARRAY_SIZE(rates); |
460 | } | 442 | } |
461 | } | 443 | } |
462 | mutex_unlock(&rt->stream_mutex); | 444 | mutex_unlock(&rt->stream_mutex); |
@@ -480,7 +462,6 @@ static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub) | |||
480 | struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub); | 462 | struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub); |
481 | struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub); | 463 | struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub); |
482 | struct snd_pcm_runtime *alsa_rt = alsa_sub->runtime; | 464 | struct snd_pcm_runtime *alsa_rt = alsa_sub->runtime; |
483 | int i; | ||
484 | int ret; | 465 | int ret; |
485 | 466 | ||
486 | if (rt->panic) | 467 | if (rt->panic) |
@@ -493,12 +474,10 @@ static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub) | |||
493 | sub->period_off = 0; | 474 | sub->period_off = 0; |
494 | 475 | ||
495 | if (rt->stream_state == STREAM_DISABLED) { | 476 | if (rt->stream_state == STREAM_DISABLED) { |
496 | for (i = 0; i < ARRAY_SIZE(rates); i++) | 477 | for (rt->rate = 0; rt->rate < ARRAY_SIZE(rates); rt->rate++) |
497 | if (alsa_rt->rate == rates[i]) { | 478 | if (alsa_rt->rate == rates[rt->rate]) |
498 | rt->rate = i; | ||
499 | break; | 479 | break; |
500 | } | 480 | if (rt->rate == ARRAY_SIZE(rates)) { |
501 | if (i == ARRAY_SIZE(rates)) { | ||
502 | mutex_unlock(&rt->stream_mutex); | 481 | mutex_unlock(&rt->stream_mutex); |
503 | snd_printk("invalid rate %d in prepare.\n", | 482 | snd_printk("invalid rate %d in prepare.\n", |
504 | alsa_rt->rate); | 483 | alsa_rt->rate); |
@@ -613,7 +592,7 @@ int __devinit usb6fire_pcm_init(struct sfire_chip *chip) | |||
613 | 592 | ||
614 | rt->chip = chip; | 593 | rt->chip = chip; |
615 | rt->stream_state = STREAM_DISABLED; | 594 | rt->stream_state = STREAM_DISABLED; |
616 | rt->rate = -1; | 595 | rt->rate = ARRAY_SIZE(rates); |
617 | init_waitqueue_head(&rt->stream_wait_queue); | 596 | init_waitqueue_head(&rt->stream_wait_queue); |
618 | mutex_init(&rt->stream_mutex); | 597 | mutex_init(&rt->stream_mutex); |
619 | 598 | ||
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig index 97724d8fa9f..8beb77563da 100644 --- a/sound/usb/Kconfig +++ b/sound/usb/Kconfig | |||
@@ -100,19 +100,17 @@ config SND_USB_US122L | |||
100 | 100 | ||
101 | config SND_USB_6FIRE | 101 | config SND_USB_6FIRE |
102 | tristate "TerraTec DMX 6Fire USB" | 102 | tristate "TerraTec DMX 6Fire USB" |
103 | depends on EXPERIMENTAL | ||
104 | select FW_LOADER | 103 | select FW_LOADER |
104 | select BITREVERSE | ||
105 | select SND_RAWMIDI | 105 | select SND_RAWMIDI |
106 | select SND_PCM | 106 | select SND_PCM |
107 | help | 107 | help |
108 | Say Y here to include support for TerraTec 6fire DMX USB interface. | 108 | Say Y here to include support for TerraTec 6fire DMX USB interface. |
109 | 109 | ||
110 | You will need firmware files in order to be able to use the device | 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 | 111 | after it has been coldstarted. An install script for the firmware |
112 | firmware loading for all devices. If you own such a device, | 112 | and further help can be found at |
113 | you could start windows and let the windows driver upload | 113 | http://sixfireusb.sourceforge.net |
114 | the firmware. As long as you do not unplug your device from power, | ||
115 | it should be usable. | ||
116 | 114 | ||
117 | endif # SND_USB | 115 | endif # SND_USB |
118 | 116 | ||
diff --git a/sound/usb/clock.c b/sound/usb/clock.c index 7754a103454..075195e8661 100644 --- a/sound/usb/clock.c +++ b/sound/usb/clock.c | |||
@@ -104,6 +104,15 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id) | |||
104 | int err; | 104 | int err; |
105 | unsigned char data; | 105 | unsigned char data; |
106 | struct usb_device *dev = chip->dev; | 106 | struct usb_device *dev = chip->dev; |
107 | struct uac_clock_source_descriptor *cs_desc = | ||
108 | snd_usb_find_clock_source(chip->ctrl_intf, source_id); | ||
109 | |||
110 | if (!cs_desc) | ||
111 | return 0; | ||
112 | |||
113 | /* If a clock source can't tell us whether it's valid, we assume it is */ | ||
114 | if (!uac2_control_is_readable(cs_desc->bmControls, UAC2_CS_CONTROL_CLOCK_VALID)) | ||
115 | return 1; | ||
107 | 116 | ||
108 | err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR, | 117 | err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR, |
109 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, | 118 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, |
@@ -114,7 +123,7 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id) | |||
114 | if (err < 0) { | 123 | if (err < 0) { |
115 | snd_printk(KERN_WARNING "%s(): cannot get clock validity for id %d\n", | 124 | snd_printk(KERN_WARNING "%s(): cannot get clock validity for id %d\n", |
116 | __func__, source_id); | 125 | __func__, source_id); |
117 | return err; | 126 | return 0; |
118 | } | 127 | } |
119 | 128 | ||
120 | return !!data; | 129 | return !!data; |
diff --git a/sound/usb/debug.h b/sound/usb/debug.h index 343ec2d9ee6..58030176f00 100644 --- a/sound/usb/debug.h +++ b/sound/usb/debug.h | |||
@@ -8,7 +8,7 @@ | |||
8 | #ifdef HW_CONST_DEBUG | 8 | #ifdef HW_CONST_DEBUG |
9 | #define hwc_debug(fmt, args...) printk(KERN_DEBUG fmt, ##args) | 9 | #define hwc_debug(fmt, args...) printk(KERN_DEBUG fmt, ##args) |
10 | #else | 10 | #else |
11 | #define hwc_debug(fmt, args...) /**/ | 11 | #define hwc_debug(fmt, args...) do { } while(0) |
12 | #endif | 12 | #endif |
13 | 13 | ||
14 | #endif /* __USBAUDIO_DEBUG_H */ | 14 | #endif /* __USBAUDIO_DEBUG_H */ |
diff --git a/sound/usb/format.c b/sound/usb/format.c index f079b5e2ab2..8d042dce0d1 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "helper.h" | 30 | #include "helper.h" |
31 | #include "debug.h" | 31 | #include "debug.h" |
32 | #include "clock.h" | 32 | #include "clock.h" |
33 | #include "format.h" | ||
33 | 34 | ||
34 | /* | 35 | /* |
35 | * parse the audio format type I descriptor | 36 | * parse the audio format type I descriptor |
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 6ec33b62e6c..eab06edcc9b 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c | |||
@@ -1097,11 +1097,13 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
1097 | append_ctl_name(kctl, control == UAC_FU_MUTE ? | 1097 | append_ctl_name(kctl, control == UAC_FU_MUTE ? |
1098 | " Switch" : " Volume"); | 1098 | " Switch" : " Volume"); |
1099 | if (control == UAC_FU_VOLUME) { | 1099 | if (control == UAC_FU_VOLUME) { |
1100 | kctl->tlv.c = mixer_vol_tlv; | ||
1101 | kctl->vd[0].access |= | ||
1102 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | | ||
1103 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; | ||
1104 | check_mapped_dB(map, cval); | 1100 | check_mapped_dB(map, cval); |
1101 | if (cval->dBmin < cval->dBmax) { | ||
1102 | kctl->tlv.c = mixer_vol_tlv; | ||
1103 | kctl->vd[0].access |= | ||
1104 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | | ||
1105 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; | ||
1106 | } | ||
1105 | } | 1107 | } |
1106 | break; | 1108 | break; |
1107 | 1109 | ||
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 73dcc8256bc..9146cffa6ed 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c | |||
@@ -61,6 +61,7 @@ static const struct rc_config { | |||
61 | { USB_ID(0x041e, 0x3020), 2, 1, 6, 6, 18, 0x0013 }, /* Audigy 2 NX */ | 61 | { USB_ID(0x041e, 0x3020), 2, 1, 6, 6, 18, 0x0013 }, /* Audigy 2 NX */ |
62 | { USB_ID(0x041e, 0x3040), 2, 2, 6, 6, 2, 0x6e91 }, /* Live! 24-bit */ | 62 | { USB_ID(0x041e, 0x3040), 2, 2, 6, 6, 2, 0x6e91 }, /* Live! 24-bit */ |
63 | { USB_ID(0x041e, 0x3042), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi S51 */ | 63 | { USB_ID(0x041e, 0x3042), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi S51 */ |
64 | { USB_ID(0x041e, 0x30df), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi S51 Pro */ | ||
64 | { USB_ID(0x041e, 0x3048), 2, 2, 6, 6, 2, 0x6e91 }, /* Toshiba SB0500 */ | 65 | { USB_ID(0x041e, 0x3048), 2, 2, 6, 6, 2, 0x6e91 }, /* Toshiba SB0500 */ |
65 | }; | 66 | }; |
66 | 67 | ||
@@ -188,6 +189,12 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
188 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, | 189 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, |
189 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | 190 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, |
190 | !value, 0, NULL, 0, 100); | 191 | !value, 0, NULL, 0, 100); |
192 | /* USB X-Fi S51 Pro */ | ||
193 | if (mixer->chip->usb_id == USB_ID(0x041e, 0x30df)) | ||
194 | err = snd_usb_ctl_msg(mixer->chip->dev, | ||
195 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, | ||
196 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | ||
197 | !value, 0, NULL, 0, 100); | ||
191 | else | 198 | else |
192 | err = snd_usb_ctl_msg(mixer->chip->dev, | 199 | err = snd_usb_ctl_msg(mixer->chip->dev, |
193 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, | 200 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, |
@@ -234,9 +241,13 @@ static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer) | |||
234 | /* USB X-Fi S51 doesn't have a CMSS LED */ | 241 | /* USB X-Fi S51 doesn't have a CMSS LED */ |
235 | if ((mixer->chip->usb_id == USB_ID(0x041e, 0x3042)) && i == 0) | 242 | if ((mixer->chip->usb_id == USB_ID(0x041e, 0x3042)) && i == 0) |
236 | continue; | 243 | continue; |
244 | /* USB X-Fi S51 Pro doesn't have one either */ | ||
245 | if ((mixer->chip->usb_id == USB_ID(0x041e, 0x30df)) && i == 0) | ||
246 | continue; | ||
237 | if (i > 1 && /* Live24ext has 2 LEDs only */ | 247 | if (i > 1 && /* Live24ext has 2 LEDs only */ |
238 | (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || | 248 | (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || |
239 | mixer->chip->usb_id == USB_ID(0x041e, 0x3042) || | 249 | mixer->chip->usb_id == USB_ID(0x041e, 0x3042) || |
250 | mixer->chip->usb_id == USB_ID(0x041e, 0x30df) || | ||
240 | mixer->chip->usb_id == USB_ID(0x041e, 0x3048))) | 251 | mixer->chip->usb_id == USB_ID(0x041e, 0x3048))) |
241 | break; | 252 | break; |
242 | err = snd_ctl_add(mixer->chip->card, | 253 | err = snd_ctl_add(mixer->chip->card, |
@@ -512,6 +523,7 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) | |||
512 | case USB_ID(0x041e, 0x3020): | 523 | case USB_ID(0x041e, 0x3020): |
513 | case USB_ID(0x041e, 0x3040): | 524 | case USB_ID(0x041e, 0x3040): |
514 | case USB_ID(0x041e, 0x3042): | 525 | case USB_ID(0x041e, 0x3042): |
526 | case USB_ID(0x041e, 0x30df): | ||
515 | case USB_ID(0x041e, 0x3048): | 527 | case USB_ID(0x041e, 0x3048): |
516 | err = snd_audigy2nx_controls_create(mixer); | 528 | err = snd_audigy2nx_controls_create(mixer); |
517 | if (err < 0) | 529 | if (err < 0) |
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index c66d3f64dcf..78792a8900c 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h | |||
@@ -1651,6 +1651,32 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1651 | } | 1651 | } |
1652 | } | 1652 | } |
1653 | }, | 1653 | }, |
1654 | { | ||
1655 | USB_DEVICE(0x0582, 0x0127), | ||
1656 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1657 | /* .vendor_name = "Roland", */ | ||
1658 | /* .product_name = "GR-55", */ | ||
1659 | .ifnum = QUIRK_ANY_INTERFACE, | ||
1660 | .type = QUIRK_COMPOSITE, | ||
1661 | .data = (const struct snd_usb_audio_quirk[]) { | ||
1662 | { | ||
1663 | .ifnum = 0, | ||
1664 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1665 | }, | ||
1666 | { | ||
1667 | .ifnum = 1, | ||
1668 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1669 | }, | ||
1670 | { | ||
1671 | .ifnum = 2, | ||
1672 | .type = QUIRK_MIDI_STANDARD_INTERFACE | ||
1673 | }, | ||
1674 | { | ||
1675 | .ifnum = -1 | ||
1676 | } | ||
1677 | } | ||
1678 | } | ||
1679 | }, | ||
1654 | 1680 | ||
1655 | /* Guillemot devices */ | 1681 | /* Guillemot devices */ |
1656 | { | 1682 | { |
@@ -1953,7 +1979,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1953 | } | 1979 | } |
1954 | }, | 1980 | }, |
1955 | { | 1981 | { |
1956 | USB_DEVICE(0x0763, 0x2080), | 1982 | USB_DEVICE_VENDOR_SPEC(0x0763, 0x2080), |
1957 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | 1983 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { |
1958 | /* .vendor_name = "M-Audio", */ | 1984 | /* .vendor_name = "M-Audio", */ |
1959 | /* .product_name = "Fast Track Ultra", */ | 1985 | /* .product_name = "Fast Track Ultra", */ |
@@ -2020,7 +2046,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
2020 | } | 2046 | } |
2021 | }, | 2047 | }, |
2022 | { | 2048 | { |
2023 | USB_DEVICE(0x0763, 0x2081), | 2049 | USB_DEVICE_VENDOR_SPEC(0x0763, 0x2081), |
2024 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | 2050 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { |
2025 | /* .vendor_name = "M-Audio", */ | 2051 | /* .vendor_name = "M-Audio", */ |
2026 | /* .product_name = "Fast Track Ultra 8R", */ | 2052 | /* .product_name = "Fast Track Ultra 8R", */ |
@@ -2179,6 +2205,17 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
2179 | } | 2205 | } |
2180 | }, | 2206 | }, |
2181 | 2207 | ||
2208 | /* KORG devices */ | ||
2209 | { | ||
2210 | USB_DEVICE_VENDOR_SPEC(0x0944, 0x0200), | ||
2211 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
2212 | .vendor_name = "KORG, Inc.", | ||
2213 | /* .product_name = "PANDORA PX5D", */ | ||
2214 | .ifnum = 3, | ||
2215 | .type = QUIRK_MIDI_STANDARD_INTERFACE, | ||
2216 | } | ||
2217 | }, | ||
2218 | |||
2182 | /* AKAI devices */ | 2219 | /* AKAI devices */ |
2183 | { | 2220 | { |
2184 | USB_DEVICE(0x09e8, 0x0062), | 2221 | USB_DEVICE(0x09e8, 0x0062), |
@@ -2332,6 +2369,12 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
2332 | 2369 | ||
2333 | /* Native Instruments MK2 series */ | 2370 | /* Native Instruments MK2 series */ |
2334 | { | 2371 | { |
2372 | /* Komplete Audio 6 */ | ||
2373 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE, | ||
2374 | .idVendor = 0x17cc, | ||
2375 | .idProduct = 0x1000, | ||
2376 | }, | ||
2377 | { | ||
2335 | /* Traktor Audio 6 */ | 2378 | /* Traktor Audio 6 */ |
2336 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE, | 2379 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE, |
2337 | .idVendor = 0x17cc, | 2380 | .idVendor = 0x17cc, |
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 1b94ec3a336..bd13d725724 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c | |||
@@ -540,6 +540,7 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev, | |||
540 | /* Access Music VirusTI Desktop */ | 540 | /* Access Music VirusTI Desktop */ |
541 | return snd_usb_accessmusic_boot_quirk(dev); | 541 | return snd_usb_accessmusic_boot_quirk(dev); |
542 | 542 | ||
543 | case USB_ID(0x17cc, 0x1000): /* Komplete Audio 6 */ | ||
543 | case USB_ID(0x17cc, 0x1010): /* Traktor Audio 6 */ | 544 | case USB_ID(0x17cc, 0x1010): /* Traktor Audio 6 */ |
544 | case USB_ID(0x17cc, 0x1020): /* Traktor Audio 10 */ | 545 | case USB_ID(0x17cc, 0x1020): /* Traktor Audio 10 */ |
545 | return snd_usb_nativeinstruments_boot_quirk(dev); | 546 | return snd_usb_nativeinstruments_boot_quirk(dev); |