Merge branch 'topic/misc' into for-linus

This commit is contained in:
Takashi Iwai
2011-05-22 10:01:29 +02:00
48 changed files with 1737 additions and 1312 deletions
+105
View File
@@ -65,6 +65,15 @@ init_data[] = {
{ 0 } /* TERMINATING ENTRY */
};
static const int rates_altsetting[] = { 1, 1, 2, 2, 3, 3 };
/* values to write to soundcard register for all samplerates */
static const u16 rates_6fire_vl[] = {0x00, 0x01, 0x00, 0x01, 0x00, 0x01};
static const u16 rates_6fire_vh[] = {0x11, 0x11, 0x10, 0x10, 0x00, 0x00};
enum {
DIGITAL_THRU_ONLY_SAMPLERATE = 3
};
static void usb6fire_control_master_vol_update(struct control_runtime *rt)
{
struct comm_runtime *comm_rt = rt->chip->comm;
@@ -95,6 +104,67 @@ static void usb6fire_control_opt_coax_update(struct control_runtime *rt)
}
}
static int usb6fire_control_set_rate(struct control_runtime *rt, int rate)
{
int ret;
struct usb_device *device = rt->chip->dev;
struct comm_runtime *comm_rt = rt->chip->comm;
if (rate < 0 || rate >= CONTROL_N_RATES)
return -EINVAL;
ret = usb_set_interface(device, 1, rates_altsetting[rate]);
if (ret < 0)
return ret;
/* set soundcard clock */
ret = comm_rt->write16(comm_rt, 0x02, 0x01, rates_6fire_vl[rate],
rates_6fire_vh[rate]);
if (ret < 0)
return ret;
return 0;
}
static int usb6fire_control_set_channels(
struct control_runtime *rt, int n_analog_out,
int n_analog_in, bool spdif_out, bool spdif_in)
{
int ret;
struct comm_runtime *comm_rt = rt->chip->comm;
/* enable analog inputs and outputs
* (one bit per stereo-channel) */
ret = comm_rt->write16(comm_rt, 0x02, 0x02,
(1 << (n_analog_out / 2)) - 1,
(1 << (n_analog_in / 2)) - 1);
if (ret < 0)
return ret;
/* disable digital inputs and outputs */
/* TODO: use spdif_x to enable/disable digital channels */
ret = comm_rt->write16(comm_rt, 0x02, 0x03, 0x00, 0x00);
if (ret < 0)
return ret;
return 0;
}
static int usb6fire_control_streaming_update(struct control_runtime *rt)
{
struct comm_runtime *comm_rt = rt->chip->comm;
if (comm_rt) {
if (!rt->usb_streaming && rt->digital_thru_switch)
usb6fire_control_set_rate(rt,
DIGITAL_THRU_ONLY_SAMPLERATE);
return comm_rt->write16(comm_rt, 0x02, 0x00, 0x00,
(rt->usb_streaming ? 0x01 : 0x00) |
(rt->digital_thru_switch ? 0x08 : 0x00));
}
return -EINVAL;
}
static int usb6fire_control_master_vol_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
@@ -195,6 +265,28 @@ static int usb6fire_control_opt_coax_get(struct snd_kcontrol *kcontrol,
return 0;
}
static int usb6fire_control_digital_thru_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
int changed = 0;
if (rt->digital_thru_switch != ucontrol->value.integer.value[0]) {
rt->digital_thru_switch = ucontrol->value.integer.value[0];
usb6fire_control_streaming_update(rt);
changed = 1;
}
return changed;
}
static int usb6fire_control_digital_thru_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = rt->digital_thru_switch;
return 0;
}
static struct __devinitdata snd_kcontrol_new elements[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -223,6 +315,15 @@ static struct __devinitdata snd_kcontrol_new elements[] = {
.get = usb6fire_control_opt_coax_get,
.put = usb6fire_control_opt_coax_put
},
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Digital Thru Playback Route",
.index = 0,
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
.info = snd_ctl_boolean_mono_info,
.get = usb6fire_control_digital_thru_get,
.put = usb6fire_control_digital_thru_put
},
{}
};
@@ -238,6 +339,9 @@ int __devinit usb6fire_control_init(struct sfire_chip *chip)
return -ENOMEM;
rt->chip = chip;
rt->update_streaming = usb6fire_control_streaming_update;
rt->set_rate = usb6fire_control_set_rate;
rt->set_channels = usb6fire_control_set_channels;
i = 0;
while (init_data[i].type) {
@@ -249,6 +353,7 @@ int __devinit usb6fire_control_init(struct sfire_chip *chip)
usb6fire_control_opt_coax_update(rt);
usb6fire_control_line_phono_update(rt);
usb6fire_control_master_vol_update(rt);
usb6fire_control_streaming_update(rt);
i = 0;
while (elements[i].name) {
+17
View File
@@ -21,12 +21,29 @@ enum {
CONTROL_MAX_ELEMENTS = 32
};
enum {
CONTROL_RATE_44KHZ,
CONTROL_RATE_48KHZ,
CONTROL_RATE_88KHZ,
CONTROL_RATE_96KHZ,
CONTROL_RATE_176KHZ,
CONTROL_RATE_192KHZ,
CONTROL_N_RATES
};
struct control_runtime {
int (*update_streaming)(struct control_runtime *rt);
int (*set_rate)(struct control_runtime *rt, int rate);
int (*set_channels)(struct control_runtime *rt, int n_analog_out,
int n_analog_in, bool spdif_out, bool spdif_in);
struct sfire_chip *chip;
struct snd_kcontrol *element[CONTROL_MAX_ELEMENTS];
bool opt_coax_switch;
bool line_phono_switch;
bool digital_thru_switch;
bool usb_streaming;
u8 master_vol;
};
+33 -40
View File
@@ -3,12 +3,6 @@
*
* Firmware loader
*
* Currently not working for all devices. To be able to use the device
* in linux, it is also possible to let the windows driver upload the firmware.
* For that, start the computer in windows and reboot.
* As long as the device is connected to the power supply, no firmware reload
* needs to be performed.
*
* Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011
* Version: 0.3.0
@@ -21,6 +15,7 @@
*/
#include <linux/firmware.h>
#include <linux/bitrev.h>
#include "firmware.h"
#include "chip.h"
@@ -33,32 +28,6 @@ enum {
FPGA_BUFSIZE = 512, FPGA_EP = 2
};
static const u8 BIT_REVERSE_TABLE[256] = {
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50,
0xd0, 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8,
0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04,
0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4,
0x34, 0xb4, 0x74, 0xf4, 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c,
0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82,
0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32,
0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 0x06, 0x86, 0x46,
0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6,
0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e,
0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1,
0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71,
0xf1, 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99,
0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25,
0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d,
0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3,
0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 0x0b,
0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb,
0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67,
0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 0x0f, 0x8f,
0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f,
0xbf, 0x7f, 0xff };
/*
* wMaxPacketSize of pcm endpoints.
* 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[] = {
0x94, 0x01, 0x5c, 0x02 /* alt 3: 404 EP2 and 604 EP6 (25 fpp) */
};
static const u8 known_fw_versions[][4] = {
{ 0x03, 0x01, 0x0b, 0x00 }
};
struct ihex_record {
u16 address;
u8 len;
@@ -340,7 +313,7 @@ static int usb6fire_fw_fpga_upload(
while (c != end) {
for (i = 0; c != end && i < FPGA_BUFSIZE; i++, c++)
buffer[i] = BIT_REVERSE_TABLE[(u8) *c];
buffer[i] = byte_rev_table[(u8) *c];
ret = usb6fire_fw_fpga_write(device, buffer, i);
if (ret < 0) {
@@ -363,6 +336,25 @@ static int usb6fire_fw_fpga_upload(
return 0;
}
/* check, if the firmware version the devices has currently loaded
* is known by this driver. 'version' needs to have 4 bytes version
* info data. */
static int usb6fire_fw_check(u8 *version)
{
int i;
for (i = 0; i < ARRAY_SIZE(known_fw_versions); i++)
if (!memcmp(version, known_fw_versions + i, 4))
return 0;
snd_printk(KERN_ERR PREFIX "invalid fimware version in device: "
"%02x %02x %02x %02x. "
"please reconnect to power. if this failure "
"still happens, check your firmware installation.",
version[0], version[1], version[2], version[3]);
return -EINVAL;
}
int usb6fire_fw_init(struct usb_interface *intf)
{
int i;
@@ -378,9 +370,7 @@ int usb6fire_fw_init(struct usb_interface *intf)
"firmware state.\n");
return ret;
}
if (buffer[0] != 0xeb || buffer[1] != 0xaa || buffer[2] != 0x55
|| buffer[4] != 0x03 || buffer[5] != 0x01 || buffer[7]
!= 0x00) {
if (buffer[0] != 0xeb || buffer[1] != 0xaa || buffer[2] != 0x55) {
snd_printk(KERN_ERR PREFIX "unknown device firmware state "
"received from device: ");
for (i = 0; i < 8; i++)
@@ -389,7 +379,7 @@ int usb6fire_fw_init(struct usb_interface *intf)
return -EIO;
}
/* do we need fpga loader ezusb firmware? */
if (buffer[3] == 0x01 && buffer[6] == 0x19) {
if (buffer[3] == 0x01) {
ret = usb6fire_fw_ezusb_upload(intf,
"6fire/dmx6firel2.ihx", 0, NULL, 0);
if (ret < 0)
@@ -397,7 +387,10 @@ int usb6fire_fw_init(struct usb_interface *intf)
return FW_NOT_READY;
}
/* do we need fpga firmware and application ezusb firmware? */
else if (buffer[3] == 0x02 && buffer[6] == 0x0b) {
else if (buffer[3] == 0x02) {
ret = usb6fire_fw_check(buffer + 4);
if (ret < 0)
return ret;
ret = usb6fire_fw_fpga_upload(intf, "6fire/dmx6firecf.bin");
if (ret < 0)
return ret;
@@ -410,8 +403,8 @@ int usb6fire_fw_init(struct usb_interface *intf)
return FW_NOT_READY;
}
/* all fw loaded? */
else if (buffer[3] == 0x03 && buffer[6] == 0x0b)
return 0;
else if (buffer[3] == 0x03)
return usb6fire_fw_check(buffer + 4);
/* unknown data? */
else {
snd_printk(KERN_ERR PREFIX "unknown device firmware state "
+38 -59
View File
@@ -17,26 +17,23 @@
#include "pcm.h"
#include "chip.h"
#include "comm.h"
#include "control.h"
enum {
OUT_N_CHANNELS = 6, IN_N_CHANNELS = 4
};
/* keep next two synced with
* FW_EP_W_MAX_PACKET_SIZE[] and RATES_MAX_PACKET_SIZE */
* FW_EP_W_MAX_PACKET_SIZE[] and RATES_MAX_PACKET_SIZE
* and CONTROL_RATE_XXX in control.h */
static const int rates_in_packet_size[] = { 228, 228, 420, 420, 404, 404 };
static const int rates_out_packet_size[] = { 228, 228, 420, 420, 604, 604 };
static const int rates[] = { 44100, 48000, 88200, 96000, 176400, 192000 };
static const int rates_altsetting[] = { 1, 1, 2, 2, 3, 3 };
static const int rates_alsaid[] = {
SNDRV_PCM_RATE_44100, SNDRV_PCM_RATE_48000,
SNDRV_PCM_RATE_88200, SNDRV_PCM_RATE_96000,
SNDRV_PCM_RATE_176400, SNDRV_PCM_RATE_192000 };
/* values to write to soundcard register for all samplerates */
static const u16 rates_6fire_vl[] = {0x00, 0x01, 0x00, 0x01, 0x00, 0x01};
static const u16 rates_6fire_vh[] = {0x11, 0x11, 0x10, 0x10, 0x00, 0x00};
enum { /* settings for pcm */
OUT_EP = 6, IN_EP = 2, MAX_BUFSIZE = 128 * 1024
};
@@ -48,15 +45,6 @@ enum { /* pcm streaming states */
STREAM_STOPPING
};
enum { /* pcm sample rates (also index into RATES_XXX[]) */
RATE_44KHZ,
RATE_48KHZ,
RATE_88KHZ,
RATE_96KHZ,
RATE_176KHZ,
RATE_192KHZ
};
static const struct snd_pcm_hardware pcm_hw = {
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
@@ -64,7 +52,7 @@ static const struct snd_pcm_hardware pcm_hw = {
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_BATCH,
.formats = SNDRV_PCM_FMTBIT_S24_LE,
.formats = SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
.rates = SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000 |
@@ -87,57 +75,34 @@ static const struct snd_pcm_hardware pcm_hw = {
static int usb6fire_pcm_set_rate(struct pcm_runtime *rt)
{
int ret;
struct usb_device *device = rt->chip->dev;
struct comm_runtime *comm_rt = rt->chip->comm;
struct control_runtime *ctrl_rt = rt->chip->control;
if (rt->rate >= ARRAY_SIZE(rates))
return -EINVAL;
/* disable streaming */
ret = comm_rt->write16(comm_rt, 0x02, 0x00, 0x00, 0x00);
ctrl_rt->usb_streaming = false;
ret = ctrl_rt->update_streaming(ctrl_rt);
if (ret < 0) {
snd_printk(KERN_ERR PREFIX "error stopping streaming while "
"setting samplerate %d.\n", rates[rt->rate]);
return ret;
}
ret = usb_set_interface(device, 1, rates_altsetting[rt->rate]);
if (ret < 0) {
snd_printk(KERN_ERR PREFIX "error setting interface "
"altsetting %d for samplerate %d.\n",
rates_altsetting[rt->rate], rates[rt->rate]);
return ret;
}
/* set soundcard clock */
ret = comm_rt->write16(comm_rt, 0x02, 0x01, rates_6fire_vl[rt->rate],
rates_6fire_vh[rt->rate]);
ret = ctrl_rt->set_rate(ctrl_rt, rt->rate);
if (ret < 0) {
snd_printk(KERN_ERR PREFIX "error setting samplerate %d.\n",
rates[rt->rate]);
return ret;
}
/* enable analog inputs and outputs
* (one bit per stereo-channel) */
ret = comm_rt->write16(comm_rt, 0x02, 0x02,
(1 << (OUT_N_CHANNELS / 2)) - 1,
(1 << (IN_N_CHANNELS / 2)) - 1);
ret = ctrl_rt->set_channels(ctrl_rt, OUT_N_CHANNELS, IN_N_CHANNELS,
false, false);
if (ret < 0) {
snd_printk(KERN_ERR PREFIX "error initializing analog channels "
snd_printk(KERN_ERR PREFIX "error initializing channels "
"while setting samplerate %d.\n",
rates[rt->rate]);
return ret;
}
/* disable digital inputs and outputs */
ret = comm_rt->write16(comm_rt, 0x02, 0x03, 0x00, 0x00);
if (ret < 0) {
snd_printk(KERN_ERR PREFIX "error initializing digital "
"channels while setting samplerate %d.\n",
rates[rt->rate]);
return ret;
}
ret = comm_rt->write16(comm_rt, 0x02, 0x00, 0x00, 0x01);
ctrl_rt->usb_streaming = true;
ret = ctrl_rt->update_streaming(ctrl_rt);
if (ret < 0) {
snd_printk(KERN_ERR PREFIX "error starting streaming while "
"setting samplerate %d.\n", rates[rt->rate]);
@@ -168,12 +133,15 @@ static struct pcm_substream *usb6fire_pcm_get_substream(
static void usb6fire_pcm_stream_stop(struct pcm_runtime *rt)
{
int i;
struct control_runtime *ctrl_rt = rt->chip->control;
if (rt->stream_state != STREAM_DISABLED) {
for (i = 0; i < PCM_N_URBS; i++) {
usb_kill_urb(&rt->in_urbs[i].instance);
usb_kill_urb(&rt->out_urbs[i].instance);
}
ctrl_rt->usb_streaming = false;
ctrl_rt->update_streaming(ctrl_rt);
rt->stream_state = STREAM_DISABLED;
}
}
@@ -228,7 +196,7 @@ static void usb6fire_pcm_capture(struct pcm_substream *sub, struct pcm_urb *urb)
unsigned int total_length = 0;
struct pcm_runtime *rt = snd_pcm_substream_chip(sub->instance);
struct snd_pcm_runtime *alsa_rt = sub->instance->runtime;
u32 *src = (u32 *) urb->buffer;
u32 *src = NULL;
u32 *dest = (u32 *) (alsa_rt->dma_area + sub->dma_off
* (alsa_rt->frame_bits >> 3));
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)
else
frame_count = 0;
src = (u32 *) (urb->buffer + total_length);
if (alsa_rt->format == SNDRV_PCM_FORMAT_S24_LE)
src = (u32 *) (urb->buffer + total_length);
else if (alsa_rt->format == SNDRV_PCM_FORMAT_S32_LE)
src = (u32 *) (urb->buffer - 1 + total_length);
else
return;
src++; /* skip leading 4 bytes of every packet */
total_length += urb->packets[i].length;
for (frame = 0; frame < frame_count; frame++) {
@@ -274,9 +247,18 @@ static void usb6fire_pcm_playback(struct pcm_substream *sub,
* (alsa_rt->frame_bits >> 3));
u32 *src_end = (u32 *) (alsa_rt->dma_area + alsa_rt->buffer_size
* (alsa_rt->frame_bits >> 3));
u32 *dest = (u32 *) urb->buffer;
u32 *dest;
int bytes_per_frame = alsa_rt->channels << 2;
if (alsa_rt->format == SNDRV_PCM_FORMAT_S32_LE)
dest = (u32 *) (urb->buffer - 1);
else if (alsa_rt->format == SNDRV_PCM_FORMAT_S24_LE)
dest = (u32 *) (urb->buffer);
else {
snd_printk(KERN_ERR PREFIX "Unknown sample format.");
return;
}
for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) {
/* at least 4 header bytes for valid packet.
* after that: 32 bits per sample for analog channels */
@@ -456,7 +438,7 @@ static int usb6fire_pcm_close(struct snd_pcm_substream *alsa_sub)
/* all substreams closed? if so, stop streaming */
if (!rt->playback.instance && !rt->capture.instance) {
usb6fire_pcm_stream_stop(rt);
rt->rate = -1;
rt->rate = ARRAY_SIZE(rates);
}
}
mutex_unlock(&rt->stream_mutex);
@@ -480,7 +462,6 @@ static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub)
struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub);
struct snd_pcm_runtime *alsa_rt = alsa_sub->runtime;
int i;
int ret;
if (rt->panic)
@@ -493,12 +474,10 @@ static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub)
sub->period_off = 0;
if (rt->stream_state == STREAM_DISABLED) {
for (i = 0; i < ARRAY_SIZE(rates); i++)
if (alsa_rt->rate == rates[i]) {
rt->rate = i;
for (rt->rate = 0; rt->rate < ARRAY_SIZE(rates); rt->rate++)
if (alsa_rt->rate == rates[rt->rate])
break;
}
if (i == ARRAY_SIZE(rates)) {
if (rt->rate == ARRAY_SIZE(rates)) {
mutex_unlock(&rt->stream_mutex);
snd_printk("invalid rate %d in prepare.\n",
alsa_rt->rate);
@@ -613,7 +592,7 @@ int __devinit usb6fire_pcm_init(struct sfire_chip *chip)
rt->chip = chip;
rt->stream_state = STREAM_DISABLED;
rt->rate = -1;
rt->rate = ARRAY_SIZE(rates);
init_waitqueue_head(&rt->stream_wait_queue);
mutex_init(&rt->stream_mutex);
+4 -6
View File
@@ -100,19 +100,17 @@ config SND_USB_US122L
config SND_USB_6FIRE
tristate "TerraTec DMX 6Fire USB"
depends on EXPERIMENTAL
select FW_LOADER
select BITREVERSE
select SND_RAWMIDI
select SND_PCM
help
Say Y here to include support for TerraTec 6fire DMX USB interface.
You will need firmware files in order to be able to use the device
after it has been coldstarted. This driver currently does not support
firmware loading for all devices. If you own such a device,
you could start windows and let the windows driver upload
the firmware. As long as you do not unplug your device from power,
it should be usable.
after it has been coldstarted. An install script for the firmware
and further help can be found at
http://sixfireusb.sourceforge.net
endif # SND_USB
+10 -1
View File
@@ -104,6 +104,15 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id)
int err;
unsigned char data;
struct usb_device *dev = chip->dev;
struct uac_clock_source_descriptor *cs_desc =
snd_usb_find_clock_source(chip->ctrl_intf, source_id);
if (!cs_desc)
return 0;
/* If a clock source can't tell us whether it's valid, we assume it is */
if (!uac2_control_is_readable(cs_desc->bmControls, UAC2_CS_CONTROL_CLOCK_VALID))
return 1;
err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
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)
if (err < 0) {
snd_printk(KERN_WARNING "%s(): cannot get clock validity for id %d\n",
__func__, source_id);
return err;
return 0;
}
return !!data;
+1 -1
View File
@@ -8,7 +8,7 @@
#ifdef HW_CONST_DEBUG
#define hwc_debug(fmt, args...) printk(KERN_DEBUG fmt, ##args)
#else
#define hwc_debug(fmt, args...) /**/
#define hwc_debug(fmt, args...) do { } while(0)
#endif
#endif /* __USBAUDIO_DEBUG_H */
+1
View File
@@ -30,6 +30,7 @@
#include "helper.h"
#include "debug.h"
#include "clock.h"
#include "format.h"
/*
* parse the audio format type I descriptor
+6 -4
View File
@@ -1097,11 +1097,13 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
append_ctl_name(kctl, control == UAC_FU_MUTE ?
" Switch" : " Volume");
if (control == UAC_FU_VOLUME) {
kctl->tlv.c = mixer_vol_tlv;
kctl->vd[0].access |=
SNDRV_CTL_ELEM_ACCESS_TLV_READ |
SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
check_mapped_dB(map, cval);
if (cval->dBmin < cval->dBmax) {
kctl->tlv.c = mixer_vol_tlv;
kctl->vd[0].access |=
SNDRV_CTL_ELEM_ACCESS_TLV_READ |
SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
}
}
break;
+12
View File
@@ -61,6 +61,7 @@ static const struct rc_config {
{ USB_ID(0x041e, 0x3020), 2, 1, 6, 6, 18, 0x0013 }, /* Audigy 2 NX */
{ USB_ID(0x041e, 0x3040), 2, 2, 6, 6, 2, 0x6e91 }, /* Live! 24-bit */
{ USB_ID(0x041e, 0x3042), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi S51 */
{ USB_ID(0x041e, 0x30df), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi S51 Pro */
{ USB_ID(0x041e, 0x3048), 2, 2, 6, 6, 2, 0x6e91 }, /* Toshiba SB0500 */
};
@@ -188,6 +189,12 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
!value, 0, NULL, 0, 100);
/* USB X-Fi S51 Pro */
if (mixer->chip->usb_id == USB_ID(0x041e, 0x30df))
err = snd_usb_ctl_msg(mixer->chip->dev,
usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
!value, 0, NULL, 0, 100);
else
err = snd_usb_ctl_msg(mixer->chip->dev,
usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
@@ -234,9 +241,13 @@ static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer)
/* USB X-Fi S51 doesn't have a CMSS LED */
if ((mixer->chip->usb_id == USB_ID(0x041e, 0x3042)) && i == 0)
continue;
/* USB X-Fi S51 Pro doesn't have one either */
if ((mixer->chip->usb_id == USB_ID(0x041e, 0x30df)) && i == 0)
continue;
if (i > 1 && /* Live24ext has 2 LEDs only */
(mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
mixer->chip->usb_id == USB_ID(0x041e, 0x3042) ||
mixer->chip->usb_id == USB_ID(0x041e, 0x30df) ||
mixer->chip->usb_id == USB_ID(0x041e, 0x3048)))
break;
err = snd_ctl_add(mixer->chip->card,
@@ -512,6 +523,7 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
case USB_ID(0x041e, 0x3020):
case USB_ID(0x041e, 0x3040):
case USB_ID(0x041e, 0x3042):
case USB_ID(0x041e, 0x30df):
case USB_ID(0x041e, 0x3048):
err = snd_audigy2nx_controls_create(mixer);
if (err < 0)
+45 -2
View File
@@ -1651,6 +1651,32 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
}
},
{
USB_DEVICE(0x0582, 0x0127),
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
/* .vendor_name = "Roland", */
/* .product_name = "GR-55", */
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
.data = (const struct snd_usb_audio_quirk[]) {
{
.ifnum = 0,
.type = QUIRK_AUDIO_STANDARD_INTERFACE
},
{
.ifnum = 1,
.type = QUIRK_AUDIO_STANDARD_INTERFACE
},
{
.ifnum = 2,
.type = QUIRK_MIDI_STANDARD_INTERFACE
},
{
.ifnum = -1
}
}
}
},
/* Guillemot devices */
{
@@ -1953,7 +1979,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
{
USB_DEVICE(0x0763, 0x2080),
USB_DEVICE_VENDOR_SPEC(0x0763, 0x2080),
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
/* .vendor_name = "M-Audio", */
/* .product_name = "Fast Track Ultra", */
@@ -2020,7 +2046,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
{
USB_DEVICE(0x0763, 0x2081),
USB_DEVICE_VENDOR_SPEC(0x0763, 0x2081),
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
/* .vendor_name = "M-Audio", */
/* .product_name = "Fast Track Ultra 8R", */
@@ -2179,6 +2205,17 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
/* KORG devices */
{
USB_DEVICE_VENDOR_SPEC(0x0944, 0x0200),
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "KORG, Inc.",
/* .product_name = "PANDORA PX5D", */
.ifnum = 3,
.type = QUIRK_MIDI_STANDARD_INTERFACE,
}
},
/* AKAI devices */
{
USB_DEVICE(0x09e8, 0x0062),
@@ -2331,6 +2368,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
},
/* Native Instruments MK2 series */
{
/* Komplete Audio 6 */
.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x17cc,
.idProduct = 0x1000,
},
{
/* Traktor Audio 6 */
.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+1
View File
@@ -540,6 +540,7 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
/* Access Music VirusTI Desktop */
return snd_usb_accessmusic_boot_quirk(dev);
case USB_ID(0x17cc, 0x1000): /* Komplete Audio 6 */
case USB_ID(0x17cc, 0x1010): /* Traktor Audio 6 */
case USB_ID(0x17cc, 0x1020): /* Traktor Audio 10 */
return snd_usb_nativeinstruments_boot_quirk(dev);