Commit 02e5fbf6 authored by Takashi Iwai's avatar Takashi Iwai

Merge branch 'topic/misc' into for-linus

parents b759b3ac bfe9fc8a
...@@ -4264,6 +4264,13 @@ M: Tim Hockin <thockin@hockin.org> ...@@ -4264,6 +4264,13 @@ M: Tim Hockin <thockin@hockin.org>
S: Maintained S: Maintained
F: drivers/net/natsemi.c F: drivers/net/natsemi.c
NATIVE INSTRUMENTS USB SOUND INTERFACE DRIVER
M: Daniel Mack <zonque@gmail.com>
S: Maintained
L: alsa-devel@alsa-project.org
W: http://www.native-instruments.com
F: sound/usb/caiaq/
NCP FILESYSTEM NCP FILESYSTEM
M: Petr Vandrovec <petr@vandrovec.name> M: Petr Vandrovec <petr@vandrovec.name>
S: Odd Fixes S: Odd Fixes
......
...@@ -166,21 +166,6 @@ config RADIO_MAXIRADIO ...@@ -166,21 +166,6 @@ config RADIO_MAXIRADIO
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called radio-maxiradio. module will be called radio-maxiradio.
config RADIO_MAESTRO
tristate "Maestro on board radio"
depends on VIDEO_V4L2 && PCI
---help---
Say Y here to directly support the on-board radio tuner on the
Maestro 2 or 2E sound card.
In order to control your radio card, you will need to use programs
that are compatible with the Video For Linux API. Information on
this API and pointers to "v4l" programs may be found at
<file:Documentation/video4linux/API.html>.
To compile this driver as a module, choose M here: the
module will be called radio-maestro.
config RADIO_MIROPCM20 config RADIO_MIROPCM20
tristate "miroSOUND PCM20 radio" tristate "miroSOUND PCM20 radio"
depends on ISA && VIDEO_V4L2 && SND depends on ISA && VIDEO_V4L2 && SND
......
...@@ -16,7 +16,6 @@ obj-$(CONFIG_RADIO_GEMTEK) += radio-gemtek.o ...@@ -16,7 +16,6 @@ obj-$(CONFIG_RADIO_GEMTEK) += radio-gemtek.o
obj-$(CONFIG_RADIO_TRUST) += radio-trust.o obj-$(CONFIG_RADIO_TRUST) += radio-trust.o
obj-$(CONFIG_I2C_SI4713) += si4713-i2c.o obj-$(CONFIG_I2C_SI4713) += si4713-i2c.o
obj-$(CONFIG_RADIO_SI4713) += radio-si4713.o obj-$(CONFIG_RADIO_SI4713) += radio-si4713.o
obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o
obj-$(CONFIG_RADIO_MIROPCM20) += radio-miropcm20.o obj-$(CONFIG_RADIO_MIROPCM20) += radio-miropcm20.o
obj-$(CONFIG_USB_DSBR) += dsbr100.o obj-$(CONFIG_USB_DSBR) += dsbr100.o
obj-$(CONFIG_RADIO_SI470X) += si470x/ obj-$(CONFIG_RADIO_SI470X) += si470x/
......
This diff is collapsed.
...@@ -113,6 +113,7 @@ struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new * kcontrolnew, v ...@@ -113,6 +113,7 @@ struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new * kcontrolnew, v
void snd_ctl_free_one(struct snd_kcontrol * kcontrol); void snd_ctl_free_one(struct snd_kcontrol * kcontrol);
int snd_ctl_add(struct snd_card * card, struct snd_kcontrol * kcontrol); int snd_ctl_add(struct snd_card * card, struct snd_kcontrol * kcontrol);
int snd_ctl_remove(struct snd_card * card, struct snd_kcontrol * kcontrol); int snd_ctl_remove(struct snd_card * card, struct snd_kcontrol * kcontrol);
int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol, bool add_on_replace);
int snd_ctl_remove_id(struct snd_card * card, struct snd_ctl_elem_id *id); int snd_ctl_remove_id(struct snd_card * card, struct snd_ctl_elem_id *id);
int snd_ctl_rename_id(struct snd_card * card, struct snd_ctl_elem_id *src_id, struct snd_ctl_elem_id *dst_id); int snd_ctl_rename_id(struct snd_card * card, struct snd_ctl_elem_id *src_id, struct snd_ctl_elem_id *dst_id);
int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id, int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id,
......
...@@ -26,29 +26,37 @@ ...@@ -26,29 +26,37 @@
#include <media/v4l2-dev.h> #include <media/v4l2-dev.h>
#include <media/v4l2-ioctl.h> #include <media/v4l2-ioctl.h>
#define TEA575X_FMIF 10700
#define TEA575X_DATA (1 << 0)
#define TEA575X_CLK (1 << 1)
#define TEA575X_WREN (1 << 2)
#define TEA575X_MOST (1 << 3)
struct snd_tea575x; struct snd_tea575x;
struct snd_tea575x_ops { struct snd_tea575x_ops {
void (*write)(struct snd_tea575x *tea, unsigned int val); void (*set_pins)(struct snd_tea575x *tea, u8 pins);
unsigned int (*read)(struct snd_tea575x *tea); u8 (*get_pins)(struct snd_tea575x *tea);
void (*mute)(struct snd_tea575x *tea, unsigned int mute); void (*set_direction)(struct snd_tea575x *tea, bool output);
}; };
struct snd_tea575x { struct snd_tea575x {
struct snd_card *card;
struct video_device *vd; /* video device */ struct video_device *vd; /* video device */
int dev_nr; /* requested device number + 1 */ bool tea5759; /* 5759 chip is present */
int tea5759; /* 5759 chip is present */ bool mute; /* Device is muted? */
int mute; /* Device is muted? */ bool stereo; /* receiving stereo */
unsigned int freq_fixup; /* crystal onboard */ bool tuned; /* tuned to a station */
unsigned int val; /* hw value */ unsigned int val; /* hw value */
unsigned long freq; /* frequency */ unsigned long freq; /* frequency */
unsigned long in_use; /* set if the device is in use */ unsigned long in_use; /* set if the device is in use */
struct snd_tea575x_ops *ops; struct snd_tea575x_ops *ops;
void *private_data; void *private_data;
u8 card[32];
u8 bus_info[32];
}; };
void snd_tea575x_init(struct snd_tea575x *tea); int snd_tea575x_init(struct snd_tea575x *tea);
void snd_tea575x_exit(struct snd_tea575x *tea); void snd_tea575x_exit(struct snd_tea575x *tea);
#endif /* __SOUND_TEA575X_TUNER_H */ #endif /* __SOUND_TEA575X_TUNER_H */
...@@ -365,6 +365,70 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol) ...@@ -365,6 +365,70 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
EXPORT_SYMBOL(snd_ctl_add); EXPORT_SYMBOL(snd_ctl_add);
/**
* snd_ctl_replace - replace the control instance of the card
* @card: the card instance
* @kcontrol: the control instance to replace
* @add_on_replace: add the control if not already added
*
* Replaces the given control. If the given control does not exist
* and the add_on_replace flag is set, the control is added. If the
* control exists, it is destroyed first.
*
* Returns zero if successful, or a negative error code on failure.
*
* It frees automatically the control which cannot be added or replaced.
*/
int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol,
bool add_on_replace)
{
struct snd_ctl_elem_id id;
unsigned int idx;
struct snd_kcontrol *old;
int ret;
if (!kcontrol)
return -EINVAL;
if (snd_BUG_ON(!card || !kcontrol->info)) {
ret = -EINVAL;
goto error;
}
id = kcontrol->id;
down_write(&card->controls_rwsem);
old = snd_ctl_find_id(card, &id);
if (!old) {
if (add_on_replace)
goto add;
up_write(&card->controls_rwsem);
ret = -EINVAL;
goto error;
}
ret = snd_ctl_remove(card, old);
if (ret < 0) {
up_write(&card->controls_rwsem);
goto error;
}
add:
if (snd_ctl_find_hole(card, kcontrol->count) < 0) {
up_write(&card->controls_rwsem);
ret = -ENOMEM;
goto error;
}
list_add_tail(&kcontrol->list, &card->controls);
card->controls_count += kcontrol->count;
kcontrol->id.numid = card->last_numid + 1;
card->last_numid += kcontrol->count;
up_write(&card->controls_rwsem);
for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++)
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
return 0;
error:
snd_ctl_free_one(kcontrol);
return ret;
}
EXPORT_SYMBOL(snd_ctl_replace);
/** /**
* snd_ctl_remove - remove the control from the card and release it * snd_ctl_remove - remove the control from the card and release it
* @card: the card instance * @card: the card instance
......
...@@ -514,7 +514,7 @@ static void snd_card_set_id_no_lock(struct snd_card *card, const char *nid) ...@@ -514,7 +514,7 @@ static void snd_card_set_id_no_lock(struct snd_card *card, const char *nid)
id = card->id; id = card->id;
if (*id == '\0') if (*id == '\0')
strcpy(id, "default"); strcpy(id, "Default");
while (1) { while (1) {
if (loops-- == 0) { if (loops-- == 0) {
......
...@@ -189,6 +189,7 @@ static void xrun(struct snd_pcm_substream *substream) ...@@ -189,6 +189,7 @@ static void xrun(struct snd_pcm_substream *substream)
#define XRUN_LOG_CNT 10 #define XRUN_LOG_CNT 10
struct hwptr_log_entry { struct hwptr_log_entry {
unsigned int in_interrupt;
unsigned long jiffies; unsigned long jiffies;
snd_pcm_uframes_t pos; snd_pcm_uframes_t pos;
snd_pcm_uframes_t period_size; snd_pcm_uframes_t period_size;
...@@ -204,7 +205,7 @@ struct snd_pcm_hwptr_log { ...@@ -204,7 +205,7 @@ struct snd_pcm_hwptr_log {
}; };
static void xrun_log(struct snd_pcm_substream *substream, static void xrun_log(struct snd_pcm_substream *substream,
snd_pcm_uframes_t pos) snd_pcm_uframes_t pos, int in_interrupt)
{ {
struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_pcm_hwptr_log *log = runtime->hwptr_log; struct snd_pcm_hwptr_log *log = runtime->hwptr_log;
...@@ -220,6 +221,7 @@ static void xrun_log(struct snd_pcm_substream *substream, ...@@ -220,6 +221,7 @@ static void xrun_log(struct snd_pcm_substream *substream,
return; return;
} }
entry = &log->entries[log->idx]; entry = &log->entries[log->idx];
entry->in_interrupt = in_interrupt;
entry->jiffies = jiffies; entry->jiffies = jiffies;
entry->pos = pos; entry->pos = pos;
entry->period_size = runtime->period_size; entry->period_size = runtime->period_size;
...@@ -246,9 +248,11 @@ static void xrun_log_show(struct snd_pcm_substream *substream) ...@@ -246,9 +248,11 @@ static void xrun_log_show(struct snd_pcm_substream *substream)
entry = &log->entries[idx]; entry = &log->entries[idx];
if (entry->period_size == 0) if (entry->period_size == 0)
break; break;
snd_printd("hwptr log: %s: j=%lu, pos=%ld/%ld/%ld, " snd_printd("hwptr log: %s: %sj=%lu, pos=%ld/%ld/%ld, "
"hwptr=%ld/%ld\n", "hwptr=%ld/%ld\n",
name, entry->jiffies, (unsigned long)entry->pos, name, entry->in_interrupt ? "[Q] " : "",
entry->jiffies,
(unsigned long)entry->pos,
(unsigned long)entry->period_size, (unsigned long)entry->period_size,
(unsigned long)entry->buffer_size, (unsigned long)entry->buffer_size,
(unsigned long)entry->old_hw_ptr, (unsigned long)entry->old_hw_ptr,
...@@ -262,7 +266,7 @@ static void xrun_log_show(struct snd_pcm_substream *substream) ...@@ -262,7 +266,7 @@ static void xrun_log_show(struct snd_pcm_substream *substream)
#else /* ! CONFIG_SND_PCM_XRUN_DEBUG */ #else /* ! CONFIG_SND_PCM_XRUN_DEBUG */
#define hw_ptr_error(substream, fmt, args...) do { } while (0) #define hw_ptr_error(substream, fmt, args...) do { } while (0)
#define xrun_log(substream, pos) do { } while (0) #define xrun_log(substream, pos, in_interrupt) do { } while (0)
#define xrun_log_show(substream) do { } while (0) #define xrun_log_show(substream) do { } while (0)
#endif #endif
...@@ -326,7 +330,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, ...@@ -326,7 +330,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
} }
pos -= pos % runtime->min_align; pos -= pos % runtime->min_align;
if (xrun_debug(substream, XRUN_DEBUG_LOG)) if (xrun_debug(substream, XRUN_DEBUG_LOG))
xrun_log(substream, pos); xrun_log(substream, pos, in_interrupt);
hw_base = runtime->hw_ptr_base; hw_base = runtime->hw_ptr_base;
new_hw_ptr = hw_base + pos; new_hw_ptr = hw_base + pos;
if (in_interrupt) { if (in_interrupt) {
......
...@@ -22,4 +22,15 @@ config SND_FIREWIRE_SPEAKERS ...@@ -22,4 +22,15 @@ config SND_FIREWIRE_SPEAKERS
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called snd-firewire-speakers. will be called snd-firewire-speakers.
config SND_ISIGHT
tristate "Apple iSight microphone"
select SND_PCM
select SND_FIREWIRE_LIB
help
Say Y here to include support for the front and rear microphones
of the Apple iSight web camera.
To compile this driver as a module, choose M here: the module
will be called snd-isight.
endif # SND_FIREWIRE endif # SND_FIREWIRE
snd-firewire-lib-objs := lib.o iso-resources.o packets-buffer.o \ snd-firewire-lib-objs := lib.o iso-resources.o packets-buffer.o \
fcp.o cmp.o amdtp.o fcp.o cmp.o amdtp.o
snd-firewire-speakers-objs := speakers.o snd-firewire-speakers-objs := speakers.o
snd-isight-objs := isight.o
obj-$(CONFIG_SND_FIREWIRE_LIB) += snd-firewire-lib.o obj-$(CONFIG_SND_FIREWIRE_LIB) += snd-firewire-lib.o
obj-$(CONFIG_SND_FIREWIRE_SPEAKERS) += snd-firewire-speakers.o obj-$(CONFIG_SND_FIREWIRE_SPEAKERS) += snd-firewire-speakers.o
obj-$(CONFIG_SND_ISIGHT) += snd-isight.o
This diff is collapsed.
...@@ -36,6 +36,7 @@ int fw_iso_resources_init(struct fw_iso_resources *r, struct fw_unit *unit) ...@@ -36,6 +36,7 @@ int fw_iso_resources_init(struct fw_iso_resources *r, struct fw_unit *unit)
return 0; return 0;
} }
EXPORT_SYMBOL(fw_iso_resources_init);
/** /**
* fw_iso_resources_destroy - destroy a resource manager * fw_iso_resources_destroy - destroy a resource manager
...@@ -48,6 +49,7 @@ void fw_iso_resources_destroy(struct fw_iso_resources *r) ...@@ -48,6 +49,7 @@ void fw_iso_resources_destroy(struct fw_iso_resources *r)
mutex_destroy(&r->mutex); mutex_destroy(&r->mutex);
fw_unit_put(r->unit); fw_unit_put(r->unit);
} }
EXPORT_SYMBOL(fw_iso_resources_destroy);
static unsigned int packet_bandwidth(unsigned int max_payload_bytes, int speed) static unsigned int packet_bandwidth(unsigned int max_payload_bytes, int speed)
{ {
...@@ -152,6 +154,7 @@ int fw_iso_resources_allocate(struct fw_iso_resources *r, ...@@ -152,6 +154,7 @@ int fw_iso_resources_allocate(struct fw_iso_resources *r,
return channel; return channel;
} }
EXPORT_SYMBOL(fw_iso_resources_allocate);
/** /**
* fw_iso_resources_update - update resource allocations after a bus reset * fw_iso_resources_update - update resource allocations after a bus reset
...@@ -203,6 +206,7 @@ int fw_iso_resources_update(struct fw_iso_resources *r) ...@@ -203,6 +206,7 @@ int fw_iso_resources_update(struct fw_iso_resources *r)
return channel; return channel;
} }
EXPORT_SYMBOL(fw_iso_resources_update);
/** /**
* fw_iso_resources_free - frees allocated resources * fw_iso_resources_free - frees allocated resources
...@@ -230,3 +234,4 @@ void fw_iso_resources_free(struct fw_iso_resources *r) ...@@ -230,3 +234,4 @@ void fw_iso_resources_free(struct fw_iso_resources *r)
mutex_unlock(&r->mutex); mutex_unlock(&r->mutex);
} }
EXPORT_SYMBOL(fw_iso_resources_free);
...@@ -60,6 +60,7 @@ int iso_packets_buffer_init(struct iso_packets_buffer *b, struct fw_unit *unit, ...@@ -60,6 +60,7 @@ int iso_packets_buffer_init(struct iso_packets_buffer *b, struct fw_unit *unit,
error: error:
return err; return err;
} }
EXPORT_SYMBOL(iso_packets_buffer_init);
/** /**
* iso_packets_buffer_destroy - frees packet buffer resources * iso_packets_buffer_destroy - frees packet buffer resources
...@@ -72,3 +73,4 @@ void iso_packets_buffer_destroy(struct iso_packets_buffer *b, ...@@ -72,3 +73,4 @@ void iso_packets_buffer_destroy(struct iso_packets_buffer *b,
fw_iso_buffer_destroy(&b->iso_buffer, fw_parent_device(unit)->card); fw_iso_buffer_destroy(&b->iso_buffer, fw_parent_device(unit)->card);
kfree(b->packets); kfree(b->packets);
} }
EXPORT_SYMBOL(iso_packets_buffer_destroy);
...@@ -14,4 +14,4 @@ snd-tea575x-tuner-objs := tea575x-tuner.o ...@@ -14,4 +14,4 @@ snd-tea575x-tuner-objs := tea575x-tuner.o
obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o
obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o
obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4113.o snd-ak4xxx-adda.o snd-pt2258.o obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4113.o snd-ak4xxx-adda.o snd-pt2258.o
obj-$(CONFIG_SND_FM801_TEA575X) += snd-tea575x-tuner.o obj-$(CONFIG_SND_TEA575X) += snd-tea575x-tuner.o
...@@ -37,8 +37,8 @@ static int radio_nr = -1; ...@@ -37,8 +37,8 @@ static int radio_nr = -1;
module_param(radio_nr, int, 0); module_param(radio_nr, int, 0);
#define RADIO_VERSION KERNEL_VERSION(0, 0, 2) #define RADIO_VERSION KERNEL_VERSION(0, 0, 2)
#define FREQ_LO (87 * 16000) #define FREQ_LO (50UL * 16000)
#define FREQ_HI (108 * 16000) #define FREQ_HI (150UL * 16000)
/* /*
* definitions * definitions
...@@ -77,27 +77,95 @@ static struct v4l2_queryctrl radio_qctrl[] = { ...@@ -77,27 +77,95 @@ static struct v4l2_queryctrl radio_qctrl[] = {
* lowlevel part * lowlevel part
*/ */
static void snd_tea575x_write(struct snd_tea575x *tea, unsigned int val)
{
u16 l;
u8 data;
tea->ops->set_direction(tea, 1);
udelay(16);
for (l = 25; l > 0; l--) {
data = (val >> 24) & TEA575X_DATA;
val <<= 1; /* shift data */
tea->ops->set_pins(tea, data | TEA575X_WREN);
udelay(2);
tea->ops->set_pins(tea, data | TEA575X_WREN | TEA575X_CLK);
udelay(2);
tea->ops->set_pins(tea, data | TEA575X_WREN);
udelay(2);
}
if (!tea->mute)
tea->ops->set_pins(tea, 0);
}
static unsigned int snd_tea575x_read(struct snd_tea575x *tea)
{
u16 l, rdata;
u32 data = 0;
tea->ops->set_direction(tea, 0);
tea->ops->set_pins(tea, 0);
udelay(16);
for (l = 24; l--;) {
tea->ops->set_pins(tea, TEA575X_CLK);
udelay(2);
if (!l)
tea->tuned = tea->ops->get_pins(tea) & TEA575X_MOST ? 0 : 1;
tea->ops->set_pins(tea, 0);
udelay(2);
data <<= 1; /* shift data */
rdata = tea->ops->get_pins(tea);
if (!l)
tea->stereo = (rdata & TEA575X_MOST) ? 0 : 1;
if (rdata & TEA575X_DATA)
data++;
udelay(2);
}
if (tea->mute)
tea->ops->set_pins(tea, TEA575X_WREN);
return data;
}
static void snd_tea575x_get_freq(struct snd_tea575x *tea)
{
unsigned long freq;
freq = snd_tea575x_read(tea) & TEA575X_BIT_FREQ_MASK;
/* freq *= 12.5 */
freq *= 125;
freq /= 10;
/* crystal fixup */
if (tea->tea5759)
freq += TEA575X_FMIF;
else
freq -= TEA575X_FMIF;
tea->freq = freq * 16; /* from kHz */
}
static void snd_tea575x_set_freq(struct snd_tea575x *tea) static void snd_tea575x_set_freq(struct snd_tea575x *tea)
{ {
unsigned long freq; unsigned long freq;
freq = tea->freq / 16; /* to kHz */ freq = clamp(tea->freq, FREQ_LO, FREQ_HI);
if (freq > 108000) freq /= 16; /* to kHz */
freq = 108000;
if (freq < 87000)
freq = 87000;
/* crystal fixup */ /* crystal fixup */
if (tea->tea5759) if (tea->tea5759)
freq -= tea->freq_fixup; freq -= TEA575X_FMIF;
else else
freq += tea->freq_fixup; freq += TEA575X_FMIF;
/* freq /= 12.5 */ /* freq /= 12.5 */
freq *= 10; freq *= 10;
freq /= 125; freq /= 125;
tea->val &= ~TEA575X_BIT_FREQ_MASK; tea->val &= ~TEA575X_BIT_FREQ_MASK;
tea->val |= freq & TEA575X_BIT_FREQ_MASK; tea->val |= freq & TEA575X_BIT_FREQ_MASK;
tea->ops->write(tea, tea->val); snd_tea575x_write(tea, tea->val);
} }
/* /*
...@@ -109,29 +177,34 @@ static int vidioc_querycap(struct file *file, void *priv, ...@@ -109,29 +177,34 @@ static int vidioc_querycap(struct file *file, void *priv,
{ {
struct snd_tea575x *tea = video_drvdata(file); struct snd_tea575x *tea = video_drvdata(file);
strcpy(v->card, tea->tea5759 ? "TEA5759" : "TEA5757");
strlcpy(v->driver, "tea575x-tuner", sizeof(v->driver)); strlcpy(v->driver, "tea575x-tuner", sizeof(v->driver));
strlcpy(v->card, "Maestro Radio", sizeof(v->card)); strlcpy(v->card, tea->card, sizeof(v->card));
sprintf(v->bus_info, "PCI"); strlcat(v->card, tea->tea5759 ? " TEA5759" : " TEA5757", sizeof(v->card));
strlcpy(v->bus_info, tea->bus_info, sizeof(v->bus_info));
v->version = RADIO_VERSION; v->version = RADIO_VERSION;
v->capabilities = V4L2_CAP_TUNER; v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
return 0; return 0;
} }
static int vidioc_g_tuner(struct file *file, void *priv, static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *v) struct v4l2_tuner *v)
{ {
struct snd_tea575x *tea = video_drvdata(file);
if (v->index > 0) if (v->index > 0)
return -EINVAL; return -EINVAL;
snd_tea575x_read(tea);
strcpy(v->name, "FM"); strcpy(v->name, "FM");
v->type = V4L2_TUNER_RADIO; v->type = V4L2_TUNER_RADIO;
v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
v->rangelow = FREQ_LO; v->rangelow = FREQ_LO;
v->rangehigh = FREQ_HI; v->rangehigh = FREQ_HI;
v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
v->capability = V4L2_TUNER_CAP_LOW; v->audmode = tea->stereo ? V4L2_TUNER_MODE_STEREO : V4L2_TUNER_MODE_MONO;
v->audmode = V4L2_TUNER_MODE_MONO; v->signal = tea->tuned ? 0xffff : 0;
v->signal = 0xffff;
return 0; return 0;
} }
...@@ -148,7 +221,10 @@ static int vidioc_g_frequency(struct file *file, void *priv, ...@@ -148,7 +221,10 @@ static int vidioc_g_frequency(struct file *file, void *priv,
{ {
struct snd_tea575x *tea = video_drvdata(file); struct snd_tea575x *tea = video_drvdata(file);
if (f->tuner != 0)
return -EINVAL;
f->type = V4L2_TUNER_RADIO; f->type = V4L2_TUNER_RADIO;
snd_tea575x_get_freq(tea);
f->frequency = tea->freq; f->frequency = tea->freq;
return 0; return 0;
} }
...@@ -158,6 +234,9 @@ static int vidioc_s_frequency(struct file *file, void *priv, ...@@ -158,6 +234,9 @@ static int vidioc_s_frequency(struct file *file, void *priv,
{ {
struct snd_tea575x *tea = video_drvdata(file); struct snd_tea575x *tea = video_drvdata(file);
if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
return -EINVAL;
if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) if (f->frequency < FREQ_LO || f->frequency > FREQ_HI)
return -EINVAL; return -EINVAL;
...@@ -209,10 +288,8 @@ static int vidioc_g_ctrl(struct file *file, void *priv, ...@@ -209,10 +288,8 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
switch (ctrl->id) { switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE: case V4L2_CID_AUDIO_MUTE:
if (tea->ops->mute) { ctrl->value = tea->mute;
ctrl->value = tea->mute; return 0;
return 0;
}
} }
return -EINVAL; return -EINVAL;
} }
...@@ -224,11 +301,11 @@ static int vidioc_s_ctrl(struct file *file, void *priv, ...@@ -224,11 +301,11 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
switch (ctrl->id) { switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE: case V4L2_CID_AUDIO_MUTE:
if (tea->ops->mute) { if (tea->mute != ctrl->value) {
tea->ops->mute(tea, ctrl->value);
tea->mute = ctrl->value; tea->mute = ctrl->value;
return 0; snd_tea575x_set_freq(tea);
} }
return 0;
} }
return -EINVAL; return -EINVAL;
} }
...@@ -293,18 +370,16 @@ static struct video_device tea575x_radio = { ...@@ -293,18 +370,16 @@ static struct video_device tea575x_radio = {
/* /*
* initialize all the tea575x chips * initialize all the tea575x chips
*/ */
void snd_tea575x_init(struct snd_tea575x *tea) int snd_tea575x_init(struct snd_tea575x *tea)
{ {
int retval; int retval;
unsigned int val;
struct video_device *tea575x_radio_inst; struct video_device *tea575x_radio_inst;
val = tea->ops->read(tea); tea->mute = 1;
if (val == 0x1ffffff || val == 0) {
snd_printk(KERN_ERR snd_tea575x_write(tea, 0x55AA);
"tea575x-tuner: Cannot find TEA575x chip\n"); if (snd_tea575x_read(tea) != 0x55AA)
return; return -ENODEV;
}
tea->in_use = 0; tea->in_use = 0;
tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_10_40; tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_10_40;
...@@ -313,7 +388,7 @@ void snd_tea575x_init(struct snd_tea575x *tea) ...@@ -313,7 +388,7 @@ void snd_tea575x_init(struct snd_tea575x *tea)
tea575x_radio_inst = video_device_alloc(); tea575x_radio_inst = video_device_alloc();
if (tea575x_radio_inst == NULL) { if (tea575x_radio_inst == NULL) {
printk(KERN_ERR "tea575x-tuner: not enough memory\n"); printk(KERN_ERR "tea575x-tuner: not enough memory\n");
return; return -ENOMEM;
} }
memcpy(tea575x_radio_inst, &tea575x_radio, sizeof(tea575x_radio)); memcpy(tea575x_radio_inst, &tea575x_radio, sizeof(tea575x_radio));
...@@ -328,17 +403,13 @@ void snd_tea575x_init(struct snd_tea575x *tea) ...@@ -328,17 +403,13 @@ void snd_tea575x_init(struct snd_tea575x *tea)
if (retval) { if (retval) {
printk(KERN_ERR "tea575x-tuner: can't register video device!\n"); printk(KERN_ERR "tea575x-tuner: can't register video device!\n");
kfree(tea575x_radio_inst); kfree(tea575x_radio_inst);
return; return retval;
} }
snd_tea575x_set_freq(tea); snd_tea575x_set_freq(tea);
/* mute on init */
if (tea->ops->mute) {
tea->ops->mute(tea, 1);
tea->mute = 1;
}
tea->vd = tea575x_radio_inst; tea->vd = tea575x_radio_inst;
return 0;
} }
void snd_tea575x_exit(struct snd_tea575x *tea) void snd_tea575x_exit(struct snd_tea575x *tea)
......
...@@ -534,6 +534,14 @@ config SND_ES1968_INPUT ...@@ -534,6 +534,14 @@ config SND_ES1968_INPUT
If you say N the buttons will directly control the master volume. If you say N the buttons will directly control the master volume.
It is recommended to say Y. It is recommended to say Y.
config SND_ES1968_RADIO
bool "Enable TEA5757 radio tuner support for es1968"
depends on SND_ES1968
depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_ES1968
help
Say Y here to include support for TEA5757 radio tuner integrated on
some MediaForte cards (e.g. SF64-PCE2).
config SND_FM801 config SND_FM801
tristate "ForteMedia FM801" tristate "ForteMedia FM801"
select SND_OPL3_LIB select SND_OPL3_LIB
...@@ -552,13 +560,13 @@ config SND_FM801_TEA575X_BOOL ...@@ -552,13 +560,13 @@ config SND_FM801_TEA575X_BOOL
depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_FM801 depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_FM801
help help
Say Y here to include support for soundcards based on the ForteMedia Say Y here to include support for soundcards based on the ForteMedia
FM801 chip with a TEA5757 tuner connected to GPIO1-3 pins (Media FM801 chip with a TEA5757 tuner (MediaForte SF256-PCS, SF256-PCP and
Forte SF256-PCS-02) into the snd-fm801 driver. SF64-PCR) into the snd-fm801 driver.
config SND_FM801_TEA575X config SND_TEA575X
tristate tristate
depends on SND_FM801_TEA575X_BOOL depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO
default SND_FM801 default SND_FM801 || SND_ES1968
source "sound/pci/hda/Kconfig" source "sound/pci/hda/Kconfig"
......
This diff is collapsed.
...@@ -200,8 +200,8 @@ static void hpi_read_block(struct dsp_obj *pdo, u32 address, u32 *pdata, ...@@ -200,8 +200,8 @@ static void hpi_read_block(struct dsp_obj *pdo, u32 address, u32 *pdata,
static void subsys_create_adapter(struct hpi_message *phm, static void subsys_create_adapter(struct hpi_message *phm,
struct hpi_response *phr); struct hpi_response *phr);
static void subsys_delete_adapter(struct hpi_message *phm, static void adapter_delete(struct hpi_adapter_obj *pao,
struct hpi_response *phr); struct hpi_message *phm, struct hpi_response *phr);
static void adapter_get_asserts(struct hpi_adapter_obj *pao, static void adapter_get_asserts(struct hpi_adapter_obj *pao,
struct hpi_message *phm, struct hpi_response *phr); struct hpi_message *phm, struct hpi_response *phr);
...@@ -222,9 +222,6 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr) ...@@ -222,9 +222,6 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
case HPI_SUBSYS_CREATE_ADAPTER: case HPI_SUBSYS_CREATE_ADAPTER:
subsys_create_adapter(phm, phr); subsys_create_adapter(phm, phr);
break; break;
case HPI_SUBSYS_DELETE_ADAPTER:
subsys_delete_adapter(phm, phr);
break;
default: default:
phr->error = HPI_ERROR_INVALID_FUNC; phr->error = HPI_ERROR_INVALID_FUNC;
break; break;
...@@ -279,6 +276,10 @@ static void adapter_message(struct hpi_adapter_obj *pao, ...@@ -279,6 +276,10 @@ static void adapter_message(struct hpi_adapter_obj *pao,
adapter_get_asserts(pao, phm, phr); adapter_get_asserts(pao, phm, phr);
break; break;
case HPI_ADAPTER_DELETE:
adapter_delete(pao, phm, phr);
break;
default: default:
hw_message(pao, phm, phr); hw_message(pao, phm, phr);
break; break;
...@@ -333,26 +334,22 @@ void HPI_6000(struct hpi_message *phm, struct hpi_response *phr) ...@@ -333,26 +334,22 @@ void HPI_6000(struct hpi_message *phm, struct hpi_response *phr)
{ {
struct hpi_adapter_obj *pao = NULL; struct hpi_adapter_obj *pao = NULL;
/* subsytem messages get executed by every HPI. */
/* All other messages are ignored unless the adapter index matches */
/* an adapter in the HPI */
/*HPI_DEBUG_LOG(DEBUG, "O %d,F %x\n", phm->wObject, phm->wFunction); */
/* if Dsp has crashed then do not communicate with it any more */
if (phm->object != HPI_OBJ_SUBSYSTEM) { if (phm->object != HPI_OBJ_SUBSYSTEM) {
pao = hpi_find_adapter(phm->adapter_index); pao = hpi_find_adapter(phm->adapter_index);
if (!pao) { if (!pao) {
HPI_DEBUG_LOG(DEBUG, hpi_init_response(phr, phm->object, phm->function,
" %d,%d refused, for another HPI?\n", HPI_ERROR_BAD_ADAPTER_NUMBER);
phm->object, phm->function); HPI_DEBUG_LOG(DEBUG, "invalid adapter index: %d \n",
phm->adapter_index);
return; return;
} }
/* Don't even try to communicate with crashed DSP */
if (pao->dsp_crashed >= 10) { if (pao->dsp_crashed >= 10) {
hpi_init_response(phr, phm->object, phm->function, hpi_init_response(phr, phm->object, phm->function,
HPI_ERROR_DSP_HARDWARE); HPI_ERROR_DSP_HARDWARE);
HPI_DEBUG_LOG(DEBUG, " %d,%d dsp crashed.\n", HPI_DEBUG_LOG(DEBUG, "adapter %d dsp crashed\n",
phm->object, phm->function); phm->adapter_index);
return; return;
} }
} }
...@@ -463,15 +460,9 @@ static void subsys_create_adapter(struct hpi_message *phm, ...@@ -463,15 +460,9 @@ static void subsys_create_adapter(struct hpi_message *phm,
phr->error = 0; phr->error = 0;
} }
static void subsys_delete_adapter(struct hpi_message *phm, static void adapter_delete(struct hpi_adapter_obj *pao,
struct hpi_response *phr) struct hpi_message *phm, struct hpi_response *phr)
{ {
struct hpi_adapter_obj *pao = NULL;
pao = hpi_find_adapter(phm->obj_index);
if (!pao)
return;
delete_adapter_obj(pao); delete_adapter_obj(pao);
hpi_delete_adapter(pao); hpi_delete_adapter(pao);
phr->error = 0; phr->error = 0;
......
...@@ -152,8 +152,8 @@ static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm, ...@@ -152,8 +152,8 @@ static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,
static void subsys_create_adapter(struct hpi_message *phm, static void subsys_create_adapter(struct hpi_message *phm,
struct hpi_response *phr); struct hpi_response *phr);
static void subsys_delete_adapter(struct hpi_message *phm, static void adapter_delete(struct hpi_adapter_obj *pao,
struct hpi_response *phr); struct hpi_message *phm, struct hpi_response *phr);
static u16 create_adapter_obj(struct hpi_adapter_obj *pao, static u16 create_adapter_obj(struct hpi_adapter_obj *pao,
u32 *pos_error_code); u32 *pos_error_code);
...@@ -223,15 +223,13 @@ static u16 boot_loader_test_pld(struct hpi_adapter_obj *pao, int dsp_index); ...@@ -223,15 +223,13 @@ static u16 boot_loader_test_pld(struct hpi_adapter_obj *pao, int dsp_index);
/*****************************************************************************/ /*****************************************************************************/
static void subsys_message(struct hpi_message *phm, struct hpi_response *phr) static void subsys_message(struct hpi_adapter_obj *pao,
struct hpi_message *phm, struct hpi_response *phr)
{ {
switch (phm->function) { switch (phm->function) {
case HPI_SUBSYS_CREATE_ADAPTER: case HPI_SUBSYS_CREATE_ADAPTER:
subsys_create_adapter(phm, phr); subsys_create_adapter(phm, phr);
break; break;
case HPI_SUBSYS_DELETE_ADAPTER:
subsys_delete_adapter(phm, phr);
break;
default: default:
phr->error = HPI_ERROR_INVALID_FUNC; phr->error = HPI_ERROR_INVALID_FUNC;
break; break;
...@@ -279,6 +277,10 @@ static void adapter_message(struct hpi_adapter_obj *pao, ...@@ -279,6 +277,10 @@ static void adapter_message(struct hpi_adapter_obj *pao,
struct hpi_message *phm, struct hpi_response *phr) struct hpi_message *phm, struct hpi_response *phr)
{ {
switch (phm->function) { switch (phm->function) {
case HPI_ADAPTER_DELETE:
adapter_delete(pao, phm, phr);
break;
default: default:
hw_message(pao, phm, phr); hw_message(pao, phm, phr);
break; break;
...@@ -371,36 +373,17 @@ static void instream_message(struct hpi_adapter_obj *pao, ...@@ -371,36 +373,17 @@ static void instream_message(struct hpi_adapter_obj *pao,
/** Entry point to this HPI backend /** Entry point to this HPI backend
* All calls to the HPI start here * All calls to the HPI start here
*/ */
void HPI_6205(struct hpi_message *phm, struct hpi_response *phr) void _HPI_6205(struct hpi_adapter_obj *pao, struct hpi_message *phm,
struct hpi_response *phr)
{ {
struct hpi_adapter_obj *pao = NULL; if (pao && (pao->dsp_crashed >= 10)
&& (phm->function != HPI_ADAPTER_DEBUG_READ)) {
/* subsytem messages are processed by every HPI. /* allow last resort debug read even after crash */
* All other messages are ignored unless the adapter index matches hpi_init_response(phr, phm->object, phm->function,
* an adapter in the HPI HPI_ERROR_DSP_HARDWARE);
*/ HPI_DEBUG_LOG(WARNING, " %d,%d dsp crashed.\n", phm->object,
/* HPI_DEBUG_LOG(DEBUG, "HPI Obj=%d, Func=%d\n", phm->wObject, phm->function);
phm->wFunction); */ return;
/* if Dsp has crashed then do not communicate with it any more */
if (phm->object != HPI_OBJ_SUBSYSTEM) {
pao = hpi_find_adapter(phm->adapter_index);
if (!pao) {
HPI_DEBUG_LOG(DEBUG,
" %d,%d refused, for another HPI?\n",
phm->object, phm->function);
return;
}
if ((pao->dsp_crashed >= 10)
&& (phm->function != HPI_ADAPTER_DEBUG_READ)) {
/* allow last resort debug read even after crash */
hpi_init_response(phr, phm->object, phm->function,
HPI_ERROR_DSP_HARDWARE);
HPI_DEBUG_LOG(WARNING, " %d,%d dsp crashed.\n",
phm->object, phm->function);
return;
}
} }
/* Init default response */ /* Init default response */
...@@ -412,7 +395,7 @@ void HPI_6205(struct hpi_message *phm, struct hpi_response *phr) ...@@ -412,7 +395,7 @@ void HPI_6205(struct hpi_message *phm, struct hpi_response *phr)
case HPI_TYPE_MESSAGE: case HPI_TYPE_MESSAGE:
switch (phm->object) { switch (phm->object) {
case HPI_OBJ_SUBSYSTEM: case HPI_OBJ_SUBSYSTEM:
subsys_message(phm, phr); subsys_message(pao, phm, phr);
break; break;
case HPI_OBJ_ADAPTER: case HPI_OBJ_ADAPTER:
...@@ -444,6 +427,26 @@ void HPI_6205(struct hpi_message *phm, struct hpi_response *phr) ...@@ -444,6 +427,26 @@ void HPI_6205(struct hpi_message *phm, struct hpi_response *phr)
} }
} }
void HPI_6205(struct hpi_message *phm, struct hpi_response *phr)
{
struct hpi_adapter_obj *pao = NULL;
if (phm->object != HPI_OBJ_SUBSYSTEM) {
/* normal messages must have valid adapter index */
pao = hpi_find_adapter(phm->adapter_index);
} else {
/* subsys messages don't address an adapter */
_HPI_6205(NULL, phm, phr);
return;
}
if (pao)
_HPI_6205(pao, phm, phr);
else
hpi_init_response(phr, phm->object, phm->function,
HPI_ERROR_BAD_ADAPTER_NUMBER);
}
/*****************************************************************************/ /*****************************************************************************/
/* SUBSYSTEM */ /* SUBSYSTEM */
...@@ -491,13 +494,11 @@ static void subsys_create_adapter(struct hpi_message *phm, ...@@ -491,13 +494,11 @@ static void subsys_create_adapter(struct hpi_message *phm,
} }
/** delete an adapter - required by WDM driver */ /** delete an adapter - required by WDM driver */
static void subsys_delete_adapter(struct hpi_message *phm, static void adapter_delete(struct hpi_adapter_obj *pao,
struct hpi_response *phr) struct hpi_message *phm, struct hpi_response *phr)
{ {
struct hpi_adapter_obj *pao;
struct hpi_hw_obj *phw; struct hpi_hw_obj *phw;
pao = hpi_find_adapter(phm->obj_index);
if (!pao) { if (!pao) {
phr->error = HPI_ERROR_INVALID_OBJ_INDEX; phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
return; return;
...@@ -563,11 +564,12 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao, ...@@ -563,11 +564,12 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao,
} }
err = adapter_boot_load_dsp(pao, pos_error_code); err = adapter_boot_load_dsp(pao, pos_error_code);
if (err) if (err) {
HPI_DEBUG_LOG(ERROR, "DSP code load failed\n");
/* no need to clean up as SubSysCreateAdapter */ /* no need to clean up as SubSysCreateAdapter */
/* calls DeleteAdapter on error. */ /* calls DeleteAdapter on error. */
return err; return err;
}
HPI_DEBUG_LOG(INFO, "load DSP code OK\n"); HPI_DEBUG_LOG(INFO, "load DSP code OK\n");
/* allow boot load even if mem alloc wont work */ /* allow boot load even if mem alloc wont work */
...@@ -604,6 +606,7 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao, ...@@ -604,6 +606,7 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao,
control_cache.number_of_controls, control_cache.number_of_controls,
interface->control_cache.size_in_bytes, interface->control_cache.size_in_bytes,
p_control_cache_virtual); p_control_cache_virtual);
if (!phw->p_cache) if (!phw->p_cache)
err = HPI_ERROR_MEMORY_ALLOC; err = HPI_ERROR_MEMORY_ALLOC;
} }
...@@ -675,16 +678,14 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao, ...@@ -675,16 +678,14 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao,
} }
/** Free memory areas allocated by adapter /** Free memory areas allocated by adapter
* this routine is called from SubSysDeleteAdapter, * this routine is called from AdapterDelete,
* and SubSysCreateAdapter if duplicate index * and SubSysCreateAdapter if duplicate index
*/ */
static void delete_adapter_obj(struct hpi_adapter_obj *pao) static void delete_adapter_obj(struct hpi_adapter_obj *pao)
{ {
struct hpi_hw_obj *phw; struct hpi_hw_obj *phw = pao->priv;
int i; int i;
phw = pao->priv;
if (hpios_locked_mem_valid(&phw->h_control_cache)) { if (hpios_locked_mem_valid(&phw->h_control_cache)) {
hpios_locked_mem_free(&phw->h_control_cache); hpios_locked_mem_free(&phw->h_control_cache);
hpi_free_control_cache(phw->p_cache); hpi_free_control_cache(phw->p_cache);
...@@ -1275,6 +1276,7 @@ static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao, ...@@ -1275,6 +1276,7 @@ static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
case HPI_ADAPTER_FAMILY_ASI(0x6300): case HPI_ADAPTER_FAMILY_ASI(0x6300):
boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(0x6400); boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(0x6400);
break; break;
case HPI_ADAPTER_FAMILY_ASI(0x5500):
case HPI_ADAPTER_FAMILY_ASI(0x5600): case HPI_ADAPTER_FAMILY_ASI(0x5600):
case HPI_ADAPTER_FAMILY_ASI(0x6500): case HPI_ADAPTER_FAMILY_ASI(0x6500):
boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(0x6600); boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(0x6600);
...@@ -2059,7 +2061,6 @@ static int wait_dsp_ack(struct hpi_hw_obj *phw, int state, int timeout_us) ...@@ -2059,7 +2061,6 @@ static int wait_dsp_ack(struct hpi_hw_obj *phw, int state, int timeout_us)
static void send_dsp_command(struct hpi_hw_obj *phw, int cmd) static void send_dsp_command(struct hpi_hw_obj *phw, int cmd)
{ {
struct bus_master_interface *interface = phw->p_interface_buffer; struct bus_master_interface *interface = phw->p_interface_buffer;
u32 r; u32 r;
interface->host_cmd = cmd; interface->host_cmd = cmd;
......
...@@ -294,7 +294,7 @@ enum HPI_CONTROL_ATTRIBUTES { ...@@ -294,7 +294,7 @@ enum HPI_CONTROL_ATTRIBUTES {
/* These defines are used to fill in protocol information for an Ethernet packet /* These defines are used to fill in protocol information for an Ethernet packet
sent using HMI on CS18102 */ sent using HMI on CS18102 */
/** ID supplied by Cirrius for ASI packets. */ /** ID supplied by Cirrus for ASI packets. */
#define HPI_ETHERNET_PACKET_ID 0x85 #define HPI_ETHERNET_PACKET_ID 0x85
/** Simple packet - no special routing required */ /** Simple packet - no special routing required */
#define HPI_ETHERNET_PACKET_V1 0x01 #define HPI_ETHERNET_PACKET_V1 0x01
...@@ -307,7 +307,7 @@ enum HPI_CONTROL_ATTRIBUTES { ...@@ -307,7 +307,7 @@ enum HPI_CONTROL_ATTRIBUTES {
/** This packet must make its way to the host across the HPI interface */ /** This packet must make its way to the host across the HPI interface */
#define HPI_ETHERNET_PACKET_HOSTED_VIA_HPI_V1 0x41 #define HPI_ETHERNET_PACKET_HOSTED_VIA_HPI_V1 0x41
#define HPI_ETHERNET_UDP_PORT (44600) /*!< UDP messaging port */ #define HPI_ETHERNET_UDP_PORT 44600 /**< HPI UDP service */
/** Default network timeout in milli-seconds. */ /** Default network timeout in milli-seconds. */
#define HPI_ETHERNET_TIMEOUT_MS 500 #define HPI_ETHERNET_TIMEOUT_MS 500
...@@ -397,14 +397,14 @@ enum HPI_FUNCTION_IDS { ...@@ -397,14 +397,14 @@ enum HPI_FUNCTION_IDS {
HPI_SUBSYS_OPEN = HPI_FUNC_ID(SUBSYSTEM, 1), HPI_SUBSYS_OPEN = HPI_FUNC_ID(SUBSYSTEM, 1),
HPI_SUBSYS_GET_VERSION = HPI_FUNC_ID(SUBSYSTEM, 2), HPI_SUBSYS_GET_VERSION = HPI_FUNC_ID(SUBSYSTEM, 2),
HPI_SUBSYS_GET_INFO = HPI_FUNC_ID(SUBSYSTEM, 3), HPI_SUBSYS_GET_INFO = HPI_FUNC_ID(SUBSYSTEM, 3),
HPI_SUBSYS_FIND_ADAPTERS = HPI_FUNC_ID(SUBSYSTEM, 4), /* HPI_SUBSYS_FIND_ADAPTERS = HPI_FUNC_ID(SUBSYSTEM, 4), */
HPI_SUBSYS_CREATE_ADAPTER = HPI_FUNC_ID(SUBSYSTEM, 5), HPI_SUBSYS_CREATE_ADAPTER = HPI_FUNC_ID(SUBSYSTEM, 5),
HPI_SUBSYS_CLOSE = HPI_FUNC_ID(SUBSYSTEM, 6), HPI_SUBSYS_CLOSE = HPI_FUNC_ID(SUBSYSTEM, 6),
HPI_SUBSYS_DELETE_ADAPTER = HPI_FUNC_ID(SUBSYSTEM, 7), /* HPI_SUBSYS_DELETE_ADAPTER = HPI_FUNC_ID(SUBSYSTEM, 7), */
HPI_SUBSYS_DRIVER_LOAD = HPI_FUNC_ID(SUBSYSTEM, 8), HPI_SUBSYS_DRIVER_LOAD = HPI_FUNC_ID(SUBSYSTEM, 8),
HPI_SUBSYS_DRIVER_UNLOAD = HPI_FUNC_ID(SUBSYSTEM, 9), HPI_SUBSYS_DRIVER_UNLOAD = HPI_FUNC_ID(SUBSYSTEM, 9),
HPI_SUBSYS_READ_PORT_8 = HPI_FUNC_ID(SUBSYSTEM, 10), /* HPI_SUBSYS_READ_PORT_8 = HPI_FUNC_ID(SUBSYSTEM, 10), */
HPI_SUBSYS_WRITE_PORT_8 = HPI_FUNC_ID(SUBSYSTEM, 11), /* HPI_SUBSYS_WRITE_PORT_8 = HPI_FUNC_ID(SUBSYSTEM, 11), */
HPI_SUBSYS_GET_NUM_ADAPTERS = HPI_FUNC_ID(SUBSYSTEM, 12), HPI_SUBSYS_GET_NUM_ADAPTERS = HPI_FUNC_ID(SUBSYSTEM, 12),
HPI_SUBSYS_GET_ADAPTER = HPI_FUNC_ID(SUBSYSTEM, 13), HPI_SUBSYS_GET_ADAPTER = HPI_FUNC_ID(SUBSYSTEM, 13),
HPI_SUBSYS_SET_NETWORK_INTERFACE = HPI_FUNC_ID(SUBSYSTEM, 14), HPI_SUBSYS_SET_NETWORK_INTERFACE = HPI_FUNC_ID(SUBSYSTEM, 14),
...@@ -433,7 +433,8 @@ enum HPI_FUNCTION_IDS { ...@@ -433,7 +433,8 @@ enum HPI_FUNCTION_IDS {
HPI_ADAPTER_DEBUG_READ = HPI_FUNC_ID(ADAPTER, 18), HPI_ADAPTER_DEBUG_READ = HPI_FUNC_ID(ADAPTER, 18),
HPI_ADAPTER_IRQ_QUERY_AND_CLEAR = HPI_FUNC_ID(ADAPTER, 19), HPI_ADAPTER_IRQ_QUERY_AND_CLEAR = HPI_FUNC_ID(ADAPTER, 19),
HPI_ADAPTER_IRQ_CALLBACK = HPI_FUNC_ID(ADAPTER, 20), HPI_ADAPTER_IRQ_CALLBACK = HPI_FUNC_ID(ADAPTER, 20),
#define HPI_ADAPTER_FUNCTION_COUNT 20 HPI_ADAPTER_DELETE = HPI_FUNC_ID(ADAPTER, 21),
#define HPI_ADAPTER_FUNCTION_COUNT 21
HPI_OSTREAM_OPEN = HPI_FUNC_ID(OSTREAM, 1), HPI_OSTREAM_OPEN = HPI_FUNC_ID(OSTREAM, 1),
HPI_OSTREAM_CLOSE = HPI_FUNC_ID(OSTREAM, 2), HPI_OSTREAM_CLOSE = HPI_FUNC_ID(OSTREAM, 2),
...@@ -1561,8 +1562,6 @@ void hpi_send_recv(struct hpi_message *phm, struct hpi_response *phr); ...@@ -1561,8 +1562,6 @@ void hpi_send_recv(struct hpi_message *phm, struct hpi_response *phr);
u16 hpi_subsys_create_adapter(const struct hpi_resource *p_resource, u16 hpi_subsys_create_adapter(const struct hpi_resource *p_resource,
u16 *pw_adapter_index); u16 *pw_adapter_index);
u16 hpi_subsys_delete_adapter(u16 adapter_index);
u16 hpi_outstream_host_buffer_get_info(u32 h_outstream, u8 **pp_buffer, u16 hpi_outstream_host_buffer_get_info(u32 h_outstream, u8 **pp_buffer,
struct hpi_hostbuffer_status **pp_status); struct hpi_hostbuffer_status **pp_status);
...@@ -1584,9 +1583,7 @@ void hpi_stream_response_to_legacy(struct hpi_stream_res *pSR); ...@@ -1584,9 +1583,7 @@ void hpi_stream_response_to_legacy(struct hpi_stream_res *pSR);
/*////////////////////////////////////////////////////////////////////////// */ /*////////////////////////////////////////////////////////////////////////// */
/* declarations for individual HPI entry points */ /* declarations for individual HPI entry points */
hpi_handler_func HPI_1000;
hpi_handler_func HPI_6000; hpi_handler_func HPI_6000;
hpi_handler_func HPI_6205; hpi_handler_func HPI_6205;
hpi_handler_func HPI_COMMON;
#endif /* _HPI_INTERNAL_H_ */ #endif /* _HPI_INTERNAL_H_ */
...@@ -227,8 +227,9 @@ static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC) ...@@ -227,8 +227,9 @@ static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC)
if (info->control_type) { if (info->control_type) {
pC->p_info[info->control_index] = info; pC->p_info[info->control_index] = info;
cached++; cached++;
} else /* dummy cache entry */ } else { /* dummy cache entry */
pC->p_info[info->control_index] = NULL; pC->p_info[info->control_index] = NULL;
}
byte_count += info->size_in32bit_words * 4; byte_count += info->size_in32bit_words * 4;
...@@ -298,7 +299,7 @@ struct pad_ofs_size { ...@@ -298,7 +299,7 @@ struct pad_ofs_size {
unsigned int field_size; unsigned int field_size;
}; };
static struct pad_ofs_size pad_desc[] = { static const struct pad_ofs_size pad_desc[] = {
HPICMN_PAD_OFS_AND_SIZE(c_channel), /* HPI_PAD_CHANNEL_NAME */ HPICMN_PAD_OFS_AND_SIZE(c_channel), /* HPI_PAD_CHANNEL_NAME */
HPICMN_PAD_OFS_AND_SIZE(c_artist), /* HPI_PAD_ARTIST */ HPICMN_PAD_OFS_AND_SIZE(c_artist), /* HPI_PAD_ARTIST */
HPICMN_PAD_OFS_AND_SIZE(c_title), /* HPI_PAD_TITLE */ HPICMN_PAD_OFS_AND_SIZE(c_title), /* HPI_PAD_TITLE */
...@@ -617,6 +618,10 @@ void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache, ...@@ -617,6 +618,10 @@ void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache,
} }
} }
/** Allocate control cache.
\return Cache pointer, or NULL if allocation fails.
*/
struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count, struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count,
const u32 size_in_bytes, u8 *p_dsp_control_buffer) const u32 size_in_bytes, u8 *p_dsp_control_buffer)
{ {
...@@ -667,7 +672,6 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr) ...@@ -667,7 +672,6 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
phr->u.s.num_adapters = adapters.gw_num_adapters; phr->u.s.num_adapters = adapters.gw_num_adapters;
break; break;
case HPI_SUBSYS_CREATE_ADAPTER: case HPI_SUBSYS_CREATE_ADAPTER:
case HPI_SUBSYS_DELETE_ADAPTER:
break; break;
default: default:
phr->error = HPI_ERROR_INVALID_FUNC; phr->error = HPI_ERROR_INVALID_FUNC;
......
...@@ -60,3 +60,5 @@ void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *pC, ...@@ -60,3 +60,5 @@ void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *pC,
struct hpi_message *phm, struct hpi_response *phr); struct hpi_message *phm, struct hpi_response *phr);
u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr); u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr);
hpi_handler_func HPI_COMMON;
...@@ -105,33 +105,6 @@ u16 hpi_subsys_get_version_ex(u32 *pversion_ex) ...@@ -105,33 +105,6 @@ u16 hpi_subsys_get_version_ex(u32 *pversion_ex)
return hr.error; return hr.error;
} }
u16 hpi_subsys_create_adapter(const struct hpi_resource *p_resource,
u16 *pw_adapter_index)
{
struct hpi_message hm;
struct hpi_response hr;
hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
HPI_SUBSYS_CREATE_ADAPTER);
hm.u.s.resource = *p_resource;
hpi_send_recv(&hm, &hr);
*pw_adapter_index = hr.u.s.adapter_index;
return hr.error;
}
u16 hpi_subsys_delete_adapter(u16 adapter_index)
{
struct hpi_message hm;
struct hpi_response hr;
hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
HPI_SUBSYS_DELETE_ADAPTER);
hm.obj_index = adapter_index;
hpi_send_recv(&hm, &hr);
return hr.error;
}
u16 hpi_subsys_get_num_adapters(int *pn_num_adapters) u16 hpi_subsys_get_num_adapters(int *pn_num_adapters)
{ {
struct hpi_message hm; struct hpi_message hm;
......
...@@ -211,24 +211,6 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr, ...@@ -211,24 +211,6 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr,
HPIMSGX__init(phm, phr); HPIMSGX__init(phm, phr);
break; break;
case HPI_SUBSYS_DELETE_ADAPTER:
HPIMSGX__cleanup(phm->obj_index, h_owner);
{
struct hpi_message hm;
struct hpi_response hr;
hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
HPI_ADAPTER_CLOSE);
hm.adapter_index = phm->obj_index;
hw_entry_point(&hm, &hr);
}
if ((phm->obj_index < HPI_MAX_ADAPTERS)
&& hpi_entry_points[phm->obj_index]) {
hpi_entry_points[phm->obj_index] (phm, phr);
hpi_entry_points[phm->obj_index] = NULL;
} else
phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
break;
default: default:
/* Must explicitly handle every subsys message in this switch */ /* Must explicitly handle every subsys message in this switch */
hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function, hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function,
...@@ -247,6 +229,19 @@ static void adapter_message(struct hpi_message *phm, struct hpi_response *phr, ...@@ -247,6 +229,19 @@ static void adapter_message(struct hpi_message *phm, struct hpi_response *phr,
case HPI_ADAPTER_CLOSE: case HPI_ADAPTER_CLOSE:
adapter_close(phm, phr); adapter_close(phm, phr);
break; break;
case HPI_ADAPTER_DELETE:
HPIMSGX__cleanup(phm->adapter_index, h_owner);
{
struct hpi_message hm;
struct hpi_response hr;
hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
HPI_ADAPTER_CLOSE);
hm.adapter_index = phm->adapter_index;
hw_entry_point(&hm, &hr);
}
hw_entry_point(phm, phr);
break;
default: default:
hw_entry_point(phm, phr); hw_entry_point(phm, phr);
break; break;
......
...@@ -25,6 +25,7 @@ Common Linux HPI ioctl and module probe/remove functions ...@@ -25,6 +25,7 @@ Common Linux HPI ioctl and module probe/remove functions
#include "hpidebug.h" #include "hpidebug.h"
#include "hpimsgx.h" #include "hpimsgx.h"
#include "hpioctl.h" #include "hpioctl.h"
#include "hpicmn.h"
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -161,26 +162,24 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -161,26 +162,24 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
goto out; goto out;
} }
pa = &adapters[hm->h.adapter_index]; switch (hm->h.function) {
case HPI_SUBSYS_CREATE_ADAPTER:
case HPI_ADAPTER_DELETE:
/* Application must not use these functions! */
hr->h.size = sizeof(hr->h);
hr->h.error = HPI_ERROR_INVALID_OPERATION;
hr->h.function = hm->h.function;
uncopied_bytes = copy_to_user(puhr, hr, hr->h.size);
if (uncopied_bytes)
err = -EFAULT;
else
err = 0;
goto out;
}
hr->h.size = res_max_size; hr->h.size = res_max_size;
if (hm->h.object == HPI_OBJ_SUBSYSTEM) { if (hm->h.object == HPI_OBJ_SUBSYSTEM) {
switch (hm->h.function) { hpi_send_recv_f(&hm->m0, &hr->r0, file);
case HPI_SUBSYS_CREATE_ADAPTER:
case HPI_SUBSYS_DELETE_ADAPTER:
/* Application must not use these functions! */
hr->h.size = sizeof(hr->h);
hr->h.error = HPI_ERROR_INVALID_OPERATION;
hr->h.function = hm->h.function;
uncopied_bytes = copy_to_user(puhr, hr, hr->h.size);
if (uncopied_bytes)
err = -EFAULT;
else
err = 0;
goto out;
default:
hpi_send_recv_f(&hm->m0, &hr->r0, file);
}
} else { } else {
u16 __user *ptr = NULL; u16 __user *ptr = NULL;
u32 size = 0; u32 size = 0;
...@@ -188,8 +187,9 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -188,8 +187,9 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
/* -1=no data 0=read from user mem, 1=write to user mem */ /* -1=no data 0=read from user mem, 1=write to user mem */
int wrflag = -1; int wrflag = -1;
u32 adapter = hm->h.adapter_index; u32 adapter = hm->h.adapter_index;
pa = &adapters[adapter];
if ((hm->h.adapter_index > HPI_MAX_ADAPTERS) || (!pa->type)) { if ((adapter > HPI_MAX_ADAPTERS) || (!pa->type)) {
hpi_init_response(&hr->r0, HPI_OBJ_ADAPTER, hpi_init_response(&hr->r0, HPI_OBJ_ADAPTER,
HPI_ADAPTER_OPEN, HPI_ADAPTER_OPEN,
HPI_ERROR_BAD_ADAPTER_NUMBER); HPI_ERROR_BAD_ADAPTER_NUMBER);
...@@ -317,7 +317,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -317,7 +317,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev, int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
const struct pci_device_id *pci_id) const struct pci_device_id *pci_id)
{ {
int err, idx, nm; int idx, nm;
unsigned int memlen; unsigned int memlen;
struct hpi_message hm; struct hpi_message hm;
struct hpi_response hr; struct hpi_response hr;
...@@ -351,11 +351,8 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev, ...@@ -351,11 +351,8 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
nm = HPI_MAX_ADAPTER_MEM_SPACES; nm = HPI_MAX_ADAPTER_MEM_SPACES;
for (idx = 0; idx < nm; idx++) { for (idx = 0; idx < nm; idx++) {
HPI_DEBUG_LOG(INFO, "resource %d %s %08llx-%08llx %04llx\n", HPI_DEBUG_LOG(INFO, "resource %d %pR\n", idx,
idx, pci_dev->resource[idx].name, &pci_dev->resource[idx]);
(unsigned long long)pci_resource_start(pci_dev, idx),
(unsigned long long)pci_resource_end(pci_dev, idx),
(unsigned long long)pci_resource_flags(pci_dev, idx));
if (pci_resource_flags(pci_dev, idx) & IORESOURCE_MEM) { if (pci_resource_flags(pci_dev, idx) & IORESOURCE_MEM) {
memlen = pci_resource_len(pci_dev, idx); memlen = pci_resource_len(pci_dev, idx);
...@@ -395,17 +392,20 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev, ...@@ -395,17 +392,20 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
adapter.index = hr.u.s.adapter_index; adapter.index = hr.u.s.adapter_index;
adapter.type = hr.u.s.adapter_type; adapter.type = hr.u.s.adapter_type;
hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
HPI_ADAPTER_OPEN);
hm.adapter_index = adapter.index; hm.adapter_index = adapter.index;
hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
err = hpi_adapter_open(adapter.index); if (hr.error)
if (err)
goto err; goto err;
adapter.snd_card_asihpi = NULL; adapter.snd_card_asihpi = NULL;
/* WARNING can't init mutex in 'adapter' /* WARNING can't init mutex in 'adapter'
* and then copy it to adapters[] ?!?! * and then copy it to adapters[] ?!?!
*/ */
adapters[hr.u.s.adapter_index] = adapter; adapters[adapter.index] = adapter;
mutex_init(&adapters[adapter.index].mutex); mutex_init(&adapters[adapter.index].mutex);
pci_set_drvdata(pci_dev, &adapters[adapter.index]); pci_set_drvdata(pci_dev, &adapters[adapter.index]);
...@@ -440,10 +440,9 @@ void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev) ...@@ -440,10 +440,9 @@ void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev)
struct hpi_adapter *pa; struct hpi_adapter *pa;
pa = pci_get_drvdata(pci_dev); pa = pci_get_drvdata(pci_dev);
hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
HPI_SUBSYS_DELETE_ADAPTER); HPI_ADAPTER_DELETE);
hm.obj_index = pa->index; hm.adapter_index = pa->index;
hm.adapter_index = HPI_ADAPTER_INDEX_INVALID;
hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
/* unmap PCI memory space, mapped during device init. */ /* unmap PCI memory space, mapped during device init. */
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
#define CHIP_AU8810 #define CHIP_AU8810
#define CARD_NAME "Aureal Advantage 3D Sound Processor" #define CARD_NAME "Aureal Advantage"
#define CARD_NAME_SHORT "au8810" #define CARD_NAME_SHORT "au8810"
#define NR_ADB 0x10 #define NR_ADB 0x10
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#define CHIP_AU8820 #define CHIP_AU8820
#define CARD_NAME "Aureal Vortex 3D Sound Processor" #define CARD_NAME "Aureal Vortex"
#define CARD_NAME_SHORT "au8820" #define CARD_NAME_SHORT "au8820"
/* Number of ADB and WT channels */ /* Number of ADB and WT channels */
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#define CHIP_AU8830 #define CHIP_AU8830
#define CARD_NAME "Aureal Vortex 2 3D Sound Processor" #define CARD_NAME "Aureal Vortex 2"
#define CARD_NAME_SHORT "au8830" #define CARD_NAME_SHORT "au8830"
#define NR_ADB 0x20 #define NR_ADB 0x20
......
...@@ -426,11 +426,11 @@ static struct snd_pcm_ops snd_vortex_playback_ops = { ...@@ -426,11 +426,11 @@ static struct snd_pcm_ops snd_vortex_playback_ops = {
*/ */
static char *vortex_pcm_prettyname[VORTEX_PCM_LAST] = { static char *vortex_pcm_prettyname[VORTEX_PCM_LAST] = {
"AU88x0 ADB", CARD_NAME " ADB",
"AU88x0 SPDIF", CARD_NAME " SPDIF",
"AU88x0 A3D", CARD_NAME " A3D",
"AU88x0 WT", CARD_NAME " WT",
"AU88x0 I2S", CARD_NAME " I2S",
}; };
static char *vortex_pcm_name[VORTEX_PCM_LAST] = { static char *vortex_pcm_name[VORTEX_PCM_LAST] = {
"adb", "adb",
...@@ -527,7 +527,8 @@ static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr) ...@@ -527,7 +527,8 @@ static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr)
nr_capt, &pcm); nr_capt, &pcm);
if (err < 0) if (err < 0)
return err; return err;
strcpy(pcm->name, vortex_pcm_name[idx]); snprintf(pcm->name, sizeof(pcm->name),
"%s %s", CARD_NAME_SHORT, vortex_pcm_name[idx]);
chip->pcm[idx] = pcm; chip->pcm[idx] = pcm;
// This is an evil hack, but it saves a lot of duplicated code. // This is an evil hack, but it saves a lot of duplicated code.
VORTEX_PCM_TYPE(pcm) = idx; VORTEX_PCM_TYPE(pcm) = idx;
......
...@@ -303,6 +303,9 @@ static const u32 db_table[101] = { ...@@ -303,6 +303,9 @@ static const u32 db_table[101] = {
static const DECLARE_TLV_DB_SCALE(snd_emu10k1_db_scale1, -4000, 40, 1); static const DECLARE_TLV_DB_SCALE(snd_emu10k1_db_scale1, -4000, 40, 1);
static const DECLARE_TLV_DB_LINEAR(snd_emu10k1_db_linear, TLV_DB_GAIN_MUTE, 0); static const DECLARE_TLV_DB_LINEAR(snd_emu10k1_db_linear, TLV_DB_GAIN_MUTE, 0);
/* EMU10K1 bass/treble db gain */
static const DECLARE_TLV_DB_SCALE(snd_emu10k1_bass_treble_db_scale, -1200, 60, 0);
static const u32 onoff_table[2] = { static const u32 onoff_table[2] = {
0x00000000, 0x00000001 0x00000000, 0x00000001
}; };
...@@ -2163,6 +2166,7 @@ static int __devinit _snd_emu10k1_init_efx(struct snd_emu10k1 *emu) ...@@ -2163,6 +2166,7 @@ static int __devinit _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
ctl->min = 0; ctl->min = 0;
ctl->max = 40; ctl->max = 40;
ctl->value[0] = ctl->value[1] = 20; ctl->value[0] = ctl->value[1] = 20;
ctl->tlv = snd_emu10k1_bass_treble_db_scale;
ctl->translation = EMU10K1_GPR_TRANSLATION_BASS; ctl->translation = EMU10K1_GPR_TRANSLATION_BASS;
ctl = &controls[i + 1]; ctl = &controls[i + 1];
ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
...@@ -2172,6 +2176,7 @@ static int __devinit _snd_emu10k1_init_efx(struct snd_emu10k1 *emu) ...@@ -2172,6 +2176,7 @@ static int __devinit _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
ctl->min = 0; ctl->min = 0;
ctl->max = 40; ctl->max = 40;
ctl->value[0] = ctl->value[1] = 20; ctl->value[0] = ctl->value[1] = 20;
ctl->tlv = snd_emu10k1_bass_treble_db_scale;
ctl->translation = EMU10K1_GPR_TRANSLATION_TREBLE; ctl->translation = EMU10K1_GPR_TRANSLATION_TREBLE;
#define BASS_GPR 0x8c #define BASS_GPR 0x8c
......
...@@ -1729,8 +1729,6 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu, ...@@ -1729,8 +1729,6 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
"Master Mono Playback Volume", "Master Mono Playback Volume",
"PCM Out Path & Mute", "PCM Out Path & Mute",
"Mono Output Select", "Mono Output Select",
"Front Playback Switch",
"Front Playback Volume",
"Surround Playback Switch", "Surround Playback Switch",
"Surround Playback Volume", "Surround Playback Volume",
"Center Playback Switch", "Center Playback Switch",
...@@ -1879,6 +1877,8 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu, ...@@ -1879,6 +1877,8 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
emu->rear_ac97 = 1; emu->rear_ac97 = 1;
snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE|AC97SLOT_REAR_LEFT|AC97SLOT_REAR_RIGHT); snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE|AC97SLOT_REAR_LEFT|AC97SLOT_REAR_RIGHT);
snd_ac97_write_cache(emu->ac97, AC97_HEADPHONE, 0x0202); snd_ac97_write_cache(emu->ac97, AC97_HEADPHONE, 0x0202);
remove_ctl(card,"Front Playback Volume");
remove_ctl(card,"Front Playback Switch");
} }
/* remove unused AC97 controls */ /* remove unused AC97 controls */
snd_ac97_write_cache(emu->ac97, AC97_SURROUND_MASTER, 0x0202); snd_ac97_write_cache(emu->ac97, AC97_SURROUND_MASTER, 0x0202);
...@@ -1913,6 +1913,12 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu, ...@@ -1913,6 +1913,12 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
for (; *c; c += 2) for (; *c; c += 2)
rename_ctl(card, c[0], c[1]); rename_ctl(card, c[0], c[1]);
if (emu->card_capabilities->subsystem == 0x80401102) { /* SB Live! Platinum CT4760P */
remove_ctl(card, "Center Playback Volume");
remove_ctl(card, "LFE Playback Volume");
remove_ctl(card, "Wave Center Playback Volume");
remove_ctl(card, "Wave LFE Playback Volume");
}
if (emu->card_capabilities->subsystem == 0x20071102) { /* Audigy 4 Pro */ if (emu->card_capabilities->subsystem == 0x20071102) { /* Audigy 4 Pro */
rename_ctl(card, "Line2 Capture Volume", "Line1/Mic Capture Volume"); rename_ctl(card, "Line2 Capture Volume", "Line1/Mic Capture Volume");
rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume"); rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume");
......
...@@ -112,6 +112,10 @@ ...@@ -112,6 +112,10 @@
#include <sound/ac97_codec.h> #include <sound/ac97_codec.h>
#include <sound/initval.h> #include <sound/initval.h>
#ifdef CONFIG_SND_ES1968_RADIO
#include <sound/tea575x-tuner.h>
#endif
#define CARD_NAME "ESS Maestro1/2" #define CARD_NAME "ESS Maestro1/2"
#define DRIVER_NAME "ES1968" #define DRIVER_NAME "ES1968"
...@@ -553,6 +557,10 @@ struct es1968 { ...@@ -553,6 +557,10 @@ struct es1968 {
spinlock_t ac97_lock; spinlock_t ac97_lock;
struct tasklet_struct hwvol_tq; struct tasklet_struct hwvol_tq;
#endif #endif
#ifdef CONFIG_SND_ES1968_RADIO
struct snd_tea575x tea;
#endif
}; };
static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id); static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id);
...@@ -2571,6 +2579,63 @@ static int __devinit snd_es1968_input_register(struct es1968 *chip) ...@@ -2571,6 +2579,63 @@ static int __devinit snd_es1968_input_register(struct es1968 *chip)
} }
#endif /* CONFIG_SND_ES1968_INPUT */ #endif /* CONFIG_SND_ES1968_INPUT */
#ifdef CONFIG_SND_ES1968_RADIO
#define GPIO_DATA 0x60
#define IO_MASK 4 /* mask register offset from GPIO_DATA
bits 1=unmask write to given bit */
#define IO_DIR 8 /* direction register offset from GPIO_DATA
bits 0/1=read/write direction */
/* mask bits for GPIO lines */
#define STR_DATA 0x0040 /* GPIO6 */
#define STR_CLK 0x0080 /* GPIO7 */
#define STR_WREN 0x0100 /* GPIO8 */
#define STR_MOST 0x0200 /* GPIO9 */
static void snd_es1968_tea575x_set_pins(struct snd_tea575x *tea, u8 pins)
{
struct es1968 *chip = tea->private_data;
unsigned long io = chip->io_port + GPIO_DATA;
u16 val = 0;
val |= (pins & TEA575X_DATA) ? STR_DATA : 0;
val |= (pins & TEA575X_CLK) ? STR_CLK : 0;
val |= (pins & TEA575X_WREN) ? STR_WREN : 0;
outw(val, io);
}
static u8 snd_es1968_tea575x_get_pins(struct snd_tea575x *tea)
{
struct es1968 *chip = tea->private_data;
unsigned long io = chip->io_port + GPIO_DATA;
u16 val = inw(io);
return (val & STR_DATA) ? TEA575X_DATA : 0 |
(val & STR_MOST) ? TEA575X_MOST : 0;
}
static void snd_es1968_tea575x_set_direction(struct snd_tea575x *tea, bool output)
{
struct es1968 *chip = tea->private_data;
unsigned long io = chip->io_port + GPIO_DATA;
u16 odir = inw(io + IO_DIR);
if (output) {
outw(~(STR_DATA | STR_CLK | STR_WREN), io + IO_MASK);
outw(odir | STR_DATA | STR_CLK | STR_WREN, io + IO_DIR);
} else {
outw(~(STR_CLK | STR_WREN | STR_DATA | STR_MOST), io + IO_MASK);
outw((odir & ~(STR_DATA | STR_MOST)) | STR_CLK | STR_WREN, io + IO_DIR);
}
}
static struct snd_tea575x_ops snd_es1968_tea_ops = {
.set_pins = snd_es1968_tea575x_set_pins,
.get_pins = snd_es1968_tea575x_get_pins,
.set_direction = snd_es1968_tea575x_set_direction,
};
#endif
static int snd_es1968_free(struct es1968 *chip) static int snd_es1968_free(struct es1968 *chip)
{ {
#ifdef CONFIG_SND_ES1968_INPUT #ifdef CONFIG_SND_ES1968_INPUT
...@@ -2585,6 +2650,10 @@ static int snd_es1968_free(struct es1968 *chip) ...@@ -2585,6 +2650,10 @@ static int snd_es1968_free(struct es1968 *chip)
outw(0, chip->io_port + ESM_PORT_HOST_IRQ); /* disable IRQ */ outw(0, chip->io_port + ESM_PORT_HOST_IRQ); /* disable IRQ */
} }
#ifdef CONFIG_SND_ES1968_RADIO
snd_tea575x_exit(&chip->tea);
#endif
if (chip->irq >= 0) if (chip->irq >= 0)
free_irq(chip->irq, chip); free_irq(chip->irq, chip);
snd_es1968_free_gameport(chip); snd_es1968_free_gameport(chip);
...@@ -2723,6 +2792,15 @@ static int __devinit snd_es1968_create(struct snd_card *card, ...@@ -2723,6 +2792,15 @@ static int __devinit snd_es1968_create(struct snd_card *card,
snd_card_set_dev(card, &pci->dev); snd_card_set_dev(card, &pci->dev);
#ifdef CONFIG_SND_ES1968_RADIO
chip->tea.private_data = chip;
chip->tea.ops = &snd_es1968_tea_ops;
strlcpy(chip->tea.card, "SF64-PCE2", sizeof(chip->tea.card));
sprintf(chip->tea.bus_info, "PCI:%s", pci_name(pci));
if (!snd_tea575x_init(&chip->tea))
printk(KERN_INFO "es1968: detected TEA575x radio\n");
#endif
*chip_ret = chip; *chip_ret = chip;
return 0; return 0;
......
This diff is collapsed.
...@@ -235,8 +235,8 @@ static DEFINE_PCI_DEVICE_TABLE(snd_intel8x0m_ids) = { ...@@ -235,8 +235,8 @@ static DEFINE_PCI_DEVICE_TABLE(snd_intel8x0m_ids) = {
{ PCI_VDEVICE(NVIDIA, 0x0069), DEVICE_NFORCE }, /* NFORCE2 */ { PCI_VDEVICE(NVIDIA, 0x0069), DEVICE_NFORCE }, /* NFORCE2 */
{ PCI_VDEVICE(NVIDIA, 0x0089), DEVICE_NFORCE }, /* NFORCE2s */ { PCI_VDEVICE(NVIDIA, 0x0089), DEVICE_NFORCE }, /* NFORCE2s */
{ PCI_VDEVICE(NVIDIA, 0x00d9), DEVICE_NFORCE }, /* NFORCE3 */ { PCI_VDEVICE(NVIDIA, 0x00d9), DEVICE_NFORCE }, /* NFORCE3 */
{ PCI_VDEVICE(AMD, 0x746e), DEVICE_INTEL }, /* AMD8111 */
#if 0 #if 0
{ PCI_VDEVICE(AMD, 0x746d), DEVICE_INTEL }, /* AMD8111 */
{ PCI_VDEVICE(AL, 0x5455), DEVICE_ALI }, /* Ali5455 */ { PCI_VDEVICE(AL, 0x5455), DEVICE_ALI }, /* Ali5455 */
#endif #endif
{ 0, } { 0, }
...@@ -1261,9 +1261,9 @@ static struct shortname_table { ...@@ -1261,9 +1261,9 @@ static struct shortname_table {
{ PCI_DEVICE_ID_NVIDIA_MCP2_MODEM, "NVidia nForce2" }, { PCI_DEVICE_ID_NVIDIA_MCP2_MODEM, "NVidia nForce2" },
{ PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM, "NVidia nForce2s" }, { PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM, "NVidia nForce2s" },
{ PCI_DEVICE_ID_NVIDIA_MCP3_MODEM, "NVidia nForce3" }, { PCI_DEVICE_ID_NVIDIA_MCP3_MODEM, "NVidia nForce3" },
{ 0x746e, "AMD AMD8111" },
#if 0 #if 0
{ 0x5455, "ALi M5455" }, { 0x5455, "ALi M5455" },
{ 0x746d, "AMD AMD8111" },
#endif #endif
{ 0 }, { 0 },
}; };
......
...@@ -1000,7 +1000,7 @@ static void device_change_handler(struct work_struct *work) ...@@ -1000,7 +1000,7 @@ static void device_change_handler(struct work_struct *work)
chip->lineout_sw_ctl); chip->lineout_sw_ctl);
if (mix->anded_reset) if (mix->anded_reset)
msleep(10); msleep(10);
check_mute(chip, &mix->amp_mute, 1, mix->auto_mute_notify, check_mute(chip, &mix->amp_mute, !IS_G4DA, mix->auto_mute_notify,
chip->speaker_sw_ctl); chip->speaker_sw_ctl);
} else { } else {
/* unmute speaker, mute others */ /* unmute speaker, mute others */
......
...@@ -65,6 +65,15 @@ init_data[] = { ...@@ -65,6 +65,15 @@ init_data[] = {
{ 0 } /* TERMINATING ENTRY */ { 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) static void usb6fire_control_master_vol_update(struct control_runtime *rt)
{ {
struct comm_runtime *comm_rt = rt->chip->comm; struct comm_runtime *comm_rt = rt->chip->comm;
...@@ -95,6 +104,67 @@ static void usb6fire_control_opt_coax_update(struct control_runtime *rt) ...@@ -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, static int usb6fire_control_master_vol_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo) struct snd_ctl_elem_info *uinfo)
{ {
...@@ -195,6 +265,28 @@ static int usb6fire_control_opt_coax_get(struct snd_kcontrol *kcontrol, ...@@ -195,6 +265,28 @@ static int usb6fire_control_opt_coax_get(struct snd_kcontrol *kcontrol,
return 0; 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[] = { static struct __devinitdata snd_kcontrol_new elements[] = {
{ {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
...@@ -223,6 +315,15 @@ static struct __devinitdata snd_kcontrol_new elements[] = { ...@@ -223,6 +315,15 @@ static struct __devinitdata snd_kcontrol_new elements[] = {
.get = usb6fire_control_opt_coax_get, .get = usb6fire_control_opt_coax_get,
.put = usb6fire_control_opt_coax_put .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) ...@@ -238,6 +339,9 @@ int __devinit usb6fire_control_init(struct sfire_chip *chip)
return -ENOMEM; return -ENOMEM;
rt->chip = chip; 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; i = 0;
while (init_data[i].type) { while (init_data[i].type) {
...@@ -249,6 +353,7 @@ int __devinit usb6fire_control_init(struct sfire_chip *chip) ...@@ -249,6 +353,7 @@ int __devinit usb6fire_control_init(struct sfire_chip *chip)
usb6fire_control_opt_coax_update(rt); usb6fire_control_opt_coax_update(rt);
usb6fire_control_line_phono_update(rt); usb6fire_control_line_phono_update(rt);
usb6fire_control_master_vol_update(rt); usb6fire_control_master_vol_update(rt);
usb6fire_control_streaming_update(rt);
i = 0; i = 0;
while (elements[i].name) { while (elements[i].name) {
......
...@@ -21,12 +21,29 @@ enum { ...@@ -21,12 +21,29 @@ enum {
CONTROL_MAX_ELEMENTS = 32 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 { 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 sfire_chip *chip;
struct snd_kcontrol *element[CONTROL_MAX_ELEMENTS]; struct snd_kcontrol *element[CONTROL_MAX_ELEMENTS];
bool opt_coax_switch; bool opt_coax_switch;
bool line_phono_switch; bool line_phono_switch;
bool digital_thru_switch;
bool usb_streaming;
u8 master_vol; u8 master_vol;
}; };
......
...@@ -3,12 +3,6 @@ ...@@ -3,12 +3,6 @@
* *
* Firmware loader * 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> * Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011 * Created: Jan 01, 2011
* Version: 0.3.0 * Version: 0.3.0
...@@ -21,6 +15,7 @@ ...@@ -21,6 +15,7 @@
*/ */
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/bitrev.h>
#include "firmware.h" #include "firmware.h"
#include "chip.h" #include "chip.h"
...@@ -33,32 +28,6 @@ enum { ...@@ -33,32 +28,6 @@ enum {
FPGA_BUFSIZE = 512, FPGA_EP = 2 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. * wMaxPacketSize of pcm endpoints.
* keep synced with rates_in_packet_size and rates_out_packet_size in pcm.c * 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,6 +41,10 @@ static const u8 ep_w_max_packet_size[] = {
0x94, 0x01, 0x5c, 0x02 /* alt 3: 404 EP2 and 604 EP6 (25 fpp) */ 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 { struct ihex_record {
u16 address; u16 address;
u8 len; u8 len;
...@@ -340,7 +313,7 @@ static int usb6fire_fw_fpga_upload( ...@@ -340,7 +313,7 @@ static int usb6fire_fw_fpga_upload(
while (c != end) { while (c != end) {
for (i = 0; c != end && i < FPGA_BUFSIZE; i++, c++) 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); ret = usb6fire_fw_fpga_write(device, buffer, i);
if (ret < 0) { if (ret < 0) {
...@@ -363,6 +336,25 @@ static int usb6fire_fw_fpga_upload( ...@@ -363,6 +336,25 @@ static int usb6fire_fw_fpga_upload(
return 0; 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 usb6fire_fw_init(struct usb_interface *intf)
{ {
int i; int i;
...@@ -378,9 +370,7 @@ int usb6fire_fw_init(struct usb_interface *intf) ...@@ -378,9 +370,7 @@ int usb6fire_fw_init(struct usb_interface *intf)
"firmware state.\n"); "firmware state.\n");
return ret; return ret;
} }
if (buffer[0] != 0xeb || buffer[1] != 0xaa || buffer[2] != 0x55 if (buffer[0] != 0xeb || buffer[1] != 0xaa || buffer[2] != 0x55) {
|| buffer[4] != 0x03 || buffer[5] != 0x01 || buffer[7]
!= 0x00) {
snd_printk(KERN_ERR PREFIX "unknown device firmware state " snd_printk(KERN_ERR PREFIX "unknown device firmware state "
"received from device: "); "received from device: ");
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
...@@ -389,7 +379,7 @@ int usb6fire_fw_init(struct usb_interface *intf) ...@@ -389,7 +379,7 @@ int usb6fire_fw_init(struct usb_interface *intf)
return -EIO; return -EIO;
} }
/* do we need fpga loader ezusb firmware? */ /* do we need fpga loader ezusb firmware? */
if (buffer[3] == 0x01 && buffer[6] == 0x19) { if (buffer[3] == 0x01) {
ret = usb6fire_fw_ezusb_upload(intf, ret = usb6fire_fw_ezusb_upload(intf,
"6fire/dmx6firel2.ihx", 0, NULL, 0); "6fire/dmx6firel2.ihx", 0, NULL, 0);
if (ret < 0) if (ret < 0)
...@@ -397,7 +387,10 @@ int usb6fire_fw_init(struct usb_interface *intf) ...@@ -397,7 +387,10 @@ int usb6fire_fw_init(struct usb_interface *intf)
return FW_NOT_READY; return FW_NOT_READY;
} }
/* do we need fpga firmware and application ezusb firmware? */ /* 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"); ret = usb6fire_fw_fpga_upload(intf, "6fire/dmx6firecf.bin");
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -410,8 +403,8 @@ int usb6fire_fw_init(struct usb_interface *intf) ...@@ -410,8 +403,8 @@ int usb6fire_fw_init(struct usb_interface *intf)
return FW_NOT_READY; return FW_NOT_READY;
} }
/* all fw loaded? */ /* all fw loaded? */
else if (buffer[3] == 0x03 && buffer[6] == 0x0b) else if (buffer[3] == 0x03)
return 0; return usb6fire_fw_check(buffer + 4);
/* unknown data? */ /* unknown data? */
else { else {
snd_printk(KERN_ERR PREFIX "unknown device firmware state " snd_printk(KERN_ERR PREFIX "unknown device firmware state "
......
...@@ -17,26 +17,23 @@ ...@@ -17,26 +17,23 @@
#include "pcm.h" #include "pcm.h"
#include "chip.h" #include "chip.h"
#include "comm.h" #include "comm.h"
#include "control.h"
enum { enum {
OUT_N_CHANNELS = 6, IN_N_CHANNELS = 4 OUT_N_CHANNELS = 6, IN_N_CHANNELS = 4
}; };
/* keep next two synced with /* 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_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_out_packet_size[] = { 228, 228, 420, 420, 604, 604 };
static const int rates[] = { 44100, 48000, 88200, 96000, 176400, 192000 }; 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[] = { static const int rates_alsaid[] = {
SNDRV_PCM_RATE_44100, SNDRV_PCM_RATE_48000, SNDRV_PCM_RATE_44100, SNDRV_PCM_RATE_48000,
SNDRV_PCM_RATE_88200, SNDRV_PCM_RATE_96000, SNDRV_PCM_RATE_88200, SNDRV_PCM_RATE_96000,
SNDRV_PCM_RATE_176400, SNDRV_PCM_RATE_192000 }; 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 */ enum { /* settings for pcm */
OUT_EP = 6, IN_EP = 2, MAX_BUFSIZE = 128 * 1024 OUT_EP = 6, IN_EP = 2, MAX_BUFSIZE = 128 * 1024
}; };
...@@ -48,15 +45,6 @@ enum { /* pcm streaming states */ ...@@ -48,15 +45,6 @@ enum { /* pcm streaming states */
STREAM_STOPPING 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 = { static const struct snd_pcm_hardware pcm_hw = {
.info = SNDRV_PCM_INFO_MMAP | .info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_INTERLEAVED |
...@@ -64,7 +52,7 @@ static const struct snd_pcm_hardware pcm_hw = { ...@@ -64,7 +52,7 @@ static const struct snd_pcm_hardware pcm_hw = {
SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_BATCH, 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 | .rates = SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_48000 |
...@@ -87,57 +75,34 @@ static const struct snd_pcm_hardware pcm_hw = { ...@@ -87,57 +75,34 @@ static const struct snd_pcm_hardware pcm_hw = {
static int usb6fire_pcm_set_rate(struct pcm_runtime *rt) static int usb6fire_pcm_set_rate(struct pcm_runtime *rt)
{ {
int ret; int ret;
struct usb_device *device = rt->chip->dev; struct control_runtime *ctrl_rt = rt->chip->control;
struct comm_runtime *comm_rt = rt->chip->comm;
if (rt->rate >= ARRAY_SIZE(rates)) ctrl_rt->usb_streaming = false;
return -EINVAL; ret = ctrl_rt->update_streaming(ctrl_rt);
/* disable streaming */
ret = comm_rt->write16(comm_rt, 0x02, 0x00, 0x00, 0x00);
if (ret < 0) { if (ret < 0) {
snd_printk(KERN_ERR PREFIX "error stopping streaming while " snd_printk(KERN_ERR PREFIX "error stopping streaming while "
"setting samplerate %d.\n", rates[rt->rate]); "setting samplerate %d.\n", rates[rt->rate]);
return ret; return ret;
} }
ret = usb_set_interface(device, 1, rates_altsetting[rt->rate]); ret = ctrl_rt->set_rate(ctrl_rt, 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]);
if (ret < 0) { if (ret < 0) {
snd_printk(KERN_ERR PREFIX "error setting samplerate %d.\n", snd_printk(KERN_ERR PREFIX "error setting samplerate %d.\n",
rates[rt->rate]); rates[rt->rate]);
return ret; return ret;
} }
/* enable analog inputs and outputs ret = ctrl_rt->set_channels(ctrl_rt, OUT_N_CHANNELS, IN_N_CHANNELS,
* (one bit per stereo-channel) */ false, false);
ret = comm_rt->write16(comm_rt, 0x02, 0x02,
(1 << (OUT_N_CHANNELS / 2)) - 1,
(1 << (IN_N_CHANNELS / 2)) - 1);
if (ret < 0) { 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", "while setting samplerate %d.\n",
rates[rt->rate]); rates[rt->rate]);
return ret; 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) { if (ret < 0) {
snd_printk(KERN_ERR PREFIX "error starting streaming while " snd_printk(KERN_ERR PREFIX "error starting streaming while "
"setting samplerate %d.\n", rates[rt->rate]); "setting samplerate %d.\n", rates[rt->rate]);
...@@ -168,12 +133,15 @@ static struct pcm_substream *usb6fire_pcm_get_substream( ...@@ -168,12 +133,15 @@ static struct pcm_substream *usb6fire_pcm_get_substream(
static void usb6fire_pcm_stream_stop(struct pcm_runtime *rt) static void usb6fire_pcm_stream_stop(struct pcm_runtime *rt)
{ {
int i; int i;
struct control_runtime *ctrl_rt = rt->chip->control;
if (rt->stream_state != STREAM_DISABLED) { if (rt->stream_state != STREAM_DISABLED) {
for (i = 0; i < PCM_N_URBS; i++) { for (i = 0; i < PCM_N_URBS; i++) {
usb_kill_urb(&rt->in_urbs[i].instance); usb_kill_urb(&rt->in_urbs[i].instance);
usb_kill_urb(&rt->out_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; rt->stream_state = STREAM_DISABLED;
} }
} }
...@@ -228,7 +196,7 @@ static void usb6fire_pcm_capture(struct pcm_substream *sub, struct pcm_urb *urb) ...@@ -228,7 +196,7 @@ static void usb6fire_pcm_capture(struct pcm_substream *sub, struct pcm_urb *urb)
unsigned int total_length = 0; unsigned int total_length = 0;
struct pcm_runtime *rt = snd_pcm_substream_chip(sub->instance); struct pcm_runtime *rt = snd_pcm_substream_chip(sub->instance);
struct snd_pcm_runtime *alsa_rt = sub->instance->runtime; 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 u32 *dest = (u32 *) (alsa_rt->dma_area + sub->dma_off
* (alsa_rt->frame_bits >> 3)); * (alsa_rt->frame_bits >> 3));
u32 *dest_end = (u32 *) (alsa_rt->dma_area + alsa_rt->buffer_size 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,7 +212,12 @@ static void usb6fire_pcm_capture(struct pcm_substream *sub, struct pcm_urb *urb)
else else
frame_count = 0; 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 */ src++; /* skip leading 4 bytes of every packet */
total_length += urb->packets[i].length; total_length += urb->packets[i].length;
for (frame = 0; frame < frame_count; frame++) { for (frame = 0; frame < frame_count; frame++) {
...@@ -274,9 +247,18 @@ static void usb6fire_pcm_playback(struct pcm_substream *sub, ...@@ -274,9 +247,18 @@ static void usb6fire_pcm_playback(struct pcm_substream *sub,
* (alsa_rt->frame_bits >> 3)); * (alsa_rt->frame_bits >> 3));
u32 *src_end = (u32 *) (alsa_rt->dma_area + alsa_rt->buffer_size u32 *src_end = (u32 *) (alsa_rt->dma_area + alsa_rt->buffer_size
* (alsa_rt->frame_bits >> 3)); * (alsa_rt->frame_bits >> 3));
u32 *dest = (u32 *) urb->buffer; u32 *dest;
int bytes_per_frame = alsa_rt->channels << 2; 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++) { for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) {
/* at least 4 header bytes for valid packet. /* at least 4 header bytes for valid packet.
* after that: 32 bits per sample for analog channels */ * 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,7 +438,7 @@ static int usb6fire_pcm_close(struct snd_pcm_substream *alsa_sub)
/* all substreams closed? if so, stop streaming */ /* all substreams closed? if so, stop streaming */
if (!rt->playback.instance && !rt->capture.instance) { if (!rt->playback.instance && !rt->capture.instance) {
usb6fire_pcm_stream_stop(rt); usb6fire_pcm_stream_stop(rt);
rt->rate = -1; rt->rate = ARRAY_SIZE(rates);
} }
} }
mutex_unlock(&rt->stream_mutex); mutex_unlock(&rt->stream_mutex);
...@@ -480,7 +462,6 @@ static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub) ...@@ -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_runtime *rt = snd_pcm_substream_chip(alsa_sub);
struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub); struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub);
struct snd_pcm_runtime *alsa_rt = alsa_sub->runtime; struct snd_pcm_runtime *alsa_rt = alsa_sub->runtime;
int i;
int ret; int ret;
if (rt->panic) if (rt->panic)
...@@ -493,12 +474,10 @@ static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub) ...@@ -493,12 +474,10 @@ static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub)
sub->period_off = 0; sub->period_off = 0;
if (rt->stream_state == STREAM_DISABLED) { if (rt->stream_state == STREAM_DISABLED) {
for (i = 0; i < ARRAY_SIZE(rates); i++) for (rt->rate = 0; rt->rate < ARRAY_SIZE(rates); rt->rate++)
if (alsa_rt->rate == rates[i]) { if (alsa_rt->rate == rates[rt->rate])
rt->rate = i;
break; break;
} if (rt->rate == ARRAY_SIZE(rates)) {
if (i == ARRAY_SIZE(rates)) {
mutex_unlock(&rt->stream_mutex); mutex_unlock(&rt->stream_mutex);
snd_printk("invalid rate %d in prepare.\n", snd_printk("invalid rate %d in prepare.\n",
alsa_rt->rate); alsa_rt->rate);
...@@ -613,7 +592,7 @@ int __devinit usb6fire_pcm_init(struct sfire_chip *chip) ...@@ -613,7 +592,7 @@ int __devinit usb6fire_pcm_init(struct sfire_chip *chip)
rt->chip = chip; rt->chip = chip;
rt->stream_state = STREAM_DISABLED; rt->stream_state = STREAM_DISABLED;
rt->rate = -1; rt->rate = ARRAY_SIZE(rates);
init_waitqueue_head(&rt->stream_wait_queue); init_waitqueue_head(&rt->stream_wait_queue);
mutex_init(&rt->stream_mutex); mutex_init(&rt->stream_mutex);
......
...@@ -100,19 +100,17 @@ config SND_USB_US122L ...@@ -100,19 +100,17 @@ config SND_USB_US122L
config SND_USB_6FIRE config SND_USB_6FIRE
tristate "TerraTec DMX 6Fire USB" tristate "TerraTec DMX 6Fire USB"
depends on EXPERIMENTAL
select FW_LOADER select FW_LOADER
select BITREVERSE
select SND_RAWMIDI select SND_RAWMIDI
select SND_PCM select SND_PCM
help help
Say Y here to include support for TerraTec 6fire DMX USB interface. 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 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 after it has been coldstarted. An install script for the firmware
firmware loading for all devices. If you own such a device, and further help can be found at
you could start windows and let the windows driver upload http://sixfireusb.sourceforge.net
the firmware. As long as you do not unplug your device from power,
it should be usable.
endif # SND_USB endif # SND_USB
...@@ -104,6 +104,15 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id) ...@@ -104,6 +104,15 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id)
int err; int err;
unsigned char data; unsigned char data;
struct usb_device *dev = chip->dev; 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, err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, 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,7 +123,7 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id)
if (err < 0) { if (err < 0) {
snd_printk(KERN_WARNING "%s(): cannot get clock validity for id %d\n", snd_printk(KERN_WARNING "%s(): cannot get clock validity for id %d\n",
__func__, source_id); __func__, source_id);
return err; return 0;
} }
return !!data; return !!data;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#ifdef HW_CONST_DEBUG #ifdef HW_CONST_DEBUG
#define hwc_debug(fmt, args...) printk(KERN_DEBUG fmt, ##args) #define hwc_debug(fmt, args...) printk(KERN_DEBUG fmt, ##args)
#else #else
#define hwc_debug(fmt, args...) /**/ #define hwc_debug(fmt, args...) do { } while(0)
#endif #endif
#endif /* __USBAUDIO_DEBUG_H */ #endif /* __USBAUDIO_DEBUG_H */
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "helper.h" #include "helper.h"
#include "debug.h" #include "debug.h"
#include "clock.h" #include "clock.h"
#include "format.h"
/* /*
* parse the audio format type I descriptor * parse the audio format type I descriptor
......
...@@ -1097,11 +1097,13 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, ...@@ -1097,11 +1097,13 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
append_ctl_name(kctl, control == UAC_FU_MUTE ? append_ctl_name(kctl, control == UAC_FU_MUTE ?
" Switch" : " Volume"); " Switch" : " Volume");
if (control == UAC_FU_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); 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; break;
......
...@@ -61,6 +61,7 @@ static const struct rc_config { ...@@ -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, 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, 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, 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 */ { 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 ...@@ -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_sndctrlpipe(mixer->chip->dev, 0), 0x24,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
!value, 0, NULL, 0, 100); !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 else
err = snd_usb_ctl_msg(mixer->chip->dev, err = snd_usb_ctl_msg(mixer->chip->dev,
usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
...@@ -234,9 +241,13 @@ static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer) ...@@ -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 */ /* USB X-Fi S51 doesn't have a CMSS LED */
if ((mixer->chip->usb_id == USB_ID(0x041e, 0x3042)) && i == 0) if ((mixer->chip->usb_id == USB_ID(0x041e, 0x3042)) && i == 0)
continue; 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 */ if (i > 1 && /* Live24ext has 2 LEDs only */
(mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
mixer->chip->usb_id == USB_ID(0x041e, 0x3042) || mixer->chip->usb_id == USB_ID(0x041e, 0x3042) ||
mixer->chip->usb_id == USB_ID(0x041e, 0x30df) ||
mixer->chip->usb_id == USB_ID(0x041e, 0x3048))) mixer->chip->usb_id == USB_ID(0x041e, 0x3048)))
break; break;
err = snd_ctl_add(mixer->chip->card, err = snd_ctl_add(mixer->chip->card,
...@@ -512,6 +523,7 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) ...@@ -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, 0x3020):
case USB_ID(0x041e, 0x3040): case USB_ID(0x041e, 0x3040):
case USB_ID(0x041e, 0x3042): case USB_ID(0x041e, 0x3042):
case USB_ID(0x041e, 0x30df):
case USB_ID(0x041e, 0x3048): case USB_ID(0x041e, 0x3048):
err = snd_audigy2nx_controls_create(mixer); err = snd_audigy2nx_controls_create(mixer);
if (err < 0) if (err < 0)
......
...@@ -1651,6 +1651,32 @@ YAMAHA_DEVICE(0x7010, "UB99"), ...@@ -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 */ /* Guillemot devices */
{ {
...@@ -1953,7 +1979,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), ...@@ -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) { .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
/* .vendor_name = "M-Audio", */ /* .vendor_name = "M-Audio", */
/* .product_name = "Fast Track Ultra", */ /* .product_name = "Fast Track Ultra", */
...@@ -2020,7 +2046,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), ...@@ -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) { .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
/* .vendor_name = "M-Audio", */ /* .vendor_name = "M-Audio", */
/* .product_name = "Fast Track Ultra 8R", */ /* .product_name = "Fast Track Ultra 8R", */
...@@ -2179,6 +2205,17 @@ YAMAHA_DEVICE(0x7010, "UB99"), ...@@ -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 */ /* AKAI devices */
{ {
USB_DEVICE(0x09e8, 0x0062), USB_DEVICE(0x09e8, 0x0062),
...@@ -2331,6 +2368,12 @@ YAMAHA_DEVICE(0x7010, "UB99"), ...@@ -2331,6 +2368,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}, },
/* Native Instruments MK2 series */ /* Native Instruments MK2 series */
{
/* Komplete Audio 6 */
.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x17cc,
.idProduct = 0x1000,
},
{ {
/* Traktor Audio 6 */ /* Traktor Audio 6 */
.match_flags = USB_DEVICE_ID_MATCH_DEVICE, .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
......
...@@ -540,6 +540,7 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev, ...@@ -540,6 +540,7 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
/* Access Music VirusTI Desktop */ /* Access Music VirusTI Desktop */
return snd_usb_accessmusic_boot_quirk(dev); 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, 0x1010): /* Traktor Audio 6 */
case USB_ID(0x17cc, 0x1020): /* Traktor Audio 10 */ case USB_ID(0x17cc, 0x1020): /* Traktor Audio 10 */
return snd_usb_nativeinstruments_boot_quirk(dev); return snd_usb_nativeinstruments_boot_quirk(dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment