mirror of
https://github.com/S3NEO/android_kernel_samsung_msm8226.git
synced 2024-11-07 03:47:13 +00:00
Merge branch 'fix/misc' into for-linus
This commit is contained in:
commit
d1227e3fe0
14 changed files with 156 additions and 54 deletions
|
@ -2582,6 +2582,13 @@ S: Maintained
|
||||||
F: drivers/hwmon/f75375s.c
|
F: drivers/hwmon/f75375s.c
|
||||||
F: include/linux/f75375s.h
|
F: include/linux/f75375s.h
|
||||||
|
|
||||||
|
FIREWIRE AUDIO DRIVERS
|
||||||
|
M: Clemens Ladisch <clemens@ladisch.de>
|
||||||
|
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
|
||||||
|
T: git git://git.alsa-project.org/alsa-kernel.git
|
||||||
|
S: Maintained
|
||||||
|
F: sound/firewire/
|
||||||
|
|
||||||
FIREWIRE SUBSYSTEM
|
FIREWIRE SUBSYSTEM
|
||||||
M: Stefan Richter <stefanr@s5r6.in-berlin.de>
|
M: Stefan Richter <stefanr@s5r6.in-berlin.de>
|
||||||
L: linux1394-devel@lists.sourceforge.net
|
L: linux1394-devel@lists.sourceforge.net
|
||||||
|
|
|
@ -704,13 +704,12 @@ static int snd_ctl_elem_list(struct snd_card *card,
|
||||||
struct snd_ctl_elem_list list;
|
struct snd_ctl_elem_list list;
|
||||||
struct snd_kcontrol *kctl;
|
struct snd_kcontrol *kctl;
|
||||||
struct snd_ctl_elem_id *dst, *id;
|
struct snd_ctl_elem_id *dst, *id;
|
||||||
unsigned int offset, space, first, jidx;
|
unsigned int offset, space, jidx;
|
||||||
|
|
||||||
if (copy_from_user(&list, _list, sizeof(list)))
|
if (copy_from_user(&list, _list, sizeof(list)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
offset = list.offset;
|
offset = list.offset;
|
||||||
space = list.space;
|
space = list.space;
|
||||||
first = 0;
|
|
||||||
/* try limit maximum space */
|
/* try limit maximum space */
|
||||||
if (space > 16384)
|
if (space > 16384)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
|
@ -342,7 +342,6 @@ static const struct file_operations snd_shutdown_f_ops =
|
||||||
int snd_card_disconnect(struct snd_card *card)
|
int snd_card_disconnect(struct snd_card *card)
|
||||||
{
|
{
|
||||||
struct snd_monitor_file *mfile;
|
struct snd_monitor_file *mfile;
|
||||||
struct file *file;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!card)
|
if (!card)
|
||||||
|
@ -366,8 +365,6 @@ int snd_card_disconnect(struct snd_card *card)
|
||||||
|
|
||||||
spin_lock(&card->files_lock);
|
spin_lock(&card->files_lock);
|
||||||
list_for_each_entry(mfile, &card->files_list, list) {
|
list_for_each_entry(mfile, &card->files_list, list) {
|
||||||
file = mfile->file;
|
|
||||||
|
|
||||||
/* it's critical part, use endless loop */
|
/* it's critical part, use endless loop */
|
||||||
/* we have no room to fail */
|
/* we have no room to fail */
|
||||||
mfile->disconnected_f_op = mfile->file->f_op;
|
mfile->disconnected_f_op = mfile->file->f_op;
|
||||||
|
|
|
@ -90,11 +90,8 @@ static snd_pcm_sframes_t linear_transfer(struct snd_pcm_plugin *plugin,
|
||||||
struct snd_pcm_plugin_channel *dst_channels,
|
struct snd_pcm_plugin_channel *dst_channels,
|
||||||
snd_pcm_uframes_t frames)
|
snd_pcm_uframes_t frames)
|
||||||
{
|
{
|
||||||
struct linear_priv *data;
|
|
||||||
|
|
||||||
if (snd_BUG_ON(!plugin || !src_channels || !dst_channels))
|
if (snd_BUG_ON(!plugin || !src_channels || !dst_channels))
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
data = (struct linear_priv *)plugin->extra_data;
|
|
||||||
if (frames == 0)
|
if (frames == 0)
|
||||||
return 0;
|
return 0;
|
||||||
#ifdef CONFIG_SND_DEBUG
|
#ifdef CONFIG_SND_DEBUG
|
||||||
|
|
|
@ -1756,8 +1756,18 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
|
||||||
wait_queue_t wait;
|
wait_queue_t wait;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
snd_pcm_uframes_t avail = 0;
|
snd_pcm_uframes_t avail = 0;
|
||||||
long tout;
|
long wait_time, tout;
|
||||||
|
|
||||||
|
if (runtime->no_period_wakeup)
|
||||||
|
wait_time = MAX_SCHEDULE_TIMEOUT;
|
||||||
|
else {
|
||||||
|
wait_time = 10;
|
||||||
|
if (runtime->rate) {
|
||||||
|
long t = runtime->period_size * 2 / runtime->rate;
|
||||||
|
wait_time = max(t, wait_time);
|
||||||
|
}
|
||||||
|
wait_time = msecs_to_jiffies(wait_time * 1000);
|
||||||
|
}
|
||||||
init_waitqueue_entry(&wait, current);
|
init_waitqueue_entry(&wait, current);
|
||||||
add_wait_queue(&runtime->tsleep, &wait);
|
add_wait_queue(&runtime->tsleep, &wait);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -1765,9 +1775,8 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
|
||||||
err = -ERESTARTSYS;
|
err = -ERESTARTSYS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
|
||||||
snd_pcm_stream_unlock_irq(substream);
|
snd_pcm_stream_unlock_irq(substream);
|
||||||
tout = schedule_timeout(msecs_to_jiffies(10000));
|
tout = schedule_timeout_interruptible(wait_time);
|
||||||
snd_pcm_stream_lock_irq(substream);
|
snd_pcm_stream_lock_irq(substream);
|
||||||
switch (runtime->status->state) {
|
switch (runtime->status->state) {
|
||||||
case SNDRV_PCM_STATE_SUSPENDED:
|
case SNDRV_PCM_STATE_SUSPENDED:
|
||||||
|
|
|
@ -1481,11 +1481,20 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
|
||||||
break; /* all drained */
|
break; /* all drained */
|
||||||
init_waitqueue_entry(&wait, current);
|
init_waitqueue_entry(&wait, current);
|
||||||
add_wait_queue(&to_check->sleep, &wait);
|
add_wait_queue(&to_check->sleep, &wait);
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
|
||||||
snd_pcm_stream_unlock_irq(substream);
|
snd_pcm_stream_unlock_irq(substream);
|
||||||
up_read(&snd_pcm_link_rwsem);
|
up_read(&snd_pcm_link_rwsem);
|
||||||
snd_power_unlock(card);
|
snd_power_unlock(card);
|
||||||
tout = schedule_timeout(10 * HZ);
|
if (runtime->no_period_wakeup)
|
||||||
|
tout = MAX_SCHEDULE_TIMEOUT;
|
||||||
|
else {
|
||||||
|
tout = 10;
|
||||||
|
if (runtime->rate) {
|
||||||
|
long t = runtime->period_size * 2 / runtime->rate;
|
||||||
|
tout = max(t, tout);
|
||||||
|
}
|
||||||
|
tout = msecs_to_jiffies(tout * 1000);
|
||||||
|
}
|
||||||
|
tout = schedule_timeout_interruptible(tout);
|
||||||
snd_power_lock(card);
|
snd_power_lock(card);
|
||||||
down_read(&snd_pcm_link_rwsem);
|
down_read(&snd_pcm_link_rwsem);
|
||||||
snd_pcm_stream_lock_irq(substream);
|
snd_pcm_stream_lock_irq(substream);
|
||||||
|
@ -1518,13 +1527,11 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
|
||||||
static int snd_pcm_drop(struct snd_pcm_substream *substream)
|
static int snd_pcm_drop(struct snd_pcm_substream *substream)
|
||||||
{
|
{
|
||||||
struct snd_pcm_runtime *runtime;
|
struct snd_pcm_runtime *runtime;
|
||||||
struct snd_card *card;
|
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
if (PCM_RUNTIME_CHECK(substream))
|
if (PCM_RUNTIME_CHECK(substream))
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
runtime = substream->runtime;
|
runtime = substream->runtime;
|
||||||
card = substream->pcm->card;
|
|
||||||
|
|
||||||
if (runtime->status->state == SNDRV_PCM_STATE_OPEN ||
|
if (runtime->status->state == SNDRV_PCM_STATE_OPEN ||
|
||||||
runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED ||
|
runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED ||
|
||||||
|
@ -2056,7 +2063,6 @@ static int snd_pcm_open_file(struct file *file,
|
||||||
{
|
{
|
||||||
struct snd_pcm_file *pcm_file;
|
struct snd_pcm_file *pcm_file;
|
||||||
struct snd_pcm_substream *substream;
|
struct snd_pcm_substream *substream;
|
||||||
struct snd_pcm_str *str;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (rpcm_file)
|
if (rpcm_file)
|
||||||
|
@ -2073,7 +2079,6 @@ static int snd_pcm_open_file(struct file *file,
|
||||||
}
|
}
|
||||||
pcm_file->substream = substream;
|
pcm_file->substream = substream;
|
||||||
if (substream->ref_count == 1) {
|
if (substream->ref_count == 1) {
|
||||||
str = substream->pstr;
|
|
||||||
substream->file = pcm_file;
|
substream->file = pcm_file;
|
||||||
substream->pcm_release = pcm_release_private;
|
substream->pcm_release = pcm_release_private;
|
||||||
}
|
}
|
||||||
|
@ -3015,11 +3020,9 @@ static const struct vm_operations_struct snd_pcm_vm_ops_status =
|
||||||
static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
|
static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
|
||||||
struct vm_area_struct *area)
|
struct vm_area_struct *area)
|
||||||
{
|
{
|
||||||
struct snd_pcm_runtime *runtime;
|
|
||||||
long size;
|
long size;
|
||||||
if (!(area->vm_flags & VM_READ))
|
if (!(area->vm_flags & VM_READ))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
runtime = substream->runtime;
|
|
||||||
size = area->vm_end - area->vm_start;
|
size = area->vm_end - area->vm_start;
|
||||||
if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status)))
|
if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status)))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -3054,11 +3057,9 @@ static const struct vm_operations_struct snd_pcm_vm_ops_control =
|
||||||
static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file,
|
static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file,
|
||||||
struct vm_area_struct *area)
|
struct vm_area_struct *area)
|
||||||
{
|
{
|
||||||
struct snd_pcm_runtime *runtime;
|
|
||||||
long size;
|
long size;
|
||||||
if (!(area->vm_flags & VM_READ))
|
if (!(area->vm_flags & VM_READ))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
runtime = substream->runtime;
|
|
||||||
size = area->vm_end - area->vm_start;
|
size = area->vm_end - area->vm_start;
|
||||||
if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control)))
|
if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control)))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
@ -467,13 +467,11 @@ int snd_seq_queue_timer_open(int queueid)
|
||||||
int snd_seq_queue_timer_close(int queueid)
|
int snd_seq_queue_timer_close(int queueid)
|
||||||
{
|
{
|
||||||
struct snd_seq_queue *queue;
|
struct snd_seq_queue *queue;
|
||||||
struct snd_seq_timer *tmr;
|
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
queue = queueptr(queueid);
|
queue = queueptr(queueid);
|
||||||
if (queue == NULL)
|
if (queue == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
tmr = queue->timer;
|
|
||||||
snd_seq_timer_close(queue);
|
snd_seq_timer_close(queue);
|
||||||
queuefree(queue);
|
queuefree(queue);
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
#include <linux/usb/audio.h>
|
#include <linux/usb/audio.h>
|
||||||
#include <linux/usb/audio-v2.h>
|
#include <linux/usb/audio-v2.h>
|
||||||
|
|
||||||
|
#include <sound/control.h>
|
||||||
#include <sound/core.h>
|
#include <sound/core.h>
|
||||||
#include <sound/info.h>
|
#include <sound/info.h>
|
||||||
#include <sound/pcm.h>
|
#include <sound/pcm.h>
|
||||||
|
@ -492,14 +493,6 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chip->txfr_quirk = 0;
|
|
||||||
err = 1; /* continue */
|
|
||||||
if (quirk && quirk->ifnum != QUIRK_NO_INTERFACE) {
|
|
||||||
/* need some special handlings */
|
|
||||||
if ((err = snd_usb_create_quirk(chip, intf, &usb_audio_driver, quirk)) < 0)
|
|
||||||
goto __error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For devices with more than one control interface, we assume the
|
* For devices with more than one control interface, we assume the
|
||||||
* first contains the audio controls. We might need a more specific
|
* first contains the audio controls. We might need a more specific
|
||||||
|
@ -508,6 +501,14 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
|
||||||
if (!chip->ctrl_intf)
|
if (!chip->ctrl_intf)
|
||||||
chip->ctrl_intf = alts;
|
chip->ctrl_intf = alts;
|
||||||
|
|
||||||
|
chip->txfr_quirk = 0;
|
||||||
|
err = 1; /* continue */
|
||||||
|
if (quirk && quirk->ifnum != QUIRK_NO_INTERFACE) {
|
||||||
|
/* need some special handlings */
|
||||||
|
if ((err = snd_usb_create_quirk(chip, intf, &usb_audio_driver, quirk)) < 0)
|
||||||
|
goto __error;
|
||||||
|
}
|
||||||
|
|
||||||
if (err > 0) {
|
if (err > 0) {
|
||||||
/* create normal USB audio interfaces */
|
/* create normal USB audio interfaces */
|
||||||
if (snd_usb_create_streams(chip, ifnum) < 0 ||
|
if (snd_usb_create_streams(chip, ifnum) < 0 ||
|
||||||
|
|
|
@ -86,16 +86,6 @@ struct mixer_build {
|
||||||
const struct usbmix_selector_map *selector_map;
|
const struct usbmix_selector_map *selector_map;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
|
||||||
USB_MIXER_BOOLEAN,
|
|
||||||
USB_MIXER_INV_BOOLEAN,
|
|
||||||
USB_MIXER_S8,
|
|
||||||
USB_MIXER_U8,
|
|
||||||
USB_MIXER_S16,
|
|
||||||
USB_MIXER_U16,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*E-mu 0202/0404/0204 eXtension Unit(XU) control*/
|
/*E-mu 0202/0404/0204 eXtension Unit(XU) control*/
|
||||||
enum {
|
enum {
|
||||||
USB_XU_CLOCK_RATE = 0xe301,
|
USB_XU_CLOCK_RATE = 0xe301,
|
||||||
|
@ -535,20 +525,21 @@ static int check_matrix_bitmap(unsigned char *bmap, int ich, int och, int num_ou
|
||||||
* if failed, give up and free the control instance.
|
* if failed, give up and free the control instance.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int add_control_to_empty(struct mixer_build *state, struct snd_kcontrol *kctl)
|
int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer,
|
||||||
|
struct snd_kcontrol *kctl)
|
||||||
{
|
{
|
||||||
struct usb_mixer_elem_info *cval = kctl->private_data;
|
struct usb_mixer_elem_info *cval = kctl->private_data;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
while (snd_ctl_find_id(state->chip->card, &kctl->id))
|
while (snd_ctl_find_id(mixer->chip->card, &kctl->id))
|
||||||
kctl->id.index++;
|
kctl->id.index++;
|
||||||
if ((err = snd_ctl_add(state->chip->card, kctl)) < 0) {
|
if ((err = snd_ctl_add(mixer->chip->card, kctl)) < 0) {
|
||||||
snd_printd(KERN_ERR "cannot add control (err = %d)\n", err);
|
snd_printd(KERN_ERR "cannot add control (err = %d)\n", err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
cval->elem_id = &kctl->id;
|
cval->elem_id = &kctl->id;
|
||||||
cval->next_id_elem = state->mixer->id_elems[cval->id];
|
cval->next_id_elem = mixer->id_elems[cval->id];
|
||||||
state->mixer->id_elems[cval->id] = cval;
|
mixer->id_elems[cval->id] = cval;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -984,6 +975,9 @@ static struct snd_kcontrol_new usb_feature_unit_ctl_ro = {
|
||||||
.put = NULL,
|
.put = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* This symbol is exported in order to allow the mixer quirks to
|
||||||
|
* hook up to the standard feature unit control mechanism */
|
||||||
|
struct snd_kcontrol_new *snd_usb_feature_unit_ctl = &usb_feature_unit_ctl;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* build a feature control
|
* build a feature control
|
||||||
|
@ -1176,7 +1170,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
|
||||||
|
|
||||||
snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",
|
snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",
|
||||||
cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res);
|
cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res);
|
||||||
add_control_to_empty(state, kctl);
|
snd_usb_mixer_add_control(state->mixer, kctl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1340,7 +1334,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state,
|
||||||
|
|
||||||
snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n",
|
snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n",
|
||||||
cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
|
cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
|
||||||
add_control_to_empty(state, kctl);
|
snd_usb_mixer_add_control(state->mixer, kctl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1641,7 +1635,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw
|
||||||
|
|
||||||
snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n",
|
snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n",
|
||||||
cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
|
cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
|
||||||
if ((err = add_control_to_empty(state, kctl)) < 0)
|
if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1858,7 +1852,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void
|
||||||
|
|
||||||
snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n",
|
snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n",
|
||||||
cval->id, kctl->id.name, desc->bNrInPins);
|
cval->id, kctl->id.name, desc->bNrInPins);
|
||||||
if ((err = add_control_to_empty(state, kctl)) < 0)
|
if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -24,7 +24,16 @@ struct usb_mixer_interface {
|
||||||
u8 xonar_u1_status;
|
u8 xonar_u1_status;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_CHANNELS 10 /* max logical channels */
|
#define MAX_CHANNELS 16 /* max logical channels */
|
||||||
|
|
||||||
|
enum {
|
||||||
|
USB_MIXER_BOOLEAN,
|
||||||
|
USB_MIXER_INV_BOOLEAN,
|
||||||
|
USB_MIXER_S8,
|
||||||
|
USB_MIXER_U8,
|
||||||
|
USB_MIXER_S16,
|
||||||
|
USB_MIXER_U16,
|
||||||
|
};
|
||||||
|
|
||||||
struct usb_mixer_elem_info {
|
struct usb_mixer_elem_info {
|
||||||
struct usb_mixer_interface *mixer;
|
struct usb_mixer_interface *mixer;
|
||||||
|
@ -55,4 +64,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
|
||||||
void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer);
|
void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer);
|
||||||
int snd_usb_mixer_activate(struct usb_mixer_interface *mixer);
|
int snd_usb_mixer_activate(struct usb_mixer_interface *mixer);
|
||||||
|
|
||||||
|
int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer,
|
||||||
|
struct snd_kcontrol *kctl);
|
||||||
|
|
||||||
#endif /* __USBMIXER_H */
|
#endif /* __USBMIXER_H */
|
||||||
|
|
|
@ -40,6 +40,8 @@
|
||||||
#include "mixer_quirks.h"
|
#include "mixer_quirks.h"
|
||||||
#include "helper.h"
|
#include "helper.h"
|
||||||
|
|
||||||
|
extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sound Blaster remote control configuration
|
* Sound Blaster remote control configuration
|
||||||
*
|
*
|
||||||
|
@ -492,6 +494,69 @@ static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* M-Audio FastTrack Ultra quirks */
|
||||||
|
|
||||||
|
/* private_free callback */
|
||||||
|
static void usb_mixer_elem_free(struct snd_kcontrol *kctl)
|
||||||
|
{
|
||||||
|
kfree(kctl->private_data);
|
||||||
|
kctl->private_data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_maudio_ftu_create_ctl(struct usb_mixer_interface *mixer,
|
||||||
|
int in, int out, const char *name)
|
||||||
|
{
|
||||||
|
struct usb_mixer_elem_info *cval;
|
||||||
|
struct snd_kcontrol *kctl;
|
||||||
|
|
||||||
|
cval = kzalloc(sizeof(*cval), GFP_KERNEL);
|
||||||
|
if (!cval)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
cval->id = 5;
|
||||||
|
cval->mixer = mixer;
|
||||||
|
cval->val_type = USB_MIXER_S16;
|
||||||
|
cval->channels = 1;
|
||||||
|
cval->control = out + 1;
|
||||||
|
cval->cmask = 1 << in;
|
||||||
|
|
||||||
|
kctl = snd_ctl_new1(snd_usb_feature_unit_ctl, cval);
|
||||||
|
if (!kctl) {
|
||||||
|
kfree(cval);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(kctl->id.name, sizeof(kctl->id.name), name);
|
||||||
|
kctl->private_free = usb_mixer_elem_free;
|
||||||
|
return snd_usb_mixer_add_control(mixer, kctl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_maudio_ftu_create_mixer(struct usb_mixer_interface *mixer)
|
||||||
|
{
|
||||||
|
char name[64];
|
||||||
|
int in, out, err;
|
||||||
|
|
||||||
|
for (out = 0; out < 8; out++) {
|
||||||
|
for (in = 0; in < 8; in++) {
|
||||||
|
snprintf(name, sizeof(name),
|
||||||
|
"AIn%d - Out%d Capture Volume", in + 1, out + 1);
|
||||||
|
err = snd_maudio_ftu_create_ctl(mixer, in, out, name);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (in = 8; in < 16; in++) {
|
||||||
|
snprintf(name, sizeof(name),
|
||||||
|
"DIn%d - Out%d Playback Volume", in - 7, out + 1);
|
||||||
|
err = snd_maudio_ftu_create_ctl(mixer, in, out, name);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
|
void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
|
||||||
unsigned char samplerate_id)
|
unsigned char samplerate_id)
|
||||||
{
|
{
|
||||||
|
@ -533,6 +598,11 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
|
||||||
snd_audigy2nx_proc_read);
|
snd_audigy2nx_proc_read);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra */
|
||||||
|
case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */
|
||||||
|
err = snd_maudio_ftu_create_mixer(mixer);
|
||||||
|
break;
|
||||||
|
|
||||||
case USB_ID(0x0b05, 0x1739):
|
case USB_ID(0x0b05, 0x1739):
|
||||||
case USB_ID(0x0b05, 0x1743):
|
case USB_ID(0x0b05, 0x1743):
|
||||||
err = snd_xonar_u1_controls_create(mixer);
|
err = snd_xonar_u1_controls_create(mixer);
|
||||||
|
|
|
@ -1988,7 +1988,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
|
||||||
.data = & (const struct snd_usb_audio_quirk[]) {
|
.data = & (const struct snd_usb_audio_quirk[]) {
|
||||||
{
|
{
|
||||||
.ifnum = 0,
|
.ifnum = 0,
|
||||||
.type = QUIRK_IGNORE_INTERFACE
|
.type = QUIRK_AUDIO_STANDARD_MIXER,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.ifnum = 1,
|
.ifnum = 1,
|
||||||
|
@ -2055,7 +2055,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
|
||||||
.data = & (const struct snd_usb_audio_quirk[]) {
|
.data = & (const struct snd_usb_audio_quirk[]) {
|
||||||
{
|
{
|
||||||
.ifnum = 0,
|
.ifnum = 0,
|
||||||
.type = QUIRK_IGNORE_INTERFACE
|
.type = QUIRK_AUDIO_STANDARD_MIXER,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.ifnum = 1,
|
.ifnum = 1,
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <linux/usb.h>
|
#include <linux/usb.h>
|
||||||
#include <linux/usb/audio.h>
|
#include <linux/usb/audio.h>
|
||||||
|
|
||||||
|
#include <sound/control.h>
|
||||||
#include <sound/core.h>
|
#include <sound/core.h>
|
||||||
#include <sound/info.h>
|
#include <sound/info.h>
|
||||||
#include <sound/pcm.h>
|
#include <sound/pcm.h>
|
||||||
|
@ -262,6 +263,20 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a standard mixer for the specified interface.
|
||||||
|
*/
|
||||||
|
static int create_standard_mixer_quirk(struct snd_usb_audio *chip,
|
||||||
|
struct usb_interface *iface,
|
||||||
|
struct usb_driver *driver,
|
||||||
|
const struct snd_usb_audio_quirk *quirk)
|
||||||
|
{
|
||||||
|
if (quirk->ifnum < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return snd_usb_create_mixer(chip, quirk->ifnum, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* audio-interface quirks
|
* audio-interface quirks
|
||||||
*
|
*
|
||||||
|
@ -294,7 +309,8 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
|
||||||
[QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk,
|
[QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk,
|
||||||
[QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk,
|
[QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk,
|
||||||
[QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk,
|
[QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk,
|
||||||
[QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk
|
[QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk,
|
||||||
|
[QUIRK_AUDIO_STANDARD_MIXER] = create_standard_mixer_quirk,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (quirk->type < QUIRK_TYPE_COUNT) {
|
if (quirk->type < QUIRK_TYPE_COUNT) {
|
||||||
|
|
|
@ -84,6 +84,7 @@ enum quirk_type {
|
||||||
QUIRK_AUDIO_FIXED_ENDPOINT,
|
QUIRK_AUDIO_FIXED_ENDPOINT,
|
||||||
QUIRK_AUDIO_EDIROL_UAXX,
|
QUIRK_AUDIO_EDIROL_UAXX,
|
||||||
QUIRK_AUDIO_ALIGN_TRANSFER,
|
QUIRK_AUDIO_ALIGN_TRANSFER,
|
||||||
|
QUIRK_AUDIO_STANDARD_MIXER,
|
||||||
|
|
||||||
QUIRK_TYPE_COUNT
|
QUIRK_TYPE_COUNT
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue