You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'topic/misc' into for-linus
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 */
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user