mirror of https://gitee.com/openkylin/linux.git
Merge branch 'topic/misc' into for-linus
This commit is contained in:
commit
79fc84c7e0
|
@ -300,6 +300,74 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
control correctly. If you have problems regarding this, try
|
||||
another ALSA compliant mixer (alsamixer works).
|
||||
|
||||
Module snd-azt1605
|
||||
------------------
|
||||
|
||||
Module for Aztech Sound Galaxy soundcards based on the Aztech AZT1605
|
||||
chipset.
|
||||
|
||||
port - port # for BASE (0x220,0x240,0x260,0x280)
|
||||
wss_port - port # for WSS (0x530,0x604,0xe80,0xf40)
|
||||
irq - IRQ # for WSS (7,9,10,11)
|
||||
dma1 - DMA # for WSS playback (0,1,3)
|
||||
dma2 - DMA # for WSS capture (0,1), -1 = disabled (default)
|
||||
mpu_port - port # for MPU-401 UART (0x300,0x330), -1 = disabled (default)
|
||||
mpu_irq - IRQ # for MPU-401 UART (3,5,7,9), -1 = disabled (default)
|
||||
fm_port - port # for OPL3 (0x388), -1 = disabled (default)
|
||||
|
||||
This module supports multiple cards. It does not support autoprobe: port,
|
||||
wss_port, irq and dma1 have to be specified. The other values are
|
||||
optional.
|
||||
|
||||
"port" needs to match the BASE ADDRESS jumper on the card (0x220 or 0x240)
|
||||
or the value stored in the card's EEPROM for cards that have an EEPROM and
|
||||
their "CONFIG MODE" jumper set to "EEPROM SETTING". The other values can
|
||||
be choosen freely from the options enumerated above.
|
||||
|
||||
If dma2 is specified and different from dma1, the card will operate in
|
||||
full-duplex mode. When dma1=3, only dma2=0 is valid and the only way to
|
||||
enable capture since only channels 0 and 1 are available for capture.
|
||||
|
||||
Generic settings are "port=0x220 wss_port=0x530 irq=10 dma1=1 dma2=0
|
||||
mpu_port=0x330 mpu_irq=9 fm_port=0x388".
|
||||
|
||||
Whatever IRQ and DMA channels you pick, be sure to reserve them for
|
||||
legacy ISA in your BIOS.
|
||||
|
||||
Module snd-azt2316
|
||||
------------------
|
||||
|
||||
Module for Aztech Sound Galaxy soundcards based on the Aztech AZT2316
|
||||
chipset.
|
||||
|
||||
port - port # for BASE (0x220,0x240,0x260,0x280)
|
||||
wss_port - port # for WSS (0x530,0x604,0xe80,0xf40)
|
||||
irq - IRQ # for WSS (7,9,10,11)
|
||||
dma1 - DMA # for WSS playback (0,1,3)
|
||||
dma2 - DMA # for WSS capture (0,1), -1 = disabled (default)
|
||||
mpu_port - port # for MPU-401 UART (0x300,0x330), -1 = disabled (default)
|
||||
mpu_irq - IRQ # for MPU-401 UART (5,7,9,10), -1 = disabled (default)
|
||||
fm_port - port # for OPL3 (0x388), -1 = disabled (default)
|
||||
|
||||
This module supports multiple cards. It does not support autoprobe: port,
|
||||
wss_port, irq and dma1 have to be specified. The other values are
|
||||
optional.
|
||||
|
||||
"port" needs to match the BASE ADDRESS jumper on the card (0x220 or 0x240)
|
||||
or the value stored in the card's EEPROM for cards that have an EEPROM and
|
||||
their "CONFIG MODE" jumper set to "EEPROM SETTING". The other values can
|
||||
be choosen freely from the options enumerated above.
|
||||
|
||||
If dma2 is specified and different from dma1, the card will operate in
|
||||
full-duplex mode. When dma1=3, only dma2=0 is valid and the only way to
|
||||
enable capture since only channels 0 and 1 are available for capture.
|
||||
|
||||
Generic settings are "port=0x220 wss_port=0x530 irq=10 dma1=1 dma2=0
|
||||
mpu_port=0x330 mpu_irq=9 fm_port=0x388".
|
||||
|
||||
Whatever IRQ and DMA channels you pick, be sure to reserve them for
|
||||
legacy ISA in your BIOS.
|
||||
|
||||
Module snd-aw2
|
||||
--------------
|
||||
|
||||
|
@ -1641,20 +1709,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
This card is also known as Audio Excel DSP 16 or Zoltrix AV302.
|
||||
|
||||
Module snd-sgalaxy
|
||||
------------------
|
||||
|
||||
Module for Aztech Sound Galaxy sound card.
|
||||
|
||||
sbport - Port # for SB16 interface (0x220,0x240)
|
||||
wssport - Port # for WSS interface (0x530,0xe80,0xf40,0x604)
|
||||
irq - IRQ # (7,9,10,11)
|
||||
dma1 - DMA #
|
||||
|
||||
This module supports multiple cards.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-sscape
|
||||
-----------------
|
||||
|
||||
|
|
|
@ -179,7 +179,7 @@ int snd_power_wait(struct snd_card *card, unsigned int power_state);
|
|||
#define snd_power_lock(card) do { (void)(card); } while (0)
|
||||
#define snd_power_unlock(card) do { (void)(card); } while (0)
|
||||
static inline int snd_power_wait(struct snd_card *card, unsigned int state) { return 0; }
|
||||
#define snd_power_get_state(card) SNDRV_CTL_POWER_D0
|
||||
#define snd_power_get_state(card) ({ (void)(card); SNDRV_CTL_POWER_D0; })
|
||||
#define snd_power_change_state(card, state) do { (void)(card); } while (0)
|
||||
|
||||
#endif /* CONFIG_PM */
|
||||
|
|
|
@ -438,6 +438,8 @@
|
|||
#define CCCA_CURRADDR_MASK 0x00ffffff /* Current address of the selected channel */
|
||||
#define CCCA_CURRADDR 0x18000008
|
||||
|
||||
/* undefine CCR to avoid conflict with the definition for SH */
|
||||
#undef CCR
|
||||
#define CCR 0x09 /* Cache control register */
|
||||
#define CCR_CACHEINVALIDSIZE 0x07190009
|
||||
#define CCR_CACHEINVALIDSIZE_MASK 0xfe000000 /* Number of invalid samples cache for this channel */
|
||||
|
|
|
@ -47,6 +47,9 @@ enum snd_jack_types {
|
|||
SND_JACK_BTN_0 = 0x4000,
|
||||
SND_JACK_BTN_1 = 0x2000,
|
||||
SND_JACK_BTN_2 = 0x1000,
|
||||
SND_JACK_BTN_3 = 0x0800,
|
||||
SND_JACK_BTN_4 = 0x0400,
|
||||
SND_JACK_BTN_5 = 0x0200,
|
||||
};
|
||||
|
||||
struct snd_jack {
|
||||
|
@ -55,7 +58,7 @@ struct snd_jack {
|
|||
int type;
|
||||
const char *id;
|
||||
char name[100];
|
||||
unsigned int key[3]; /* Keep in sync with definitions above */
|
||||
unsigned int key[6]; /* Keep in sync with definitions above */
|
||||
void *private_data;
|
||||
void (*private_free)(struct snd_jack *);
|
||||
};
|
||||
|
|
|
@ -278,6 +278,7 @@ struct snd_pcm_runtime {
|
|||
snd_pcm_uframes_t hw_ptr_base; /* Position at buffer restart */
|
||||
snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time */
|
||||
unsigned long hw_ptr_jiffies; /* Time when hw_ptr is updated */
|
||||
unsigned long hw_ptr_buffer_jiffies; /* buffer time in jiffies */
|
||||
snd_pcm_sframes_t delay; /* extra delay; typically FIFO size */
|
||||
|
||||
/* -- HW params -- */
|
||||
|
|
|
@ -607,11 +607,16 @@ card_id_store_attr(struct device *dev, struct device_attribute *attr,
|
|||
return -EEXIST;
|
||||
}
|
||||
for (idx = 0; idx < snd_ecards_limit; idx++) {
|
||||
if (snd_cards[idx] && !strcmp(snd_cards[idx]->id, buf1))
|
||||
goto __exist;
|
||||
if (snd_cards[idx] && !strcmp(snd_cards[idx]->id, buf1)) {
|
||||
if (card == snd_cards[idx])
|
||||
goto __ok;
|
||||
else
|
||||
goto __exist;
|
||||
}
|
||||
}
|
||||
strcpy(card->id, buf1);
|
||||
snd_info_card_id_change(card);
|
||||
__ok:
|
||||
mutex_unlock(&snd_card_mutex);
|
||||
|
||||
return count;
|
||||
|
|
|
@ -77,7 +77,7 @@ static int snd_mixer_oss_release(struct inode *inode, struct file *file)
|
|||
struct snd_mixer_oss_file *fmixer;
|
||||
|
||||
if (file->private_data) {
|
||||
fmixer = (struct snd_mixer_oss_file *) file->private_data;
|
||||
fmixer = file->private_data;
|
||||
module_put(fmixer->card->module);
|
||||
snd_card_file_remove(fmixer->card, file);
|
||||
kfree(fmixer);
|
||||
|
@ -368,7 +368,7 @@ static int snd_mixer_oss_ioctl1(struct snd_mixer_oss_file *fmixer, unsigned int
|
|||
|
||||
static long snd_mixer_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
return snd_mixer_oss_ioctl1((struct snd_mixer_oss_file *) file->private_data, cmd, arg);
|
||||
return snd_mixer_oss_ioctl1(file->private_data, cmd, arg);
|
||||
}
|
||||
|
||||
int snd_mixer_oss_ioctl_card(struct snd_card *card, unsigned int cmd, unsigned long arg)
|
||||
|
@ -582,7 +582,7 @@ static int snd_mixer_oss_get_volume1(struct snd_mixer_oss_file *fmixer,
|
|||
struct snd_mixer_oss_slot *pslot,
|
||||
int *left, int *right)
|
||||
{
|
||||
struct slot *slot = (struct slot *)pslot->private_data;
|
||||
struct slot *slot = pslot->private_data;
|
||||
|
||||
*left = *right = 100;
|
||||
if (slot->present & SNDRV_MIXER_OSS_PRESENT_PVOLUME) {
|
||||
|
@ -618,8 +618,10 @@ static void snd_mixer_oss_put_volume1_vol(struct snd_mixer_oss_file *fmixer,
|
|||
if (numid == ID_UNKNOWN)
|
||||
return;
|
||||
down_read(&card->controls_rwsem);
|
||||
if ((kctl = snd_ctl_find_numid(card, numid)) == NULL)
|
||||
if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) {
|
||||
up_read(&card->controls_rwsem);
|
||||
return;
|
||||
}
|
||||
uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
|
||||
uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
|
||||
if (uinfo == NULL || uctl == NULL)
|
||||
|
@ -658,7 +660,7 @@ static void snd_mixer_oss_put_volume1_sw(struct snd_mixer_oss_file *fmixer,
|
|||
return;
|
||||
down_read(&card->controls_rwsem);
|
||||
if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) {
|
||||
up_read(&fmixer->card->controls_rwsem);
|
||||
up_read(&card->controls_rwsem);
|
||||
return;
|
||||
}
|
||||
uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
|
||||
|
@ -691,7 +693,7 @@ static int snd_mixer_oss_put_volume1(struct snd_mixer_oss_file *fmixer,
|
|||
struct snd_mixer_oss_slot *pslot,
|
||||
int left, int right)
|
||||
{
|
||||
struct slot *slot = (struct slot *)pslot->private_data;
|
||||
struct slot *slot = pslot->private_data;
|
||||
|
||||
if (slot->present & SNDRV_MIXER_OSS_PRESENT_PVOLUME) {
|
||||
snd_mixer_oss_put_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PVOLUME], left, right);
|
||||
|
@ -740,7 +742,7 @@ static int snd_mixer_oss_get_recsrc1_sw(struct snd_mixer_oss_file *fmixer,
|
|||
struct snd_mixer_oss_slot *pslot,
|
||||
int *active)
|
||||
{
|
||||
struct slot *slot = (struct slot *)pslot->private_data;
|
||||
struct slot *slot = pslot->private_data;
|
||||
int left, right;
|
||||
|
||||
left = right = 1;
|
||||
|
@ -753,7 +755,7 @@ static int snd_mixer_oss_get_recsrc1_route(struct snd_mixer_oss_file *fmixer,
|
|||
struct snd_mixer_oss_slot *pslot,
|
||||
int *active)
|
||||
{
|
||||
struct slot *slot = (struct slot *)pslot->private_data;
|
||||
struct slot *slot = pslot->private_data;
|
||||
int left, right;
|
||||
|
||||
left = right = 1;
|
||||
|
@ -766,7 +768,7 @@ static int snd_mixer_oss_put_recsrc1_sw(struct snd_mixer_oss_file *fmixer,
|
|||
struct snd_mixer_oss_slot *pslot,
|
||||
int active)
|
||||
{
|
||||
struct slot *slot = (struct slot *)pslot->private_data;
|
||||
struct slot *slot = pslot->private_data;
|
||||
|
||||
snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CSWITCH], active, active, 0);
|
||||
return 0;
|
||||
|
@ -776,7 +778,7 @@ static int snd_mixer_oss_put_recsrc1_route(struct snd_mixer_oss_file *fmixer,
|
|||
struct snd_mixer_oss_slot *pslot,
|
||||
int active)
|
||||
{
|
||||
struct slot *slot = (struct slot *)pslot->private_data;
|
||||
struct slot *slot = pslot->private_data;
|
||||
|
||||
snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CROUTE], active, active, 1);
|
||||
return 0;
|
||||
|
@ -797,7 +799,7 @@ static int snd_mixer_oss_get_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned
|
|||
uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
|
||||
if (uinfo == NULL || uctl == NULL) {
|
||||
err = -ENOMEM;
|
||||
goto __unlock;
|
||||
goto __free_only;
|
||||
}
|
||||
down_read(&card->controls_rwsem);
|
||||
kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
|
||||
|
@ -813,7 +815,7 @@ static int snd_mixer_oss_get_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned
|
|||
if (!(mixer->mask_recsrc & (1 << idx)))
|
||||
continue;
|
||||
pslot = &mixer->slots[idx];
|
||||
slot = (struct slot *)pslot->private_data;
|
||||
slot = pslot->private_data;
|
||||
if (slot->signature != SNDRV_MIXER_OSS_SIGNATURE)
|
||||
continue;
|
||||
if (!(slot->present & SNDRV_MIXER_OSS_PRESENT_CAPTURE))
|
||||
|
@ -826,6 +828,7 @@ static int snd_mixer_oss_get_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned
|
|||
err = 0;
|
||||
__unlock:
|
||||
up_read(&card->controls_rwsem);
|
||||
__free_only:
|
||||
kfree(uctl);
|
||||
kfree(uinfo);
|
||||
return err;
|
||||
|
@ -847,7 +850,7 @@ static int snd_mixer_oss_put_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned
|
|||
uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
|
||||
if (uinfo == NULL || uctl == NULL) {
|
||||
err = -ENOMEM;
|
||||
goto __unlock;
|
||||
goto __free_only;
|
||||
}
|
||||
down_read(&card->controls_rwsem);
|
||||
kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
|
||||
|
@ -861,7 +864,7 @@ static int snd_mixer_oss_put_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned
|
|||
if (!(mixer->mask_recsrc & (1 << idx)))
|
||||
continue;
|
||||
pslot = &mixer->slots[idx];
|
||||
slot = (struct slot *)pslot->private_data;
|
||||
slot = pslot->private_data;
|
||||
if (slot->signature != SNDRV_MIXER_OSS_SIGNATURE)
|
||||
continue;
|
||||
if (!(slot->present & SNDRV_MIXER_OSS_PRESENT_CAPTURE))
|
||||
|
@ -880,6 +883,7 @@ static int snd_mixer_oss_put_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned
|
|||
err = 0;
|
||||
__unlock:
|
||||
up_read(&card->controls_rwsem);
|
||||
__free_only:
|
||||
kfree(uctl);
|
||||
kfree(uinfo);
|
||||
return err;
|
||||
|
@ -925,7 +929,7 @@ static int snd_mixer_oss_build_test(struct snd_mixer_oss *mixer, struct slot *sl
|
|||
|
||||
static void snd_mixer_oss_slot_free(struct snd_mixer_oss_slot *chn)
|
||||
{
|
||||
struct slot *p = (struct slot *)chn->private_data;
|
||||
struct slot *p = chn->private_data;
|
||||
if (p) {
|
||||
if (p->allocated && p->assigned) {
|
||||
kfree(p->assigned->name);
|
||||
|
|
|
@ -364,8 +364,7 @@ static void snd_pcm_stream_proc_info_read(struct snd_info_entry *entry,
|
|||
static void snd_pcm_substream_proc_info_read(struct snd_info_entry *entry,
|
||||
struct snd_info_buffer *buffer)
|
||||
{
|
||||
snd_pcm_proc_info_read((struct snd_pcm_substream *)entry->private_data,
|
||||
buffer);
|
||||
snd_pcm_proc_info_read(entry->private_data, buffer);
|
||||
}
|
||||
|
||||
static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry,
|
||||
|
|
|
@ -334,11 +334,15 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
|
|||
/* delta = "expected next hw_ptr" for in_interrupt != 0 */
|
||||
delta = runtime->hw_ptr_interrupt + runtime->period_size;
|
||||
if (delta > new_hw_ptr) {
|
||||
hw_base += runtime->buffer_size;
|
||||
if (hw_base >= runtime->boundary)
|
||||
hw_base = 0;
|
||||
new_hw_ptr = hw_base + pos;
|
||||
goto __delta;
|
||||
/* check for double acknowledged interrupts */
|
||||
hdelta = jiffies - runtime->hw_ptr_jiffies;
|
||||
if (hdelta > runtime->hw_ptr_buffer_jiffies/2) {
|
||||
hw_base += runtime->buffer_size;
|
||||
if (hw_base >= runtime->boundary)
|
||||
hw_base = 0;
|
||||
new_hw_ptr = hw_base + pos;
|
||||
goto __delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* new_hw_ptr might be lower than old_hw_ptr in case when */
|
||||
|
|
|
@ -142,7 +142,7 @@ int snd_pcm_info_user(struct snd_pcm_substream *substream,
|
|||
|
||||
#ifdef RULES_DEBUG
|
||||
#define HW_PARAM(v) [SNDRV_PCM_HW_PARAM_##v] = #v
|
||||
char *snd_pcm_hw_param_names[] = {
|
||||
static const char * const snd_pcm_hw_param_names[] = {
|
||||
HW_PARAM(ACCESS),
|
||||
HW_PARAM(FORMAT),
|
||||
HW_PARAM(SUBFORMAT),
|
||||
|
@ -864,6 +864,8 @@ static void snd_pcm_post_start(struct snd_pcm_substream *substream, int state)
|
|||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
snd_pcm_trigger_tstamp(substream);
|
||||
runtime->hw_ptr_jiffies = jiffies;
|
||||
runtime->hw_ptr_buffer_jiffies = (runtime->buffer_size * HZ) /
|
||||
runtime->rate;
|
||||
runtime->status->state = state;
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
|
||||
runtime->silence_size > 0)
|
||||
|
|
|
@ -74,6 +74,25 @@ config SND_DUMMY
|
|||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-dummy.
|
||||
|
||||
config SND_ALOOP
|
||||
tristate "Generic loopback driver (PCM)"
|
||||
select SND_PCM
|
||||
help
|
||||
Say 'Y' or 'M' to include support for the PCM loopback device.
|
||||
This module returns played samples back to the user space using
|
||||
the standard ALSA PCM device. The devices are routed 0->1 and
|
||||
1->0, where first number is the playback PCM device and second
|
||||
number is the capture device. Module creates two PCM devices and
|
||||
configured number of substreams (see the pcm_substreams module
|
||||
parameter).
|
||||
|
||||
The looback device allow time sychronization with an external
|
||||
timing source using the time shift universal control (+-20%
|
||||
of system time).
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-aloop.
|
||||
|
||||
config SND_VIRMIDI
|
||||
tristate "Virtual MIDI soundcard"
|
||||
depends on SND_SEQUENCER
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#
|
||||
|
||||
snd-dummy-objs := dummy.o
|
||||
snd-aloop-objs := aloop.o
|
||||
snd-mtpav-objs := mtpav.o
|
||||
snd-mts64-objs := mts64.o
|
||||
snd-portman2x4-objs := portman2x4.o
|
||||
|
@ -13,6 +14,7 @@ snd-ml403-ac97cr-objs := ml403-ac97cr.o pcm-indirect2.o
|
|||
|
||||
# Toplevel Module Dependency
|
||||
obj-$(CONFIG_SND_DUMMY) += snd-dummy.o
|
||||
obj-$(CONFIG_SND_ALOOP) += snd-aloop.o
|
||||
obj-$(CONFIG_SND_VIRMIDI) += snd-virmidi.o
|
||||
obj-$(CONFIG_SND_SERIAL_U16550) += snd-serial-u16550.o
|
||||
obj-$(CONFIG_SND_MTPAV) += snd-mtpav.o
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -94,7 +94,7 @@ static int __devinit snd_virmidi_probe(struct platform_device *devptr)
|
|||
sizeof(struct snd_card_virmidi), &card);
|
||||
if (err < 0)
|
||||
return err;
|
||||
vmidi = (struct snd_card_virmidi *)card->private_data;
|
||||
vmidi = card->private_data;
|
||||
vmidi->card = card;
|
||||
|
||||
if (midi_devs[dev] > MAX_MIDI_DEVICES) {
|
||||
|
|
|
@ -878,7 +878,7 @@ static int build_deemphasis(struct snd_akm4xxx *ak, int num_emphs)
|
|||
static void proc_regs_read(struct snd_info_entry *entry,
|
||||
struct snd_info_buffer *buffer)
|
||||
{
|
||||
struct snd_akm4xxx *ak = (struct snd_akm4xxx *)entry->private_data;
|
||||
struct snd_akm4xxx *ak = entry->private_data;
|
||||
int reg, val, chip;
|
||||
for (chip = 0; chip < ak->num_chips; chip++) {
|
||||
for (reg = 0; reg < ak->total_regs; reg++) {
|
||||
|
|
|
@ -77,6 +77,32 @@ config SND_ALS100
|
|||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-als100.
|
||||
|
||||
config SND_AZT1605
|
||||
tristate "Aztech AZT1605 Driver"
|
||||
depends on SND
|
||||
select SND_WSS_LIB
|
||||
select SND_MPU401_UART
|
||||
select SND_OPL3_LIB
|
||||
help
|
||||
Say Y here to include support for Aztech Sound Galaxy cards
|
||||
based on the AZT1605 chipset.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-azt1605.
|
||||
|
||||
config SND_AZT2316
|
||||
tristate "Aztech AZT2316 Driver"
|
||||
depends on SND
|
||||
select SND_WSS_LIB
|
||||
select SND_MPU401_UART
|
||||
select SND_OPL3_LIB
|
||||
help
|
||||
Say Y here to include support for Aztech Sound Galaxy cards
|
||||
based on the AZT2316 chipset.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-azt2316.
|
||||
|
||||
config SND_AZT2320
|
||||
tristate "Aztech Systems AZT2320"
|
||||
depends on PNP
|
||||
|
@ -351,16 +377,6 @@ config SND_SB16_CSP
|
|||
coprocessor can do variable tasks like various compression and
|
||||
decompression algorithms.
|
||||
|
||||
config SND_SGALAXY
|
||||
tristate "Aztech Sound Galaxy"
|
||||
select SND_WSS_LIB
|
||||
help
|
||||
Say Y here to include support for Aztech Sound Galaxy
|
||||
soundcards.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-sgalaxy.
|
||||
|
||||
config SND_SSCAPE
|
||||
tristate "Ensoniq SoundScape driver"
|
||||
select SND_MPU401_UART
|
||||
|
|
|
@ -10,7 +10,6 @@ snd-cmi8330-objs := cmi8330.o
|
|||
snd-es18xx-objs := es18xx.o
|
||||
snd-opl3sa2-objs := opl3sa2.o
|
||||
snd-sc6000-objs := sc6000.o
|
||||
snd-sgalaxy-objs := sgalaxy.o
|
||||
snd-sscape-objs := sscape.o
|
||||
|
||||
# Toplevel Module Dependency
|
||||
|
@ -21,8 +20,7 @@ obj-$(CONFIG_SND_CMI8330) += snd-cmi8330.o
|
|||
obj-$(CONFIG_SND_ES18XX) += snd-es18xx.o
|
||||
obj-$(CONFIG_SND_OPL3SA2) += snd-opl3sa2.o
|
||||
obj-$(CONFIG_SND_SC6000) += snd-sc6000.o
|
||||
obj-$(CONFIG_SND_SGALAXY) += snd-sgalaxy.o
|
||||
obj-$(CONFIG_SND_SSCAPE) += snd-sscape.o
|
||||
|
||||
obj-$(CONFIG_SND) += ad1816a/ ad1848/ cs423x/ es1688/ gus/ msnd/ opti9xx/ \
|
||||
obj-$(CONFIG_SND) += ad1816a/ ad1848/ cs423x/ es1688/ galaxy/ gus/ msnd/ opti9xx/ \
|
||||
sb/ wavefront/ wss/
|
||||
|
|
|
@ -162,7 +162,7 @@ static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard
|
|||
sizeof(struct snd_card_ad1816a), &card);
|
||||
if (error < 0)
|
||||
return error;
|
||||
acard = (struct snd_card_ad1816a *)card->private_data;
|
||||
acard = card->private_data;
|
||||
|
||||
if ((error = snd_card_ad1816a_pnp(dev, acard, pcard, pid))) {
|
||||
snd_card_free(card);
|
||||
|
|
|
@ -188,7 +188,7 @@ static int __devinit snd_card_azt2320_probe(int dev,
|
|||
sizeof(struct snd_card_azt2320), &card);
|
||||
if (error < 0)
|
||||
return error;
|
||||
acard = (struct snd_card_azt2320 *)card->private_data;
|
||||
acard = card->private_data;
|
||||
|
||||
if ((error = snd_card_azt2320_pnp(dev, acard, pcard, pid))) {
|
||||
snd_card_free(card);
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
#
|
||||
# Makefile for ALSA
|
||||
# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
|
||||
#
|
||||
|
||||
snd-azt1605-objs := azt1605.o
|
||||
snd-azt2316-objs := azt2316.o
|
||||
|
||||
obj-$(CONFIG_SND_AZT1605) += snd-azt1605.o
|
||||
obj-$(CONFIG_SND_AZT2316) += snd-azt2316.o
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Aztech AZT1605 Driver
|
||||
* Copyright (C) 2007,2010 Rene Herman
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#define AZT1605
|
||||
|
||||
#define CRD_NAME "Aztech AZT1605"
|
||||
#define DRV_NAME "AZT1605"
|
||||
#define DEV_NAME "azt1605"
|
||||
|
||||
#define GALAXY_DSP_MAJOR 2
|
||||
#define GALAXY_DSP_MINOR 1
|
||||
|
||||
#define GALAXY_CONFIG_SIZE 3
|
||||
|
||||
/*
|
||||
* 24-bit config register
|
||||
*/
|
||||
|
||||
#define GALAXY_CONFIG_SBA_220 (0 << 0)
|
||||
#define GALAXY_CONFIG_SBA_240 (1 << 0)
|
||||
#define GALAXY_CONFIG_SBA_260 (2 << 0)
|
||||
#define GALAXY_CONFIG_SBA_280 (3 << 0)
|
||||
#define GALAXY_CONFIG_SBA_MASK GALAXY_CONFIG_SBA_280
|
||||
|
||||
#define GALAXY_CONFIG_MPUA_300 (0 << 2)
|
||||
#define GALAXY_CONFIG_MPUA_330 (1 << 2)
|
||||
|
||||
#define GALAXY_CONFIG_MPU_ENABLE (1 << 3)
|
||||
|
||||
#define GALAXY_CONFIG_GAME_ENABLE (1 << 4)
|
||||
|
||||
#define GALAXY_CONFIG_CD_PANASONIC (1 << 5)
|
||||
#define GALAXY_CONFIG_CD_MITSUMI (1 << 6)
|
||||
#define GALAXY_CONFIG_CD_MASK (\
|
||||
GALAXY_CONFIG_CD_PANASONIC | GALAXY_CONFIG_CD_MITSUMI)
|
||||
|
||||
#define GALAXY_CONFIG_UNUSED (1 << 7)
|
||||
#define GALAXY_CONFIG_UNUSED_MASK GALAXY_CONFIG_UNUSED
|
||||
|
||||
#define GALAXY_CONFIG_SBIRQ_2 (1 << 8)
|
||||
#define GALAXY_CONFIG_SBIRQ_3 (1 << 9)
|
||||
#define GALAXY_CONFIG_SBIRQ_5 (1 << 10)
|
||||
#define GALAXY_CONFIG_SBIRQ_7 (1 << 11)
|
||||
|
||||
#define GALAXY_CONFIG_MPUIRQ_2 (1 << 12)
|
||||
#define GALAXY_CONFIG_MPUIRQ_3 (1 << 13)
|
||||
#define GALAXY_CONFIG_MPUIRQ_5 (1 << 14)
|
||||
#define GALAXY_CONFIG_MPUIRQ_7 (1 << 15)
|
||||
|
||||
#define GALAXY_CONFIG_WSSA_530 (0 << 16)
|
||||
#define GALAXY_CONFIG_WSSA_604 (1 << 16)
|
||||
#define GALAXY_CONFIG_WSSA_E80 (2 << 16)
|
||||
#define GALAXY_CONFIG_WSSA_F40 (3 << 16)
|
||||
|
||||
#define GALAXY_CONFIG_WSS_ENABLE (1 << 18)
|
||||
|
||||
#define GALAXY_CONFIG_CDIRQ_11 (1 << 19)
|
||||
#define GALAXY_CONFIG_CDIRQ_12 (1 << 20)
|
||||
#define GALAXY_CONFIG_CDIRQ_15 (1 << 21)
|
||||
#define GALAXY_CONFIG_CDIRQ_MASK (\
|
||||
GALAXY_CONFIG_CDIRQ_11 | GALAXY_CONFIG_CDIRQ_12 |\
|
||||
GALAXY_CONFIG_CDIRQ_15)
|
||||
|
||||
#define GALAXY_CONFIG_CDDMA_DISABLE (0 << 22)
|
||||
#define GALAXY_CONFIG_CDDMA_0 (1 << 22)
|
||||
#define GALAXY_CONFIG_CDDMA_1 (2 << 22)
|
||||
#define GALAXY_CONFIG_CDDMA_3 (3 << 22)
|
||||
#define GALAXY_CONFIG_CDDMA_MASK GALAXY_CONFIG_CDDMA_3
|
||||
|
||||
#define GALAXY_CONFIG_MASK (\
|
||||
GALAXY_CONFIG_SBA_MASK | GALAXY_CONFIG_CD_MASK |\
|
||||
GALAXY_CONFIG_UNUSED_MASK | GALAXY_CONFIG_CDIRQ_MASK |\
|
||||
GALAXY_CONFIG_CDDMA_MASK)
|
||||
|
||||
#include "galaxy.c"
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Aztech AZT2316 Driver
|
||||
* Copyright (C) 2007,2010 Rene Herman
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#define AZT2316
|
||||
|
||||
#define CRD_NAME "Aztech AZT2316"
|
||||
#define DRV_NAME "AZT2316"
|
||||
#define DEV_NAME "azt2316"
|
||||
|
||||
#define GALAXY_DSP_MAJOR 3
|
||||
#define GALAXY_DSP_MINOR 1
|
||||
|
||||
#define GALAXY_CONFIG_SIZE 4
|
||||
|
||||
/*
|
||||
* 32-bit config register
|
||||
*/
|
||||
|
||||
#define GALAXY_CONFIG_SBA_220 (0 << 0)
|
||||
#define GALAXY_CONFIG_SBA_240 (1 << 0)
|
||||
#define GALAXY_CONFIG_SBA_260 (2 << 0)
|
||||
#define GALAXY_CONFIG_SBA_280 (3 << 0)
|
||||
#define GALAXY_CONFIG_SBA_MASK GALAXY_CONFIG_SBA_280
|
||||
|
||||
#define GALAXY_CONFIG_SBIRQ_2 (1 << 2)
|
||||
#define GALAXY_CONFIG_SBIRQ_5 (1 << 3)
|
||||
#define GALAXY_CONFIG_SBIRQ_7 (1 << 4)
|
||||
#define GALAXY_CONFIG_SBIRQ_10 (1 << 5)
|
||||
|
||||
#define GALAXY_CONFIG_SBDMA_DISABLE (0 << 6)
|
||||
#define GALAXY_CONFIG_SBDMA_0 (1 << 6)
|
||||
#define GALAXY_CONFIG_SBDMA_1 (2 << 6)
|
||||
#define GALAXY_CONFIG_SBDMA_3 (3 << 6)
|
||||
|
||||
#define GALAXY_CONFIG_WSSA_530 (0 << 8)
|
||||
#define GALAXY_CONFIG_WSSA_604 (1 << 8)
|
||||
#define GALAXY_CONFIG_WSSA_E80 (2 << 8)
|
||||
#define GALAXY_CONFIG_WSSA_F40 (3 << 8)
|
||||
|
||||
#define GALAXY_CONFIG_WSS_ENABLE (1 << 10)
|
||||
|
||||
#define GALAXY_CONFIG_GAME_ENABLE (1 << 11)
|
||||
|
||||
#define GALAXY_CONFIG_MPUA_300 (0 << 12)
|
||||
#define GALAXY_CONFIG_MPUA_330 (1 << 12)
|
||||
|
||||
#define GALAXY_CONFIG_MPU_ENABLE (1 << 13)
|
||||
|
||||
#define GALAXY_CONFIG_CDA_310 (0 << 14)
|
||||
#define GALAXY_CONFIG_CDA_320 (1 << 14)
|
||||
#define GALAXY_CONFIG_CDA_340 (2 << 14)
|
||||
#define GALAXY_CONFIG_CDA_350 (3 << 14)
|
||||
#define GALAXY_CONFIG_CDA_MASK GALAXY_CONFIG_CDA_350
|
||||
|
||||
#define GALAXY_CONFIG_CD_DISABLE (0 << 16)
|
||||
#define GALAXY_CONFIG_CD_PANASONIC (1 << 16)
|
||||
#define GALAXY_CONFIG_CD_SONY (2 << 16)
|
||||
#define GALAXY_CONFIG_CD_MITSUMI (3 << 16)
|
||||
#define GALAXY_CONFIG_CD_AZTECH (4 << 16)
|
||||
#define GALAXY_CONFIG_CD_UNUSED_5 (5 << 16)
|
||||
#define GALAXY_CONFIG_CD_UNUSED_6 (6 << 16)
|
||||
#define GALAXY_CONFIG_CD_UNUSED_7 (7 << 16)
|
||||
#define GALAXY_CONFIG_CD_MASK GALAXY_CONFIG_CD_UNUSED_7
|
||||
|
||||
#define GALAXY_CONFIG_CDDMA8_DISABLE (0 << 20)
|
||||
#define GALAXY_CONFIG_CDDMA8_0 (1 << 20)
|
||||
#define GALAXY_CONFIG_CDDMA8_1 (2 << 20)
|
||||
#define GALAXY_CONFIG_CDDMA8_3 (3 << 20)
|
||||
#define GALAXY_CONFIG_CDDMA8_MASK GALAXY_CONFIG_CDDMA8_3
|
||||
|
||||
#define GALAXY_CONFIG_CDDMA16_DISABLE (0 << 22)
|
||||
#define GALAXY_CONFIG_CDDMA16_5 (1 << 22)
|
||||
#define GALAXY_CONFIG_CDDMA16_6 (2 << 22)
|
||||
#define GALAXY_CONFIG_CDDMA16_7 (3 << 22)
|
||||
#define GALAXY_CONFIG_CDDMA16_MASK GALAXY_CONFIG_CDDMA16_7
|
||||
|
||||
#define GALAXY_CONFIG_MPUIRQ_2 (1 << 24)
|
||||
#define GALAXY_CONFIG_MPUIRQ_5 (1 << 25)
|
||||
#define GALAXY_CONFIG_MPUIRQ_7 (1 << 26)
|
||||
#define GALAXY_CONFIG_MPUIRQ_10 (1 << 27)
|
||||
|
||||
#define GALAXY_CONFIG_CDIRQ_5 (1 << 28)
|
||||
#define GALAXY_CONFIG_CDIRQ_11 (1 << 29)
|
||||
#define GALAXY_CONFIG_CDIRQ_12 (1 << 30)
|
||||
#define GALAXY_CONFIG_CDIRQ_15 (1 << 31)
|
||||
#define GALAXY_CONFIG_CDIRQ_MASK (\
|
||||
GALAXY_CONFIG_CDIRQ_5 | GALAXY_CONFIG_CDIRQ_11 |\
|
||||
GALAXY_CONFIG_CDIRQ_12 | GALAXY_CONFIG_CDIRQ_15)
|
||||
|
||||
#define GALAXY_CONFIG_MASK (\
|
||||
GALAXY_CONFIG_SBA_MASK | GALAXY_CONFIG_CDA_MASK |\
|
||||
GALAXY_CONFIG_CD_MASK | GALAXY_CONFIG_CDDMA16_MASK |\
|
||||
GALAXY_CONFIG_CDDMA8_MASK | GALAXY_CONFIG_CDIRQ_MASK)
|
||||
|
||||
#include "galaxy.c"
|
|
@ -0,0 +1,652 @@
|
|||
/*
|
||||
* Aztech AZT1605/AZT2316 Driver
|
||||
* Copyright (C) 2007,2010 Rene Herman
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/isa.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/processor.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/wss.h>
|
||||
#include <sound/mpu401.h>
|
||||
#include <sound/opl3.h>
|
||||
|
||||
MODULE_DESCRIPTION(CRD_NAME);
|
||||
MODULE_AUTHOR("Rene Herman");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
|
||||
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
|
||||
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;
|
||||
|
||||
module_param_array(index, int, NULL, 0444);
|
||||
MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard.");
|
||||
module_param_array(id, charp, NULL, 0444);
|
||||
MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
|
||||
module_param_array(enable, bool, NULL, 0444);
|
||||
MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
|
||||
|
||||
static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
|
||||
static long wss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
|
||||
static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
|
||||
static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
|
||||
static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
|
||||
static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
|
||||
static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
|
||||
static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
|
||||
|
||||
module_param_array(port, long, NULL, 0444);
|
||||
MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
|
||||
module_param_array(wss_port, long, NULL, 0444);
|
||||
MODULE_PARM_DESC(wss_port, "WSS port # for " CRD_NAME " driver.");
|
||||
module_param_array(mpu_port, long, NULL, 0444);
|
||||
MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver.");
|
||||
module_param_array(fm_port, long, NULL, 0444);
|
||||
MODULE_PARM_DESC(fm_port, "FM port # for " CRD_NAME " driver.");
|
||||
module_param_array(irq, int, NULL, 0444);
|
||||
MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver.");
|
||||
module_param_array(mpu_irq, int, NULL, 0444);
|
||||
MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver.");
|
||||
module_param_array(dma1, int, NULL, 0444);
|
||||
MODULE_PARM_DESC(dma1, "Playback DMA # for " CRD_NAME " driver.");
|
||||
module_param_array(dma2, int, NULL, 0444);
|
||||
MODULE_PARM_DESC(dma2, "Capture DMA # for " CRD_NAME " driver.");
|
||||
|
||||
/*
|
||||
* Generic SB DSP support routines
|
||||
*/
|
||||
|
||||
#define DSP_PORT_RESET 0x6
|
||||
#define DSP_PORT_READ 0xa
|
||||
#define DSP_PORT_COMMAND 0xc
|
||||
#define DSP_PORT_STATUS 0xc
|
||||
#define DSP_PORT_DATA_AVAIL 0xe
|
||||
|
||||
#define DSP_SIGNATURE 0xaa
|
||||
|
||||
#define DSP_COMMAND_GET_VERSION 0xe1
|
||||
|
||||
static int __devinit dsp_get_byte(void __iomem *port, u8 *val)
|
||||
{
|
||||
int loops = 1000;
|
||||
|
||||
while (!(ioread8(port + DSP_PORT_DATA_AVAIL) & 0x80)) {
|
||||
if (!loops--)
|
||||
return -EIO;
|
||||
cpu_relax();
|
||||
}
|
||||
*val = ioread8(port + DSP_PORT_READ);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit dsp_reset(void __iomem *port)
|
||||
{
|
||||
u8 val;
|
||||
|
||||
iowrite8(1, port + DSP_PORT_RESET);
|
||||
udelay(10);
|
||||
iowrite8(0, port + DSP_PORT_RESET);
|
||||
|
||||
if (dsp_get_byte(port, &val) < 0 || val != DSP_SIGNATURE)
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit dsp_command(void __iomem *port, u8 cmd)
|
||||
{
|
||||
int loops = 1000;
|
||||
|
||||
while (ioread8(port + DSP_PORT_STATUS) & 0x80) {
|
||||
if (!loops--)
|
||||
return -EIO;
|
||||
cpu_relax();
|
||||
}
|
||||
iowrite8(cmd, port + DSP_PORT_COMMAND);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit dsp_get_version(void __iomem *port, u8 *major, u8 *minor)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = dsp_command(port, DSP_COMMAND_GET_VERSION);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = dsp_get_byte(port, major);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = dsp_get_byte(port, minor);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic WSS support routines
|
||||
*/
|
||||
|
||||
#define WSS_CONFIG_DMA_0 (1 << 0)
|
||||
#define WSS_CONFIG_DMA_1 (2 << 0)
|
||||
#define WSS_CONFIG_DMA_3 (3 << 0)
|
||||
#define WSS_CONFIG_DUPLEX (1 << 2)
|
||||
#define WSS_CONFIG_IRQ_7 (1 << 3)
|
||||
#define WSS_CONFIG_IRQ_9 (2 << 3)
|
||||
#define WSS_CONFIG_IRQ_10 (3 << 3)
|
||||
#define WSS_CONFIG_IRQ_11 (4 << 3)
|
||||
|
||||
#define WSS_PORT_CONFIG 0
|
||||
#define WSS_PORT_SIGNATURE 3
|
||||
|
||||
#define WSS_SIGNATURE 4
|
||||
|
||||
static int __devinit wss_detect(void __iomem *wss_port)
|
||||
{
|
||||
if ((ioread8(wss_port + WSS_PORT_SIGNATURE) & 0x3f) != WSS_SIGNATURE)
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wss_set_config(void __iomem *wss_port, u8 wss_config)
|
||||
{
|
||||
iowrite8(wss_config, wss_port + WSS_PORT_CONFIG);
|
||||
}
|
||||
|
||||
/*
|
||||
* Aztech Sound Galaxy specifics
|
||||
*/
|
||||
|
||||
#define GALAXY_PORT_CONFIG 1024
|
||||
#define CONFIG_PORT_SET 4
|
||||
|
||||
#define DSP_COMMAND_GALAXY_8 8
|
||||
#define GALAXY_COMMAND_GET_TYPE 5
|
||||
|
||||
#define DSP_COMMAND_GALAXY_9 9
|
||||
#define GALAXY_COMMAND_WSSMODE 0
|
||||
#define GALAXY_COMMAND_SB8MODE 1
|
||||
|
||||
#define GALAXY_MODE_WSS GALAXY_COMMAND_WSSMODE
|
||||
#define GALAXY_MODE_SB8 GALAXY_COMMAND_SB8MODE
|
||||
|
||||
struct snd_galaxy {
|
||||
void __iomem *port;
|
||||
void __iomem *config_port;
|
||||
void __iomem *wss_port;
|
||||
u32 config;
|
||||
struct resource *res_port;
|
||||
struct resource *res_config_port;
|
||||
struct resource *res_wss_port;
|
||||
};
|
||||
|
||||
static u32 config[SNDRV_CARDS];
|
||||
static u8 wss_config[SNDRV_CARDS];
|
||||
|
||||
static int __devinit snd_galaxy_match(struct device *dev, unsigned int n)
|
||||
{
|
||||
if (!enable[n])
|
||||
return 0;
|
||||
|
||||
switch (port[n]) {
|
||||
case SNDRV_AUTO_PORT:
|
||||
dev_err(dev, "please specify port\n");
|
||||
return 0;
|
||||
case 0x220:
|
||||
config[n] |= GALAXY_CONFIG_SBA_220;
|
||||
break;
|
||||
case 0x240:
|
||||
config[n] |= GALAXY_CONFIG_SBA_240;
|
||||
break;
|
||||
case 0x260:
|
||||
config[n] |= GALAXY_CONFIG_SBA_260;
|
||||
break;
|
||||
case 0x280:
|
||||
config[n] |= GALAXY_CONFIG_SBA_280;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "invalid port %#lx\n", port[n]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (wss_port[n]) {
|
||||
case SNDRV_AUTO_PORT:
|
||||
dev_err(dev, "please specify wss_port\n");
|
||||
return 0;
|
||||
case 0x530:
|
||||
config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_530;
|
||||
break;
|
||||
case 0x604:
|
||||
config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_604;
|
||||
break;
|
||||
case 0xe80:
|
||||
config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_E80;
|
||||
break;
|
||||
case 0xf40:
|
||||
config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_F40;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "invalid WSS port %#lx\n", wss_port[n]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (irq[n]) {
|
||||
case SNDRV_AUTO_IRQ:
|
||||
dev_err(dev, "please specify irq\n");
|
||||
return 0;
|
||||
case 7:
|
||||
wss_config[n] |= WSS_CONFIG_IRQ_7;
|
||||
break;
|
||||
case 2:
|
||||
irq[n] = 9;
|
||||
case 9:
|
||||
wss_config[n] |= WSS_CONFIG_IRQ_9;
|
||||
break;
|
||||
case 10:
|
||||
wss_config[n] |= WSS_CONFIG_IRQ_10;
|
||||
break;
|
||||
case 11:
|
||||
wss_config[n] |= WSS_CONFIG_IRQ_11;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "invalid IRQ %d\n", irq[n]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (dma1[n]) {
|
||||
case SNDRV_AUTO_DMA:
|
||||
dev_err(dev, "please specify dma1\n");
|
||||
return 0;
|
||||
case 0:
|
||||
wss_config[n] |= WSS_CONFIG_DMA_0;
|
||||
break;
|
||||
case 1:
|
||||
wss_config[n] |= WSS_CONFIG_DMA_1;
|
||||
break;
|
||||
case 3:
|
||||
wss_config[n] |= WSS_CONFIG_DMA_3;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "invalid playback DMA %d\n", dma1[n]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dma2[n] == SNDRV_AUTO_DMA || dma2[n] == dma1[n]) {
|
||||
dma2[n] = -1;
|
||||
goto mpu;
|
||||
}
|
||||
|
||||
wss_config[n] |= WSS_CONFIG_DUPLEX;
|
||||
switch (dma2[n]) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
if (dma1[n] == 0)
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "invalid capture DMA %d\n", dma2[n]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mpu:
|
||||
switch (mpu_port[n]) {
|
||||
case SNDRV_AUTO_PORT:
|
||||
dev_warn(dev, "mpu_port not specified; not using MPU-401\n");
|
||||
mpu_port[n] = -1;
|
||||
goto fm;
|
||||
case 0x300:
|
||||
config[n] |= GALAXY_CONFIG_MPU_ENABLE | GALAXY_CONFIG_MPUA_300;
|
||||
break;
|
||||
case 0x330:
|
||||
config[n] |= GALAXY_CONFIG_MPU_ENABLE | GALAXY_CONFIG_MPUA_330;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "invalid MPU port %#lx\n", mpu_port[n]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (mpu_irq[n]) {
|
||||
case SNDRV_AUTO_IRQ:
|
||||
dev_warn(dev, "mpu_irq not specified: using polling mode\n");
|
||||
mpu_irq[n] = -1;
|
||||
break;
|
||||
case 2:
|
||||
mpu_irq[n] = 9;
|
||||
case 9:
|
||||
config[n] |= GALAXY_CONFIG_MPUIRQ_2;
|
||||
break;
|
||||
#ifdef AZT1605
|
||||
case 3:
|
||||
config[n] |= GALAXY_CONFIG_MPUIRQ_3;
|
||||
break;
|
||||
#endif
|
||||
case 5:
|
||||
config[n] |= GALAXY_CONFIG_MPUIRQ_5;
|
||||
break;
|
||||
case 7:
|
||||
config[n] |= GALAXY_CONFIG_MPUIRQ_7;
|
||||
break;
|
||||
#ifdef AZT2316
|
||||
case 10:
|
||||
config[n] |= GALAXY_CONFIG_MPUIRQ_10;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
dev_err(dev, "invalid MPU IRQ %d\n", mpu_irq[n]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mpu_irq[n] == irq[n]) {
|
||||
dev_err(dev, "cannot share IRQ between WSS and MPU-401\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
fm:
|
||||
switch (fm_port[n]) {
|
||||
case SNDRV_AUTO_PORT:
|
||||
dev_warn(dev, "fm_port not specified: not using OPL3\n");
|
||||
fm_port[n] = -1;
|
||||
break;
|
||||
case 0x388:
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "illegal FM port %#lx\n", fm_port[n]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
config[n] |= GALAXY_CONFIG_GAME_ENABLE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __devinit galaxy_init(struct snd_galaxy *galaxy, u8 *type)
|
||||
{
|
||||
u8 major;
|
||||
u8 minor;
|
||||
int err;
|
||||
|
||||
err = dsp_reset(galaxy->port);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = dsp_get_version(galaxy->port, &major, &minor);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (major != GALAXY_DSP_MAJOR || minor != GALAXY_DSP_MINOR)
|
||||
return -ENODEV;
|
||||
|
||||
err = dsp_command(galaxy->port, DSP_COMMAND_GALAXY_8);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = dsp_command(galaxy->port, GALAXY_COMMAND_GET_TYPE);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = dsp_get_byte(galaxy->port, type);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit galaxy_set_mode(struct snd_galaxy *galaxy, u8 mode)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = dsp_command(galaxy->port, DSP_COMMAND_GALAXY_9);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = dsp_command(galaxy->port, mode);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
#ifdef AZT1605
|
||||
/*
|
||||
* Needed for MPU IRQ on AZT1605, but AZT2316 loses WSS again
|
||||
*/
|
||||
err = dsp_reset(galaxy->port);
|
||||
if (err < 0)
|
||||
return err;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void galaxy_set_config(struct snd_galaxy *galaxy, u32 config)
|
||||
{
|
||||
u8 tmp = ioread8(galaxy->config_port + CONFIG_PORT_SET);
|
||||
int i;
|
||||
|
||||
iowrite8(tmp | 0x80, galaxy->config_port + CONFIG_PORT_SET);
|
||||
for (i = 0; i < GALAXY_CONFIG_SIZE; i++) {
|
||||
iowrite8(config, galaxy->config_port + i);
|
||||
config >>= 8;
|
||||
}
|
||||
iowrite8(tmp & 0x7f, galaxy->config_port + CONFIG_PORT_SET);
|
||||
msleep(10);
|
||||
}
|
||||
|
||||
static void __devinit galaxy_config(struct snd_galaxy *galaxy, u32 config)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = GALAXY_CONFIG_SIZE; i; i--) {
|
||||
u8 tmp = ioread8(galaxy->config_port + i - 1);
|
||||
galaxy->config = (galaxy->config << 8) | tmp;
|
||||
}
|
||||
config |= galaxy->config & GALAXY_CONFIG_MASK;
|
||||
galaxy_set_config(galaxy, config);
|
||||
}
|
||||
|
||||
static int __devinit galaxy_wss_config(struct snd_galaxy *galaxy, u8 wss_config)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = wss_detect(galaxy->wss_port);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
wss_set_config(galaxy->wss_port, wss_config);
|
||||
|
||||
err = galaxy_set_mode(galaxy, GALAXY_MODE_WSS);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void snd_galaxy_free(struct snd_card *card)
|
||||
{
|
||||
struct snd_galaxy *galaxy = card->private_data;
|
||||
|
||||
if (galaxy->wss_port) {
|
||||
wss_set_config(galaxy->wss_port, 0);
|
||||
ioport_unmap(galaxy->wss_port);
|
||||
release_and_free_resource(galaxy->res_wss_port);
|
||||
}
|
||||
if (galaxy->config_port) {
|
||||
galaxy_set_config(galaxy, galaxy->config);
|
||||
ioport_unmap(galaxy->config_port);
|
||||
release_and_free_resource(galaxy->res_config_port);
|
||||
}
|
||||
if (galaxy->port) {
|
||||
ioport_unmap(galaxy->port);
|
||||
release_and_free_resource(galaxy->res_port);
|
||||
}
|
||||
}
|
||||
|
||||
static int __devinit snd_galaxy_probe(struct device *dev, unsigned int n)
|
||||
{
|
||||
struct snd_galaxy *galaxy;
|
||||
struct snd_wss *chip;
|
||||
struct snd_card *card;
|
||||
u8 type;
|
||||
int err;
|
||||
|
||||
err = snd_card_create(index[n], id[n], THIS_MODULE, sizeof *galaxy,
|
||||
&card);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
snd_card_set_dev(card, dev);
|
||||
|
||||
card->private_free = snd_galaxy_free;
|
||||
galaxy = card->private_data;
|
||||
|
||||
galaxy->res_port = request_region(port[n], 16, DRV_NAME);
|
||||
if (!galaxy->res_port) {
|
||||
dev_err(dev, "could not grab ports %#lx-%#lx\n", port[n],
|
||||
port[n] + 15);
|
||||
err = -EBUSY;
|
||||
goto error;
|
||||
}
|
||||
galaxy->port = ioport_map(port[n], 16);
|
||||
|
||||
err = galaxy_init(galaxy, &type);
|
||||
if (err < 0) {
|
||||
dev_err(dev, "did not find a Sound Galaxy at %#lx\n", port[n]);
|
||||
goto error;
|
||||
}
|
||||
dev_info(dev, "Sound Galaxy (type %d) found at %#lx\n", type, port[n]);
|
||||
|
||||
galaxy->res_config_port = request_region(port[n] + GALAXY_PORT_CONFIG,
|
||||
16, DRV_NAME);
|
||||
if (!galaxy->res_config_port) {
|
||||
dev_err(dev, "could not grab ports %#lx-%#lx\n",
|
||||
port[n] + GALAXY_PORT_CONFIG,
|
||||
port[n] + GALAXY_PORT_CONFIG + 15);
|
||||
err = -EBUSY;
|
||||
goto error;
|
||||
}
|
||||
galaxy->config_port = ioport_map(port[n] + GALAXY_PORT_CONFIG, 16);
|
||||
|
||||
galaxy_config(galaxy, config[n]);
|
||||
|
||||
galaxy->res_wss_port = request_region(wss_port[n], 4, DRV_NAME);
|
||||
if (!galaxy->res_wss_port) {
|
||||
dev_err(dev, "could not grab ports %#lx-%#lx\n", wss_port[n],
|
||||
wss_port[n] + 3);
|
||||
err = -EBUSY;
|
||||
goto error;
|
||||
}
|
||||
galaxy->wss_port = ioport_map(wss_port[n], 4);
|
||||
|
||||
err = galaxy_wss_config(galaxy, wss_config[n]);
|
||||
if (err < 0) {
|
||||
dev_err(dev, "could not configure WSS\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
strcpy(card->driver, DRV_NAME);
|
||||
strcpy(card->shortname, DRV_NAME);
|
||||
sprintf(card->longname, "%s at %#lx/%#lx, irq %d, dma %d/%d",
|
||||
card->shortname, port[n], wss_port[n], irq[n], dma1[n],
|
||||
dma2[n]);
|
||||
|
||||
err = snd_wss_create(card, wss_port[n] + 4, -1, irq[n], dma1[n],
|
||||
dma2[n], WSS_HW_DETECT, 0, &chip);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
err = snd_wss_pcm(chip, 0, NULL);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
err = snd_wss_mixer(chip);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
err = snd_wss_timer(chip, 0, NULL);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
if (mpu_port[n] >= 0) {
|
||||
err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
|
||||
mpu_port[n], 0, mpu_irq[n],
|
||||
IRQF_DISABLED, NULL);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (fm_port[n] >= 0) {
|
||||
struct snd_opl3 *opl3;
|
||||
|
||||
err = snd_opl3_create(card, fm_port[n], fm_port[n] + 2,
|
||||
OPL3_HW_AUTO, 0, &opl3);
|
||||
if (err < 0) {
|
||||
dev_err(dev, "no OPL device at %#lx\n", fm_port[n]);
|
||||
goto error;
|
||||
}
|
||||
err = snd_opl3_timer_new(opl3, 1, 2);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
err = snd_card_register(card);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
dev_set_drvdata(dev, card);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
snd_card_free(card);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devexit snd_galaxy_remove(struct device *dev, unsigned int n)
|
||||
{
|
||||
snd_card_free(dev_get_drvdata(dev));
|
||||
dev_set_drvdata(dev, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct isa_driver snd_galaxy_driver = {
|
||||
.match = snd_galaxy_match,
|
||||
.probe = snd_galaxy_probe,
|
||||
.remove = __devexit_p(snd_galaxy_remove),
|
||||
|
||||
.driver = {
|
||||
.name = DEV_NAME
|
||||
}
|
||||
};
|
||||
|
||||
static int __init alsa_card_galaxy_init(void)
|
||||
{
|
||||
return isa_register_driver(&snd_galaxy_driver, SNDRV_CARDS);
|
||||
}
|
||||
|
||||
static void __exit alsa_card_galaxy_exit(void)
|
||||
{
|
||||
isa_unregister_driver(&snd_galaxy_driver);
|
||||
}
|
||||
|
||||
module_init(alsa_card_galaxy_init);
|
||||
module_exit(alsa_card_galaxy_exit);
|
|
@ -191,7 +191,7 @@ static int __devinit snd_gusmax_mixer(struct snd_wss *chip)
|
|||
|
||||
static void snd_gusmax_free(struct snd_card *card)
|
||||
{
|
||||
struct snd_gusmax *maxcard = (struct snd_gusmax *)card->private_data;
|
||||
struct snd_gusmax *maxcard = card->private_data;
|
||||
|
||||
if (maxcard == NULL)
|
||||
return;
|
||||
|
@ -219,7 +219,7 @@ static int __devinit snd_gusmax_probe(struct device *pdev, unsigned int dev)
|
|||
if (err < 0)
|
||||
return err;
|
||||
card->private_free = snd_gusmax_free;
|
||||
maxcard = (struct snd_gusmax *)card->private_data;
|
||||
maxcard = card->private_data;
|
||||
maxcard->card = card;
|
||||
maxcard->irq = -1;
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ static irqreturn_t snd_sb8_interrupt(int irq, void *dev_id)
|
|||
|
||||
static void snd_sb8_free(struct snd_card *card)
|
||||
{
|
||||
struct snd_sb8 *acard = (struct snd_sb8 *)card->private_data;
|
||||
struct snd_sb8 *acard = card->private_data;
|
||||
|
||||
if (acard == NULL)
|
||||
return;
|
||||
|
|
|
@ -1,369 +0,0 @@
|
|||
/*
|
||||
* Driver for Aztech Sound Galaxy cards
|
||||
* Copyright (c) by Christopher Butler <chrisb@sandy.force9.co.uk.
|
||||
*
|
||||
* I don't have documentation for this card, I based this driver on the
|
||||
* driver for OSS/Free included in the kernel source (drivers/sound/sgalaxy.c)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/isa.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <asm/dma.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/sb.h>
|
||||
#include <sound/wss.h>
|
||||
#include <sound/control.h>
|
||||
#define SNDRV_LEGACY_FIND_FREE_IRQ
|
||||
#define SNDRV_LEGACY_FIND_FREE_DMA
|
||||
#include <sound/initval.h>
|
||||
|
||||
MODULE_AUTHOR("Christopher Butler <chrisb@sandy.force9.co.uk>");
|
||||
MODULE_DESCRIPTION("Aztech Sound Galaxy");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_SUPPORTED_DEVICE("{{Aztech Systems,Sound Galaxy}}");
|
||||
|
||||
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
|
||||
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
|
||||
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
|
||||
static long sbport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240 */
|
||||
static long wssport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x530,0xe80,0xf40,0x604 */
|
||||
static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 7,9,10,11 */
|
||||
static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */
|
||||
|
||||
module_param_array(index, int, NULL, 0444);
|
||||
MODULE_PARM_DESC(index, "Index value for Sound Galaxy soundcard.");
|
||||
module_param_array(id, charp, NULL, 0444);
|
||||
MODULE_PARM_DESC(id, "ID string for Sound Galaxy soundcard.");
|
||||
module_param_array(sbport, long, NULL, 0444);
|
||||
MODULE_PARM_DESC(sbport, "Port # for Sound Galaxy SB driver.");
|
||||
module_param_array(wssport, long, NULL, 0444);
|
||||
MODULE_PARM_DESC(wssport, "Port # for Sound Galaxy WSS driver.");
|
||||
module_param_array(irq, int, NULL, 0444);
|
||||
MODULE_PARM_DESC(irq, "IRQ # for Sound Galaxy driver.");
|
||||
module_param_array(dma1, int, NULL, 0444);
|
||||
MODULE_PARM_DESC(dma1, "DMA1 # for Sound Galaxy driver.");
|
||||
|
||||
#define SGALAXY_AUXC_LEFT 18
|
||||
#define SGALAXY_AUXC_RIGHT 19
|
||||
|
||||
#define PFX "sgalaxy: "
|
||||
|
||||
/*
|
||||
|
||||
*/
|
||||
|
||||
#define AD1848P1( port, x ) ( port + c_d_c_AD1848##x )
|
||||
|
||||
/* from lowlevel/sb/sb.c - to avoid having to allocate a struct snd_sb for the */
|
||||
/* short time we actually need it.. */
|
||||
|
||||
static int snd_sgalaxy_sbdsp_reset(unsigned long port)
|
||||
{
|
||||
int i;
|
||||
|
||||
outb(1, SBP1(port, RESET));
|
||||
udelay(10);
|
||||
outb(0, SBP1(port, RESET));
|
||||
udelay(30);
|
||||
for (i = 0; i < 1000 && !(inb(SBP1(port, DATA_AVAIL)) & 0x80); i++);
|
||||
if (inb(SBP1(port, READ)) != 0xaa) {
|
||||
snd_printd("sb_reset: failed at 0x%lx!!!\n", port);
|
||||
return -ENODEV;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit snd_sgalaxy_sbdsp_command(unsigned long port,
|
||||
unsigned char val)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 10000; i; i--)
|
||||
if ((inb(SBP1(port, STATUS)) & 0x80) == 0) {
|
||||
outb(val, SBP1(port, COMMAND));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t snd_sgalaxy_dummy_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
static int __devinit snd_sgalaxy_setup_wss(unsigned long port, int irq, int dma)
|
||||
{
|
||||
static int interrupt_bits[] = {-1, -1, -1, -1, -1, -1, -1, 0x08, -1,
|
||||
0x10, 0x18, 0x20, -1, -1, -1, -1};
|
||||
static int dma_bits[] = {1, 2, 0, 3};
|
||||
int tmp, tmp1;
|
||||
|
||||
if ((tmp = inb(port + 3)) == 0xff)
|
||||
{
|
||||
snd_printdd("I/O address dead (0x%lx)\n", port);
|
||||
return 0;
|
||||
}
|
||||
#if 0
|
||||
snd_printdd("WSS signature = 0x%x\n", tmp);
|
||||
#endif
|
||||
|
||||
if ((tmp & 0x3f) != 0x04 &&
|
||||
(tmp & 0x3f) != 0x0f &&
|
||||
(tmp & 0x3f) != 0x00) {
|
||||
snd_printdd("No WSS signature detected on port 0x%lx\n",
|
||||
port + 3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
snd_printdd(PFX "setting up IRQ/DMA for WSS\n");
|
||||
#endif
|
||||
|
||||
/* initialize IRQ for WSS codec */
|
||||
tmp = interrupt_bits[irq % 16];
|
||||
if (tmp < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (request_irq(irq, snd_sgalaxy_dummy_interrupt, IRQF_DISABLED, "sgalaxy", NULL)) {
|
||||
snd_printk(KERN_ERR "sgalaxy: can't grab irq %d\n", irq);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
outb(tmp | 0x40, port);
|
||||
tmp1 = dma_bits[dma % 4];
|
||||
outb(tmp | tmp1, port);
|
||||
|
||||
free_irq(irq, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit snd_sgalaxy_detect(int dev, int irq, int dma)
|
||||
{
|
||||
#if 0
|
||||
snd_printdd(PFX "switching to WSS mode\n");
|
||||
#endif
|
||||
|
||||
/* switch to WSS mode */
|
||||
snd_sgalaxy_sbdsp_reset(sbport[dev]);
|
||||
|
||||
snd_sgalaxy_sbdsp_command(sbport[dev], 9);
|
||||
snd_sgalaxy_sbdsp_command(sbport[dev], 0);
|
||||
|
||||
udelay(400);
|
||||
return snd_sgalaxy_setup_wss(wssport[dev], irq, dma);
|
||||
}
|
||||
|
||||
static struct snd_kcontrol_new snd_sgalaxy_controls[] = {
|
||||
WSS_DOUBLE("Aux Playback Switch", 0,
|
||||
SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 7, 7, 1, 1),
|
||||
WSS_DOUBLE("Aux Playback Volume", 0,
|
||||
SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 0, 0, 31, 0)
|
||||
};
|
||||
|
||||
static int __devinit snd_sgalaxy_mixer(struct snd_wss *chip)
|
||||
{
|
||||
struct snd_card *card = chip->card;
|
||||
struct snd_ctl_elem_id id1, id2;
|
||||
unsigned int idx;
|
||||
int err;
|
||||
|
||||
memset(&id1, 0, sizeof(id1));
|
||||
memset(&id2, 0, sizeof(id2));
|
||||
id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
/* reassign AUX0 to LINE */
|
||||
strcpy(id1.name, "Aux Playback Switch");
|
||||
strcpy(id2.name, "Line Playback Switch");
|
||||
if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
|
||||
return err;
|
||||
strcpy(id1.name, "Aux Playback Volume");
|
||||
strcpy(id2.name, "Line Playback Volume");
|
||||
if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
|
||||
return err;
|
||||
/* reassign AUX1 to FM */
|
||||
strcpy(id1.name, "Aux Playback Switch"); id1.index = 1;
|
||||
strcpy(id2.name, "FM Playback Switch");
|
||||
if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
|
||||
return err;
|
||||
strcpy(id1.name, "Aux Playback Volume");
|
||||
strcpy(id2.name, "FM Playback Volume");
|
||||
if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
|
||||
return err;
|
||||
/* build AUX2 input */
|
||||
for (idx = 0; idx < ARRAY_SIZE(snd_sgalaxy_controls); idx++) {
|
||||
err = snd_ctl_add(card,
|
||||
snd_ctl_new1(&snd_sgalaxy_controls[idx], chip));
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit snd_sgalaxy_match(struct device *devptr, unsigned int dev)
|
||||
{
|
||||
if (!enable[dev])
|
||||
return 0;
|
||||
if (sbport[dev] == SNDRV_AUTO_PORT) {
|
||||
snd_printk(KERN_ERR PFX "specify SB port\n");
|
||||
return 0;
|
||||
}
|
||||
if (wssport[dev] == SNDRV_AUTO_PORT) {
|
||||
snd_printk(KERN_ERR PFX "specify WSS port\n");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __devinit snd_sgalaxy_probe(struct device *devptr, unsigned int dev)
|
||||
{
|
||||
static int possible_irqs[] = {7, 9, 10, 11, -1};
|
||||
static int possible_dmas[] = {1, 3, 0, -1};
|
||||
int err, xirq, xdma1;
|
||||
struct snd_card *card;
|
||||
struct snd_wss *chip;
|
||||
|
||||
err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
xirq = irq[dev];
|
||||
if (xirq == SNDRV_AUTO_IRQ) {
|
||||
if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
|
||||
snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
|
||||
err = -EBUSY;
|
||||
goto _err;
|
||||
}
|
||||
}
|
||||
xdma1 = dma1[dev];
|
||||
if (xdma1 == SNDRV_AUTO_DMA) {
|
||||
if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
|
||||
snd_printk(KERN_ERR PFX "unable to find a free DMA\n");
|
||||
err = -EBUSY;
|
||||
goto _err;
|
||||
}
|
||||
}
|
||||
|
||||
if ((err = snd_sgalaxy_detect(dev, xirq, xdma1)) < 0)
|
||||
goto _err;
|
||||
|
||||
err = snd_wss_create(card, wssport[dev] + 4, -1,
|
||||
xirq, xdma1, -1,
|
||||
WSS_HW_DETECT, 0, &chip);
|
||||
if (err < 0)
|
||||
goto _err;
|
||||
card->private_data = chip;
|
||||
|
||||
err = snd_wss_pcm(chip, 0, NULL);
|
||||
if (err < 0) {
|
||||
snd_printdd(PFX "error creating new WSS PCM device\n");
|
||||
goto _err;
|
||||
}
|
||||
err = snd_wss_mixer(chip);
|
||||
if (err < 0) {
|
||||
snd_printdd(PFX "error creating new WSS mixer\n");
|
||||
goto _err;
|
||||
}
|
||||
if ((err = snd_sgalaxy_mixer(chip)) < 0) {
|
||||
snd_printdd(PFX "the mixer rewrite failed\n");
|
||||
goto _err;
|
||||
}
|
||||
|
||||
strcpy(card->driver, "Sound Galaxy");
|
||||
strcpy(card->shortname, "Sound Galaxy");
|
||||
sprintf(card->longname, "Sound Galaxy at 0x%lx, irq %d, dma %d",
|
||||
wssport[dev], xirq, xdma1);
|
||||
|
||||
snd_card_set_dev(card, devptr);
|
||||
|
||||
if ((err = snd_card_register(card)) < 0)
|
||||
goto _err;
|
||||
|
||||
dev_set_drvdata(devptr, card);
|
||||
return 0;
|
||||
|
||||
_err:
|
||||
snd_card_free(card);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devexit snd_sgalaxy_remove(struct device *devptr, unsigned int dev)
|
||||
{
|
||||
snd_card_free(dev_get_drvdata(devptr));
|
||||
dev_set_drvdata(devptr, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int snd_sgalaxy_suspend(struct device *pdev, unsigned int n,
|
||||
pm_message_t state)
|
||||
{
|
||||
struct snd_card *card = dev_get_drvdata(pdev);
|
||||
struct snd_wss *chip = card->private_data;
|
||||
|
||||
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
|
||||
chip->suspend(chip);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_sgalaxy_resume(struct device *pdev, unsigned int n)
|
||||
{
|
||||
struct snd_card *card = dev_get_drvdata(pdev);
|
||||
struct snd_wss *chip = card->private_data;
|
||||
|
||||
chip->resume(chip);
|
||||
snd_wss_out(chip, SGALAXY_AUXC_LEFT, chip->image[SGALAXY_AUXC_LEFT]);
|
||||
snd_wss_out(chip, SGALAXY_AUXC_RIGHT, chip->image[SGALAXY_AUXC_RIGHT]);
|
||||
|
||||
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define DEV_NAME "sgalaxy"
|
||||
|
||||
static struct isa_driver snd_sgalaxy_driver = {
|
||||
.match = snd_sgalaxy_match,
|
||||
.probe = snd_sgalaxy_probe,
|
||||
.remove = __devexit_p(snd_sgalaxy_remove),
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = snd_sgalaxy_suspend,
|
||||
.resume = snd_sgalaxy_resume,
|
||||
#endif
|
||||
.driver = {
|
||||
.name = DEV_NAME
|
||||
},
|
||||
};
|
||||
|
||||
static int __init alsa_card_sgalaxy_init(void)
|
||||
{
|
||||
return isa_register_driver(&snd_sgalaxy_driver, SNDRV_CARDS);
|
||||
}
|
||||
|
||||
static void __exit alsa_card_sgalaxy_exit(void)
|
||||
{
|
||||
isa_unregister_driver(&snd_sgalaxy_driver);
|
||||
}
|
||||
|
||||
module_init(alsa_card_sgalaxy_init)
|
||||
module_exit(alsa_card_sgalaxy_exit)
|
|
@ -545,11 +545,3 @@ config SOUND_KAHLUA
|
|||
|
||||
endif # SOUND_OSS
|
||||
|
||||
config SOUND_SH_DAC_AUDIO
|
||||
tristate "SuperH DAC audio support"
|
||||
depends on CPU_SH3 && HIGH_RES_TIMERS
|
||||
|
||||
config SOUND_SH_DAC_AUDIO_CHANNEL
|
||||
int "DAC channel"
|
||||
default "1"
|
||||
depends on SOUND_SH_DAC_AUDIO
|
||||
|
|
|
@ -9,7 +9,6 @@ obj-$(CONFIG_SOUND_OSS) += sound.o
|
|||
|
||||
# Please leave it as is, cause the link order is significant !
|
||||
|
||||
obj-$(CONFIG_SOUND_SH_DAC_AUDIO) += sh_dac_audio.o
|
||||
obj-$(CONFIG_SOUND_AEDSP16) += aedsp16.o
|
||||
obj-$(CONFIG_SOUND_PSS) += pss.o ad1848.o mpu401.o
|
||||
obj-$(CONFIG_SOUND_TRIX) += trix.o ad1848.o sb_lib.o uart401.o
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
#include <linux/sound.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/soundcard.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
|
@ -77,6 +76,7 @@
|
|||
/* Boot options
|
||||
* 0 = no VRA, 1 = use VRA if codec supports it
|
||||
*/
|
||||
static DEFINE_MUTEX(au1550_ac97_mutex);
|
||||
static int vra = 1;
|
||||
module_param(vra, bool, 0);
|
||||
MODULE_PARM_DESC(vra, "if 1 use VRA if codec supports it");
|
||||
|
@ -171,7 +171,7 @@ au1550_delay(int msec)
|
|||
static u16
|
||||
rdcodec(struct ac97_codec *codec, u8 addr)
|
||||
{
|
||||
struct au1550_state *s = (struct au1550_state *)codec->private_data;
|
||||
struct au1550_state *s = codec->private_data;
|
||||
unsigned long flags;
|
||||
u32 cmd, val;
|
||||
u16 data;
|
||||
|
@ -239,7 +239,7 @@ rdcodec(struct ac97_codec *codec, u8 addr)
|
|||
static void
|
||||
wrcodec(struct ac97_codec *codec, u8 addr, u16 data)
|
||||
{
|
||||
struct au1550_state *s = (struct au1550_state *)codec->private_data;
|
||||
struct au1550_state *s = codec->private_data;
|
||||
unsigned long flags;
|
||||
u32 cmd, val;
|
||||
int i;
|
||||
|
@ -798,9 +798,9 @@ au1550_llseek(struct file *file, loff_t offset, int origin)
|
|||
static int
|
||||
au1550_open_mixdev(struct inode *inode, struct file *file)
|
||||
{
|
||||
lock_kernel();
|
||||
mutex_lock(&au1550_ac97_mutex);
|
||||
file->private_data = &au1550_state;
|
||||
unlock_kernel();
|
||||
mutex_unlock(&au1550_ac97_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -820,13 +820,13 @@ mixdev_ioctl(struct ac97_codec *codec, unsigned int cmd,
|
|||
static long
|
||||
au1550_ioctl_mixdev(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct au1550_state *s = (struct au1550_state *)file->private_data;
|
||||
struct au1550_state *s = file->private_data;
|
||||
struct ac97_codec *codec = s->codec;
|
||||
int ret;
|
||||
|
||||
lock_kernel();
|
||||
mutex_lock(&au1550_ac97_mutex);
|
||||
ret = mixdev_ioctl(codec, cmd, arg);
|
||||
unlock_kernel();
|
||||
mutex_unlock(&au1550_ac97_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1031,7 +1031,7 @@ copy_dmabuf_user(struct dmabuf *db, char* userbuf, int count, int to_user)
|
|||
static ssize_t
|
||||
au1550_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
|
||||
{
|
||||
struct au1550_state *s = (struct au1550_state *)file->private_data;
|
||||
struct au1550_state *s = file->private_data;
|
||||
struct dmabuf *db = &s->dma_adc;
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
ssize_t ret;
|
||||
|
@ -1111,7 +1111,7 @@ au1550_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
|
|||
static ssize_t
|
||||
au1550_write(struct file *file, const char *buffer, size_t count, loff_t * ppos)
|
||||
{
|
||||
struct au1550_state *s = (struct au1550_state *)file->private_data;
|
||||
struct au1550_state *s = file->private_data;
|
||||
struct dmabuf *db = &s->dma_dac;
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
ssize_t ret = 0;
|
||||
|
@ -1211,7 +1211,7 @@ au1550_write(struct file *file, const char *buffer, size_t count, loff_t * ppos)
|
|||
static unsigned int
|
||||
au1550_poll(struct file *file, struct poll_table_struct *wait)
|
||||
{
|
||||
struct au1550_state *s = (struct au1550_state *)file->private_data;
|
||||
struct au1550_state *s = file->private_data;
|
||||
unsigned long flags;
|
||||
unsigned int mask = 0;
|
||||
|
||||
|
@ -1250,12 +1250,12 @@ au1550_poll(struct file *file, struct poll_table_struct *wait)
|
|||
static int
|
||||
au1550_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
{
|
||||
struct au1550_state *s = (struct au1550_state *)file->private_data;
|
||||
struct au1550_state *s = file->private_data;
|
||||
struct dmabuf *db;
|
||||
unsigned long size;
|
||||
int ret = 0;
|
||||
|
||||
lock_kernel();
|
||||
mutex_lock(&au1550_ac97_mutex);
|
||||
mutex_lock(&s->sem);
|
||||
if (vma->vm_flags & VM_WRITE)
|
||||
db = &s->dma_dac;
|
||||
|
@ -1283,7 +1283,7 @@ au1550_mmap(struct file *file, struct vm_area_struct *vma)
|
|||
db->mapped = 1;
|
||||
out:
|
||||
mutex_unlock(&s->sem);
|
||||
unlock_kernel();
|
||||
mutex_unlock(&au1550_ac97_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1342,7 +1342,7 @@ dma_count_done(struct dmabuf *db)
|
|||
static int
|
||||
au1550_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct au1550_state *s = (struct au1550_state *)file->private_data;
|
||||
struct au1550_state *s = file->private_data;
|
||||
unsigned long flags;
|
||||
audio_buf_info abinfo;
|
||||
count_info cinfo;
|
||||
|
@ -1781,9 +1781,9 @@ au1550_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
{
|
||||
int ret;
|
||||
|
||||
lock_kernel();
|
||||
mutex_lock(&au1550_ac97_mutex);
|
||||
ret = au1550_ioctl(file, cmd, arg);
|
||||
unlock_kernel();
|
||||
mutex_unlock(&au1550_ac97_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1804,7 +1804,7 @@ au1550_open(struct inode *inode, struct file *file)
|
|||
#endif
|
||||
|
||||
file->private_data = s;
|
||||
lock_kernel();
|
||||
mutex_lock(&au1550_ac97_mutex);
|
||||
/* wait for device to become free */
|
||||
mutex_lock(&s->open_mutex);
|
||||
while (s->open_mode & file->f_mode) {
|
||||
|
@ -1861,21 +1861,21 @@ au1550_open(struct inode *inode, struct file *file)
|
|||
out:
|
||||
mutex_unlock(&s->open_mutex);
|
||||
out2:
|
||||
unlock_kernel();
|
||||
mutex_unlock(&au1550_ac97_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
au1550_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct au1550_state *s = (struct au1550_state *)file->private_data;
|
||||
struct au1550_state *s = file->private_data;
|
||||
|
||||
lock_kernel();
|
||||
mutex_lock(&au1550_ac97_mutex);
|
||||
|
||||
if (file->f_mode & FMODE_WRITE) {
|
||||
unlock_kernel();
|
||||
mutex_unlock(&au1550_ac97_mutex);
|
||||
drain_dac(s, file->f_flags & O_NONBLOCK);
|
||||
lock_kernel();
|
||||
mutex_lock(&au1550_ac97_mutex);
|
||||
}
|
||||
|
||||
mutex_lock(&s->open_mutex);
|
||||
|
@ -1892,7 +1892,7 @@ au1550_release(struct inode *inode, struct file *file)
|
|||
s->open_mode &= ((~file->f_mode) & (FMODE_READ|FMODE_WRITE));
|
||||
mutex_unlock(&s->open_mutex);
|
||||
wake_up(&s->open_wait);
|
||||
unlock_kernel();
|
||||
mutex_unlock(&au1550_ac97_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -181,7 +181,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/soundcard.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
|
@ -194,6 +194,7 @@
|
|||
* Declarations
|
||||
*/
|
||||
|
||||
static DEFINE_MUTEX(dmasound_core_mutex);
|
||||
int dmasound_catchRadius = 0;
|
||||
module_param(dmasound_catchRadius, int, 0);
|
||||
|
||||
|
@ -323,22 +324,22 @@ static struct {
|
|||
|
||||
static int mixer_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
lock_kernel();
|
||||
mutex_lock(&dmasound_core_mutex);
|
||||
if (!try_module_get(dmasound.mach.owner)) {
|
||||
unlock_kernel();
|
||||
mutex_unlock(&dmasound_core_mutex);
|
||||
return -ENODEV;
|
||||
}
|
||||
mixer.busy = 1;
|
||||
unlock_kernel();
|
||||
mutex_unlock(&dmasound_core_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mixer_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
lock_kernel();
|
||||
mutex_lock(&dmasound_core_mutex);
|
||||
mixer.busy = 0;
|
||||
module_put(dmasound.mach.owner);
|
||||
unlock_kernel();
|
||||
mutex_unlock(&dmasound_core_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -370,9 +371,9 @@ static long mixer_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
|
|||
{
|
||||
int ret;
|
||||
|
||||
lock_kernel();
|
||||
mutex_lock(&dmasound_core_mutex);
|
||||
ret = mixer_ioctl(file, cmd, arg);
|
||||
unlock_kernel();
|
||||
mutex_unlock(&dmasound_core_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -752,9 +753,9 @@ static int sq_open(struct inode *inode, struct file *file)
|
|||
{
|
||||
int rc;
|
||||
|
||||
lock_kernel();
|
||||
mutex_lock(&dmasound_core_mutex);
|
||||
if (!try_module_get(dmasound.mach.owner)) {
|
||||
unlock_kernel();
|
||||
mutex_unlock(&dmasound_core_mutex);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -799,11 +800,11 @@ static int sq_open(struct inode *inode, struct file *file)
|
|||
sound_set_format(AFMT_MU_LAW);
|
||||
}
|
||||
#endif
|
||||
unlock_kernel();
|
||||
mutex_unlock(&dmasound_core_mutex);
|
||||
return 0;
|
||||
out:
|
||||
module_put(dmasound.mach.owner);
|
||||
unlock_kernel();
|
||||
mutex_unlock(&dmasound_core_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -869,7 +870,7 @@ static int sq_release(struct inode *inode, struct file *file)
|
|||
{
|
||||
int rc = 0;
|
||||
|
||||
lock_kernel();
|
||||
mutex_lock(&dmasound_core_mutex);
|
||||
|
||||
if (file->f_mode & FMODE_WRITE) {
|
||||
if (write_sq.busy)
|
||||
|
@ -900,7 +901,7 @@ static int sq_release(struct inode *inode, struct file *file)
|
|||
write_sq_wake_up(file); /* checks f_mode */
|
||||
#endif /* blocking open() */
|
||||
|
||||
unlock_kernel();
|
||||
mutex_unlock(&dmasound_core_mutex);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -1141,9 +1142,9 @@ static long sq_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
|
|||
{
|
||||
int ret;
|
||||
|
||||
lock_kernel();
|
||||
mutex_lock(&dmasound_core_mutex);
|
||||
ret = sq_ioctl(file, cmd, arg);
|
||||
unlock_kernel();
|
||||
mutex_unlock(&dmasound_core_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1257,7 +1258,7 @@ static int state_open(struct inode *inode, struct file *file)
|
|||
int len = 0;
|
||||
int ret;
|
||||
|
||||
lock_kernel();
|
||||
mutex_lock(&dmasound_core_mutex);
|
||||
ret = -EBUSY;
|
||||
if (state.busy)
|
||||
goto out;
|
||||
|
@ -1329,16 +1330,16 @@ printk("dmasound: stat buffer used %d bytes\n", len) ;
|
|||
state.len = len;
|
||||
ret = 0;
|
||||
out:
|
||||
unlock_kernel();
|
||||
mutex_unlock(&dmasound_core_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int state_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
lock_kernel();
|
||||
mutex_lock(&dmasound_core_mutex);
|
||||
state.busy = 0;
|
||||
module_put(dmasound.mach.owner);
|
||||
unlock_kernel();
|
||||
mutex_unlock(&dmasound_core_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/io.h>
|
||||
|
@ -79,6 +79,7 @@
|
|||
dev.rec_sample_rate / \
|
||||
dev.rec_channels)
|
||||
|
||||
static DEFINE_MUTEX(msnd_pinnacle_mutex);
|
||||
static multisound_dev_t dev;
|
||||
|
||||
#ifndef HAVE_DSPCODEH
|
||||
|
@ -651,12 +652,12 @@ static long dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
|
||||
ret = -EINVAL;
|
||||
|
||||
lock_kernel();
|
||||
mutex_lock(&msnd_pinnacle_mutex);
|
||||
if (minor == dev.dsp_minor)
|
||||
ret = dsp_ioctl(file, cmd, arg);
|
||||
else if (minor == dev.mixer_minor)
|
||||
ret = mixer_ioctl(cmd, arg);
|
||||
unlock_kernel();
|
||||
mutex_unlock(&msnd_pinnacle_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -761,7 +762,7 @@ static int dev_open(struct inode *inode, struct file *file)
|
|||
int minor = iminor(inode);
|
||||
int err = 0;
|
||||
|
||||
lock_kernel();
|
||||
mutex_lock(&msnd_pinnacle_mutex);
|
||||
if (minor == dev.dsp_minor) {
|
||||
if ((file->f_mode & FMODE_WRITE &&
|
||||
test_bit(F_AUDIO_WRITE_INUSE, &dev.flags)) ||
|
||||
|
@ -791,7 +792,7 @@ static int dev_open(struct inode *inode, struct file *file)
|
|||
} else
|
||||
err = -EINVAL;
|
||||
out:
|
||||
unlock_kernel();
|
||||
mutex_unlock(&msnd_pinnacle_mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -800,14 +801,14 @@ static int dev_release(struct inode *inode, struct file *file)
|
|||
int minor = iminor(inode);
|
||||
int err = 0;
|
||||
|
||||
lock_kernel();
|
||||
mutex_lock(&msnd_pinnacle_mutex);
|
||||
if (minor == dev.dsp_minor)
|
||||
err = dsp_release(file);
|
||||
else if (minor == dev.mixer_minor) {
|
||||
/* nothing */
|
||||
} else
|
||||
err = -EINVAL;
|
||||
unlock_kernel();
|
||||
mutex_unlock(&msnd_pinnacle_mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,325 +0,0 @@
|
|||
/*
|
||||
* sound/oss/sh_dac_audio.c
|
||||
*
|
||||
* SH DAC based sound :(
|
||||
*
|
||||
* Copyright (C) 2004,2005 Andriy Skulysh
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/sound.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/soundcard.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/hrtimer.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/delay.h>
|
||||
#include <asm/clock.h>
|
||||
#include <cpu/dac.h>
|
||||
#include <asm/machvec.h>
|
||||
#include <mach/hp6xx.h>
|
||||
#include <asm/hd64461.h>
|
||||
|
||||
#define MODNAME "sh_dac_audio"
|
||||
|
||||
#define BUFFER_SIZE 48000
|
||||
|
||||
static int rate;
|
||||
static int empty;
|
||||
static char *data_buffer, *buffer_begin, *buffer_end;
|
||||
static int in_use, device_major;
|
||||
static struct hrtimer hrtimer;
|
||||
static ktime_t wakeups_per_second;
|
||||
|
||||
static void dac_audio_start_timer(void)
|
||||
{
|
||||
hrtimer_start(&hrtimer, wakeups_per_second, HRTIMER_MODE_REL);
|
||||
}
|
||||
|
||||
static void dac_audio_stop_timer(void)
|
||||
{
|
||||
hrtimer_cancel(&hrtimer);
|
||||
}
|
||||
|
||||
static void dac_audio_reset(void)
|
||||
{
|
||||
dac_audio_stop_timer();
|
||||
buffer_begin = buffer_end = data_buffer;
|
||||
empty = 1;
|
||||
}
|
||||
|
||||
static void dac_audio_sync(void)
|
||||
{
|
||||
while (!empty)
|
||||
schedule();
|
||||
}
|
||||
|
||||
static void dac_audio_start(void)
|
||||
{
|
||||
if (mach_is_hp6xx()) {
|
||||
u16 v = __raw_readw(HD64461_GPADR);
|
||||
v &= ~HD64461_GPADR_SPEAKER;
|
||||
__raw_writew(v, HD64461_GPADR);
|
||||
}
|
||||
|
||||
sh_dac_enable(CONFIG_SOUND_SH_DAC_AUDIO_CHANNEL);
|
||||
}
|
||||
static void dac_audio_stop(void)
|
||||
{
|
||||
dac_audio_stop_timer();
|
||||
|
||||
if (mach_is_hp6xx()) {
|
||||
u16 v = __raw_readw(HD64461_GPADR);
|
||||
v |= HD64461_GPADR_SPEAKER;
|
||||
__raw_writew(v, HD64461_GPADR);
|
||||
}
|
||||
|
||||
sh_dac_output(0, CONFIG_SOUND_SH_DAC_AUDIO_CHANNEL);
|
||||
sh_dac_disable(CONFIG_SOUND_SH_DAC_AUDIO_CHANNEL);
|
||||
}
|
||||
|
||||
static void dac_audio_set_rate(void)
|
||||
{
|
||||
wakeups_per_second = ktime_set(0, 1000000000 / rate);
|
||||
}
|
||||
|
||||
static int dac_audio_ioctl(struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int val;
|
||||
|
||||
switch (cmd) {
|
||||
case OSS_GETVERSION:
|
||||
return put_user(SOUND_VERSION, (int *)arg);
|
||||
|
||||
case SNDCTL_DSP_SYNC:
|
||||
dac_audio_sync();
|
||||
return 0;
|
||||
|
||||
case SNDCTL_DSP_RESET:
|
||||
dac_audio_reset();
|
||||
return 0;
|
||||
|
||||
case SNDCTL_DSP_GETFMTS:
|
||||
return put_user(AFMT_U8, (int *)arg);
|
||||
|
||||
case SNDCTL_DSP_SETFMT:
|
||||
return put_user(AFMT_U8, (int *)arg);
|
||||
|
||||
case SNDCTL_DSP_NONBLOCK:
|
||||
spin_lock(&file->f_lock);
|
||||
file->f_flags |= O_NONBLOCK;
|
||||
spin_unlock(&file->f_lock);
|
||||
return 0;
|
||||
|
||||
case SNDCTL_DSP_GETCAPS:
|
||||
return 0;
|
||||
|
||||
case SOUND_PCM_WRITE_RATE:
|
||||
val = *(int *)arg;
|
||||
if (val > 0) {
|
||||
rate = val;
|
||||
dac_audio_set_rate();
|
||||
}
|
||||
return put_user(rate, (int *)arg);
|
||||
|
||||
case SNDCTL_DSP_STEREO:
|
||||
return put_user(0, (int *)arg);
|
||||
|
||||
case SOUND_PCM_WRITE_CHANNELS:
|
||||
return put_user(1, (int *)arg);
|
||||
|
||||
case SNDCTL_DSP_SETDUPLEX:
|
||||
return -EINVAL;
|
||||
|
||||
case SNDCTL_DSP_PROFILE:
|
||||
return -EINVAL;
|
||||
|
||||
case SNDCTL_DSP_GETBLKSIZE:
|
||||
return put_user(BUFFER_SIZE, (int *)arg);
|
||||
|
||||
case SNDCTL_DSP_SETFRAGMENT:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
printk(KERN_ERR "sh_dac_audio: unimplemented ioctl=0x%x\n",
|
||||
cmd);
|
||||
return -EINVAL;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static long dac_audio_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
lock_kernel();
|
||||
ret = dac_audio_ioctl(file, cmd, arg);
|
||||
unlock_kernel();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t dac_audio_write(struct file *file, const char *buf, size_t count,
|
||||
loff_t * ppos)
|
||||
{
|
||||
int free;
|
||||
int nbytes;
|
||||
|
||||
if (!count) {
|
||||
dac_audio_sync();
|
||||
return 0;
|
||||
}
|
||||
|
||||
free = buffer_begin - buffer_end;
|
||||
|
||||
if (free < 0)
|
||||
free += BUFFER_SIZE;
|
||||
if ((free == 0) && (empty))
|
||||
free = BUFFER_SIZE;
|
||||
if (count > free)
|
||||
count = free;
|
||||
if (buffer_begin > buffer_end) {
|
||||
if (copy_from_user((void *)buffer_end, buf, count))
|
||||
return -EFAULT;
|
||||
|
||||
buffer_end += count;
|
||||
} else {
|
||||
nbytes = data_buffer + BUFFER_SIZE - buffer_end;
|
||||
if (nbytes > count) {
|
||||
if (copy_from_user((void *)buffer_end, buf, count))
|
||||
return -EFAULT;
|
||||
buffer_end += count;
|
||||
} else {
|
||||
if (copy_from_user((void *)buffer_end, buf, nbytes))
|
||||
return -EFAULT;
|
||||
if (copy_from_user
|
||||
((void *)data_buffer, buf + nbytes, count - nbytes))
|
||||
return -EFAULT;
|
||||
buffer_end = data_buffer + count - nbytes;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty) {
|
||||
empty = 0;
|
||||
dac_audio_start_timer();
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t dac_audio_read(struct file *file, char *buf, size_t count,
|
||||
loff_t * ppos)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int dac_audio_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
if (file->f_mode & FMODE_READ)
|
||||
return -ENODEV;
|
||||
|
||||
lock_kernel();
|
||||
if (in_use) {
|
||||
unlock_kernel();
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
in_use = 1;
|
||||
|
||||
dac_audio_start();
|
||||
unlock_kernel();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dac_audio_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
dac_audio_sync();
|
||||
dac_audio_stop();
|
||||
in_use = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct file_operations dac_audio_fops = {
|
||||
.read = dac_audio_read,
|
||||
.write = dac_audio_write,
|
||||
.unlocked_ioctl = dac_audio_unlocked_ioctl,
|
||||
.open = dac_audio_open,
|
||||
.release = dac_audio_release,
|
||||
};
|
||||
|
||||
static enum hrtimer_restart sh_dac_audio_timer(struct hrtimer *handle)
|
||||
{
|
||||
if (!empty) {
|
||||
sh_dac_output(*buffer_begin, CONFIG_SOUND_SH_DAC_AUDIO_CHANNEL);
|
||||
buffer_begin++;
|
||||
|
||||
if (buffer_begin == data_buffer + BUFFER_SIZE)
|
||||
buffer_begin = data_buffer;
|
||||
if (buffer_begin == buffer_end)
|
||||
empty = 1;
|
||||
}
|
||||
|
||||
if (!empty)
|
||||
hrtimer_start(&hrtimer, wakeups_per_second, HRTIMER_MODE_REL);
|
||||
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
static int __init dac_audio_init(void)
|
||||
{
|
||||
if ((device_major = register_sound_dsp(&dac_audio_fops, -1)) < 0) {
|
||||
printk(KERN_ERR "Cannot register dsp device");
|
||||
return device_major;
|
||||
}
|
||||
|
||||
in_use = 0;
|
||||
|
||||
data_buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);
|
||||
if (data_buffer == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
dac_audio_reset();
|
||||
rate = 8000;
|
||||
dac_audio_set_rate();
|
||||
|
||||
/* Today: High Resolution Timer driven DAC playback.
|
||||
* The timer callback gets called once per sample. Ouch.
|
||||
*
|
||||
* Future: A much better approach would be to use the
|
||||
* SH7720 CMT+DMAC+DAC hardware combination like this:
|
||||
* - Program sample rate using CMT0 or CMT1
|
||||
* - Program DMAC to use CMT for timing and output to DAC
|
||||
* - Play sound using DMAC, let CPU sleep.
|
||||
* - While at it, rewrite this driver to use ALSA.
|
||||
*/
|
||||
|
||||
hrtimer_init(&hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
hrtimer.function = sh_dac_audio_timer;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit dac_audio_exit(void)
|
||||
{
|
||||
unregister_sound_dsp(device_major);
|
||||
kfree((void *)data_buffer);
|
||||
}
|
||||
|
||||
module_init(dac_audio_init);
|
||||
module_exit(dac_audio_exit);
|
||||
|
||||
MODULE_AUTHOR("Andriy Skulysh, askulysh@image.kiev.ua");
|
||||
MODULE_DESCRIPTION("SH DAC sound driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -40,7 +40,7 @@
|
|||
#include <linux/major.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/device.h>
|
||||
|
@ -56,6 +56,7 @@
|
|||
* Table for permanently allocated memory (used when unloading the module)
|
||||
*/
|
||||
void * sound_mem_blocks[MAX_MEM_BLOCKS];
|
||||
static DEFINE_MUTEX(soundcard_mutex);
|
||||
int sound_nblocks = 0;
|
||||
|
||||
/* Persistent DMA buffers */
|
||||
|
@ -151,7 +152,7 @@ static ssize_t sound_read(struct file *file, char __user *buf, size_t count, lof
|
|||
* big one anyway, we might as well bandage here..
|
||||
*/
|
||||
|
||||
lock_kernel();
|
||||
mutex_lock(&soundcard_mutex);
|
||||
|
||||
DEB(printk("sound_read(dev=%d, count=%d)\n", dev, count));
|
||||
switch (dev & 0x0f) {
|
||||
|
@ -169,7 +170,7 @@ static ssize_t sound_read(struct file *file, char __user *buf, size_t count, lof
|
|||
case SND_DEV_MIDIN:
|
||||
ret = MIDIbuf_read(dev, file, buf, count);
|
||||
}
|
||||
unlock_kernel();
|
||||
mutex_unlock(&soundcard_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -178,7 +179,7 @@ static ssize_t sound_write(struct file *file, const char __user *buf, size_t cou
|
|||
int dev = iminor(file->f_path.dentry->d_inode);
|
||||
int ret = -EINVAL;
|
||||
|
||||
lock_kernel();
|
||||
mutex_lock(&soundcard_mutex);
|
||||
DEB(printk("sound_write(dev=%d, count=%d)\n", dev, count));
|
||||
switch (dev & 0x0f) {
|
||||
case SND_DEV_SEQ:
|
||||
|
@ -196,7 +197,7 @@ static ssize_t sound_write(struct file *file, const char __user *buf, size_t cou
|
|||
ret = MIDIbuf_write(dev, file, buf, count);
|
||||
break;
|
||||
}
|
||||
unlock_kernel();
|
||||
mutex_unlock(&soundcard_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -210,7 +211,7 @@ static int sound_open(struct inode *inode, struct file *file)
|
|||
printk(KERN_ERR "Invalid minor device %d\n", dev);
|
||||
return -ENXIO;
|
||||
}
|
||||
lock_kernel();
|
||||
mutex_lock(&soundcard_mutex);
|
||||
switch (dev & 0x0f) {
|
||||
case SND_DEV_CTL:
|
||||
dev >>= 4;
|
||||
|
@ -247,15 +248,15 @@ static int sound_open(struct inode *inode, struct file *file)
|
|||
retval = -ENXIO;
|
||||
}
|
||||
|
||||
unlock_kernel();
|
||||
return 0;
|
||||
mutex_unlock(&soundcard_mutex);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int sound_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
int dev = iminor(inode);
|
||||
|
||||
lock_kernel();
|
||||
mutex_lock(&soundcard_mutex);
|
||||
DEB(printk("sound_release(dev=%d)\n", dev));
|
||||
switch (dev & 0x0f) {
|
||||
case SND_DEV_CTL:
|
||||
|
@ -280,7 +281,7 @@ static int sound_release(struct inode *inode, struct file *file)
|
|||
default:
|
||||
printk(KERN_ERR "Sound error: Releasing unknown device 0x%02x\n", dev);
|
||||
}
|
||||
unlock_kernel();
|
||||
mutex_unlock(&soundcard_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -354,7 +355,7 @@ static long sound_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
if (cmd == OSS_GETVERSION)
|
||||
return __put_user(SOUND_VERSION, (int __user *)p);
|
||||
|
||||
lock_kernel();
|
||||
mutex_lock(&soundcard_mutex);
|
||||
if (_IOC_TYPE(cmd) == 'M' && num_mixers > 0 && /* Mixer ioctl */
|
||||
(dev & 0x0f) != SND_DEV_CTL) {
|
||||
dtype = dev & 0x0f;
|
||||
|
@ -369,7 +370,7 @@ static long sound_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
ret = sound_mixer_ioctl(dev >> 4, cmd, p);
|
||||
break;
|
||||
}
|
||||
unlock_kernel();
|
||||
mutex_unlock(&soundcard_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -399,7 +400,7 @@ static long sound_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
break;
|
||||
|
||||
}
|
||||
unlock_kernel();
|
||||
mutex_unlock(&soundcard_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -439,35 +440,35 @@ static int sound_mmap(struct file *file, struct vm_area_struct *vma)
|
|||
printk(KERN_ERR "Sound: mmap() not supported for other than audio devices\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
lock_kernel();
|
||||
mutex_lock(&soundcard_mutex);
|
||||
if (vma->vm_flags & VM_WRITE) /* Map write and read/write to the output buf */
|
||||
dmap = audio_devs[dev]->dmap_out;
|
||||
else if (vma->vm_flags & VM_READ)
|
||||
dmap = audio_devs[dev]->dmap_in;
|
||||
else {
|
||||
printk(KERN_ERR "Sound: Undefined mmap() access\n");
|
||||
unlock_kernel();
|
||||
mutex_unlock(&soundcard_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (dmap == NULL) {
|
||||
printk(KERN_ERR "Sound: mmap() error. dmap == NULL\n");
|
||||
unlock_kernel();
|
||||
mutex_unlock(&soundcard_mutex);
|
||||
return -EIO;
|
||||
}
|
||||
if (dmap->raw_buf == NULL) {
|
||||
printk(KERN_ERR "Sound: mmap() called when raw_buf == NULL\n");
|
||||
unlock_kernel();
|
||||
mutex_unlock(&soundcard_mutex);
|
||||
return -EIO;
|
||||
}
|
||||
if (dmap->mapping_flags) {
|
||||
printk(KERN_ERR "Sound: mmap() called twice for the same DMA buffer\n");
|
||||
unlock_kernel();
|
||||
mutex_unlock(&soundcard_mutex);
|
||||
return -EIO;
|
||||
}
|
||||
if (vma->vm_pgoff != 0) {
|
||||
printk(KERN_ERR "Sound: mmap() offset must be 0.\n");
|
||||
unlock_kernel();
|
||||
mutex_unlock(&soundcard_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
size = vma->vm_end - vma->vm_start;
|
||||
|
@ -478,7 +479,7 @@ static int sound_mmap(struct file *file, struct vm_area_struct *vma)
|
|||
if (remap_pfn_range(vma, vma->vm_start,
|
||||
virt_to_phys(dmap->raw_buf) >> PAGE_SHIFT,
|
||||
vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
|
||||
unlock_kernel();
|
||||
mutex_unlock(&soundcard_mutex);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
|
@ -490,7 +491,7 @@ static int sound_mmap(struct file *file, struct vm_area_struct *vma)
|
|||
memset(dmap->raw_buf,
|
||||
dmap->neutral_byte,
|
||||
dmap->bytes_in_use);
|
||||
unlock_kernel();
|
||||
mutex_unlock(&soundcard_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,6 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/sound.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/soundcard.h>
|
||||
#include <linux/ac97_codec.h>
|
||||
#include <linux/pci.h>
|
||||
|
@ -94,6 +93,7 @@
|
|||
|
||||
struct cs4297a_state;
|
||||
|
||||
static DEFINE_MUTEX(swarm_cs4297a_mutex);
|
||||
static void stop_dac(struct cs4297a_state *s);
|
||||
static void stop_adc(struct cs4297a_state *s);
|
||||
static void start_dac(struct cs4297a_state *s);
|
||||
|
@ -1535,7 +1535,7 @@ static int cs4297a_open_mixdev(struct inode *inode, struct file *file)
|
|||
CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4,
|
||||
printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()+\n"));
|
||||
|
||||
lock_kernel();
|
||||
mutex_lock(&swarm_cs4297a_mutex);
|
||||
list_for_each(entry, &cs4297a_devs)
|
||||
{
|
||||
s = list_entry(entry, struct cs4297a_state, list);
|
||||
|
@ -1547,7 +1547,7 @@ static int cs4297a_open_mixdev(struct inode *inode, struct file *file)
|
|||
CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2,
|
||||
printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()- -ENODEV\n"));
|
||||
|
||||
unlock_kernel();
|
||||
mutex_unlock(&swarm_cs4297a_mutex);
|
||||
return -ENODEV;
|
||||
}
|
||||
VALIDATE_STATE(s);
|
||||
|
@ -1555,7 +1555,7 @@ static int cs4297a_open_mixdev(struct inode *inode, struct file *file)
|
|||
|
||||
CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4,
|
||||
printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()- 0\n"));
|
||||
unlock_kernel();
|
||||
mutex_unlock(&swarm_cs4297a_mutex);
|
||||
|
||||
return nonseekable_open(inode, file);
|
||||
}
|
||||
|
@ -1575,10 +1575,10 @@ static int cs4297a_ioctl_mixdev(struct file *file,
|
|||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int ret;
|
||||
lock_kernel();
|
||||
mutex_lock(&swarm_cs4297a_mutex);
|
||||
ret = mixer_ioctl((struct cs4297a_state *) file->private_data, cmd,
|
||||
arg);
|
||||
unlock_kernel();
|
||||
mutex_unlock(&swarm_cs4297a_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2350,9 +2350,9 @@ static long cs4297a_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
|
|||
{
|
||||
int ret;
|
||||
|
||||
lock_kernel();
|
||||
mutex_lock(&swarm_cs4297a_mutex);
|
||||
ret = cs4297a_ioctl(file, cmd, arg);
|
||||
unlock_kernel();
|
||||
mutex_unlock(&swarm_cs4297a_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -2509,9 +2509,9 @@ static int cs4297a_open(struct inode *inode, struct file *file)
|
|||
{
|
||||
int ret;
|
||||
|
||||
lock_kernel();
|
||||
mutex_lock(&swarm_cs4297a_mutex);
|
||||
ret = cs4297a_open(inode, file);
|
||||
unlock_kernel();
|
||||
mutex_unlock(&swarm_cs4297a_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -145,7 +145,6 @@
|
|||
#include <linux/init.h>
|
||||
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mutex.h>
|
||||
|
@ -160,6 +159,7 @@
|
|||
|
||||
#ifdef VWSND_DEBUG
|
||||
|
||||
static DEFINE_MUTEX(vwsnd_mutex);
|
||||
static int shut_up = 1;
|
||||
|
||||
/*
|
||||
|
@ -2891,11 +2891,11 @@ static long vwsnd_audio_ioctl(struct file *file,
|
|||
vwsnd_dev_t *devc = (vwsnd_dev_t *) file->private_data;
|
||||
int ret;
|
||||
|
||||
lock_kernel();
|
||||
mutex_lock(&vwsnd_mutex);
|
||||
mutex_lock(&devc->io_mutex);
|
||||
ret = vwsnd_audio_do_ioctl(file, cmd, arg);
|
||||
mutex_unlock(&devc->io_mutex);
|
||||
unlock_kernel();
|
||||
mutex_unlock(&vwsnd_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -2922,7 +2922,7 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
|
|||
|
||||
DBGE("(inode=0x%p, file=0x%p)\n", inode, file);
|
||||
|
||||
lock_kernel();
|
||||
mutex_lock(&vwsnd_mutex);
|
||||
INC_USE_COUNT;
|
||||
for (devc = vwsnd_dev_list; devc; devc = devc->next_dev)
|
||||
if ((devc->audio_minor & ~0x0F) == (minor & ~0x0F))
|
||||
|
@ -2930,7 +2930,7 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
|
|||
|
||||
if (devc == NULL) {
|
||||
DEC_USE_COUNT;
|
||||
unlock_kernel();
|
||||
mutex_unlock(&vwsnd_mutex);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -2939,13 +2939,13 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
|
|||
mutex_unlock(&devc->open_mutex);
|
||||
if (file->f_flags & O_NONBLOCK) {
|
||||
DEC_USE_COUNT;
|
||||
unlock_kernel();
|
||||
mutex_unlock(&vwsnd_mutex);
|
||||
return -EBUSY;
|
||||
}
|
||||
interruptible_sleep_on(&devc->open_wait);
|
||||
if (signal_pending(current)) {
|
||||
DEC_USE_COUNT;
|
||||
unlock_kernel();
|
||||
mutex_unlock(&vwsnd_mutex);
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
mutex_lock(&devc->open_mutex);
|
||||
|
@ -2998,7 +2998,7 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
|
|||
|
||||
file->private_data = devc;
|
||||
DBGRV();
|
||||
unlock_kernel();
|
||||
mutex_unlock(&vwsnd_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3012,7 +3012,7 @@ static int vwsnd_audio_release(struct inode *inode, struct file *file)
|
|||
vwsnd_port_t *wport = NULL, *rport = NULL;
|
||||
int err = 0;
|
||||
|
||||
lock_kernel();
|
||||
mutex_lock(&vwsnd_mutex);
|
||||
mutex_lock(&devc->io_mutex);
|
||||
{
|
||||
DBGEV("(inode=0x%p, file=0x%p)\n", inode, file);
|
||||
|
@ -3040,7 +3040,7 @@ static int vwsnd_audio_release(struct inode *inode, struct file *file)
|
|||
wake_up(&devc->open_wait);
|
||||
DEC_USE_COUNT;
|
||||
DBGR();
|
||||
unlock_kernel();
|
||||
mutex_unlock(&vwsnd_mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -3068,18 +3068,18 @@ static int vwsnd_mixer_open(struct inode *inode, struct file *file)
|
|||
DBGEV("(inode=0x%p, file=0x%p)\n", inode, file);
|
||||
|
||||
INC_USE_COUNT;
|
||||
lock_kernel();
|
||||
mutex_lock(&vwsnd_mutex);
|
||||
for (devc = vwsnd_dev_list; devc; devc = devc->next_dev)
|
||||
if (devc->mixer_minor == iminor(inode))
|
||||
break;
|
||||
|
||||
if (devc == NULL) {
|
||||
DEC_USE_COUNT;
|
||||
unlock_kernel();
|
||||
mutex_unlock(&vwsnd_mutex);
|
||||
return -ENODEV;
|
||||
}
|
||||
file->private_data = devc;
|
||||
unlock_kernel();
|
||||
mutex_unlock(&vwsnd_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3223,7 +3223,7 @@ static long vwsnd_mixer_ioctl(struct file *file,
|
|||
|
||||
DBGEV("(devc=0x%p, cmd=0x%x, arg=0x%lx)\n", devc, cmd, arg);
|
||||
|
||||
lock_kernel();
|
||||
mutex_lock(&vwsnd_mutex);
|
||||
mutex_lock(&devc->mix_mutex);
|
||||
{
|
||||
if ((cmd & ~nrmask) == MIXER_READ(0))
|
||||
|
@ -3234,7 +3234,7 @@ static long vwsnd_mixer_ioctl(struct file *file,
|
|||
retval = -EINVAL;
|
||||
}
|
||||
mutex_unlock(&devc->mix_mutex);
|
||||
unlock_kernel();
|
||||
mutex_unlock(&vwsnd_mutex);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
|
@ -207,12 +207,12 @@ config SND_CMIPCI
|
|||
|
||||
config SND_OXYGEN_LIB
|
||||
tristate
|
||||
select SND_PCM
|
||||
select SND_MPU401_UART
|
||||
|
||||
config SND_OXYGEN
|
||||
tristate "C-Media 8788 (Oxygen)"
|
||||
select SND_OXYGEN_LIB
|
||||
select SND_PCM
|
||||
select SND_MPU401_UART
|
||||
help
|
||||
Say Y here to include support for sound cards based on the
|
||||
C-Media CMI8788 (Oxygen HD Audio) chip:
|
||||
|
@ -581,6 +581,8 @@ config SND_HDSPM
|
|||
config SND_HIFIER
|
||||
tristate "TempoTec HiFier Fantasia"
|
||||
select SND_OXYGEN_LIB
|
||||
select SND_PCM
|
||||
select SND_MPU401_UART
|
||||
help
|
||||
Say Y here to include support for the MediaTek/TempoTec HiFier
|
||||
Fantasia sound card.
|
||||
|
@ -815,14 +817,17 @@ config SND_VIA82XX_MODEM
|
|||
will be called snd-via82xx-modem.
|
||||
|
||||
config SND_VIRTUOSO
|
||||
tristate "Asus Virtuoso 100/200 (Xonar)"
|
||||
tristate "Asus Virtuoso 66/100/200 (Xonar)"
|
||||
select SND_OXYGEN_LIB
|
||||
select SND_PCM
|
||||
select SND_MPU401_UART
|
||||
select SND_JACK if INPUT=y || INPUT=SND
|
||||
help
|
||||
Say Y here to include support for sound cards based on the
|
||||
Asus AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X,
|
||||
Asus AV66/AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, DS,
|
||||
Essence ST (Deluxe), and Essence STX.
|
||||
Support for the DS is experimental.
|
||||
Support for the HDAV1.3 (Deluxe) is very experimental.
|
||||
Support for the HDAV1.3 (Deluxe) is incomplete; for the
|
||||
HDAV1.3 Slim and Xense, missing.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-virtuoso.
|
||||
|
|
|
@ -23,7 +23,7 @@ static int __devinit snd_vortex_mixer(vortex_t * vortex)
|
|||
if ((err = snd_ac97_bus(vortex->card, 0, &ops, NULL, &pbus)) < 0)
|
||||
return err;
|
||||
memset(&ac97, 0, sizeof(ac97));
|
||||
// Intialize AC97 codec stuff.
|
||||
// Initialize AC97 codec stuff.
|
||||
ac97.private_data = vortex;
|
||||
ac97.scaps = AC97_SCAP_NO_SPDIF;
|
||||
err = snd_ac97_mixer(pbus, &ac97, &vortex->codec);
|
||||
|
|
|
@ -670,8 +670,9 @@ struct snd_ca0106_details {
|
|||
gpio_type = 2 -> shared side-out/line-in. */
|
||||
int i2c_adc; /* with i2c_adc=1, the driver adds some capture volume
|
||||
controls, phone, mic, line-in and aux. */
|
||||
int spi_dac; /* spi_dac=1 adds the mute switch for each analog
|
||||
output, front, rear, etc. */
|
||||
u16 spi_dac; /* spi_dac = 0 -> no spi interface for DACs
|
||||
spi_dac = 0x<front><rear><center-lfe><side>
|
||||
-> specifies DAC id for each channel pair. */
|
||||
};
|
||||
|
||||
// definition of the chip-specific record
|
||||
|
|
|
@ -227,7 +227,7 @@ static struct snd_ca0106_details ca0106_chip_details[] = {
|
|||
.name = "Audigy SE [SB0570]",
|
||||
.gpio_type = 1,
|
||||
.i2c_adc = 1,
|
||||
.spi_dac = 1 } ,
|
||||
.spi_dac = 0x4021 } ,
|
||||
/* New Audigy LS. Has a different DAC. */
|
||||
/* SB0570:
|
||||
* CTRL:CA0106-DAT
|
||||
|
@ -238,7 +238,17 @@ static struct snd_ca0106_details ca0106_chip_details[] = {
|
|||
.name = "Audigy SE OEM [SB0570a]",
|
||||
.gpio_type = 1,
|
||||
.i2c_adc = 1,
|
||||
.spi_dac = 1 } ,
|
||||
.spi_dac = 0x4021 } ,
|
||||
/* Sound Blaster 5.1vx
|
||||
* Tested: Playback on front, rear, center/lfe speakers
|
||||
* Not-Tested: Capture
|
||||
*/
|
||||
{ .serial = 0x10041102,
|
||||
.name = "Sound Blaster 5.1vx [SB1070]",
|
||||
.gpio_type = 1,
|
||||
.i2c_adc = 0,
|
||||
.spi_dac = 0x0124
|
||||
} ,
|
||||
/* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */
|
||||
/* SB0438
|
||||
* CTRL:CA0106-DAT
|
||||
|
@ -254,7 +264,7 @@ static struct snd_ca0106_details ca0106_chip_details[] = {
|
|||
.name = "MSI K8N Diamond MB",
|
||||
.gpio_type = 2,
|
||||
.i2c_adc = 1,
|
||||
.spi_dac = 1 } ,
|
||||
.spi_dac = 0x4021 } ,
|
||||
/* Giga-byte GA-G1975X mobo
|
||||
* Novell bnc#395807
|
||||
*/
|
||||
|
@ -483,16 +493,18 @@ static void snd_ca0106_pcm_free_substream(struct snd_pcm_runtime *runtime)
|
|||
}
|
||||
|
||||
static const int spi_dacd_reg[] = {
|
||||
[PCM_FRONT_CHANNEL] = SPI_DACD4_REG,
|
||||
[PCM_REAR_CHANNEL] = SPI_DACD0_REG,
|
||||
[PCM_CENTER_LFE_CHANNEL]= SPI_DACD2_REG,
|
||||
[PCM_UNKNOWN_CHANNEL] = SPI_DACD1_REG,
|
||||
SPI_DACD0_REG,
|
||||
SPI_DACD1_REG,
|
||||
SPI_DACD2_REG,
|
||||
0,
|
||||
SPI_DACD4_REG,
|
||||
};
|
||||
static const int spi_dacd_bit[] = {
|
||||
[PCM_FRONT_CHANNEL] = SPI_DACD4_BIT,
|
||||
[PCM_REAR_CHANNEL] = SPI_DACD0_BIT,
|
||||
[PCM_CENTER_LFE_CHANNEL]= SPI_DACD2_BIT,
|
||||
[PCM_UNKNOWN_CHANNEL] = SPI_DACD1_BIT,
|
||||
SPI_DACD0_BIT,
|
||||
SPI_DACD1_BIT,
|
||||
SPI_DACD2_BIT,
|
||||
0,
|
||||
SPI_DACD4_BIT,
|
||||
};
|
||||
|
||||
static void restore_spdif_bits(struct snd_ca0106 *chip, int idx)
|
||||
|
@ -504,6 +516,45 @@ static void restore_spdif_bits(struct snd_ca0106 *chip, int idx)
|
|||
}
|
||||
}
|
||||
|
||||
static int snd_ca0106_channel_dac(struct snd_ca0106_details *details,
|
||||
int channel_id)
|
||||
{
|
||||
switch (channel_id) {
|
||||
case PCM_FRONT_CHANNEL:
|
||||
return (details->spi_dac & 0xf000) >> (4 * 3);
|
||||
case PCM_REAR_CHANNEL:
|
||||
return (details->spi_dac & 0x0f00) >> (4 * 2);
|
||||
case PCM_CENTER_LFE_CHANNEL:
|
||||
return (details->spi_dac & 0x00f0) >> (4 * 1);
|
||||
case PCM_UNKNOWN_CHANNEL:
|
||||
return (details->spi_dac & 0x000f) >> (4 * 0);
|
||||
default:
|
||||
snd_printk(KERN_DEBUG "ca0106: unknown channel_id %d\n",
|
||||
channel_id);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_ca0106_pcm_power_dac(struct snd_ca0106 *chip, int channel_id,
|
||||
int power)
|
||||
{
|
||||
if (chip->details->spi_dac) {
|
||||
const int dac = snd_ca0106_channel_dac(chip->details,
|
||||
channel_id);
|
||||
const int reg = spi_dacd_reg[dac];
|
||||
const int bit = spi_dacd_bit[dac];
|
||||
|
||||
if (power)
|
||||
/* Power up */
|
||||
chip->spi_dac_reg[reg] &= ~bit;
|
||||
else
|
||||
/* Power down */
|
||||
chip->spi_dac_reg[reg] |= bit;
|
||||
return snd_ca0106_spi_write(chip, chip->spi_dac_reg[reg]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* open_playback callback */
|
||||
static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream,
|
||||
int channel_id)
|
||||
|
@ -543,12 +594,9 @@ static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substr
|
|||
return err;
|
||||
snd_pcm_set_sync(substream);
|
||||
|
||||
if (chip->details->spi_dac && channel_id != PCM_FRONT_CHANNEL) {
|
||||
const int reg = spi_dacd_reg[channel_id];
|
||||
|
||||
/* Power up dac */
|
||||
chip->spi_dac_reg[reg] &= ~spi_dacd_bit[channel_id];
|
||||
err = snd_ca0106_spi_write(chip, chip->spi_dac_reg[reg]);
|
||||
/* Front channel dac should already be on */
|
||||
if (channel_id != PCM_FRONT_CHANNEL) {
|
||||
err = snd_ca0106_pcm_power_dac(chip, channel_id, 1);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
@ -568,13 +616,14 @@ static int snd_ca0106_pcm_close_playback(struct snd_pcm_substream *substream)
|
|||
|
||||
restore_spdif_bits(chip, epcm->channel_id);
|
||||
|
||||
if (chip->details->spi_dac && epcm->channel_id != PCM_FRONT_CHANNEL) {
|
||||
const int reg = spi_dacd_reg[epcm->channel_id];
|
||||
|
||||
/* Power down DAC */
|
||||
chip->spi_dac_reg[reg] |= spi_dacd_bit[epcm->channel_id];
|
||||
snd_ca0106_spi_write(chip, chip->spi_dac_reg[reg]);
|
||||
/* Front channel dac should stay on */
|
||||
if (epcm->channel_id != PCM_FRONT_CHANNEL) {
|
||||
int err;
|
||||
err = snd_ca0106_pcm_power_dac(chip, epcm->channel_id, 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* FIXME: maybe zero others */
|
||||
return 0;
|
||||
}
|
||||
|
@ -1002,29 +1051,27 @@ snd_ca0106_pcm_pointer_playback(struct snd_pcm_substream *substream)
|
|||
struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_ca0106_pcm *epcm = runtime->private_data;
|
||||
snd_pcm_uframes_t ptr, ptr1, ptr2,ptr3,ptr4 = 0;
|
||||
unsigned int ptr, prev_ptr;
|
||||
int channel = epcm->channel_id;
|
||||
int timeout = 10;
|
||||
|
||||
if (!epcm->running)
|
||||
return 0;
|
||||
|
||||
ptr3 = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel);
|
||||
ptr1 = snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel);
|
||||
ptr4 = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel);
|
||||
if (ptr3 != ptr4) ptr1 = snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel);
|
||||
ptr2 = bytes_to_frames(runtime, ptr1);
|
||||
ptr2+= (ptr4 >> 3) * runtime->period_size;
|
||||
ptr=ptr2;
|
||||
if (ptr >= runtime->buffer_size)
|
||||
ptr -= runtime->buffer_size;
|
||||
/*
|
||||
printk(KERN_DEBUG "ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, "
|
||||
"buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n",
|
||||
ptr1, ptr2, ptr, (int)runtime->buffer_size,
|
||||
(int)runtime->period_size, (int)runtime->frame_bits,
|
||||
(int)runtime->rate);
|
||||
*/
|
||||
return ptr;
|
||||
prev_ptr = -1;
|
||||
do {
|
||||
ptr = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel);
|
||||
ptr = (ptr >> 3) * runtime->period_size;
|
||||
ptr += bytes_to_frames(runtime,
|
||||
snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel));
|
||||
if (ptr >= runtime->buffer_size)
|
||||
ptr -= runtime->buffer_size;
|
||||
if (prev_ptr == ptr)
|
||||
return ptr;
|
||||
prev_ptr = ptr;
|
||||
} while (--timeout);
|
||||
snd_printk(KERN_WARNING "ca0106: unstable DMA pointer!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* pointer_capture callback */
|
||||
|
@ -1362,7 +1409,7 @@ static unsigned int spi_dac_init[] = {
|
|||
SPI_REG(12, 0x00),
|
||||
SPI_REG(SPI_LDA4_REG, SPI_DA_BIT_0dB),
|
||||
SPI_REG(SPI_RDA4_REG, SPI_DA_BIT_0dB | SPI_DA_BIT_UPDATE),
|
||||
SPI_REG(SPI_DACD4_REG, 0x00),
|
||||
SPI_REG(SPI_DACD4_REG, SPI_DACD4_BIT),
|
||||
};
|
||||
|
||||
static unsigned int i2c_adc_init[][2] = {
|
||||
|
@ -1541,7 +1588,7 @@ static void ca0106_init_chip(struct snd_ca0106 *chip, int resume)
|
|||
/* snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); */
|
||||
}
|
||||
|
||||
if (chip->details->spi_dac == 1) {
|
||||
if (chip->details->spi_dac) {
|
||||
/* The SB0570 use SPI to control DAC. */
|
||||
int size, n;
|
||||
|
||||
|
@ -1553,6 +1600,9 @@ static void ca0106_init_chip(struct snd_ca0106 *chip, int resume)
|
|||
if (reg < ARRAY_SIZE(chip->spi_dac_reg))
|
||||
chip->spi_dac_reg[reg] = spi_dac_init[n];
|
||||
}
|
||||
|
||||
/* Enable front dac only */
|
||||
snd_ca0106_pcm_power_dac(chip, PCM_FRONT_CHANNEL, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -676,27 +676,64 @@ static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] __devinitdata =
|
|||
I2C_VOLUME("Aux Capture Volume", 3),
|
||||
};
|
||||
|
||||
#define SPI_SWITCH(xname,reg,bit) \
|
||||
{ \
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
|
||||
.info = spi_mute_info, \
|
||||
.get = spi_mute_get, \
|
||||
.put = spi_mute_put, \
|
||||
.private_value = (reg<<SPI_REG_SHIFT) | (bit) \
|
||||
}
|
||||
|
||||
static struct snd_kcontrol_new snd_ca0106_volume_spi_dac_ctls[]
|
||||
__devinitdata = {
|
||||
SPI_SWITCH("Analog Front Playback Switch",
|
||||
SPI_DMUTE4_REG, SPI_DMUTE4_BIT),
|
||||
SPI_SWITCH("Analog Rear Playback Switch",
|
||||
SPI_DMUTE0_REG, SPI_DMUTE0_BIT),
|
||||
SPI_SWITCH("Analog Center/LFE Playback Switch",
|
||||
SPI_DMUTE2_REG, SPI_DMUTE2_BIT),
|
||||
SPI_SWITCH("Analog Side Playback Switch",
|
||||
SPI_DMUTE1_REG, SPI_DMUTE1_BIT),
|
||||
static const int spi_dmute_reg[] = {
|
||||
SPI_DMUTE0_REG,
|
||||
SPI_DMUTE1_REG,
|
||||
SPI_DMUTE2_REG,
|
||||
0,
|
||||
SPI_DMUTE4_REG,
|
||||
};
|
||||
static const int spi_dmute_bit[] = {
|
||||
SPI_DMUTE0_BIT,
|
||||
SPI_DMUTE1_BIT,
|
||||
SPI_DMUTE2_BIT,
|
||||
0,
|
||||
SPI_DMUTE4_BIT,
|
||||
};
|
||||
|
||||
static struct snd_kcontrol_new __devinit
|
||||
snd_ca0106_volume_spi_dac_ctl(struct snd_ca0106_details *details,
|
||||
int channel_id)
|
||||
{
|
||||
struct snd_kcontrol_new spi_switch = {0};
|
||||
int reg, bit;
|
||||
int dac_id;
|
||||
|
||||
spi_switch.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
spi_switch.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
|
||||
spi_switch.info = spi_mute_info;
|
||||
spi_switch.get = spi_mute_get;
|
||||
spi_switch.put = spi_mute_put;
|
||||
|
||||
switch (channel_id) {
|
||||
case PCM_FRONT_CHANNEL:
|
||||
spi_switch.name = "Analog Front Playback Switch";
|
||||
dac_id = (details->spi_dac & 0xf000) >> (4 * 3);
|
||||
break;
|
||||
case PCM_REAR_CHANNEL:
|
||||
spi_switch.name = "Analog Rear Playback Switch";
|
||||
dac_id = (details->spi_dac & 0x0f00) >> (4 * 2);
|
||||
break;
|
||||
case PCM_CENTER_LFE_CHANNEL:
|
||||
spi_switch.name = "Analog Center/LFE Playback Switch";
|
||||
dac_id = (details->spi_dac & 0x00f0) >> (4 * 1);
|
||||
break;
|
||||
case PCM_UNKNOWN_CHANNEL:
|
||||
spi_switch.name = "Analog Side Playback Switch";
|
||||
dac_id = (details->spi_dac & 0x000f) >> (4 * 0);
|
||||
break;
|
||||
default:
|
||||
/* Unused channel */
|
||||
spi_switch.name = NULL;
|
||||
dac_id = 0;
|
||||
}
|
||||
reg = spi_dmute_reg[dac_id];
|
||||
bit = spi_dmute_bit[dac_id];
|
||||
|
||||
spi_switch.private_value = (reg << SPI_REG_SHIFT) | bit;
|
||||
|
||||
return spi_switch;
|
||||
}
|
||||
|
||||
static int __devinit remove_ctl(struct snd_card *card, const char *name)
|
||||
{
|
||||
|
@ -832,8 +869,18 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
|
|||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
if (emu->details->spi_dac == 1)
|
||||
ADD_CTLS(emu, snd_ca0106_volume_spi_dac_ctls);
|
||||
if (emu->details->spi_dac) {
|
||||
int i;
|
||||
for (i = 0;; i++) {
|
||||
struct snd_kcontrol_new ctl;
|
||||
ctl = snd_ca0106_volume_spi_dac_ctl(emu->details, i);
|
||||
if (!ctl.name)
|
||||
break;
|
||||
err = snd_ctl_add(card, snd_ctl_new1(&ctl, emu));
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create virtual master controls */
|
||||
vmaster = snd_ctl_make_virtual_master("Master Playback Volume",
|
||||
|
@ -845,7 +892,7 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
|
|||
return err;
|
||||
add_slaves(card, vmaster, slave_vols);
|
||||
|
||||
if (emu->details->spi_dac == 1) {
|
||||
if (emu->details->spi_dac) {
|
||||
vmaster = snd_ctl_make_virtual_master("Master Playback Switch",
|
||||
NULL);
|
||||
if (!vmaster)
|
||||
|
|
|
@ -321,7 +321,7 @@ static struct snd_rawmidi_ops snd_emu10k1_midi_input =
|
|||
|
||||
static void snd_emu10k1_midi_free(struct snd_rawmidi *rmidi)
|
||||
{
|
||||
struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)rmidi->private_data;
|
||||
struct snd_emu10k1_midi *midi = rmidi->private_data;
|
||||
midi->interrupt = NULL;
|
||||
midi->rmidi = NULL;
|
||||
}
|
||||
|
|
|
@ -563,6 +563,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
|
|||
case ICE1712_SUBDEVICE_DELTA1010E:
|
||||
case ICE1712_SUBDEVICE_DELTA1010LT:
|
||||
case ICE1712_SUBDEVICE_MEDIASTATION:
|
||||
case ICE1712_SUBDEVICE_EDIROLDA2496:
|
||||
ice->num_total_dacs = 8;
|
||||
ice->num_total_adcs = 8;
|
||||
break;
|
||||
|
@ -635,6 +636,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
|
|||
err = snd_ice1712_akm4xxx_init(ak, &akm_delta410, &akm_delta410_priv, ice);
|
||||
break;
|
||||
case ICE1712_SUBDEVICE_DELTA1010LT:
|
||||
case ICE1712_SUBDEVICE_EDIROLDA2496:
|
||||
err = snd_ice1712_akm4xxx_init(ak, &akm_delta1010lt, &akm_delta1010lt_priv, ice);
|
||||
break;
|
||||
case ICE1712_SUBDEVICE_DELTA66:
|
||||
|
@ -734,6 +736,7 @@ static int __devinit snd_ice1712_delta_add_controls(struct snd_ice1712 *ice)
|
|||
case ICE1712_SUBDEVICE_DELTA66:
|
||||
case ICE1712_SUBDEVICE_VX442:
|
||||
case ICE1712_SUBDEVICE_DELTA66E:
|
||||
case ICE1712_SUBDEVICE_EDIROLDA2496:
|
||||
err = snd_ice1712_akm4xxx_build_controls(ice);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
@ -813,5 +816,12 @@ struct snd_ice1712_card_info snd_ice1712_delta_cards[] __devinitdata = {
|
|||
.chip_init = snd_ice1712_delta_init,
|
||||
.build_controls = snd_ice1712_delta_add_controls,
|
||||
},
|
||||
{
|
||||
.subvendor = ICE1712_SUBDEVICE_EDIROLDA2496,
|
||||
.name = "Edirol DA2496",
|
||||
.model = "da2496",
|
||||
.chip_init = snd_ice1712_delta_init,
|
||||
.build_controls = snd_ice1712_delta_add_controls,
|
||||
},
|
||||
{ } /* terminator */
|
||||
};
|
||||
|
|
|
@ -34,7 +34,8 @@
|
|||
"{MidiMan M Audio,Delta 410},"\
|
||||
"{MidiMan M Audio,Audiophile 24/96},"\
|
||||
"{Digigram,VX442},"\
|
||||
"{Lionstracs,Mediastation},"
|
||||
"{Lionstracs,Mediastation},"\
|
||||
"{Edirol,DA2496},"
|
||||
|
||||
#define ICE1712_SUBDEVICE_DELTA1010 0x121430d6
|
||||
#define ICE1712_SUBDEVICE_DELTA1010E 0xff1430d6
|
||||
|
@ -47,6 +48,7 @@
|
|||
#define ICE1712_SUBDEVICE_DELTA1010LT 0x12143bd6
|
||||
#define ICE1712_SUBDEVICE_VX442 0x12143cd6
|
||||
#define ICE1712_SUBDEVICE_MEDIASTATION 0x694c0100
|
||||
#define ICE1712_SUBDEVICE_EDIROLDA2496 0xce164010
|
||||
|
||||
/* entry point */
|
||||
extern struct snd_ice1712_card_info snd_ice1712_delta_cards[];
|
||||
|
|
|
@ -638,7 +638,7 @@ static struct snd_kcontrol_new pontis_controls[] __devinitdata = {
|
|||
*/
|
||||
static void wm_proc_regs_write(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
|
||||
{
|
||||
struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data;
|
||||
struct snd_ice1712 *ice = entry->private_data;
|
||||
char line[64];
|
||||
unsigned int reg, val;
|
||||
mutex_lock(&ice->gpio_mutex);
|
||||
|
@ -653,7 +653,7 @@ static void wm_proc_regs_write(struct snd_info_entry *entry, struct snd_info_buf
|
|||
|
||||
static void wm_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
|
||||
{
|
||||
struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data;
|
||||
struct snd_ice1712 *ice = entry->private_data;
|
||||
int reg, val;
|
||||
|
||||
mutex_lock(&ice->gpio_mutex);
|
||||
|
@ -676,7 +676,7 @@ static void wm_proc_init(struct snd_ice1712 *ice)
|
|||
|
||||
static void cs_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
|
||||
{
|
||||
struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data;
|
||||
struct snd_ice1712 *ice = entry->private_data;
|
||||
int reg, val;
|
||||
|
||||
mutex_lock(&ice->gpio_mutex);
|
||||
|
|
|
@ -654,7 +654,7 @@ static int prodigy192_ak4114_init(struct snd_ice1712 *ice)
|
|||
static void stac9460_proc_regs_read(struct snd_info_entry *entry,
|
||||
struct snd_info_buffer *buffer)
|
||||
{
|
||||
struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data;
|
||||
struct snd_ice1712 *ice = entry->private_data;
|
||||
int reg, val;
|
||||
/* registers 0x0 - 0x14 */
|
||||
for (reg = 0; reg <= 0x15; reg++) {
|
||||
|
|
|
@ -79,6 +79,7 @@ static DEFINE_PCI_DEVICE_TABLE(oxygen_ids) = {
|
|||
{ OXYGEN_PCI_SUBID(0x13f6, 0x0001), .driver_data = MODEL_CMEDIA_REF },
|
||||
{ OXYGEN_PCI_SUBID(0x13f6, 0x0010), .driver_data = MODEL_CMEDIA_REF },
|
||||
{ OXYGEN_PCI_SUBID(0x13f6, 0x8788), .driver_data = MODEL_CMEDIA_REF },
|
||||
{ OXYGEN_PCI_SUBID(0x13f6, 0xffff), .driver_data = MODEL_CMEDIA_REF },
|
||||
{ OXYGEN_PCI_SUBID(0x147a, 0xa017), .driver_data = MODEL_CMEDIA_REF },
|
||||
{ OXYGEN_PCI_SUBID(0x1a58, 0x0910), .driver_data = MODEL_CMEDIA_REF },
|
||||
{ OXYGEN_PCI_SUBID(0x415a, 0x5431), .driver_data = MODEL_MERIDIAN },
|
||||
|
@ -505,7 +506,8 @@ static const struct oxygen_model model_generic = {
|
|||
PLAYBACK_2_TO_AC97_1 |
|
||||
CAPTURE_0_FROM_I2S_1 |
|
||||
CAPTURE_1_FROM_SPDIF |
|
||||
CAPTURE_2_FROM_AC97_1,
|
||||
CAPTURE_2_FROM_AC97_1 |
|
||||
AC97_CD_INPUT,
|
||||
.dac_channels = 8,
|
||||
.dac_volume_min = 0,
|
||||
.dac_volume_max = 255,
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
/* CAPTURE_3_FROM_I2S_3 not implemented */
|
||||
#define MIDI_OUTPUT 0x0800
|
||||
#define MIDI_INPUT 0x1000
|
||||
#define AC97_CD_INPUT 0x2000
|
||||
|
||||
enum {
|
||||
CONTROL_SPDIF_PCM,
|
||||
|
|
|
@ -308,25 +308,46 @@ static void oxygen_restore_eeprom(struct oxygen *chip,
|
|||
}
|
||||
}
|
||||
|
||||
static void pci_bridge_magic(void)
|
||||
static void configure_pcie_bridge(struct pci_dev *pci)
|
||||
{
|
||||
struct pci_dev *pci = NULL;
|
||||
enum { PEX811X, PI7C9X110 };
|
||||
static const struct pci_device_id bridge_ids[] = {
|
||||
{ PCI_VDEVICE(PLX, 0x8111), .driver_data = PEX811X },
|
||||
{ PCI_VDEVICE(PLX, 0x8112), .driver_data = PEX811X },
|
||||
{ PCI_DEVICE(0x12d8, 0xe110), .driver_data = PI7C9X110 },
|
||||
{ }
|
||||
};
|
||||
struct pci_dev *bridge;
|
||||
const struct pci_device_id *id;
|
||||
u32 tmp;
|
||||
|
||||
for (;;) {
|
||||
/* If there is any Pericom PI7C9X110 PCI-E/PCI bridge ... */
|
||||
pci = pci_get_device(0x12d8, 0xe110, pci);
|
||||
if (!pci)
|
||||
break;
|
||||
/*
|
||||
* ... configure its secondary internal arbiter to park to
|
||||
* the secondary port, instead of to the last master.
|
||||
*/
|
||||
if (!pci_read_config_dword(pci, 0x40, &tmp)) {
|
||||
tmp |= 1;
|
||||
pci_write_config_dword(pci, 0x40, tmp);
|
||||
}
|
||||
/* Why? Try asking C-Media. */
|
||||
if (!pci->bus || !pci->bus->self)
|
||||
return;
|
||||
bridge = pci->bus->self;
|
||||
|
||||
id = pci_match_id(bridge_ids, bridge);
|
||||
if (!id)
|
||||
return;
|
||||
|
||||
switch (id->driver_data) {
|
||||
case PEX811X: /* PLX PEX8111/PEX8112 PCIe/PCI bridge */
|
||||
pci_read_config_dword(bridge, 0x48, &tmp);
|
||||
tmp |= 1; /* enable blind prefetching */
|
||||
tmp |= 1 << 11; /* enable beacon generation */
|
||||
pci_write_config_dword(bridge, 0x48, tmp);
|
||||
|
||||
pci_write_config_dword(bridge, 0x84, 0x0c);
|
||||
pci_read_config_dword(bridge, 0x88, &tmp);
|
||||
tmp &= ~(7 << 27);
|
||||
tmp |= 2 << 27; /* set prefetch size to 128 bytes */
|
||||
pci_write_config_dword(bridge, 0x88, tmp);
|
||||
break;
|
||||
|
||||
case PI7C9X110: /* Pericom PI7C9X110 PCIe/PCI bridge */
|
||||
pci_read_config_dword(bridge, 0x40, &tmp);
|
||||
tmp |= 1; /* park the PCI arbiter to the sound chip */
|
||||
pci_write_config_dword(bridge, 0x40, tmp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -613,7 +634,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
|
|||
snd_card_set_dev(card, &pci->dev);
|
||||
card->private_free = oxygen_card_free;
|
||||
|
||||
pci_bridge_magic();
|
||||
configure_pcie_bridge(pci);
|
||||
oxygen_init(chip);
|
||||
chip->model.init(chip);
|
||||
|
||||
|
|
|
@ -708,7 +708,7 @@ static int ac97_fp_rec_volume_put(struct snd_kcontrol *ctl,
|
|||
.private_value = ((codec) << 24) | ((stereo) << 16) | (index), \
|
||||
}
|
||||
|
||||
static DECLARE_TLV_DB_SCALE(monitor_db_scale, -1000, 1000, 0);
|
||||
static DECLARE_TLV_DB_SCALE(monitor_db_scale, -600, 600, 0);
|
||||
static DECLARE_TLV_DB_SCALE(ac97_db_scale, -3450, 150, 0);
|
||||
static DECLARE_TLV_DB_SCALE(ac97_rec_db_scale, 0, 150, 0);
|
||||
|
||||
|
@ -972,6 +972,9 @@ static int add_controls(struct oxygen *chip,
|
|||
if (!strcmp(template.name, "Stereo Upmixing") &&
|
||||
chip->model.dac_channels == 2)
|
||||
continue;
|
||||
if (!strncmp(template.name, "CD Capture ", 11) &&
|
||||
!(chip->model.device_config & AC97_CD_INPUT))
|
||||
continue;
|
||||
if (!strcmp(template.name, "Master Playback Volume") &&
|
||||
chip->model.dac_tlv) {
|
||||
template.tlv.p = chip->model.dac_tlv;
|
||||
|
|
|
@ -56,8 +56,8 @@ static const struct snd_pcm_hardware oxygen_stereo_hardware = {
|
|||
.channels_max = 2,
|
||||
.buffer_bytes_max = BUFFER_BYTES_MAX,
|
||||
.period_bytes_min = PERIOD_BYTES_MIN,
|
||||
.period_bytes_max = BUFFER_BYTES_MAX / 2,
|
||||
.periods_min = 2,
|
||||
.period_bytes_max = BUFFER_BYTES_MAX,
|
||||
.periods_min = 1,
|
||||
.periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN,
|
||||
};
|
||||
static const struct snd_pcm_hardware oxygen_multichannel_hardware = {
|
||||
|
@ -82,8 +82,8 @@ static const struct snd_pcm_hardware oxygen_multichannel_hardware = {
|
|||
.channels_max = 8,
|
||||
.buffer_bytes_max = BUFFER_BYTES_MAX_MULTICH,
|
||||
.period_bytes_min = PERIOD_BYTES_MIN,
|
||||
.period_bytes_max = BUFFER_BYTES_MAX_MULTICH / 2,
|
||||
.periods_min = 2,
|
||||
.period_bytes_max = BUFFER_BYTES_MAX_MULTICH,
|
||||
.periods_min = 1,
|
||||
.periods_max = BUFFER_BYTES_MAX_MULTICH / PERIOD_BYTES_MIN,
|
||||
};
|
||||
static const struct snd_pcm_hardware oxygen_ac97_hardware = {
|
||||
|
@ -100,8 +100,8 @@ static const struct snd_pcm_hardware oxygen_ac97_hardware = {
|
|||
.channels_max = 2,
|
||||
.buffer_bytes_max = BUFFER_BYTES_MAX,
|
||||
.period_bytes_min = PERIOD_BYTES_MIN,
|
||||
.period_bytes_max = BUFFER_BYTES_MAX / 2,
|
||||
.periods_min = 2,
|
||||
.period_bytes_max = BUFFER_BYTES_MAX,
|
||||
.periods_min = 1,
|
||||
.periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN,
|
||||
};
|
||||
|
||||
|
|
|
@ -436,13 +436,15 @@
|
|||
/* OXYGEN_CHANNEL_* */
|
||||
|
||||
#define OXYGEN_CODEC_VERSION 0xe4
|
||||
#define OXYGEN_XCID_MASK 0x07
|
||||
#define OXYGEN_CODEC_ID_MASK 0x07
|
||||
|
||||
#define OXYGEN_REVISION 0xe6
|
||||
#define OXYGEN_REVISION_XPKGID_MASK 0x0007
|
||||
#define OXYGEN_PACKAGE_ID_MASK 0x0007
|
||||
#define OXYGEN_PACKAGE_ID_8786 0x0004
|
||||
#define OXYGEN_PACKAGE_ID_8787 0x0006
|
||||
#define OXYGEN_PACKAGE_ID_8788 0x0007
|
||||
#define OXYGEN_REVISION_MASK 0xfff8
|
||||
#define OXYGEN_REVISION_2 0x0008 /* bit flag */
|
||||
#define OXYGEN_REVISION_8787 0x0014 /* 8 bits */
|
||||
#define OXYGEN_REVISION_2 0x0008
|
||||
|
||||
#define OXYGEN_OFFSIN_48K 0xe8
|
||||
#define OXYGEN_OFFSBASE_48K 0xe9
|
||||
|
|
|
@ -25,9 +25,9 @@
|
|||
#include "xonar.h"
|
||||
|
||||
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
|
||||
MODULE_DESCRIPTION("Asus AVx00 driver");
|
||||
MODULE_DESCRIPTION("Asus Virtuoso driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_SUPPORTED_DEVICE("{{Asus,AV100},{Asus,AV200}}");
|
||||
MODULE_SUPPORTED_DEVICE("{{Asus,AV66},{Asus,AV100},{Asus,AV200}}");
|
||||
|
||||
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
|
||||
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
|
||||
|
@ -49,6 +49,7 @@ static DEFINE_PCI_DEVICE_TABLE(xonar_ids) = {
|
|||
{ OXYGEN_PCI_SUBID(0x1043, 0x834f) },
|
||||
{ OXYGEN_PCI_SUBID(0x1043, 0x835c) },
|
||||
{ OXYGEN_PCI_SUBID(0x1043, 0x835d) },
|
||||
{ OXYGEN_PCI_SUBID(0x1043, 0x835e) },
|
||||
{ OXYGEN_PCI_SUBID(0x1043, 0x838e) },
|
||||
{ OXYGEN_PCI_SUBID_BROKEN_EEPROM },
|
||||
{ }
|
||||
|
|
|
@ -367,13 +367,6 @@ static void xonar_d1_line_mic_ac97_switch(struct oxygen *chip,
|
|||
|
||||
static const DECLARE_TLV_DB_SCALE(cs4362a_db_scale, -6000, 100, 0);
|
||||
|
||||
static int xonar_d1_control_filter(struct snd_kcontrol_new *template)
|
||||
{
|
||||
if (!strncmp(template->name, "CD Capture ", 11))
|
||||
return 1; /* no CD input */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xonar_d1_mixer_init(struct oxygen *chip)
|
||||
{
|
||||
int err;
|
||||
|
@ -391,7 +384,6 @@ static const struct oxygen_model model_xonar_d1 = {
|
|||
.longname = "Asus Virtuoso 100",
|
||||
.chip = "AV200",
|
||||
.init = xonar_d1_init,
|
||||
.control_filter = xonar_d1_control_filter,
|
||||
.mixer_init = xonar_d1_mixer_init,
|
||||
.cleanup = xonar_d1_cleanup,
|
||||
.suspend = xonar_d1_suspend,
|
||||
|
|
|
@ -132,6 +132,18 @@
|
|||
* GPIO 5 <- 0
|
||||
*/
|
||||
|
||||
/*
|
||||
* Xonar HDAV1.3 Slim
|
||||
* ------------------
|
||||
*
|
||||
* CMI8788:
|
||||
*
|
||||
* GPIO 1 -> enable output
|
||||
*
|
||||
* TXD -> HDMI controller
|
||||
* RXD <- HDMI controller
|
||||
*/
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/mutex.h>
|
||||
|
@ -362,7 +374,6 @@ static void xonar_st_init_common(struct oxygen *chip)
|
|||
{
|
||||
struct xonar_pcm179x *data = chip->model_data;
|
||||
|
||||
data->generic.anti_pop_delay = 100;
|
||||
data->generic.output_enable_bit = GPIO_ST_OUTPUT_ENABLE;
|
||||
data->dacs = chip->model.private_data ? 4 : 1;
|
||||
data->hp_gain_offset = 2*-18;
|
||||
|
@ -408,6 +419,7 @@ static void xonar_st_init(struct oxygen *chip)
|
|||
{
|
||||
struct xonar_pcm179x *data = chip->model_data;
|
||||
|
||||
data->generic.anti_pop_delay = 100;
|
||||
data->has_cs2000 = 1;
|
||||
data->cs2000_fun_cfg_1 = CS2000_REF_CLK_DIV_1;
|
||||
|
||||
|
@ -428,6 +440,7 @@ static void xonar_stx_init(struct oxygen *chip)
|
|||
struct xonar_pcm179x *data = chip->model_data;
|
||||
|
||||
xonar_st_init_i2c(chip);
|
||||
data->generic.anti_pop_delay = 800;
|
||||
data->generic.ext_power_reg = OXYGEN_GPI_DATA;
|
||||
data->generic.ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
|
||||
data->generic.ext_power_bit = GPI_EXT_POWER;
|
||||
|
@ -915,13 +928,6 @@ static int xonar_d2_control_filter(struct snd_kcontrol_new *template)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int xonar_st_control_filter(struct snd_kcontrol_new *template)
|
||||
{
|
||||
if (!strncmp(template->name, "CD Capture ", 11))
|
||||
return 1; /* no CD input */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int add_pcm1796_controls(struct oxygen *chip)
|
||||
{
|
||||
int err;
|
||||
|
@ -991,7 +997,8 @@ static const struct oxygen_model model_xonar_d2 = {
|
|||
CAPTURE_0_FROM_I2S_2 |
|
||||
CAPTURE_1_FROM_SPDIF |
|
||||
MIDI_OUTPUT |
|
||||
MIDI_INPUT,
|
||||
MIDI_INPUT |
|
||||
AC97_CD_INPUT,
|
||||
.dac_channels = 8,
|
||||
.dac_volume_min = 255 - 2*60,
|
||||
.dac_volume_max = 255,
|
||||
|
@ -1037,7 +1044,6 @@ static const struct oxygen_model model_xonar_st = {
|
|||
.longname = "Asus Virtuoso 100",
|
||||
.chip = "AV200",
|
||||
.init = xonar_st_init,
|
||||
.control_filter = xonar_st_control_filter,
|
||||
.mixer_init = xonar_st_mixer_init,
|
||||
.cleanup = xonar_st_cleanup,
|
||||
.suspend = xonar_st_suspend,
|
||||
|
@ -1108,6 +1114,9 @@ int __devinit get_xonar_pcm179x_model(struct oxygen *chip,
|
|||
chip->model.resume = xonar_stx_resume;
|
||||
chip->model.set_dac_params = set_pcm1796_params;
|
||||
break;
|
||||
case 0x835e:
|
||||
snd_printk(KERN_ERR "the HDAV1.3 Slim is not supported\n");
|
||||
return -ENODEV;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
@ -25,16 +25,24 @@
|
|||
* SPI 0 -> WM8766 (surround, center/LFE, back)
|
||||
* SPI 1 -> WM8776 (front, input)
|
||||
*
|
||||
* GPIO 4 <- headphone detect
|
||||
* GPIO 6 -> route input jack to input 1/2 (1/0)
|
||||
* GPIO 7 -> enable output to speakers
|
||||
* GPIO 8 -> enable output to speakers
|
||||
* GPIO 4 <- headphone detect, 0 = plugged
|
||||
* GPIO 6 -> route input jack to mic-in (0) or line-in (1)
|
||||
* GPIO 7 -> enable output to front L/R speaker channels
|
||||
* GPIO 8 -> enable output to other speaker channels and front panel headphone
|
||||
*
|
||||
* WM8766:
|
||||
*
|
||||
* input 1 <- line
|
||||
* input 2 <- mic
|
||||
* input 3 <- front mic
|
||||
* input 4 <- aux
|
||||
*/
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/delay.h>
|
||||
#include <sound/control.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/jack.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/tlv.h>
|
||||
|
@ -44,7 +52,8 @@
|
|||
|
||||
#define GPIO_DS_HP_DETECT 0x0010
|
||||
#define GPIO_DS_INPUT_ROUTE 0x0040
|
||||
#define GPIO_DS_OUTPUT_ENABLE 0x0180
|
||||
#define GPIO_DS_OUTPUT_FRONTLR 0x0080
|
||||
#define GPIO_DS_OUTPUT_ENABLE 0x0100
|
||||
|
||||
#define LC_CONTROL_LIMITER 0x40000000
|
||||
#define LC_CONTROL_ALC 0x20000000
|
||||
|
@ -56,6 +65,7 @@ struct xonar_wm87x6 {
|
|||
struct snd_kcontrol *line_adcmux_control;
|
||||
struct snd_kcontrol *mic_adcmux_control;
|
||||
struct snd_kcontrol *lc_controls[13];
|
||||
struct snd_jack *hp_jack;
|
||||
};
|
||||
|
||||
static void wm8776_write(struct oxygen *chip,
|
||||
|
@ -97,8 +107,12 @@ static void wm8766_write(struct oxygen *chip,
|
|||
(0 << OXYGEN_SPI_CODEC_SHIFT) |
|
||||
OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
|
||||
(reg << 9) | value);
|
||||
if (reg < ARRAY_SIZE(data->wm8766_regs))
|
||||
if (reg < ARRAY_SIZE(data->wm8766_regs)) {
|
||||
if ((reg >= WM8766_LDA1 && reg <= WM8766_RDA1) ||
|
||||
(reg >= WM8766_LDA2 && reg <= WM8766_MASTDA))
|
||||
value &= ~WM8766_UPDATE;
|
||||
data->wm8766_regs[reg] = value;
|
||||
}
|
||||
}
|
||||
|
||||
static void wm8766_write_cached(struct oxygen *chip,
|
||||
|
@ -107,12 +121,8 @@ static void wm8766_write_cached(struct oxygen *chip,
|
|||
struct xonar_wm87x6 *data = chip->model_data;
|
||||
|
||||
if (reg >= ARRAY_SIZE(data->wm8766_regs) ||
|
||||
value != data->wm8766_regs[reg]) {
|
||||
if ((reg >= WM8766_LDA1 && reg <= WM8766_RDA1) ||
|
||||
(reg >= WM8766_LDA2 && reg <= WM8766_MASTDA))
|
||||
value &= ~WM8766_UPDATE;
|
||||
value != data->wm8766_regs[reg])
|
||||
wm8766_write(chip, reg, value);
|
||||
}
|
||||
}
|
||||
|
||||
static void wm8776_registers_init(struct oxygen *chip)
|
||||
|
@ -141,7 +151,10 @@ static void wm8776_registers_init(struct oxygen *chip)
|
|||
|
||||
static void wm8766_registers_init(struct oxygen *chip)
|
||||
{
|
||||
struct xonar_wm87x6 *data = chip->model_data;
|
||||
|
||||
wm8766_write(chip, WM8766_RESET, 0);
|
||||
wm8766_write(chip, WM8766_DAC_CTRL, data->wm8766_regs[WM8766_DAC_CTRL]);
|
||||
wm8766_write(chip, WM8766_INT_CTRL, WM8766_FMT_LJUST | WM8766_IWL_24);
|
||||
wm8766_write(chip, WM8766_DAC_CTRL2,
|
||||
WM8766_ZCD | (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
|
||||
|
@ -170,6 +183,40 @@ static void wm8776_init(struct oxygen *chip)
|
|||
wm8776_registers_init(chip);
|
||||
}
|
||||
|
||||
static void wm8766_init(struct oxygen *chip)
|
||||
{
|
||||
struct xonar_wm87x6 *data = chip->model_data;
|
||||
|
||||
data->wm8766_regs[WM8766_DAC_CTRL] =
|
||||
WM8766_PL_LEFT_LEFT | WM8766_PL_RIGHT_RIGHT;
|
||||
wm8766_registers_init(chip);
|
||||
}
|
||||
|
||||
static void xonar_ds_handle_hp_jack(struct oxygen *chip)
|
||||
{
|
||||
struct xonar_wm87x6 *data = chip->model_data;
|
||||
bool hp_plugged;
|
||||
unsigned int reg;
|
||||
|
||||
mutex_lock(&chip->mutex);
|
||||
|
||||
hp_plugged = !(oxygen_read16(chip, OXYGEN_GPIO_DATA) &
|
||||
GPIO_DS_HP_DETECT);
|
||||
|
||||
oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
|
||||
hp_plugged ? 0 : GPIO_DS_OUTPUT_FRONTLR,
|
||||
GPIO_DS_OUTPUT_FRONTLR);
|
||||
|
||||
reg = data->wm8766_regs[WM8766_DAC_CTRL] & ~WM8766_MUTEALL;
|
||||
if (hp_plugged)
|
||||
reg |= WM8766_MUTEALL;
|
||||
wm8766_write_cached(chip, WM8766_DAC_CTRL, reg);
|
||||
|
||||
snd_jack_report(data->hp_jack, hp_plugged ? SND_JACK_HEADPHONE : 0);
|
||||
|
||||
mutex_unlock(&chip->mutex);
|
||||
}
|
||||
|
||||
static void xonar_ds_init(struct oxygen *chip)
|
||||
{
|
||||
struct xonar_wm87x6 *data = chip->model_data;
|
||||
|
@ -178,16 +225,22 @@ static void xonar_ds_init(struct oxygen *chip)
|
|||
data->generic.output_enable_bit = GPIO_DS_OUTPUT_ENABLE;
|
||||
|
||||
wm8776_init(chip);
|
||||
wm8766_registers_init(chip);
|
||||
wm8766_init(chip);
|
||||
|
||||
oxygen_write16_masked(chip, OXYGEN_GPIO_CONTROL, GPIO_DS_INPUT_ROUTE,
|
||||
GPIO_DS_HP_DETECT | GPIO_DS_INPUT_ROUTE);
|
||||
oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
|
||||
GPIO_DS_INPUT_ROUTE | GPIO_DS_OUTPUT_FRONTLR);
|
||||
oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL,
|
||||
GPIO_DS_HP_DETECT);
|
||||
oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DS_INPUT_ROUTE);
|
||||
oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_DS_HP_DETECT);
|
||||
chip->interrupt_mask |= OXYGEN_INT_GPIO;
|
||||
|
||||
xonar_enable_output(chip);
|
||||
|
||||
snd_jack_new(chip->card, "Headphone",
|
||||
SND_JACK_HEADPHONE, &data->hp_jack);
|
||||
xonar_ds_handle_hp_jack(chip);
|
||||
|
||||
snd_component_add(chip->card, "WM8776");
|
||||
snd_component_add(chip->card, "WM8766");
|
||||
}
|
||||
|
@ -208,6 +261,7 @@ static void xonar_ds_resume(struct oxygen *chip)
|
|||
wm8776_registers_init(chip);
|
||||
wm8766_registers_init(chip);
|
||||
xonar_enable_output(chip);
|
||||
xonar_ds_handle_hp_jack(chip);
|
||||
}
|
||||
|
||||
static void wm8776_adc_hardware_filter(unsigned int channel,
|
||||
|
@ -323,12 +377,27 @@ static void update_wm87x6_mute(struct oxygen *chip)
|
|||
(chip->dac_mute ? WM8766_DMUTE_MASK : 0));
|
||||
}
|
||||
|
||||
static void update_wm8766_center_lfe_mix(struct oxygen *chip, bool mixed)
|
||||
{
|
||||
struct xonar_wm87x6 *data = chip->model_data;
|
||||
unsigned int reg;
|
||||
|
||||
/*
|
||||
* The WM8766 can mix left and right channels, but this setting
|
||||
* applies to all three stereo pairs.
|
||||
*/
|
||||
reg = data->wm8766_regs[WM8766_DAC_CTRL] &
|
||||
~(WM8766_PL_LEFT_MASK | WM8766_PL_RIGHT_MASK);
|
||||
if (mixed)
|
||||
reg |= WM8766_PL_LEFT_LRMIX | WM8766_PL_RIGHT_LRMIX;
|
||||
else
|
||||
reg |= WM8766_PL_LEFT_LEFT | WM8766_PL_RIGHT_RIGHT;
|
||||
wm8766_write_cached(chip, WM8766_DAC_CTRL, reg);
|
||||
}
|
||||
|
||||
static void xonar_ds_gpio_changed(struct oxygen *chip)
|
||||
{
|
||||
u16 bits;
|
||||
|
||||
bits = oxygen_read16(chip, OXYGEN_GPIO_DATA);
|
||||
snd_printk(KERN_INFO "HP detect: %d\n", !!(bits & GPIO_DS_HP_DETECT));
|
||||
xonar_ds_handle_hp_jack(chip);
|
||||
}
|
||||
|
||||
static int wm8776_bit_switch_get(struct snd_kcontrol *ctl,
|
||||
|
@ -896,7 +965,10 @@ static const struct snd_kcontrol_new ds_controls[] = {
|
|||
.put = wm8776_input_mux_put,
|
||||
.private_value = 1 << 1,
|
||||
},
|
||||
WM8776_BIT_SWITCH("Aux", WM8776_ADCMUX, 1 << 2, 0, 0),
|
||||
WM8776_BIT_SWITCH("Front Mic Capture Switch",
|
||||
WM8776_ADCMUX, 1 << 2, 0, 0),
|
||||
WM8776_BIT_SWITCH("Aux Capture Switch",
|
||||
WM8776_ADCMUX, 1 << 3, 0, 0),
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.name = "ADC Filter Capture Enum",
|
||||
|
@ -956,13 +1028,6 @@ static const struct snd_kcontrol_new lc_controls[] = {
|
|||
LC_CONTROL_ALC, wm8776_ngth_db_scale),
|
||||
};
|
||||
|
||||
static int xonar_ds_control_filter(struct snd_kcontrol_new *template)
|
||||
{
|
||||
if (!strncmp(template->name, "CD Capture ", 11))
|
||||
return 1; /* no CD input */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xonar_ds_mixer_init(struct oxygen *chip)
|
||||
{
|
||||
struct xonar_wm87x6 *data = chip->model_data;
|
||||
|
@ -999,10 +1064,9 @@ static int xonar_ds_mixer_init(struct oxygen *chip)
|
|||
|
||||
static const struct oxygen_model model_xonar_ds = {
|
||||
.shortname = "Xonar DS",
|
||||
.longname = "Asus Virtuoso 200",
|
||||
.longname = "Asus Virtuoso 66",
|
||||
.chip = "AV200",
|
||||
.init = xonar_ds_init,
|
||||
.control_filter = xonar_ds_control_filter,
|
||||
.mixer_init = xonar_ds_mixer_init,
|
||||
.cleanup = xonar_ds_cleanup,
|
||||
.suspend = xonar_ds_suspend,
|
||||
|
@ -1013,6 +1077,7 @@ static const struct oxygen_model model_xonar_ds = {
|
|||
.set_adc_params = set_wm8776_adc_params,
|
||||
.update_dac_volume = update_wm87x6_volume,
|
||||
.update_dac_mute = update_wm87x6_mute,
|
||||
.update_center_lfe_mix = update_wm8766_center_lfe_mix,
|
||||
.gpio_changed = xonar_ds_gpio_changed,
|
||||
.dac_tlv = wm87x6_dac_db_scale,
|
||||
.model_data_size = sizeof(struct xonar_wm87x6),
|
||||
|
|
|
@ -1527,14 +1527,14 @@ snd_rme96_free(void *private_data)
|
|||
static void
|
||||
snd_rme96_free_spdif_pcm(struct snd_pcm *pcm)
|
||||
{
|
||||
struct rme96 *rme96 = (struct rme96 *) pcm->private_data;
|
||||
struct rme96 *rme96 = pcm->private_data;
|
||||
rme96->spdif_pcm = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
snd_rme96_free_adat_pcm(struct snd_pcm *pcm)
|
||||
{
|
||||
struct rme96 *rme96 = (struct rme96 *) pcm->private_data;
|
||||
struct rme96 *rme96 = pcm->private_data;
|
||||
rme96->adat_pcm = NULL;
|
||||
}
|
||||
|
||||
|
@ -1661,7 +1661,7 @@ static void
|
|||
snd_rme96_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
|
||||
{
|
||||
int n;
|
||||
struct rme96 *rme96 = (struct rme96 *)entry->private_data;
|
||||
struct rme96 *rme96 = entry->private_data;
|
||||
|
||||
rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER);
|
||||
|
||||
|
@ -2348,7 +2348,7 @@ snd_rme96_probe(struct pci_dev *pci,
|
|||
if (err < 0)
|
||||
return err;
|
||||
card->private_free = snd_rme96_card_free;
|
||||
rme96 = (struct rme96 *)card->private_data;
|
||||
rme96 = card->private_data;
|
||||
rme96->card = card;
|
||||
rme96->pci = pci;
|
||||
snd_card_set_dev(card, &pci->dev);
|
||||
|
|
|
@ -3284,7 +3284,7 @@ static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp)
|
|||
static void
|
||||
snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
|
||||
{
|
||||
struct hdsp *hdsp = (struct hdsp *) entry->private_data;
|
||||
struct hdsp *hdsp = entry->private_data;
|
||||
unsigned int status;
|
||||
unsigned int status2;
|
||||
char *pref_sync_ref;
|
||||
|
@ -4566,7 +4566,7 @@ static int hdsp_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rm
|
|||
|
||||
static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct hdsp *hdsp = (struct hdsp *)hw->private_data;
|
||||
struct hdsp *hdsp = hw->private_data;
|
||||
void __user *argp = (void __user *)arg;
|
||||
int err;
|
||||
|
||||
|
@ -5156,7 +5156,7 @@ static int snd_hdsp_free(struct hdsp *hdsp)
|
|||
|
||||
static void snd_hdsp_card_free(struct snd_card *card)
|
||||
{
|
||||
struct hdsp *hdsp = (struct hdsp *) card->private_data;
|
||||
struct hdsp *hdsp = card->private_data;
|
||||
|
||||
if (hdsp)
|
||||
snd_hdsp_free(hdsp);
|
||||
|
@ -5182,7 +5182,7 @@ static int __devinit snd_hdsp_probe(struct pci_dev *pci,
|
|||
if (err < 0)
|
||||
return err;
|
||||
|
||||
hdsp = (struct hdsp *) card->private_data;
|
||||
hdsp = card->private_data;
|
||||
card->private_free = snd_hdsp_card_free;
|
||||
hdsp->dev = dev;
|
||||
hdsp->pci = pci;
|
||||
|
|
|
@ -785,7 +785,7 @@ static int snapper_set_capture_source(struct pmac_tumbler *mix)
|
|||
if (! mix->i2c.client)
|
||||
return -ENODEV;
|
||||
if (mix->capture_source)
|
||||
mix->acs = mix->acs |= 2;
|
||||
mix->acs |= 2;
|
||||
else
|
||||
mix->acs &= ~2;
|
||||
return i2c_smbus_write_byte_data(mix->i2c.client, TAS_REG_ACS, mix->acs);
|
||||
|
|
|
@ -150,7 +150,7 @@ static int __init sffsdr_init(void)
|
|||
sffsdr_snd_resources,
|
||||
ARRAY_SIZE(sffsdr_snd_resources));
|
||||
if (ret) {
|
||||
printk(KERN_ERR "platform device add ressources failed\n");
|
||||
printk(KERN_ERR "platform device add resources failed\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
|
|
@ -182,7 +182,7 @@ static int neo1973_gta02_voice_hw_params(
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* configue and enable PLL for 12.288MHz output */
|
||||
/* configure and enable PLL for 12.288MHz output */
|
||||
ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0,
|
||||
iis_clkrate / 4, 12288000);
|
||||
if (ret < 0)
|
||||
|
|
|
@ -201,7 +201,7 @@ static int neo1973_voice_hw_params(struct snd_pcm_substream *substream,
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* configue and enable PLL for 12.288MHz output */
|
||||
/* configure and enable PLL for 12.288MHz output */
|
||||
ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0,
|
||||
iis_clkrate / 4, 12288000);
|
||||
if (ret < 0)
|
||||
|
|
|
@ -128,6 +128,9 @@ snd_emux_init_hwdep(struct snd_emux *emu)
|
|||
strcpy(hw->name, SNDRV_EMUX_HWDEP_NAME);
|
||||
hw->iface = SNDRV_HWDEP_IFACE_EMUX_WAVETABLE;
|
||||
hw->ops.ioctl = snd_emux_hwdep_ioctl;
|
||||
/* The ioctl parameter types are compatible between 32- and
|
||||
* 64-bit architectures, so use the same function. */
|
||||
hw->ops.ioctl_compat = snd_emux_hwdep_ioctl;
|
||||
hw->exclusive = 1;
|
||||
hw->private_data = emu;
|
||||
if ((err = snd_card_register(emu->card)) < 0)
|
||||
|
|
|
@ -65,6 +65,7 @@ config SND_USB_CAIAQ
|
|||
* Native Instruments Guitar Rig Session I/O
|
||||
* Native Instruments Guitar Rig mobile
|
||||
* Native Instruments Traktor Kontrol X1
|
||||
* Native Instruments Traktor Kontrol S4
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-usb-caiaq.
|
||||
|
@ -82,6 +83,7 @@ config SND_USB_CAIAQ_INPUT
|
|||
* Native Instruments Kore Controller
|
||||
* Native Instruments Kore Controller 2
|
||||
* Native Instruments Audio Kontrol 1
|
||||
* Native Instruments Traktor Kontrol S4
|
||||
|
||||
config SND_USB_US122L
|
||||
tristate "Tascam US-122L USB driver"
|
||||
|
|
|
@ -111,7 +111,7 @@ static int stream_start(struct snd_usb_caiaqdev *dev)
|
|||
memset(dev->sub_capture, 0, sizeof(dev->sub_capture));
|
||||
dev->input_panic = 0;
|
||||
dev->output_panic = 0;
|
||||
dev->first_packet = 1;
|
||||
dev->first_packet = 4;
|
||||
dev->streaming = 1;
|
||||
dev->warned = 0;
|
||||
|
||||
|
@ -169,7 +169,7 @@ static int snd_usb_caiaq_substream_close(struct snd_pcm_substream *substream)
|
|||
}
|
||||
|
||||
static int snd_usb_caiaq_pcm_hw_params(struct snd_pcm_substream *sub,
|
||||
struct snd_pcm_hw_params *hw_params)
|
||||
struct snd_pcm_hw_params *hw_params)
|
||||
{
|
||||
debug("%s(%p)\n", __func__, sub);
|
||||
return snd_pcm_lib_malloc_pages(sub, params_buffer_bytes(hw_params));
|
||||
|
@ -189,7 +189,7 @@ static int snd_usb_caiaq_pcm_hw_free(struct snd_pcm_substream *sub)
|
|||
#endif
|
||||
|
||||
static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100,
|
||||
48000, 64000, 88200, 96000, 176400, 192000 };
|
||||
48000, 64000, 88200, 96000, 176400, 192000 };
|
||||
|
||||
static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
|
||||
{
|
||||
|
@ -201,12 +201,39 @@ static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
|
|||
debug("%s(%p)\n", __func__, substream);
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
dev->period_out_count[index] = BYTES_PER_SAMPLE + 1;
|
||||
dev->audio_out_buf_pos[index] = BYTES_PER_SAMPLE + 1;
|
||||
int out_pos;
|
||||
|
||||
switch (dev->spec.data_alignment) {
|
||||
case 0:
|
||||
case 2:
|
||||
out_pos = BYTES_PER_SAMPLE + 1;
|
||||
break;
|
||||
case 3:
|
||||
default:
|
||||
out_pos = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
dev->period_out_count[index] = out_pos;
|
||||
dev->audio_out_buf_pos[index] = out_pos;
|
||||
} else {
|
||||
int in_pos = (dev->spec.data_alignment == 2) ? 0 : 2;
|
||||
dev->period_in_count[index] = BYTES_PER_SAMPLE + in_pos;
|
||||
dev->audio_in_buf_pos[index] = BYTES_PER_SAMPLE + in_pos;
|
||||
int in_pos;
|
||||
|
||||
switch (dev->spec.data_alignment) {
|
||||
case 0:
|
||||
in_pos = BYTES_PER_SAMPLE + 2;
|
||||
break;
|
||||
case 2:
|
||||
in_pos = BYTES_PER_SAMPLE;
|
||||
break;
|
||||
case 3:
|
||||
default:
|
||||
in_pos = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
dev->period_in_count[index] = in_pos;
|
||||
dev->audio_in_buf_pos[index] = in_pos;
|
||||
}
|
||||
|
||||
if (dev->streaming)
|
||||
|
@ -221,7 +248,7 @@ static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
|
|||
snd_pcm_limit_hw_rates(runtime);
|
||||
|
||||
bytes_per_sample = BYTES_PER_SAMPLE;
|
||||
if (dev->spec.data_alignment == 2)
|
||||
if (dev->spec.data_alignment >= 2)
|
||||
bytes_per_sample++;
|
||||
|
||||
bpp = ((runtime->rate / 8000) + CLOCK_DRIFT_TOLERANCE)
|
||||
|
@ -253,6 +280,8 @@ static int snd_usb_caiaq_pcm_trigger(struct snd_pcm_substream *sub, int cmd)
|
|||
{
|
||||
struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(sub);
|
||||
|
||||
debug("%s(%p) cmd %d\n", __func__, sub, cmd);
|
||||
|
||||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
|
@ -402,6 +431,61 @@ static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev,
|
|||
}
|
||||
}
|
||||
|
||||
static void read_in_urb_mode3(struct snd_usb_caiaqdev *dev,
|
||||
const struct urb *urb,
|
||||
const struct usb_iso_packet_descriptor *iso)
|
||||
{
|
||||
unsigned char *usb_buf = urb->transfer_buffer + iso->offset;
|
||||
int stream, i;
|
||||
|
||||
/* paranoia check */
|
||||
if (iso->actual_length % (BYTES_PER_SAMPLE_USB * CHANNELS_PER_STREAM))
|
||||
return;
|
||||
|
||||
for (i = 0; i < iso->actual_length;) {
|
||||
for (stream = 0; stream < dev->n_streams; stream++) {
|
||||
struct snd_pcm_substream *sub = dev->sub_capture[stream];
|
||||
char *audio_buf = NULL;
|
||||
int c, n, sz = 0;
|
||||
|
||||
if (sub && !dev->input_panic) {
|
||||
struct snd_pcm_runtime *rt = sub->runtime;
|
||||
audio_buf = rt->dma_area;
|
||||
sz = frames_to_bytes(rt, rt->buffer_size);
|
||||
}
|
||||
|
||||
for (c = 0; c < CHANNELS_PER_STREAM; c++) {
|
||||
/* 3 audio data bytes, followed by 1 check byte */
|
||||
if (audio_buf) {
|
||||
for (n = 0; n < BYTES_PER_SAMPLE; n++) {
|
||||
audio_buf[dev->audio_in_buf_pos[stream]++] = usb_buf[i+n];
|
||||
|
||||
if (dev->audio_in_buf_pos[stream] == sz)
|
||||
dev->audio_in_buf_pos[stream] = 0;
|
||||
}
|
||||
|
||||
dev->period_in_count[stream] += BYTES_PER_SAMPLE;
|
||||
}
|
||||
|
||||
i += BYTES_PER_SAMPLE;
|
||||
|
||||
if (usb_buf[i] != ((stream << 1) | c) &&
|
||||
!dev->first_packet) {
|
||||
if (!dev->input_panic)
|
||||
printk(" EXPECTED: %02x got %02x, c %d, stream %d, i %d\n",
|
||||
((stream << 1) | c), usb_buf[i], c, stream, i);
|
||||
dev->input_panic = 1;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->first_packet > 0)
|
||||
dev->first_packet--;
|
||||
}
|
||||
|
||||
static void read_in_urb(struct snd_usb_caiaqdev *dev,
|
||||
const struct urb *urb,
|
||||
const struct usb_iso_packet_descriptor *iso)
|
||||
|
@ -419,6 +503,9 @@ static void read_in_urb(struct snd_usb_caiaqdev *dev,
|
|||
case 2:
|
||||
read_in_urb_mode2(dev, urb, iso);
|
||||
break;
|
||||
case 3:
|
||||
read_in_urb_mode3(dev, urb, iso);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((dev->input_panic || dev->output_panic) && !dev->warned) {
|
||||
|
@ -429,9 +516,9 @@ static void read_in_urb(struct snd_usb_caiaqdev *dev,
|
|||
}
|
||||
}
|
||||
|
||||
static void fill_out_urb(struct snd_usb_caiaqdev *dev,
|
||||
struct urb *urb,
|
||||
const struct usb_iso_packet_descriptor *iso)
|
||||
static void fill_out_urb_mode_0(struct snd_usb_caiaqdev *dev,
|
||||
struct urb *urb,
|
||||
const struct usb_iso_packet_descriptor *iso)
|
||||
{
|
||||
unsigned char *usb_buf = urb->transfer_buffer + iso->offset;
|
||||
struct snd_pcm_substream *sub;
|
||||
|
@ -457,9 +544,67 @@ static void fill_out_urb(struct snd_usb_caiaqdev *dev,
|
|||
/* fill in the check bytes */
|
||||
if (dev->spec.data_alignment == 2 &&
|
||||
i % (dev->n_streams * BYTES_PER_SAMPLE_USB) ==
|
||||
(dev->n_streams * CHANNELS_PER_STREAM))
|
||||
for (stream = 0; stream < dev->n_streams; stream++, i++)
|
||||
usb_buf[i] = MAKE_CHECKBYTE(dev, stream, i);
|
||||
(dev->n_streams * CHANNELS_PER_STREAM))
|
||||
for (stream = 0; stream < dev->n_streams; stream++, i++)
|
||||
usb_buf[i] = MAKE_CHECKBYTE(dev, stream, i);
|
||||
}
|
||||
}
|
||||
|
||||
static void fill_out_urb_mode_3(struct snd_usb_caiaqdev *dev,
|
||||
struct urb *urb,
|
||||
const struct usb_iso_packet_descriptor *iso)
|
||||
{
|
||||
unsigned char *usb_buf = urb->transfer_buffer + iso->offset;
|
||||
int stream, i;
|
||||
|
||||
for (i = 0; i < iso->length;) {
|
||||
for (stream = 0; stream < dev->n_streams; stream++) {
|
||||
struct snd_pcm_substream *sub = dev->sub_playback[stream];
|
||||
char *audio_buf = NULL;
|
||||
int c, n, sz = 0;
|
||||
|
||||
if (sub) {
|
||||
struct snd_pcm_runtime *rt = sub->runtime;
|
||||
audio_buf = rt->dma_area;
|
||||
sz = frames_to_bytes(rt, rt->buffer_size);
|
||||
}
|
||||
|
||||
for (c = 0; c < CHANNELS_PER_STREAM; c++) {
|
||||
for (n = 0; n < BYTES_PER_SAMPLE; n++) {
|
||||
if (audio_buf) {
|
||||
usb_buf[i+n] = audio_buf[dev->audio_out_buf_pos[stream]++];
|
||||
|
||||
if (dev->audio_out_buf_pos[stream] == sz)
|
||||
dev->audio_out_buf_pos[stream] = 0;
|
||||
} else {
|
||||
usb_buf[i+n] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (audio_buf)
|
||||
dev->period_out_count[stream] += BYTES_PER_SAMPLE;
|
||||
|
||||
i += BYTES_PER_SAMPLE;
|
||||
|
||||
/* fill in the check byte pattern */
|
||||
usb_buf[i++] = (stream << 1) | c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void fill_out_urb(struct snd_usb_caiaqdev *dev,
|
||||
struct urb *urb,
|
||||
const struct usb_iso_packet_descriptor *iso)
|
||||
{
|
||||
switch (dev->spec.data_alignment) {
|
||||
case 0:
|
||||
case 2:
|
||||
fill_out_urb_mode_0(dev, urb, iso);
|
||||
break;
|
||||
case 3:
|
||||
fill_out_urb_mode_3(dev, urb, iso);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -55,6 +55,10 @@ static int control_info(struct snd_kcontrol *kcontrol,
|
|||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
|
||||
maxval = 127;
|
||||
break;
|
||||
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
|
||||
maxval = 31;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_intval) {
|
||||
|
@ -93,6 +97,7 @@ static int control_put(struct snd_kcontrol *kcontrol,
|
|||
struct snd_usb_audio *chip = snd_kcontrol_chip(kcontrol);
|
||||
struct snd_usb_caiaqdev *dev = caiaqdev(chip->card);
|
||||
int pos = kcontrol->private_value;
|
||||
int v = ucontrol->value.integer.value[0];
|
||||
unsigned char cmd = EP1_CMD_WRITE_IO;
|
||||
|
||||
if (dev->chip.usb_id ==
|
||||
|
@ -100,12 +105,27 @@ static int control_put(struct snd_kcontrol *kcontrol,
|
|||
cmd = EP1_CMD_DIMM_LEDS;
|
||||
|
||||
if (pos & CNT_INTVAL) {
|
||||
dev->control_state[pos & ~CNT_INTVAL]
|
||||
= ucontrol->value.integer.value[0];
|
||||
snd_usb_caiaq_send_command(dev, cmd,
|
||||
dev->control_state, sizeof(dev->control_state));
|
||||
int i = pos & ~CNT_INTVAL;
|
||||
|
||||
dev->control_state[i] = v;
|
||||
|
||||
if (dev->chip.usb_id ==
|
||||
USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4)) {
|
||||
int actual_len;
|
||||
|
||||
dev->ep8_out_buf[0] = i;
|
||||
dev->ep8_out_buf[1] = v;
|
||||
|
||||
usb_bulk_msg(dev->chip.dev,
|
||||
usb_sndbulkpipe(dev->chip.dev, 8),
|
||||
dev->ep8_out_buf, sizeof(dev->ep8_out_buf),
|
||||
&actual_len, 200);
|
||||
} else {
|
||||
snd_usb_caiaq_send_command(dev, cmd,
|
||||
dev->control_state, sizeof(dev->control_state));
|
||||
}
|
||||
} else {
|
||||
if (ucontrol->value.integer.value[0])
|
||||
if (v)
|
||||
dev->control_state[pos / 8] |= 1 << (pos % 8);
|
||||
else
|
||||
dev->control_state[pos / 8] &= ~(1 << (pos % 8));
|
||||
|
@ -296,6 +316,179 @@ static struct caiaq_controller kontrolx1_controller[] = {
|
|||
{ "LED Deck B: SYNC", 8 | CNT_INTVAL },
|
||||
};
|
||||
|
||||
static struct caiaq_controller kontrols4_controller[] = {
|
||||
{ "LED: Master: Quant", 10 | CNT_INTVAL },
|
||||
{ "LED: Master: Headphone", 11 | CNT_INTVAL },
|
||||
{ "LED: Master: Master", 12 | CNT_INTVAL },
|
||||
{ "LED: Master: Snap", 14 | CNT_INTVAL },
|
||||
{ "LED: Master: Warning", 15 | CNT_INTVAL },
|
||||
{ "LED: Master: Master button", 112 | CNT_INTVAL },
|
||||
{ "LED: Master: Snap button", 113 | CNT_INTVAL },
|
||||
{ "LED: Master: Rec", 118 | CNT_INTVAL },
|
||||
{ "LED: Master: Size", 119 | CNT_INTVAL },
|
||||
{ "LED: Master: Quant button", 120 | CNT_INTVAL },
|
||||
{ "LED: Master: Browser button", 121 | CNT_INTVAL },
|
||||
{ "LED: Master: Play button", 126 | CNT_INTVAL },
|
||||
{ "LED: Master: Undo button", 127 | CNT_INTVAL },
|
||||
|
||||
{ "LED: Channel A: >", 4 | CNT_INTVAL },
|
||||
{ "LED: Channel A: <", 5 | CNT_INTVAL },
|
||||
{ "LED: Channel A: Meter 1", 97 | CNT_INTVAL },
|
||||
{ "LED: Channel A: Meter 2", 98 | CNT_INTVAL },
|
||||
{ "LED: Channel A: Meter 3", 99 | CNT_INTVAL },
|
||||
{ "LED: Channel A: Meter 4", 100 | CNT_INTVAL },
|
||||
{ "LED: Channel A: Meter 5", 101 | CNT_INTVAL },
|
||||
{ "LED: Channel A: Meter 6", 102 | CNT_INTVAL },
|
||||
{ "LED: Channel A: Meter clip", 103 | CNT_INTVAL },
|
||||
{ "LED: Channel A: Active", 114 | CNT_INTVAL },
|
||||
{ "LED: Channel A: Cue", 116 | CNT_INTVAL },
|
||||
{ "LED: Channel A: FX1", 149 | CNT_INTVAL },
|
||||
{ "LED: Channel A: FX2", 148 | CNT_INTVAL },
|
||||
|
||||
{ "LED: Channel B: >", 2 | CNT_INTVAL },
|
||||
{ "LED: Channel B: <", 3 | CNT_INTVAL },
|
||||
{ "LED: Channel B: Meter 1", 89 | CNT_INTVAL },
|
||||
{ "LED: Channel B: Meter 2", 90 | CNT_INTVAL },
|
||||
{ "LED: Channel B: Meter 3", 91 | CNT_INTVAL },
|
||||
{ "LED: Channel B: Meter 4", 92 | CNT_INTVAL },
|
||||
{ "LED: Channel B: Meter 5", 93 | CNT_INTVAL },
|
||||
{ "LED: Channel B: Meter 6", 94 | CNT_INTVAL },
|
||||
{ "LED: Channel B: Meter clip", 95 | CNT_INTVAL },
|
||||
{ "LED: Channel B: Active", 122 | CNT_INTVAL },
|
||||
{ "LED: Channel B: Cue", 125 | CNT_INTVAL },
|
||||
{ "LED: Channel B: FX1", 147 | CNT_INTVAL },
|
||||
{ "LED: Channel B: FX2", 146 | CNT_INTVAL },
|
||||
|
||||
{ "LED: Channel C: >", 6 | CNT_INTVAL },
|
||||
{ "LED: Channel C: <", 7 | CNT_INTVAL },
|
||||
{ "LED: Channel C: Meter 1", 105 | CNT_INTVAL },
|
||||
{ "LED: Channel C: Meter 2", 106 | CNT_INTVAL },
|
||||
{ "LED: Channel C: Meter 3", 107 | CNT_INTVAL },
|
||||
{ "LED: Channel C: Meter 4", 108 | CNT_INTVAL },
|
||||
{ "LED: Channel C: Meter 5", 109 | CNT_INTVAL },
|
||||
{ "LED: Channel C: Meter 6", 110 | CNT_INTVAL },
|
||||
{ "LED: Channel C: Meter clip", 111 | CNT_INTVAL },
|
||||
{ "LED: Channel C: Active", 115 | CNT_INTVAL },
|
||||
{ "LED: Channel C: Cue", 117 | CNT_INTVAL },
|
||||
{ "LED: Channel C: FX1", 151 | CNT_INTVAL },
|
||||
{ "LED: Channel C: FX2", 150 | CNT_INTVAL },
|
||||
|
||||
{ "LED: Channel D: >", 0 | CNT_INTVAL },
|
||||
{ "LED: Channel D: <", 1 | CNT_INTVAL },
|
||||
{ "LED: Channel D: Meter 1", 81 | CNT_INTVAL },
|
||||
{ "LED: Channel D: Meter 2", 82 | CNT_INTVAL },
|
||||
{ "LED: Channel D: Meter 3", 83 | CNT_INTVAL },
|
||||
{ "LED: Channel D: Meter 4", 84 | CNT_INTVAL },
|
||||
{ "LED: Channel D: Meter 5", 85 | CNT_INTVAL },
|
||||
{ "LED: Channel D: Meter 6", 86 | CNT_INTVAL },
|
||||
{ "LED: Channel D: Meter clip", 87 | CNT_INTVAL },
|
||||
{ "LED: Channel D: Active", 123 | CNT_INTVAL },
|
||||
{ "LED: Channel D: Cue", 124 | CNT_INTVAL },
|
||||
{ "LED: Channel D: FX1", 145 | CNT_INTVAL },
|
||||
{ "LED: Channel D: FX2", 144 | CNT_INTVAL },
|
||||
|
||||
{ "LED: Deck A: 1 (blue)", 22 | CNT_INTVAL },
|
||||
{ "LED: Deck A: 1 (green)", 23 | CNT_INTVAL },
|
||||
{ "LED: Deck A: 2 (blue)", 20 | CNT_INTVAL },
|
||||
{ "LED: Deck A: 2 (green)", 21 | CNT_INTVAL },
|
||||
{ "LED: Deck A: 3 (blue)", 18 | CNT_INTVAL },
|
||||
{ "LED: Deck A: 3 (green)", 19 | CNT_INTVAL },
|
||||
{ "LED: Deck A: 4 (blue)", 16 | CNT_INTVAL },
|
||||
{ "LED: Deck A: 4 (green)", 17 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Load", 44 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Deck C button", 45 | CNT_INTVAL },
|
||||
{ "LED: Deck A: In", 47 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Out", 46 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Shift", 24 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Sync", 27 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Cue", 26 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Play", 25 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Tempo up", 33 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Tempo down", 32 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Master", 34 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Keylock", 35 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Deck A", 37 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Deck C", 36 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Samples", 38 | CNT_INTVAL },
|
||||
{ "LED: Deck A: On Air", 39 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Sample 1", 31 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Sample 2", 30 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Sample 3", 29 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Sample 4", 28 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Digit 1 - A", 55 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Digit 1 - B", 54 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Digit 1 - C", 53 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Digit 1 - D", 52 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Digit 1 - E", 51 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Digit 1 - F", 50 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Digit 1 - G", 49 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Digit 1 - dot", 48 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Digit 2 - A", 63 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Digit 2 - B", 62 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Digit 2 - C", 61 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Digit 2 - D", 60 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Digit 2 - E", 59 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Digit 2 - F", 58 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Digit 2 - G", 57 | CNT_INTVAL },
|
||||
{ "LED: Deck A: Digit 2 - dot", 56 | CNT_INTVAL },
|
||||
|
||||
{ "LED: Deck B: 1 (blue)", 78 | CNT_INTVAL },
|
||||
{ "LED: Deck B: 1 (green)", 79 | CNT_INTVAL },
|
||||
{ "LED: Deck B: 2 (blue)", 76 | CNT_INTVAL },
|
||||
{ "LED: Deck B: 2 (green)", 77 | CNT_INTVAL },
|
||||
{ "LED: Deck B: 3 (blue)", 74 | CNT_INTVAL },
|
||||
{ "LED: Deck B: 3 (green)", 75 | CNT_INTVAL },
|
||||
{ "LED: Deck B: 4 (blue)", 72 | CNT_INTVAL },
|
||||
{ "LED: Deck B: 4 (green)", 73 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Load", 180 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Deck D button", 181 | CNT_INTVAL },
|
||||
{ "LED: Deck B: In", 183 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Out", 182 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Shift", 64 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Sync", 67 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Cue", 66 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Play", 65 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Tempo up", 185 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Tempo down", 184 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Master", 186 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Keylock", 187 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Deck B", 189 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Deck D", 188 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Samples", 190 | CNT_INTVAL },
|
||||
{ "LED: Deck B: On Air", 191 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Sample 1", 71 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Sample 2", 70 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Sample 3", 69 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Sample 4", 68 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Digit 1 - A", 175 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Digit 1 - B", 174 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Digit 1 - C", 173 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Digit 1 - D", 172 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Digit 1 - E", 171 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Digit 1 - F", 170 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Digit 1 - G", 169 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Digit 1 - dot", 168 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Digit 2 - A", 167 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Digit 2 - B", 166 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Digit 2 - C", 165 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Digit 2 - D", 164 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Digit 2 - E", 163 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Digit 2 - F", 162 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Digit 2 - G", 161 | CNT_INTVAL },
|
||||
{ "LED: Deck B: Digit 2 - dot", 160 | CNT_INTVAL },
|
||||
|
||||
{ "LED: FX1: dry/wet", 153 | CNT_INTVAL },
|
||||
{ "LED: FX1: 1", 154 | CNT_INTVAL },
|
||||
{ "LED: FX1: 2", 155 | CNT_INTVAL },
|
||||
{ "LED: FX1: 3", 156 | CNT_INTVAL },
|
||||
{ "LED: FX1: Mode", 157 | CNT_INTVAL },
|
||||
{ "LED: FX2: dry/wet", 129 | CNT_INTVAL },
|
||||
{ "LED: FX2: 1", 130 | CNT_INTVAL },
|
||||
{ "LED: FX2: 2", 131 | CNT_INTVAL },
|
||||
{ "LED: FX2: 3", 132 | CNT_INTVAL },
|
||||
{ "LED: FX2: Mode", 133 | CNT_INTVAL },
|
||||
};
|
||||
|
||||
static int __devinit add_controls(struct caiaq_controller *c, int num,
|
||||
struct snd_usb_caiaqdev *dev)
|
||||
{
|
||||
|
@ -354,6 +547,11 @@ int __devinit snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *dev)
|
|||
ret = add_controls(kontrolx1_controller,
|
||||
ARRAY_SIZE(kontrolx1_controller), dev);
|
||||
break;
|
||||
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
|
||||
ret = add_controls(kontrols4_controller,
|
||||
ARRAY_SIZE(kontrols4_controller), dev);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
#include "input.h"
|
||||
|
||||
MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
|
||||
MODULE_DESCRIPTION("caiaq USB audio, version 1.3.21");
|
||||
MODULE_DESCRIPTION("caiaq USB audio");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
|
||||
"{Native Instruments, RigKontrol3},"
|
||||
|
@ -48,7 +48,8 @@ MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
|
|||
"{Native Instruments, Audio 8 DJ},"
|
||||
"{Native Instruments, Session I/O},"
|
||||
"{Native Instruments, GuitarRig mobile}"
|
||||
"{Native Instruments, Traktor Kontrol X1}");
|
||||
"{Native Instruments, Traktor Kontrol X1}"
|
||||
"{Native Instruments, Traktor Kontrol S4}");
|
||||
|
||||
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */
|
||||
static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */
|
||||
|
@ -134,6 +135,11 @@ static struct usb_device_id snd_usb_id_table[] = {
|
|||
.idVendor = USB_VID_NATIVEINSTRUMENTS,
|
||||
.idProduct = USB_PID_TRAKTORKONTROLX1
|
||||
},
|
||||
{
|
||||
.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
|
||||
.idVendor = USB_VID_NATIVEINSTRUMENTS,
|
||||
.idProduct = USB_PID_TRAKTORKONTROLS4
|
||||
},
|
||||
{ /* terminator */ }
|
||||
};
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#define USB_PID_SESSIONIO 0x1915
|
||||
#define USB_PID_GUITARRIGMOBILE 0x0d8d
|
||||
#define USB_PID_TRAKTORKONTROLX1 0x2305
|
||||
#define USB_PID_TRAKTORKONTROLS4 0xbaff
|
||||
|
||||
#define EP1_BUFSIZE 64
|
||||
#define EP4_BUFSIZE 512
|
||||
|
@ -99,13 +100,14 @@ struct snd_usb_caiaqdev {
|
|||
struct snd_pcm_substream *sub_capture[MAX_STREAMS];
|
||||
|
||||
/* Controls */
|
||||
unsigned char control_state[64];
|
||||
unsigned char control_state[256];
|
||||
unsigned char ep8_out_buf[2];
|
||||
|
||||
/* Linux input */
|
||||
#ifdef CONFIG_SND_USB_CAIAQ_INPUT
|
||||
struct input_dev *input_dev;
|
||||
char phys[64]; /* physical device path */
|
||||
unsigned short keycode[64];
|
||||
unsigned short keycode[128];
|
||||
struct urb *ep4_in_urb;
|
||||
unsigned char ep4_in_buf[EP4_BUFSIZE];
|
||||
#endif
|
||||
|
|
|
@ -67,7 +67,12 @@ static unsigned short keycode_kore[] = {
|
|||
KEY_BRL_DOT5
|
||||
};
|
||||
|
||||
#define KONTROLX1_INPUTS 40
|
||||
#define KONTROLX1_INPUTS (40)
|
||||
#define KONTROLS4_BUTTONS (12 * 8)
|
||||
#define KONTROLS4_AXIS (46)
|
||||
|
||||
#define KONTROLS4_BUTTON(X) ((X) + BTN_MISC)
|
||||
#define KONTROLS4_ABS(X) ((X) + ABS_HAT0X)
|
||||
|
||||
#define DEG90 (range / 2)
|
||||
#define DEG180 (range)
|
||||
|
@ -139,6 +144,13 @@ static unsigned int decode_erp(unsigned char a, unsigned char b)
|
|||
#undef HIGH_PEAK
|
||||
#undef LOW_PEAK
|
||||
|
||||
static inline void snd_caiaq_input_report_abs(struct snd_usb_caiaqdev *dev,
|
||||
int axis, const unsigned char *buf,
|
||||
int offset)
|
||||
{
|
||||
input_report_abs(dev->input_dev, axis,
|
||||
(buf[offset * 2] << 8) | buf[offset * 2 + 1]);
|
||||
}
|
||||
|
||||
static void snd_caiaq_input_read_analog(struct snd_usb_caiaqdev *dev,
|
||||
const unsigned char *buf,
|
||||
|
@ -148,36 +160,30 @@ static void snd_caiaq_input_read_analog(struct snd_usb_caiaqdev *dev,
|
|||
|
||||
switch (dev->chip.usb_id) {
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2):
|
||||
input_report_abs(input_dev, ABS_X, (buf[4] << 8) | buf[5]);
|
||||
input_report_abs(input_dev, ABS_Y, (buf[0] << 8) | buf[1]);
|
||||
input_report_abs(input_dev, ABS_Z, (buf[2] << 8) | buf[3]);
|
||||
input_sync(input_dev);
|
||||
snd_caiaq_input_report_abs(dev, ABS_X, buf, 2);
|
||||
snd_caiaq_input_report_abs(dev, ABS_Y, buf, 0);
|
||||
snd_caiaq_input_report_abs(dev, ABS_Z, buf, 1);
|
||||
break;
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3):
|
||||
input_report_abs(input_dev, ABS_X, (buf[0] << 8) | buf[1]);
|
||||
input_report_abs(input_dev, ABS_Y, (buf[2] << 8) | buf[3]);
|
||||
input_report_abs(input_dev, ABS_Z, (buf[4] << 8) | buf[5]);
|
||||
input_sync(input_dev);
|
||||
break;
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER):
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2):
|
||||
input_report_abs(input_dev, ABS_X, (buf[0] << 8) | buf[1]);
|
||||
input_report_abs(input_dev, ABS_Y, (buf[2] << 8) | buf[3]);
|
||||
input_report_abs(input_dev, ABS_Z, (buf[4] << 8) | buf[5]);
|
||||
input_sync(input_dev);
|
||||
snd_caiaq_input_report_abs(dev, ABS_X, buf, 0);
|
||||
snd_caiaq_input_report_abs(dev, ABS_Y, buf, 1);
|
||||
snd_caiaq_input_report_abs(dev, ABS_Z, buf, 2);
|
||||
break;
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
|
||||
input_report_abs(input_dev, ABS_HAT0X, (buf[8] << 8) | buf[9]);
|
||||
input_report_abs(input_dev, ABS_HAT0Y, (buf[4] << 8) | buf[5]);
|
||||
input_report_abs(input_dev, ABS_HAT1X, (buf[12] << 8) | buf[13]);
|
||||
input_report_abs(input_dev, ABS_HAT1Y, (buf[2] << 8) | buf[3]);
|
||||
input_report_abs(input_dev, ABS_HAT2X, (buf[14] << 8) | buf[15]);
|
||||
input_report_abs(input_dev, ABS_HAT2Y, (buf[0] << 8) | buf[1]);
|
||||
input_report_abs(input_dev, ABS_HAT3X, (buf[10] << 8) | buf[11]);
|
||||
input_report_abs(input_dev, ABS_HAT3Y, (buf[6] << 8) | buf[7]);
|
||||
input_sync(input_dev);
|
||||
snd_caiaq_input_report_abs(dev, ABS_HAT0X, buf, 4);
|
||||
snd_caiaq_input_report_abs(dev, ABS_HAT0Y, buf, 2);
|
||||
snd_caiaq_input_report_abs(dev, ABS_HAT1X, buf, 6);
|
||||
snd_caiaq_input_report_abs(dev, ABS_HAT1Y, buf, 1);
|
||||
snd_caiaq_input_report_abs(dev, ABS_HAT2X, buf, 7);
|
||||
snd_caiaq_input_report_abs(dev, ABS_HAT2Y, buf, 0);
|
||||
snd_caiaq_input_report_abs(dev, ABS_HAT3X, buf, 5);
|
||||
snd_caiaq_input_report_abs(dev, ABS_HAT3Y, buf, 3);
|
||||
break;
|
||||
}
|
||||
|
||||
input_sync(input_dev);
|
||||
}
|
||||
|
||||
static void snd_caiaq_input_read_erp(struct snd_usb_caiaqdev *dev,
|
||||
|
@ -250,6 +256,150 @@ static void snd_caiaq_input_read_io(struct snd_usb_caiaqdev *dev,
|
|||
input_sync(input_dev);
|
||||
}
|
||||
|
||||
#define TKS4_MSGBLOCK_SIZE 16
|
||||
|
||||
static void snd_usb_caiaq_tks4_dispatch(struct snd_usb_caiaqdev *dev,
|
||||
const unsigned char *buf,
|
||||
unsigned int len)
|
||||
{
|
||||
while (len) {
|
||||
unsigned int i, block_id = (buf[0] << 8) | buf[1];
|
||||
|
||||
switch (block_id) {
|
||||
case 0:
|
||||
/* buttons */
|
||||
for (i = 0; i < KONTROLS4_BUTTONS; i++)
|
||||
input_report_key(dev->input_dev, KONTROLS4_BUTTON(i),
|
||||
(buf[4 + (i / 8)] >> (i % 8)) & 1);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
/* left wheel */
|
||||
input_report_abs(dev->input_dev, KONTROLS4_ABS(36), buf[9] | ((buf[8] & 0x3) << 8));
|
||||
/* right wheel */
|
||||
input_report_abs(dev->input_dev, KONTROLS4_ABS(37), buf[13] | ((buf[12] & 0x3) << 8));
|
||||
|
||||
/* rotary encoders */
|
||||
input_report_abs(dev->input_dev, KONTROLS4_ABS(38), buf[3] & 0xf);
|
||||
input_report_abs(dev->input_dev, KONTROLS4_ABS(39), buf[4] >> 4);
|
||||
input_report_abs(dev->input_dev, KONTROLS4_ABS(40), buf[4] & 0xf);
|
||||
input_report_abs(dev->input_dev, KONTROLS4_ABS(41), buf[5] >> 4);
|
||||
input_report_abs(dev->input_dev, KONTROLS4_ABS(42), buf[5] & 0xf);
|
||||
input_report_abs(dev->input_dev, KONTROLS4_ABS(43), buf[6] >> 4);
|
||||
input_report_abs(dev->input_dev, KONTROLS4_ABS(44), buf[6] & 0xf);
|
||||
input_report_abs(dev->input_dev, KONTROLS4_ABS(45), buf[7] >> 4);
|
||||
input_report_abs(dev->input_dev, KONTROLS4_ABS(46), buf[7] & 0xf);
|
||||
|
||||
break;
|
||||
case 2:
|
||||
/* Volume Fader Channel D */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(0), buf, 1);
|
||||
/* Volume Fader Channel B */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(1), buf, 2);
|
||||
/* Volume Fader Channel A */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(2), buf, 3);
|
||||
/* Volume Fader Channel C */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(3), buf, 4);
|
||||
/* Loop Volume */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(4), buf, 6);
|
||||
/* Crossfader */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(7), buf, 7);
|
||||
|
||||
break;
|
||||
|
||||
case 3:
|
||||
/* Tempo Fader R */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(6), buf, 3);
|
||||
/* Tempo Fader L */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(5), buf, 4);
|
||||
/* Mic Volume */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(8), buf, 6);
|
||||
/* Cue Mix */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(9), buf, 7);
|
||||
|
||||
break;
|
||||
|
||||
case 4:
|
||||
/* Wheel distance sensor L */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(10), buf, 1);
|
||||
/* Wheel distance sensor R */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(11), buf, 2);
|
||||
/* Channel D EQ - Filter */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(12), buf, 3);
|
||||
/* Channel D EQ - Low */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(13), buf, 4);
|
||||
/* Channel D EQ - Mid */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(14), buf, 5);
|
||||
/* Channel D EQ - Hi */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(15), buf, 6);
|
||||
/* FX2 - dry/wet */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(16), buf, 7);
|
||||
|
||||
break;
|
||||
|
||||
case 5:
|
||||
/* FX2 - 1 */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(17), buf, 1);
|
||||
/* FX2 - 2 */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(18), buf, 2);
|
||||
/* FX2 - 3 */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(19), buf, 3);
|
||||
/* Channel B EQ - Filter */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(20), buf, 4);
|
||||
/* Channel B EQ - Low */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(21), buf, 5);
|
||||
/* Channel B EQ - Mid */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(22), buf, 6);
|
||||
/* Channel B EQ - Hi */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(23), buf, 7);
|
||||
|
||||
break;
|
||||
|
||||
case 6:
|
||||
/* Channel A EQ - Filter */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(24), buf, 1);
|
||||
/* Channel A EQ - Low */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(25), buf, 2);
|
||||
/* Channel A EQ - Mid */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(26), buf, 3);
|
||||
/* Channel A EQ - Hi */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(27), buf, 4);
|
||||
/* Channel C EQ - Filter */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(28), buf, 5);
|
||||
/* Channel C EQ - Low */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(29), buf, 6);
|
||||
/* Channel C EQ - Mid */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(30), buf, 7);
|
||||
|
||||
break;
|
||||
|
||||
case 7:
|
||||
/* Channel C EQ - Hi */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(31), buf, 1);
|
||||
/* FX1 - wet/dry */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(32), buf, 2);
|
||||
/* FX1 - 1 */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(33), buf, 3);
|
||||
/* FX1 - 2 */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(34), buf, 4);
|
||||
/* FX1 - 3 */
|
||||
snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(35), buf, 5);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
debug("%s(): bogus block (id %d)\n",
|
||||
__func__, block_id);
|
||||
return;
|
||||
}
|
||||
|
||||
len -= TKS4_MSGBLOCK_SIZE;
|
||||
buf += TKS4_MSGBLOCK_SIZE;
|
||||
}
|
||||
|
||||
input_sync(dev->input_dev);
|
||||
}
|
||||
|
||||
static void snd_usb_caiaq_ep4_reply_dispatch(struct urb *urb)
|
||||
{
|
||||
struct snd_usb_caiaqdev *dev = urb->context;
|
||||
|
@ -259,11 +409,11 @@ static void snd_usb_caiaq_ep4_reply_dispatch(struct urb *urb)
|
|||
if (urb->status || !dev || urb != dev->ep4_in_urb)
|
||||
return;
|
||||
|
||||
if (urb->actual_length < 24)
|
||||
goto requeue;
|
||||
|
||||
switch (dev->chip.usb_id) {
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
|
||||
if (urb->actual_length < 24)
|
||||
goto requeue;
|
||||
|
||||
if (buf[0] & 0x3)
|
||||
snd_caiaq_input_read_io(dev, buf + 1, 7);
|
||||
|
||||
|
@ -271,6 +421,10 @@ static void snd_usb_caiaq_ep4_reply_dispatch(struct urb *urb)
|
|||
snd_caiaq_input_read_analog(dev, buf + 8, 16);
|
||||
|
||||
break;
|
||||
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
|
||||
snd_usb_caiaq_tks4_dispatch(dev, buf, urb->actual_length);
|
||||
break;
|
||||
}
|
||||
|
||||
requeue:
|
||||
|
@ -289,6 +443,7 @@ static int snd_usb_caiaq_input_open(struct input_dev *idev)
|
|||
|
||||
switch (dev->chip.usb_id) {
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
|
||||
if (usb_submit_urb(dev->ep4_in_urb, GFP_KERNEL) != 0)
|
||||
return -EIO;
|
||||
break;
|
||||
|
@ -306,6 +461,7 @@ static void snd_usb_caiaq_input_close(struct input_dev *idev)
|
|||
|
||||
switch (dev->chip.usb_id) {
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
|
||||
usb_kill_urb(dev->ep4_in_urb);
|
||||
break;
|
||||
}
|
||||
|
@ -456,6 +612,46 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
|
|||
snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5);
|
||||
|
||||
break;
|
||||
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
|
||||
input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
|
||||
BUILD_BUG_ON(sizeof(dev->keycode) < KONTROLS4_BUTTONS);
|
||||
for (i = 0; i < KONTROLS4_BUTTONS; i++)
|
||||
dev->keycode[i] = KONTROLS4_BUTTON(i);
|
||||
input->keycodemax = KONTROLS4_BUTTONS;
|
||||
|
||||
for (i = 0; i < KONTROLS4_AXIS; i++) {
|
||||
int axis = KONTROLS4_ABS(i);
|
||||
input->absbit[BIT_WORD(axis)] |= BIT_MASK(axis);
|
||||
}
|
||||
|
||||
/* 36 analog potentiometers and faders */
|
||||
for (i = 0; i < 36; i++)
|
||||
input_set_abs_params(input, KONTROLS4_ABS(i), 0, 0xfff, 0, 10);
|
||||
|
||||
/* 2 encoder wheels */
|
||||
input_set_abs_params(input, KONTROLS4_ABS(36), 0, 0x3ff, 0, 1);
|
||||
input_set_abs_params(input, KONTROLS4_ABS(37), 0, 0x3ff, 0, 1);
|
||||
|
||||
/* 9 rotary encoders */
|
||||
for (i = 0; i < 9; i++)
|
||||
input_set_abs_params(input, KONTROLS4_ABS(38+i), 0, 0xf, 0, 1);
|
||||
|
||||
dev->ep4_in_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!dev->ep4_in_urb) {
|
||||
ret = -ENOMEM;
|
||||
goto exit_free_idev;
|
||||
}
|
||||
|
||||
usb_fill_bulk_urb(dev->ep4_in_urb, usb_dev,
|
||||
usb_rcvbulkpipe(usb_dev, 0x4),
|
||||
dev->ep4_in_buf, EP4_BUFSIZE,
|
||||
snd_usb_caiaq_ep4_reply_dispatch, dev);
|
||||
|
||||
snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
/* no input methods supported on this device */
|
||||
goto exit_free_idev;
|
||||
|
|
|
@ -300,9 +300,13 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
|
|||
|
||||
*rchip = NULL;
|
||||
|
||||
if (snd_usb_get_speed(dev) != USB_SPEED_LOW &&
|
||||
snd_usb_get_speed(dev) != USB_SPEED_FULL &&
|
||||
snd_usb_get_speed(dev) != USB_SPEED_HIGH) {
|
||||
switch (snd_usb_get_speed(dev)) {
|
||||
case USB_SPEED_LOW:
|
||||
case USB_SPEED_FULL:
|
||||
case USB_SPEED_HIGH:
|
||||
case USB_SPEED_SUPER:
|
||||
break;
|
||||
default:
|
||||
snd_printk(KERN_ERR "unknown device speed %d\n", snd_usb_get_speed(dev));
|
||||
return -ENXIO;
|
||||
}
|
||||
|
@ -378,11 +382,22 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
|
|||
if (len < sizeof(card->longname))
|
||||
usb_make_path(dev, card->longname + len, sizeof(card->longname) - len);
|
||||
|
||||
strlcat(card->longname,
|
||||
snd_usb_get_speed(dev) == USB_SPEED_LOW ? ", low speed" :
|
||||
snd_usb_get_speed(dev) == USB_SPEED_FULL ? ", full speed" :
|
||||
", high speed",
|
||||
sizeof(card->longname));
|
||||
switch (snd_usb_get_speed(dev)) {
|
||||
case USB_SPEED_LOW:
|
||||
strlcat(card->longname, ", low speed", sizeof(card->longname));
|
||||
break;
|
||||
case USB_SPEED_FULL:
|
||||
strlcat(card->longname, ", full speed", sizeof(card->longname));
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
strlcat(card->longname, ", high speed", sizeof(card->longname));
|
||||
break;
|
||||
case USB_SPEED_SUPER:
|
||||
strlcat(card->longname, ", super speed", sizeof(card->longname));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
snd_usb_audio_create_proc(chip);
|
||||
|
||||
|
|
|
@ -405,8 +405,6 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
|
|||
break;
|
||||
case USB_ID(0x041e, 0x3020): /* Creative SB Audigy 2 NX */
|
||||
case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
|
||||
case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra 8 */
|
||||
case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */
|
||||
/* doesn't set the sample rate attribute, but supports it */
|
||||
fp->attributes |= UAC_EP_CS_ATTR_SAMPLE_RATE;
|
||||
break;
|
||||
|
|
|
@ -103,11 +103,16 @@ int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request,
|
|||
unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip,
|
||||
struct usb_host_interface *alts)
|
||||
{
|
||||
if (snd_usb_get_speed(chip->dev) == USB_SPEED_HIGH &&
|
||||
get_endpoint(alts, 0)->bInterval >= 1 &&
|
||||
get_endpoint(alts, 0)->bInterval <= 4)
|
||||
return get_endpoint(alts, 0)->bInterval - 1;
|
||||
else
|
||||
return 0;
|
||||
switch (snd_usb_get_speed(chip->dev)) {
|
||||
case USB_SPEED_HIGH:
|
||||
case USB_SPEED_SUPER:
|
||||
if (get_endpoint(alts, 0)->bInterval >= 1 &&
|
||||
get_endpoint(alts, 0)->bInterval <= 4)
|
||||
return get_endpoint(alts, 0)->bInterval - 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -784,7 +784,7 @@ static struct usb_protocol_ops snd_usbmidi_novation_ops = {
|
|||
};
|
||||
|
||||
/*
|
||||
* "raw" protocol: used by the MOTU FastLane.
|
||||
* "raw" protocol: just move raw MIDI bytes from/to the endpoint
|
||||
*/
|
||||
|
||||
static void snd_usbmidi_raw_input(struct snd_usb_midi_in_endpoint* ep,
|
||||
|
@ -834,7 +834,14 @@ static void snd_usbmidi_us122l_output(struct snd_usb_midi_out_endpoint *ep,
|
|||
|
||||
if (!ep->ports[0].active)
|
||||
return;
|
||||
count = snd_usb_get_speed(ep->umidi->dev) == USB_SPEED_HIGH ? 1 : 2;
|
||||
switch (snd_usb_get_speed(ep->umidi->dev)) {
|
||||
case USB_SPEED_HIGH:
|
||||
case USB_SPEED_SUPER:
|
||||
count = 1;
|
||||
break;
|
||||
default:
|
||||
count = 2;
|
||||
}
|
||||
count = snd_rawmidi_transmit(ep->ports[0].substream,
|
||||
urb->transfer_buffer,
|
||||
count);
|
||||
|
@ -2115,7 +2122,7 @@ int snd_usbmidi_create(struct snd_card *card,
|
|||
umidi->usb_protocol_ops = &snd_usbmidi_novation_ops;
|
||||
err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
|
||||
break;
|
||||
case QUIRK_MIDI_FASTLANE:
|
||||
case QUIRK_MIDI_RAW_BYTES:
|
||||
umidi->usb_protocol_ops = &snd_usbmidi_raw_ops;
|
||||
/*
|
||||
* Interface 1 contains isochronous endpoints, but with the same
|
||||
|
@ -2126,7 +2133,8 @@ int snd_usbmidi_create(struct snd_card *card,
|
|||
* interface 0, so we have to make sure that the USB core looks
|
||||
* again at interface 0 by calling usb_set_interface() on it.
|
||||
*/
|
||||
usb_set_interface(umidi->dev, 0, 0);
|
||||
if (umidi->usb_id == USB_ID(0x07fd, 0x0001)) /* MOTU Fastlane */
|
||||
usb_set_interface(umidi->dev, 0, 0);
|
||||
err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
|
||||
break;
|
||||
case QUIRK_MIDI_EMAGIC:
|
||||
|
|
|
@ -759,8 +759,6 @@ static void usb_mixer_elem_free(struct snd_kcontrol *kctl)
|
|||
*/
|
||||
static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
|
||||
{
|
||||
struct snd_usb_audio *chip = cval->mixer->chip;
|
||||
|
||||
/* for failsafe */
|
||||
cval->min = default_min;
|
||||
cval->max = cval->min + 1;
|
||||
|
@ -783,7 +781,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
|
|||
if (get_ctl_value(cval, UAC_GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 ||
|
||||
get_ctl_value(cval, UAC_GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) {
|
||||
snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n",
|
||||
cval->id, snd_usb_ctrl_intf(chip), cval->control, cval->id);
|
||||
cval->id, snd_usb_ctrl_intf(cval->mixer->chip), cval->control, cval->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (get_ctl_value(cval, UAC_GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) {
|
||||
|
@ -1642,9 +1640,10 @@ static int mixer_ctl_selector_info(struct snd_kcontrol *kcontrol, struct snd_ctl
|
|||
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
|
||||
uinfo->count = 1;
|
||||
uinfo->value.enumerated.items = cval->max;
|
||||
if ((int)uinfo->value.enumerated.item >= cval->max)
|
||||
if (uinfo->value.enumerated.item >= cval->max)
|
||||
uinfo->value.enumerated.item = cval->max - 1;
|
||||
strcpy(uinfo->value.enumerated.name, itemlist[uinfo->value.enumerated.item]);
|
||||
strlcpy(uinfo->value.enumerated.name, itemlist[uinfo->value.enumerated.item],
|
||||
sizeof(uinfo->value.enumerated.name));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@ static const struct rc_config {
|
|||
{ USB_ID(0x041e, 0x3000), 0, 1, 2, 1, 18, 0x0013 }, /* Extigy */
|
||||
{ USB_ID(0x041e, 0x3020), 2, 1, 6, 6, 18, 0x0013 }, /* Audigy 2 NX */
|
||||
{ USB_ID(0x041e, 0x3040), 2, 2, 6, 6, 2, 0x6e91 }, /* Live! 24-bit */
|
||||
{ USB_ID(0x041e, 0x3042), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi */
|
||||
{ USB_ID(0x041e, 0x3048), 2, 2, 6, 6, 2, 0x6e91 }, /* Toshiba SB0500 */
|
||||
};
|
||||
|
||||
|
|
|
@ -466,7 +466,7 @@ static int hw_check_valid_format(struct snd_usb_substream *subs,
|
|||
return 0;
|
||||
}
|
||||
/* check whether the period time is >= the data packet interval */
|
||||
if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH) {
|
||||
if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) {
|
||||
ptime = 125 * (1 << fp->datainterval);
|
||||
if (ptime > pt->max || (ptime == pt->max && pt->openmax)) {
|
||||
hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max);
|
||||
|
@ -734,7 +734,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
|
|||
}
|
||||
|
||||
param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME;
|
||||
if (snd_usb_get_speed(subs->dev) != USB_SPEED_HIGH)
|
||||
if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
|
||||
/* full speed devices have fixed data packet interval */
|
||||
ptmin = 1000;
|
||||
if (ptmin == 1000)
|
||||
|
|
|
@ -107,7 +107,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s
|
|||
}
|
||||
snd_iprintf(buffer, "\n");
|
||||
}
|
||||
if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH)
|
||||
if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL)
|
||||
snd_iprintf(buffer, " Data packet interval: %d us\n",
|
||||
125 * (1 << fp->datainterval));
|
||||
// snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize);
|
||||
|
|
|
@ -240,9 +240,21 @@ YAMAHA_DEVICE(0x104f, NULL),
|
|||
YAMAHA_DEVICE(0x1050, NULL),
|
||||
YAMAHA_DEVICE(0x1051, NULL),
|
||||
YAMAHA_DEVICE(0x1052, NULL),
|
||||
YAMAHA_INTERFACE(0x1053, 0, NULL),
|
||||
YAMAHA_INTERFACE(0x1054, 0, NULL),
|
||||
YAMAHA_DEVICE(0x1055, NULL),
|
||||
YAMAHA_DEVICE(0x1056, NULL),
|
||||
YAMAHA_DEVICE(0x1057, NULL),
|
||||
YAMAHA_DEVICE(0x1058, NULL),
|
||||
YAMAHA_DEVICE(0x1059, NULL),
|
||||
YAMAHA_DEVICE(0x105a, NULL),
|
||||
YAMAHA_DEVICE(0x105b, NULL),
|
||||
YAMAHA_DEVICE(0x105c, NULL),
|
||||
YAMAHA_DEVICE(0x105d, NULL),
|
||||
YAMAHA_DEVICE(0x2000, "DGP-7"),
|
||||
YAMAHA_DEVICE(0x2001, "DGP-5"),
|
||||
YAMAHA_DEVICE(0x2002, NULL),
|
||||
YAMAHA_DEVICE(0x2003, NULL),
|
||||
YAMAHA_DEVICE(0x5000, "CS1D"),
|
||||
YAMAHA_DEVICE(0x5001, "DSP1D"),
|
||||
YAMAHA_DEVICE(0x5002, "DME32"),
|
||||
|
@ -1135,12 +1147,35 @@ YAMAHA_DEVICE(0x7010, "UB99"),
|
|||
.type = QUIRK_MIDI_STANDARD_INTERFACE
|
||||
}
|
||||
},
|
||||
{
|
||||
/* has ID 0x0066 when not in "Advanced Driver" mode */
|
||||
USB_DEVICE(0x0582, 0x0064),
|
||||
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
|
||||
/* .vendor_name = "EDIROL", */
|
||||
/* .product_name = "PCR-1", */
|
||||
.ifnum = QUIRK_ANY_INTERFACE,
|
||||
.type = QUIRK_COMPOSITE,
|
||||
.data = (const struct snd_usb_audio_quirk[]) {
|
||||
{
|
||||
.ifnum = 1,
|
||||
.type = QUIRK_AUDIO_STANDARD_INTERFACE
|
||||
},
|
||||
{
|
||||
.ifnum = 2,
|
||||
.type = QUIRK_AUDIO_STANDARD_INTERFACE
|
||||
},
|
||||
{
|
||||
.ifnum = -1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
/* has ID 0x0067 when not in "Advanced Driver" mode */
|
||||
USB_DEVICE(0x0582, 0x0065),
|
||||
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
|
||||
.vendor_name = "EDIROL",
|
||||
.product_name = "PCR-1",
|
||||
/* .vendor_name = "EDIROL", */
|
||||
/* .product_name = "PCR-1", */
|
||||
.ifnum = 0,
|
||||
.type = QUIRK_MIDI_FIXED_ENDPOINT,
|
||||
.data = & (const struct snd_usb_midi_endpoint_info) {
|
||||
|
@ -1525,6 +1560,50 @@ YAMAHA_DEVICE(0x7010, "UB99"),
|
|||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
/* has ID 0x0110 when not in Advanced Driver mode */
|
||||
USB_DEVICE_VENDOR_SPEC(0x0582, 0x010f),
|
||||
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
|
||||
/* .vendor_name = "Roland", */
|
||||
/* .product_name = "A-PRO", */
|
||||
.ifnum = 1,
|
||||
.type = QUIRK_MIDI_FIXED_ENDPOINT,
|
||||
.data = & (const struct snd_usb_midi_endpoint_info) {
|
||||
.out_cables = 0x0003,
|
||||
.in_cables = 0x0007
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
USB_DEVICE(0x0582, 0x0113),
|
||||
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
|
||||
/* .vendor_name = "BOSS", */
|
||||
/* .product_name = "ME-25", */
|
||||
.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_FIXED_ENDPOINT,
|
||||
.data = & (const struct snd_usb_midi_endpoint_info) {
|
||||
.out_cables = 0x0001,
|
||||
.in_cables = 0x0001
|
||||
}
|
||||
},
|
||||
{
|
||||
.ifnum = -1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/* Guillemot devices */
|
||||
{
|
||||
|
@ -1830,7 +1909,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
|
|||
USB_DEVICE(0x0763, 0x2080),
|
||||
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
|
||||
/* .vendor_name = "M-Audio", */
|
||||
/* .product_name = "Fast Track Ultra 8", */
|
||||
/* .product_name = "Fast Track Ultra", */
|
||||
.ifnum = QUIRK_ANY_INTERFACE,
|
||||
.type = QUIRK_COMPOSITE,
|
||||
.data = & (const struct snd_usb_audio_quirk[]) {
|
||||
|
@ -1840,11 +1919,51 @@ YAMAHA_DEVICE(0x7010, "UB99"),
|
|||
},
|
||||
{
|
||||
.ifnum = 1,
|
||||
.type = QUIRK_AUDIO_STANDARD_INTERFACE
|
||||
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
|
||||
.data = & (const struct audioformat) {
|
||||
.formats = SNDRV_PCM_FMTBIT_S24_3LE,
|
||||
.channels = 8,
|
||||
.iface = 1,
|
||||
.altsetting = 1,
|
||||
.altset_idx = 1,
|
||||
.attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
|
||||
.endpoint = 0x01,
|
||||
.ep_attr = 0x09,
|
||||
.rates = SNDRV_PCM_RATE_44100 |
|
||||
SNDRV_PCM_RATE_48000 |
|
||||
SNDRV_PCM_RATE_88200 |
|
||||
SNDRV_PCM_RATE_96000,
|
||||
.rate_min = 44100,
|
||||
.rate_max = 96000,
|
||||
.nr_rates = 4,
|
||||
.rate_table = (unsigned int[]) {
|
||||
44100, 48000, 88200, 96000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
.ifnum = 2,
|
||||
.type = QUIRK_AUDIO_STANDARD_INTERFACE
|
||||
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
|
||||
.data = & (const struct audioformat) {
|
||||
.formats = SNDRV_PCM_FMTBIT_S24_3LE,
|
||||
.channels = 8,
|
||||
.iface = 2,
|
||||
.altsetting = 1,
|
||||
.altset_idx = 1,
|
||||
.attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
|
||||
.endpoint = 0x81,
|
||||
.ep_attr = 0x05,
|
||||
.rates = SNDRV_PCM_RATE_44100 |
|
||||
SNDRV_PCM_RATE_48000 |
|
||||
SNDRV_PCM_RATE_88200 |
|
||||
SNDRV_PCM_RATE_96000,
|
||||
.rate_min = 44100,
|
||||
.rate_max = 96000,
|
||||
.nr_rates = 4,
|
||||
.rate_table = (unsigned int[]) {
|
||||
44100, 48000, 88200, 96000
|
||||
}
|
||||
}
|
||||
},
|
||||
/* interface 3 (MIDI) is standard compliant */
|
||||
{
|
||||
|
@ -1867,11 +1986,51 @@ YAMAHA_DEVICE(0x7010, "UB99"),
|
|||
},
|
||||
{
|
||||
.ifnum = 1,
|
||||
.type = QUIRK_AUDIO_STANDARD_INTERFACE
|
||||
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
|
||||
.data = & (const struct audioformat) {
|
||||
.formats = SNDRV_PCM_FMTBIT_S24_3LE,
|
||||
.channels = 8,
|
||||
.iface = 1,
|
||||
.altsetting = 1,
|
||||
.altset_idx = 1,
|
||||
.attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
|
||||
.endpoint = 0x01,
|
||||
.ep_attr = 0x09,
|
||||
.rates = SNDRV_PCM_RATE_44100 |
|
||||
SNDRV_PCM_RATE_48000 |
|
||||
SNDRV_PCM_RATE_88200 |
|
||||
SNDRV_PCM_RATE_96000,
|
||||
.rate_min = 44100,
|
||||
.rate_max = 96000,
|
||||
.nr_rates = 4,
|
||||
.rate_table = (unsigned int[]) {
|
||||
44100, 48000, 88200, 96000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
.ifnum = 2,
|
||||
.type = QUIRK_AUDIO_STANDARD_INTERFACE
|
||||
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
|
||||
.data = & (const struct audioformat) {
|
||||
.formats = SNDRV_PCM_FMTBIT_S24_3LE,
|
||||
.channels = 8,
|
||||
.iface = 2,
|
||||
.altsetting = 1,
|
||||
.altset_idx = 1,
|
||||
.attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
|
||||
.endpoint = 0x81,
|
||||
.ep_attr = 0x05,
|
||||
.rates = SNDRV_PCM_RATE_44100 |
|
||||
SNDRV_PCM_RATE_48000 |
|
||||
SNDRV_PCM_RATE_88200 |
|
||||
SNDRV_PCM_RATE_96000,
|
||||
.rate_min = 44100,
|
||||
.rate_max = 96000,
|
||||
.nr_rates = 4,
|
||||
.rate_table = (unsigned int[]) {
|
||||
44100, 48000, 88200, 96000
|
||||
}
|
||||
}
|
||||
},
|
||||
/* interface 3 (MIDI) is standard compliant */
|
||||
{
|
||||
|
@ -1919,7 +2078,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
|
|||
.data = & (const struct snd_usb_audio_quirk[]) {
|
||||
{
|
||||
.ifnum = 0,
|
||||
.type = QUIRK_MIDI_FASTLANE
|
||||
.type = QUIRK_MIDI_RAW_BYTES
|
||||
},
|
||||
{
|
||||
.ifnum = 1,
|
||||
|
@ -2067,6 +2226,15 @@ YAMAHA_DEVICE(0x7010, "UB99"),
|
|||
.type = QUIRK_MIDI_NOVATION
|
||||
}
|
||||
},
|
||||
{
|
||||
USB_DEVICE(0x1235, 0x000e),
|
||||
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
|
||||
/* .vendor_name = "Novation", */
|
||||
/* .product_name = "Launchpad", */
|
||||
.ifnum = 0,
|
||||
.type = QUIRK_MIDI_RAW_BYTES
|
||||
}
|
||||
},
|
||||
{
|
||||
USB_DEVICE_VENDOR_SPEC(0x1235, 0x4661),
|
||||
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
|
||||
|
|
|
@ -287,7 +287,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
|
|||
[QUIRK_MIDI_YAMAHA] = create_any_midi_quirk,
|
||||
[QUIRK_MIDI_MIDIMAN] = create_any_midi_quirk,
|
||||
[QUIRK_MIDI_NOVATION] = create_any_midi_quirk,
|
||||
[QUIRK_MIDI_FASTLANE] = create_any_midi_quirk,
|
||||
[QUIRK_MIDI_RAW_BYTES] = create_any_midi_quirk,
|
||||
[QUIRK_MIDI_EMAGIC] = create_any_midi_quirk,
|
||||
[QUIRK_MIDI_CME] = create_any_midi_quirk,
|
||||
[QUIRK_MIDI_AKAI] = create_any_midi_quirk,
|
||||
|
|
|
@ -244,7 +244,7 @@ int snd_usb_init_substream_urbs(struct snd_usb_substream *subs,
|
|||
else
|
||||
subs->curpacksize = maxsize;
|
||||
|
||||
if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH)
|
||||
if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL)
|
||||
packs_per_ms = 8 >> subs->datainterval;
|
||||
else
|
||||
packs_per_ms = 1;
|
||||
|
|
|
@ -70,7 +70,7 @@ enum quirk_type {
|
|||
QUIRK_MIDI_YAMAHA,
|
||||
QUIRK_MIDI_MIDIMAN,
|
||||
QUIRK_MIDI_NOVATION,
|
||||
QUIRK_MIDI_FASTLANE,
|
||||
QUIRK_MIDI_RAW_BYTES,
|
||||
QUIRK_MIDI_EMAGIC,
|
||||
QUIRK_MIDI_CME,
|
||||
QUIRK_MIDI_AKAI,
|
||||
|
|
|
@ -36,9 +36,9 @@
|
|||
plain usx2y alsa mode is able to achieve 64frames, 4periods, but only at the
|
||||
cost of easier triggered i.e. aeolus xruns (128 or 256frames,
|
||||
2periods works but is useless cause of crackling).
|
||||
|
||||
|
||||
This is a first "proof of concept" implementation.
|
||||
Later, funcionalities should migrate to more apropriate places:
|
||||
Later, functionalities should migrate to more apropriate places:
|
||||
Userland:
|
||||
- The jackd could mmap its float-pcm buffers directly from alsa-lib.
|
||||
- alsa-lib could provide power of 2 period sized shaping combined with int/float
|
||||
|
@ -54,7 +54,7 @@
|
|||
#include <linux/gfp.h>
|
||||
#include "usbusx2yaudio.c"
|
||||
|
||||
#if defined(USX2Y_NRPACKS_VARIABLE) || (!defined(USX2Y_NRPACKS_VARIABLE) && USX2Y_NRPACKS == 1)
|
||||
#if defined(USX2Y_NRPACKS_VARIABLE) || USX2Y_NRPACKS == 1
|
||||
|
||||
#include <sound/hwdep.h>
|
||||
|
||||
|
|
Loading…
Reference in New Issue