Merge branch 'for-next' into for-linus

这个提交包含在:
Takashi Iwai
2014-12-08 11:33:24 +01:00
当前提交 77de61c397
修改 511 个文件,包含 9986 行新增6836 行删除

查看文件

@@ -25,8 +25,8 @@
#include "comm.h"
#include "chip.h"
static char *opt_coax_texts[2] = { "Optical", "Coax" };
static char *line_phono_texts[2] = { "Line", "Phono" };
static const char * const opt_coax_texts[2] = { "Optical", "Coax" };
static const char * const line_phono_texts[2] = { "Line", "Phono" };
/*
* data that needs to be sent to device. sets up card internal stuff.
@@ -327,14 +327,7 @@ static int usb6fire_control_input_vol_get(struct snd_kcontrol *kcontrol,
static int usb6fire_control_line_phono_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
uinfo->value.enumerated.items = 2;
if (uinfo->value.enumerated.item > 1)
uinfo->value.enumerated.item = 1;
strcpy(uinfo->value.enumerated.name,
line_phono_texts[uinfo->value.enumerated.item]);
return 0;
return snd_ctl_enum_info(uinfo, 1, 2, line_phono_texts);
}
static int usb6fire_control_line_phono_put(struct snd_kcontrol *kcontrol,
@@ -361,14 +354,7 @@ static int usb6fire_control_line_phono_get(struct snd_kcontrol *kcontrol,
static int usb6fire_control_opt_coax_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
uinfo->value.enumerated.items = 2;
if (uinfo->value.enumerated.item > 1)
uinfo->value.enumerated.item = 1;
strcpy(uinfo->value.enumerated.name,
opt_coax_texts[uinfo->value.enumerated.item]);
return 0;
return snd_ctl_enum_info(uinfo, 1, 2, opt_coax_texts);
}
static int usb6fire_control_opt_coax_put(struct snd_kcontrol *kcontrol,

查看文件

@@ -316,7 +316,7 @@ static int usb6fire_fw_fpga_upload(
while (c != end) {
for (i = 0; c != end && i < FPGA_BUFSIZE; i++, c++)
buffer[i] = byte_rev_table[(u8) *c];
buffer[i] = bitrev8((u8)*c);
ret = usb6fire_fw_fpga_write(device, buffer, i);
if (ret < 0) {

查看文件

@@ -679,25 +679,16 @@ int usb6fire_pcm_init(struct sfire_chip *chip)
void usb6fire_pcm_abort(struct sfire_chip *chip)
{
struct pcm_runtime *rt = chip->pcm;
unsigned long flags;
int i;
if (rt) {
rt->panic = true;
if (rt->playback.instance) {
snd_pcm_stream_lock_irqsave(rt->playback.instance, flags);
snd_pcm_stop(rt->playback.instance,
SNDRV_PCM_STATE_XRUN);
snd_pcm_stream_unlock_irqrestore(rt->playback.instance, flags);
}
if (rt->playback.instance)
snd_pcm_stop_xrun(rt->playback.instance);
if (rt->capture.instance) {
snd_pcm_stream_lock_irqsave(rt->capture.instance, flags);
snd_pcm_stop(rt->capture.instance,
SNDRV_PCM_STATE_XRUN);
snd_pcm_stream_unlock_irqrestore(rt->capture.instance, flags);
}
if (rt->capture.instance)
snd_pcm_stop_xrun(rt->capture.instance);
for (i = 0; i < PCM_N_URBS; i++) {
usb_poison_urb(&rt->in_urbs[i].instance);

查看文件

@@ -9,6 +9,7 @@ snd-usb-audio-objs := card.o \
helper.o \
mixer.o \
mixer_quirks.o \
mixer_scarlett.o \
pcm.o \
proc.o \
quirks.o \

查看文件

@@ -112,15 +112,13 @@ static struct usb_driver usb_audio_driver;
/*
* disconnect streams
* called from snd_usb_audio_disconnect()
* called from usb_audio_disconnect()
*/
static void snd_usb_stream_disconnect(struct list_head *head)
static void snd_usb_stream_disconnect(struct snd_usb_stream *as)
{
int idx;
struct snd_usb_stream *as;
struct snd_usb_substream *subs;
as = list_entry(head, struct snd_usb_stream, list);
for (idx = 0; idx < 2; idx++) {
subs = &as->substream[idx];
if (!subs->num_formats)
@@ -307,10 +305,10 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
static int snd_usb_audio_free(struct snd_usb_audio *chip)
{
struct list_head *p, *n;
struct snd_usb_endpoint *ep, *n;
list_for_each_safe(p, n, &chip->ep_list)
snd_usb_endpoint_free(p);
list_for_each_entry_safe(ep, n, &chip->ep_list, list)
snd_usb_endpoint_free(ep);
mutex_destroy(&chip->mutex);
kfree(chip);
@@ -323,16 +321,6 @@ static int snd_usb_audio_dev_free(struct snd_device *device)
return snd_usb_audio_free(chip);
}
static void remove_trailing_spaces(char *str)
{
char *p;
if (!*str)
return;
for (p = str + strlen(str) - 1; p >= str && isspace(*p); p--)
*p = 0;
}
/*
* create a chip instance and set its names.
*/
@@ -416,7 +404,7 @@ static int snd_usb_audio_create(struct usb_interface *intf,
USB_ID_PRODUCT(chip->usb_id));
}
}
remove_trailing_spaces(card->shortname);
strim(card->shortname);
/* retrieve the vendor and device strings as longname */
if (quirk && quirk->vendor_name && *quirk->vendor_name) {
@@ -430,7 +418,7 @@ static int snd_usb_audio_create(struct usb_interface *intf,
/* we don't really care if there isn't any vendor string */
}
if (len > 0) {
remove_trailing_spaces(card->longname);
strim(card->longname);
if (*card->longname)
strlcat(card->longname, " ", sizeof(card->longname));
}
@@ -475,14 +463,14 @@ static int snd_usb_audio_create(struct usb_interface *intf,
* only at the first time. the successive calls of this function will
* append the pcm interface to the corresponding card.
*/
static struct snd_usb_audio *
snd_usb_audio_probe(struct usb_device *dev,
struct usb_interface *intf,
const struct usb_device_id *usb_id)
static int usb_audio_probe(struct usb_interface *intf,
const struct usb_device_id *usb_id)
{
const struct snd_usb_audio_quirk *quirk = (const struct snd_usb_audio_quirk *)usb_id->driver_info;
int i, err;
struct usb_device *dev = interface_to_usbdev(intf);
const struct snd_usb_audio_quirk *quirk =
(const struct snd_usb_audio_quirk *)usb_id->driver_info;
struct snd_usb_audio *chip;
int i, err;
struct usb_host_interface *alts;
int ifnum;
u32 id;
@@ -492,10 +480,11 @@ snd_usb_audio_probe(struct usb_device *dev,
id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
le16_to_cpu(dev->descriptor.idProduct));
if (quirk && quirk->ifnum >= 0 && ifnum != quirk->ifnum)
goto __err_val;
return -ENXIO;
if (snd_usb_apply_boot_quirk(dev, intf, quirk) < 0)
goto __err_val;
err = snd_usb_apply_boot_quirk(dev, intf, quirk);
if (err < 0)
return err;
/*
* found a config. now register to ALSA
@@ -508,6 +497,7 @@ snd_usb_audio_probe(struct usb_device *dev,
if (usb_chip[i] && usb_chip[i]->dev == dev) {
if (usb_chip[i]->shutdown) {
dev_err(&dev->dev, "USB device is in the shutdown state, cannot create a card instance\n");
err = -EIO;
goto __error;
}
chip = usb_chip[i];
@@ -523,15 +513,16 @@ snd_usb_audio_probe(struct usb_device *dev,
if (enable[i] && ! usb_chip[i] &&
(vid[i] == -1 || vid[i] == USB_ID_VENDOR(id)) &&
(pid[i] == -1 || pid[i] == USB_ID_PRODUCT(id))) {
if (snd_usb_audio_create(intf, dev, i, quirk,
&chip) < 0) {
err = snd_usb_audio_create(intf, dev, i, quirk,
&chip);
if (err < 0)
goto __error;
}
chip->pm_intf = intf;
break;
}
if (!chip) {
dev_err(&dev->dev, "no available usb audio device\n");
err = -ENODEV;
goto __error;
}
}
@@ -548,28 +539,32 @@ snd_usb_audio_probe(struct usb_device *dev,
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)
err = snd_usb_create_quirk(chip, intf, &usb_audio_driver, quirk);
if (err < 0)
goto __error;
}
if (err > 0) {
/* create normal USB audio interfaces */
if (snd_usb_create_streams(chip, ifnum) < 0 ||
snd_usb_create_mixer(chip, ifnum, ignore_ctl_error) < 0) {
err = snd_usb_create_streams(chip, ifnum);
if (err < 0)
goto __error;
err = snd_usb_create_mixer(chip, ifnum, ignore_ctl_error);
if (err < 0)
goto __error;
}
}
/* we are allowed to call snd_card_register() many times */
if (snd_card_register(chip->card) < 0) {
err = snd_card_register(chip->card);
if (err < 0)
goto __error;
}
usb_chip[chip->index] = chip;
chip->num_interfaces++;
chip->probing = 0;
usb_set_intfdata(intf, chip);
mutex_unlock(&register_mutex);
return chip;
return 0;
__error:
if (chip) {
@@ -578,17 +573,16 @@ snd_usb_audio_probe(struct usb_device *dev,
chip->probing = 0;
}
mutex_unlock(&register_mutex);
__err_val:
return NULL;
return err;
}
/*
* we need to take care of counter, since disconnection can be called also
* many times as well as usb_audio_probe().
*/
static void snd_usb_audio_disconnect(struct usb_device *dev,
struct snd_usb_audio *chip)
static void usb_audio_disconnect(struct usb_interface *intf)
{
struct snd_usb_audio *chip = usb_get_intfdata(intf);
struct snd_card *card;
struct list_head *p;
bool was_shutdown;
@@ -604,12 +598,14 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
mutex_lock(&register_mutex);
if (!was_shutdown) {
struct snd_usb_stream *as;
struct snd_usb_endpoint *ep;
struct usb_mixer_interface *mixer;
snd_card_disconnect(card);
/* release the pcm resources */
list_for_each(p, &chip->pcm_list) {
snd_usb_stream_disconnect(p);
list_for_each_entry(as, &chip->pcm_list, list) {
snd_usb_stream_disconnect(as);
}
/* release the endpoint resources */
list_for_each_entry(ep, &chip->ep_list, list) {
@@ -620,8 +616,8 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
snd_usbmidi_disconnect(p);
}
/* release mixer resources */
list_for_each(p, &chip->mixer_list) {
snd_usb_mixer_disconnect(p);
list_for_each_entry(mixer, &chip->mixer_list, list) {
snd_usb_mixer_disconnect(mixer);
}
}
@@ -635,27 +631,6 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
}
}
/*
* new 2.5 USB kernel API
*/
static int usb_audio_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct snd_usb_audio *chip;
chip = snd_usb_audio_probe(interface_to_usbdev(intf), intf, id);
if (chip) {
usb_set_intfdata(intf, chip);
return 0;
} else
return -EIO;
}
static void usb_audio_disconnect(struct usb_interface *intf)
{
snd_usb_audio_disconnect(interface_to_usbdev(intf),
usb_get_intfdata(intf));
}
#ifdef CONFIG_PM
int snd_usb_autoresume(struct snd_usb_audio *chip)

查看文件

@@ -348,6 +348,8 @@ static void snd_complete_urb(struct urb *urb)
{
struct snd_urb_ctx *ctx = urb->context;
struct snd_usb_endpoint *ep = ctx->ep;
struct snd_pcm_substream *substream;
unsigned long flags;
int err;
if (unlikely(urb->status == -ENOENT || /* unlinked */
@@ -364,8 +366,6 @@ static void snd_complete_urb(struct urb *urb)
goto exit_clear;
if (snd_usb_endpoint_implicit_feedback_sink(ep)) {
unsigned long flags;
spin_lock_irqsave(&ep->lock, flags);
list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs);
spin_unlock_irqrestore(&ep->lock, flags);
@@ -389,7 +389,10 @@ static void snd_complete_urb(struct urb *urb)
return;
usb_audio_err(ep->chip, "cannot submit urb (err = %d)\n", err);
//snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
if (ep->data_subs && ep->data_subs->pcm_substream) {
substream = ep->data_subs->pcm_substream;
snd_pcm_stop_xrun(substream);
}
exit_clear:
clear_bit(ctx->index, &ep->active_mask);
@@ -1002,15 +1005,12 @@ void snd_usb_endpoint_release(struct snd_usb_endpoint *ep)
/**
* snd_usb_endpoint_free: Free the resources of an snd_usb_endpoint
*
* @ep: the list header of the endpoint to free
* @ep: the endpoint to free
*
* This free all resources of the given ep.
*/
void snd_usb_endpoint_free(struct list_head *head)
void snd_usb_endpoint_free(struct snd_usb_endpoint *ep)
{
struct snd_usb_endpoint *ep;
ep = list_entry(head, struct snd_usb_endpoint, list);
kfree(ep);
}

查看文件

@@ -24,7 +24,7 @@ void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep);
int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep);
void snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep);
void snd_usb_endpoint_release(struct snd_usb_endpoint *ep);
void snd_usb_endpoint_free(struct list_head *head);
void snd_usb_endpoint_free(struct snd_usb_endpoint *ep);
int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep);
int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep);

查看文件

@@ -613,24 +613,14 @@ static int start_usb_playback(struct ua101 *ua)
static void abort_alsa_capture(struct ua101 *ua)
{
unsigned long flags;
if (test_bit(ALSA_CAPTURE_RUNNING, &ua->states)) {
snd_pcm_stream_lock_irqsave(ua->capture.substream, flags);
snd_pcm_stop(ua->capture.substream, SNDRV_PCM_STATE_XRUN);
snd_pcm_stream_unlock_irqrestore(ua->capture.substream, flags);
}
if (test_bit(ALSA_CAPTURE_RUNNING, &ua->states))
snd_pcm_stop_xrun(ua->capture.substream);
}
static void abort_alsa_playback(struct ua101 *ua)
{
unsigned long flags;
if (test_bit(ALSA_PLAYBACK_RUNNING, &ua->states)) {
snd_pcm_stream_lock_irqsave(ua->playback.substream, flags);
snd_pcm_stop(ua->playback.substream, SNDRV_PCM_STATE_XRUN);
snd_pcm_stream_unlock_irqrestore(ua->playback.substream, flags);
}
if (test_bit(ALSA_PLAYBACK_RUNNING, &ua->states))
snd_pcm_stop_xrun(ua->playback.substream);
}
static int set_stream_hw(struct ua101 *ua, struct snd_pcm_substream *substream,

查看文件

@@ -136,6 +136,10 @@ check_mapped_name(const struct usbmix_name_map *p, char *buf, int buflen)
return strlcpy(buf, p->name, buflen);
}
/* ignore the error value if ignore_ctl_error flag is set */
#define filter_error(cval, err) \
((cval)->head.mixer->ignore_ctl_error ? 0 : (err))
/* check whether the control should be ignored */
static inline int
check_ignored_ctl(const struct usbmix_name_map *p)
@@ -286,13 +290,13 @@ static int get_abs_value(struct usb_mixer_elem_info *cval, int val)
static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request,
int validx, int *value_ret)
{
struct snd_usb_audio *chip = cval->mixer->chip;
struct snd_usb_audio *chip = cval->head.mixer->chip;
unsigned char buf[2];
int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
int timeout = 10;
int idx = 0, err;
err = snd_usb_autoresume(cval->mixer->chip);
err = snd_usb_autoresume(chip);
if (err < 0)
return -EIO;
@@ -300,7 +304,7 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request,
while (timeout-- > 0) {
if (chip->shutdown)
break;
idx = snd_usb_ctrl_intf(chip) | (cval->id << 8);
idx = snd_usb_ctrl_intf(chip) | (cval->head.id << 8);
if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
validx, idx, buf, val_len) >= val_len) {
@@ -316,14 +320,14 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request,
out:
up_read(&chip->shutdown_rwsem);
snd_usb_autosuspend(cval->mixer->chip);
snd_usb_autosuspend(chip);
return err;
}
static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request,
int validx, int *value_ret)
{
struct snd_usb_audio *chip = cval->mixer->chip;
struct snd_usb_audio *chip = cval->head.mixer->chip;
unsigned char buf[2 + 3 * sizeof(__u16)]; /* enough space for one range */
unsigned char *val;
int idx = 0, ret, size;
@@ -347,7 +351,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request,
if (chip->shutdown) {
ret = -ENODEV;
} else {
idx = snd_usb_ctrl_intf(chip) | (cval->id << 8);
idx = snd_usb_ctrl_intf(chip) | (cval->head.id << 8);
ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
validx, idx, buf, size);
@@ -392,7 +396,7 @@ static int get_ctl_value(struct usb_mixer_elem_info *cval, int request,
{
validx += cval->idx_off;
return (cval->mixer->protocol == UAC_VERSION_1) ?
return (cval->head.mixer->protocol == UAC_VERSION_1) ?
get_ctl_value_v1(cval, request, validx, value_ret) :
get_ctl_value_v2(cval, request, validx, value_ret);
}
@@ -412,7 +416,7 @@ static inline int get_cur_mix_raw(struct usb_mixer_elem_info *cval,
value);
}
static int get_cur_mix_value(struct usb_mixer_elem_info *cval,
int snd_usb_get_cur_mix_value(struct usb_mixer_elem_info *cval,
int channel, int index, int *value)
{
int err;
@@ -423,8 +427,8 @@ static int get_cur_mix_value(struct usb_mixer_elem_info *cval,
}
err = get_cur_mix_raw(cval, channel, value);
if (err < 0) {
if (!cval->mixer->ignore_ctl_error)
usb_audio_dbg(cval->mixer->chip,
if (!cval->head.mixer->ignore_ctl_error)
usb_audio_dbg(cval->head.mixer->chip,
"cannot get current value for control %d ch %d: err = %d\n",
cval->control, channel, err);
return err;
@@ -441,13 +445,13 @@ static int get_cur_mix_value(struct usb_mixer_elem_info *cval,
int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
int request, int validx, int value_set)
{
struct snd_usb_audio *chip = cval->mixer->chip;
struct snd_usb_audio *chip = cval->head.mixer->chip;
unsigned char buf[2];
int idx = 0, val_len, err, timeout = 10;
validx += cval->idx_off;
if (cval->mixer->protocol == UAC_VERSION_1) {
if (cval->head.mixer->protocol == UAC_VERSION_1) {
val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
} else { /* UAC_VERSION_2 */
/* audio class v2 controls are always 2 bytes in size */
@@ -472,7 +476,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
while (timeout-- > 0) {
if (chip->shutdown)
break;
idx = snd_usb_ctrl_intf(chip) | (cval->id << 8);
idx = snd_usb_ctrl_intf(chip) | (cval->head.id << 8);
if (snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0), request,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
@@ -497,7 +501,7 @@ static int set_cur_ctl_value(struct usb_mixer_elem_info *cval,
return snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR, validx, value);
}
static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel,
int snd_usb_set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel,
int index, int value)
{
int err;
@@ -506,7 +510,7 @@ static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel,
cval->ch_readonly & (1 << (channel - 1));
if (read_only) {
usb_audio_dbg(cval->mixer->chip,
usb_audio_dbg(cval->head.mixer->chip,
"%s(): channel %d of control %d is read_only\n",
__func__, channel, cval->control);
return 0;
@@ -565,10 +569,10 @@ static int check_matrix_bitmap(unsigned char *bmap,
* if failed, give up and free the control instance.
*/
int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer,
int snd_usb_mixer_add_control(struct usb_mixer_elem_list *list,
struct snd_kcontrol *kctl)
{
struct usb_mixer_elem_info *cval = kctl->private_data;
struct usb_mixer_interface *mixer = list->mixer;
int err;
while (snd_ctl_find_id(mixer->chip->card, &kctl->id))
@@ -578,9 +582,9 @@ int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer,
err);
return err;
}
cval->elem_id = &kctl->id;
cval->next_id_elem = mixer->id_elems[cval->id];
mixer->id_elems[cval->id] = cval;
list->kctl = kctl;
list->next_id_elem = mixer->id_elems[list->id];
mixer->id_elems[list->id] = list;
return 0;
}
@@ -815,7 +819,7 @@ static struct usb_feature_control_info audio_feature_info[] = {
};
/* private_free callback */
static void usb_mixer_elem_free(struct snd_kcontrol *kctl)
void snd_usb_mixer_elem_free(struct snd_kcontrol *kctl)
{
kfree(kctl->private_data);
kctl->private_data = NULL;
@@ -829,7 +833,7 @@ static void usb_mixer_elem_free(struct snd_kcontrol *kctl)
static void volume_control_quirks(struct usb_mixer_elem_info *cval,
struct snd_kcontrol *kctl)
{
struct snd_usb_audio *chip = cval->mixer->chip;
struct snd_usb_audio *chip = cval->head.mixer->chip;
switch (chip->usb_id) {
case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */
case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */
@@ -954,10 +958,10 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
}
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) {
usb_audio_err(cval->mixer->chip,
usb_audio_err(cval->head.mixer->chip,
"%d:%d: cannot get min/max values for control %d (id %d)\n",
cval->id, snd_usb_ctrl_intf(cval->mixer->chip),
cval->control, cval->id);
cval->head.id, snd_usb_ctrl_intf(cval->head.mixer->chip),
cval->control, cval->head.id);
return -EINVAL;
}
if (get_ctl_value(cval, UAC_GET_RES,
@@ -998,7 +1002,7 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
else
test -= cval->res;
if (test < cval->min || test > cval->max ||
set_cur_mix_value(cval, minchn, 0, test) ||
snd_usb_set_cur_mix_value(cval, minchn, 0, test) ||
get_cur_mix_raw(cval, minchn, &check)) {
cval->res = last_valid_res;
break;
@@ -1007,7 +1011,7 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
break;
cval->res *= 2;
}
set_cur_mix_value(cval, minchn, 0, saved);
snd_usb_set_cur_mix_value(cval, minchn, 0, saved);
}
cval->initialized = 1;
@@ -1061,7 +1065,7 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol,
kcontrol->vd[0].access &=
~(SNDRV_CTL_ELEM_ACCESS_TLV_READ |
SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK);
snd_ctl_notify(cval->mixer->chip->card,
snd_ctl_notify(cval->head.mixer->chip->card,
SNDRV_CTL_EVENT_MASK_INFO,
&kcontrol->id);
}
@@ -1086,9 +1090,9 @@ static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol,
for (c = 0; c < MAX_CHANNELS; c++) {
if (!(cval->cmask & (1 << c)))
continue;
err = get_cur_mix_value(cval, c + 1, cnt, &val);
err = snd_usb_get_cur_mix_value(cval, c + 1, cnt, &val);
if (err < 0)
return cval->mixer->ignore_ctl_error ? 0 : err;
return filter_error(cval, err);
val = get_relative_value(cval, val);
ucontrol->value.integer.value[cnt] = val;
cnt++;
@@ -1096,9 +1100,9 @@ static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol,
return 0;
} else {
/* master channel */
err = get_cur_mix_value(cval, 0, 0, &val);
err = snd_usb_get_cur_mix_value(cval, 0, 0, &val);
if (err < 0)
return cval->mixer->ignore_ctl_error ? 0 : err;
return filter_error(cval, err);
val = get_relative_value(cval, val);
ucontrol->value.integer.value[0] = val;
}
@@ -1118,26 +1122,26 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol,
for (c = 0; c < MAX_CHANNELS; c++) {
if (!(cval->cmask & (1 << c)))
continue;
err = get_cur_mix_value(cval, c + 1, cnt, &oval);
err = snd_usb_get_cur_mix_value(cval, c + 1, cnt, &oval);
if (err < 0)
return cval->mixer->ignore_ctl_error ? 0 : err;
return filter_error(cval, err);
val = ucontrol->value.integer.value[cnt];
val = get_abs_value(cval, val);
if (oval != val) {
set_cur_mix_value(cval, c + 1, cnt, val);
snd_usb_set_cur_mix_value(cval, c + 1, cnt, val);
changed = 1;
}
cnt++;
}
} else {
/* master channel */
err = get_cur_mix_value(cval, 0, 0, &oval);
err = snd_usb_get_cur_mix_value(cval, 0, 0, &oval);
if (err < 0)
return cval->mixer->ignore_ctl_error ? 0 : err;
return filter_error(cval, err);
val = ucontrol->value.integer.value[0];
val = get_abs_value(cval, val);
if (val != oval) {
set_cur_mix_value(cval, 0, 0, val);
snd_usb_set_cur_mix_value(cval, 0, 0, val);
changed = 1;
}
}
@@ -1231,8 +1235,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
cval = kzalloc(sizeof(*cval), GFP_KERNEL);
if (!cval)
return;
cval->mixer = state->mixer;
cval->id = unitid;
snd_usb_mixer_elem_init_std(&cval->head, state->mixer, unitid);
cval->control = control;
cval->cmask = ctl_mask;
cval->val_type = audio_feature_info[control-1].type;
@@ -1250,7 +1253,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
/*
* If all channels in the mask are marked read-only, make the control
* read-only. set_cur_mix_value() will check the mask again and won't
* read-only. snd_usb_set_cur_mix_value() will check the mask again and won't
* issue write commands to read-only channels.
*/
if (cval->channels == readonly_mask)
@@ -1263,7 +1266,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
kfree(cval);
return;
}
kctl->private_free = usb_mixer_elem_free;
kctl->private_free = snd_usb_mixer_elem_free;
len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name));
mapped_name = len != 0;
@@ -1290,9 +1293,8 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
kctl->id.name,
sizeof(kctl->id.name), 1);
if (!len)
len = snprintf(kctl->id.name,
sizeof(kctl->id.name),
"Feature %d", unitid);
snprintf(kctl->id.name, sizeof(kctl->id.name),
"Feature %d", unitid);
}
if (!mapped_name)
@@ -1305,9 +1307,9 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
*/
if (!mapped_name && !(state->oterm.type >> 16)) {
if ((state->oterm.type & 0xff00) == 0x0100)
len = append_ctl_name(kctl, " Capture");
append_ctl_name(kctl, " Capture");
else
len = append_ctl_name(kctl, " Playback");
append_ctl_name(kctl, " Playback");
}
append_ctl_name(kctl, control == UAC_FU_MUTE ?
" Switch" : " Volume");
@@ -1344,14 +1346,14 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
range);
usb_audio_warn(state->chip,
"[%d] FU [%s] ch = %d, val = %d/%d/%d",
cval->id, kctl->id.name, cval->channels,
cval->head.id, kctl->id.name, cval->channels,
cval->min, cval->max, cval->res);
}
usb_audio_dbg(state->chip, "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",
cval->id, kctl->id.name, cval->channels,
cval->head.id, kctl->id.name, cval->channels,
cval->min, cval->max, cval->res);
snd_usb_mixer_add_control(state->mixer, kctl);
snd_usb_mixer_add_control(&cval->head, kctl);
}
/*
@@ -1525,8 +1527,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state,
if (!cval)
return;
cval->mixer = state->mixer;
cval->id = unitid;
snd_usb_mixer_elem_init_std(&cval->head, state->mixer, unitid);
cval->control = in_ch + 1; /* based on 1 */
cval->val_type = USB_MIXER_S16;
for (i = 0; i < num_outs; i++) {
@@ -1547,7 +1548,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state,
kfree(cval);
return;
}
kctl->private_free = usb_mixer_elem_free;
kctl->private_free = snd_usb_mixer_elem_free;
len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name));
if (!len)
@@ -1558,8 +1559,8 @@ static void build_mixer_unit_ctl(struct mixer_build *state,
append_ctl_name(kctl, " Volume");
usb_audio_dbg(state->chip, "[%d] MU [%s] ch = %d, val = %d/%d\n",
cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
snd_usb_mixer_add_control(state->mixer, kctl);
cval->head.id, kctl->id.name, cval->channels, cval->min, cval->max);
snd_usb_mixer_add_control(&cval->head, kctl);
}
/*
@@ -1629,12 +1630,10 @@ static int mixer_ctl_procunit_get(struct snd_kcontrol *kcontrol,
int err, val;
err = get_cur_ctl_value(cval, cval->control << 8, &val);
if (err < 0 && cval->mixer->ignore_ctl_error) {
if (err < 0) {
ucontrol->value.integer.value[0] = cval->min;
return 0;
return filter_error(cval, err);
}
if (err < 0)
return err;
val = get_relative_value(cval, val);
ucontrol->value.integer.value[0] = val;
return 0;
@@ -1648,11 +1647,8 @@ static int mixer_ctl_procunit_put(struct snd_kcontrol *kcontrol,
int val, oval, err;
err = get_cur_ctl_value(cval, cval->control << 8, &oval);
if (err < 0) {
if (cval->mixer->ignore_ctl_error)
return 0;
return err;
}
if (err < 0)
return filter_error(cval, err);
val = ucontrol->value.integer.value[0];
val = get_abs_value(cval, val);
if (val != oval) {
@@ -1814,8 +1810,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
cval = kzalloc(sizeof(*cval), GFP_KERNEL);
if (!cval)
return -ENOMEM;
cval->mixer = state->mixer;
cval->id = unitid;
snd_usb_mixer_elem_init_std(&cval->head, state->mixer, unitid);
cval->control = valinfo->control;
cval->val_type = valinfo->val_type;
cval->channels = 1;
@@ -1847,7 +1842,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
kfree(cval);
return -ENOMEM;
}
kctl->private_free = usb_mixer_elem_free;
kctl->private_free = snd_usb_mixer_elem_free;
if (check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name))) {
/* nothing */ ;
@@ -1868,10 +1863,10 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
usb_audio_dbg(state->chip,
"[%d] PU [%s] ch = %d, val = %d/%d\n",
cval->id, kctl->id.name, cval->channels,
cval->head.id, kctl->id.name, cval->channels,
cval->min, cval->max);
err = snd_usb_mixer_add_control(state->mixer, kctl);
err = snd_usb_mixer_add_control(&cval->head, kctl);
if (err < 0)
return err;
}
@@ -1924,11 +1919,8 @@ static int mixer_ctl_selector_get(struct snd_kcontrol *kcontrol,
err = get_cur_ctl_value(cval, cval->control << 8, &val);
if (err < 0) {
if (cval->mixer->ignore_ctl_error) {
ucontrol->value.enumerated.item[0] = 0;
return 0;
}
return err;
ucontrol->value.enumerated.item[0] = 0;
return filter_error(cval, err);
}
val = get_relative_value(cval, val);
ucontrol->value.enumerated.item[0] = val;
@@ -1943,11 +1935,8 @@ static int mixer_ctl_selector_put(struct snd_kcontrol *kcontrol,
int val, oval, err;
err = get_cur_ctl_value(cval, cval->control << 8, &oval);
if (err < 0) {
if (cval->mixer->ignore_ctl_error)
return 0;
return err;
}
if (err < 0)
return filter_error(cval, err);
val = ucontrol->value.enumerated.item[0];
val = get_abs_value(cval, val);
if (val != oval) {
@@ -2024,8 +2013,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid,
cval = kzalloc(sizeof(*cval), GFP_KERNEL);
if (!cval)
return -ENOMEM;
cval->mixer = state->mixer;
cval->id = unitid;
snd_usb_mixer_elem_init_std(&cval->head, state->mixer, unitid);
cval->val_type = USB_MIXER_U8;
cval->channels = 1;
cval->min = 1;
@@ -2096,11 +2084,8 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid,
}
usb_audio_dbg(state->chip, "[%d] SU [%s] items = %d\n",
cval->id, kctl->id.name, desc->bNrInPins);
if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0)
return err;
return 0;
cval->head.id, kctl->id.name, desc->bNrInPins);
return snd_usb_mixer_add_control(&cval->head, kctl);
}
/*
@@ -2245,25 +2230,21 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid)
{
struct usb_mixer_elem_info *info;
struct usb_mixer_elem_list *list;
for (info = mixer->id_elems[unitid]; info; info = info->next_id_elem)
for (list = mixer->id_elems[unitid]; list; list = list->next_id_elem)
snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
info->elem_id);
&list->kctl->id);
}
static void snd_usb_mixer_dump_cval(struct snd_info_buffer *buffer,
int unitid,
struct usb_mixer_elem_info *cval)
struct usb_mixer_elem_list *list)
{
struct usb_mixer_elem_info *cval = (struct usb_mixer_elem_info *)list;
static char *val_types[] = {"BOOLEAN", "INV_BOOLEAN",
"S8", "U8", "S16", "U16"};
snd_iprintf(buffer, " Unit: %i\n", unitid);
if (cval->elem_id)
snd_iprintf(buffer, " Control: name=\"%s\", index=%i\n",
cval->elem_id->name, cval->elem_id->index);
snd_iprintf(buffer, " Info: id=%i, control=%i, cmask=0x%x, "
"channels=%i, type=\"%s\"\n", cval->id,
"channels=%i, type=\"%s\"\n", cval->head.id,
cval->control, cval->cmask, cval->channels,
val_types[cval->val_type]);
snd_iprintf(buffer, " Volume: min=%i, max=%i, dBmin=%i, dBmax=%i\n",
@@ -2275,7 +2256,7 @@ static void snd_usb_mixer_proc_read(struct snd_info_entry *entry,
{
struct snd_usb_audio *chip = entry->private_data;
struct usb_mixer_interface *mixer;
struct usb_mixer_elem_info *cval;
struct usb_mixer_elem_list *list;
int unitid;
list_for_each_entry(mixer, &chip->mixer_list, list) {
@@ -2285,9 +2266,17 @@ static void snd_usb_mixer_proc_read(struct snd_info_entry *entry,
mixer->ignore_ctl_error);
snd_iprintf(buffer, "Card: %s\n", chip->card->longname);
for (unitid = 0; unitid < MAX_ID_ELEMS; unitid++) {
for (cval = mixer->id_elems[unitid]; cval;
cval = cval->next_id_elem)
snd_usb_mixer_dump_cval(buffer, unitid, cval);
for (list = mixer->id_elems[unitid]; list;
list = list->next_id_elem) {
snd_iprintf(buffer, " Unit: %i\n", list->id);
if (list->kctl)
snd_iprintf(buffer,
" Control: name=\"%s\", index=%i\n",
list->kctl->id.name,
list->kctl->id.index);
if (list->dump)
list->dump(buffer, list);
}
}
}
}
@@ -2295,7 +2284,7 @@ static void snd_usb_mixer_proc_read(struct snd_info_entry *entry,
static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer,
int attribute, int value, int index)
{
struct usb_mixer_elem_info *info;
struct usb_mixer_elem_list *list;
__u8 unitid = (index >> 8) & 0xff;
__u8 control = (value >> 8) & 0xff;
__u8 channel = value & 0xff;
@@ -2307,7 +2296,13 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer,
return;
}
for (info = mixer->id_elems[unitid]; info; info = info->next_id_elem) {
for (list = mixer->id_elems[unitid]; list; list = list->next_id_elem) {
struct usb_mixer_elem_info *info;
if (!list->kctl)
continue;
info = (struct usb_mixer_elem_info *)list;
if (info->control != control)
continue;
@@ -2320,7 +2315,7 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer,
info->cached = 0;
snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
info->elem_id);
&info->head.kctl->id);
break;
case UAC2_CS_RANGE:
@@ -2485,11 +2480,8 @@ _error:
return err;
}
void snd_usb_mixer_disconnect(struct list_head *p)
void snd_usb_mixer_disconnect(struct usb_mixer_interface *mixer)
{
struct usb_mixer_interface *mixer;
mixer = list_entry(p, struct usb_mixer_interface, list);
usb_kill_urb(mixer->urb);
usb_kill_urb(mixer->rc_urb);
}
@@ -2521,8 +2513,9 @@ int snd_usb_mixer_suspend(struct usb_mixer_interface *mixer)
return 0;
}
static int restore_mixer_value(struct usb_mixer_elem_info *cval)
static int restore_mixer_value(struct usb_mixer_elem_list *list)
{
struct usb_mixer_elem_info *cval = (struct usb_mixer_elem_info *)list;
int c, err, idx;
if (cval->cmask) {
@@ -2531,7 +2524,7 @@ static int restore_mixer_value(struct usb_mixer_elem_info *cval)
if (!(cval->cmask & (1 << c)))
continue;
if (cval->cached & (1 << c)) {
err = set_cur_mix_value(cval, c + 1, idx,
err = snd_usb_set_cur_mix_value(cval, c + 1, idx,
cval->cache_val[idx]);
if (err < 0)
return err;
@@ -2541,7 +2534,7 @@ static int restore_mixer_value(struct usb_mixer_elem_info *cval)
} else {
/* master */
if (cval->cached) {
err = set_cur_mix_value(cval, 0, 0, *cval->cache_val);
err = snd_usb_set_cur_mix_value(cval, 0, 0, *cval->cache_val);
if (err < 0)
return err;
}
@@ -2552,19 +2545,19 @@ static int restore_mixer_value(struct usb_mixer_elem_info *cval)
int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume)
{
struct usb_mixer_elem_info *cval;
struct usb_mixer_elem_list *list;
int id, err;
/* FIXME: any mixer quirks? */
if (reset_resume) {
/* restore cached mixer values */
for (id = 0; id < MAX_ID_ELEMS; id++) {
for (cval = mixer->id_elems[id]; cval;
cval = cval->next_id_elem) {
err = restore_mixer_value(cval);
if (err < 0)
return err;
for (list = mixer->id_elems[id]; list;
list = list->next_id_elem) {
if (list->resume) {
err = list->resume(list);
if (err < 0)
return err;
}
}
}
}
@@ -2572,3 +2565,15 @@ int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume)
return snd_usb_mixer_activate(mixer);
}
#endif
void snd_usb_mixer_elem_init_std(struct usb_mixer_elem_list *list,
struct usb_mixer_interface *mixer,
int unitid)
{
list->mixer = mixer;
list->id = unitid;
list->dump = snd_usb_mixer_dump_cval;
#ifdef CONFIG_PM
list->resume = restore_mixer_value;
#endif
}

查看文件

@@ -1,6 +1,8 @@
#ifndef __USBMIXER_H
#define __USBMIXER_H
#include <sound/info.h>
struct usb_mixer_interface {
struct snd_usb_audio *chip;
struct usb_host_interface *hostif;
@@ -8,7 +10,7 @@ struct usb_mixer_interface {
unsigned int ignore_ctl_error;
struct urb *urb;
/* array[MAX_ID_ELEMS], indexed by unit id */
struct usb_mixer_elem_info **id_elems;
struct usb_mixer_elem_list **id_elems;
/* the usb audio specification version this interface complies to */
int protocol;
@@ -20,9 +22,6 @@ struct usb_mixer_interface {
struct urb *rc_urb;
struct usb_ctrlrequest *rc_setup_packet;
u8 rc_buffer[6];
u8 audigy2nx_leds[3];
u8 xonar_u1_status;
};
#define MAX_CHANNELS 16 /* max logical channels */
@@ -36,11 +35,21 @@ enum {
USB_MIXER_U16,
};
struct usb_mixer_elem_info {
typedef void (*usb_mixer_elem_dump_func_t)(struct snd_info_buffer *buffer,
struct usb_mixer_elem_list *list);
typedef int (*usb_mixer_elem_resume_func_t)(struct usb_mixer_elem_list *elem);
struct usb_mixer_elem_list {
struct usb_mixer_interface *mixer;
struct usb_mixer_elem_info *next_id_elem; /* list of controls with same id */
struct snd_ctl_elem_id *elem_id;
struct usb_mixer_elem_list *next_id_elem; /* list of controls with same id */
struct snd_kcontrol *kctl;
unsigned int id;
usb_mixer_elem_dump_func_t dump;
usb_mixer_elem_resume_func_t resume;
};
struct usb_mixer_elem_info {
struct usb_mixer_elem_list head;
unsigned int control; /* CS or ICN (high byte) */
unsigned int cmask; /* channel mask bitmap: 0 = master */
unsigned int idx_off; /* Control index offset */
@@ -53,20 +62,25 @@ struct usb_mixer_elem_info {
int cached;
int cache_val[MAX_CHANNELS];
u8 initialized;
void *private_data;
};
int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
int ignore_error);
void snd_usb_mixer_disconnect(struct list_head *p);
void snd_usb_mixer_disconnect(struct usb_mixer_interface *mixer);
void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid);
int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
int request, int validx, int value_set);
int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer,
int snd_usb_mixer_add_control(struct usb_mixer_elem_list *list,
struct snd_kcontrol *kctl);
void snd_usb_mixer_elem_init_std(struct usb_mixer_elem_list *list,
struct usb_mixer_interface *mixer,
int unitid);
int snd_usb_mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
unsigned int size, unsigned int __user *_tlv);
@@ -75,4 +89,12 @@ int snd_usb_mixer_suspend(struct usb_mixer_interface *mixer);
int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume);
#endif
int snd_usb_set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel,
int index, int value);
int snd_usb_get_cur_mix_value(struct usb_mixer_elem_info *cval,
int channel, int index, int *value);
extern void snd_usb_mixer_elem_free(struct snd_kcontrol *kctl);
#endif /* __USBMIXER_H */

查看文件

@@ -179,6 +179,11 @@ static struct usbmix_name_map audigy2nx_map[] = {
{ 0 } /* terminator */
};
static struct usbmix_name_map mbox1_map[] = {
{ 1, "Clock" },
{ 0 } /* terminator */
};
static struct usbmix_selector_map c400_selectors[] = {
{
.id = 0x80,
@@ -415,6 +420,10 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = {
.id = USB_ID(0x0ccd, 0x0028),
.map = aureon_51_2_map,
},
{
.id = USB_ID(0x0dba, 0x1000),
.map = mbox1_map,
},
{
.id = USB_ID(0x13e5, 0x0001),
.map = scratch_live_map,

文件差异内容过多而无法显示 加载差异

1004
sound/usb/mixer_scarlett.c 普通文件

文件差异内容过多而无法显示 加载差异

查看文件

@@ -0,0 +1,6 @@
#ifndef __USB_MIXER_SCARLETT_H
#define __USB_MIXER_SCARLETT_H
int snd_scarlett_controls_create(struct usb_mixer_interface *mixer);
#endif /* __USB_MIXER_SCARLETT_H */

查看文件

@@ -482,6 +482,11 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
/* set interface */
if (subs->interface != fmt->iface ||
subs->altset_idx != fmt->altset_idx) {
err = snd_usb_select_mode_quirk(subs, fmt);
if (err < 0)
return -EIO;
err = usb_set_interface(dev, fmt->iface, fmt->altsetting);
if (err < 0) {
dev_err(&dev->dev,

查看文件

@@ -2667,57 +2667,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.type = QUIRK_MIDI_NOVATION
}
},
{
/*
* Focusrite Scarlett 18i6
*
* Avoid mixer creation, which otherwise fails because some of
* the interface descriptor subtypes for interface 0 are
* unknown. That should be fixed or worked-around but this at
* least allows the device to be used successfully with a DAW
* and an external mixer. See comments below about other
* ignored interfaces.
*/
USB_DEVICE(0x1235, 0x8004),
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Focusrite",
.product_name = "Scarlett 18i6",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
.data = & (const struct snd_usb_audio_quirk[]) {
{
/* InterfaceSubClass 1 (Control Device) */
.ifnum = 0,
.type = QUIRK_IGNORE_INTERFACE
},
{
.ifnum = 1,
.type = QUIRK_AUDIO_STANDARD_INTERFACE
},
{
.ifnum = 2,
.type = QUIRK_AUDIO_STANDARD_INTERFACE
},
{
/* InterfaceSubClass 1 (Control Device) */
.ifnum = 3,
.type = QUIRK_IGNORE_INTERFACE
},
{
.ifnum = 4,
.type = QUIRK_MIDI_STANDARD_INTERFACE
},
{
/* InterfaceSubClass 1 (Device Firmware Update) */
.ifnum = 5,
.type = QUIRK_IGNORE_INTERFACE
},
{
.ifnum = -1
}
}
}
},
/* Access Music devices */
{
@@ -2944,7 +2893,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.data = (const struct snd_usb_audio_quirk[]){
{
.ifnum = 0,
.type = QUIRK_IGNORE_INTERFACE,
.type = QUIRK_AUDIO_STANDARD_MIXER,
},
{
.ifnum = 1,
@@ -2955,16 +2904,40 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.iface = 1,
.altsetting = 1,
.altset_idx = 1,
.attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
.attributes = 0x4,
.endpoint = 0x02,
.ep_attr = 0x01,
.rates = SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000,
.rate_min = 44100,
.ep_attr = USB_ENDPOINT_XFER_ISOC |
USB_ENDPOINT_SYNC_SYNC,
.maxpacksize = 0x130,
.rates = SNDRV_PCM_RATE_48000,
.rate_min = 48000,
.rate_max = 48000,
.nr_rates = 2,
.nr_rates = 1,
.rate_table = (unsigned int[]) {
44100, 48000
48000
}
}
},
{
.ifnum = 1,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = &(const struct audioformat) {
.formats = SNDRV_PCM_FMTBIT_S24_3BE,
.channels = 2,
.iface = 1,
.altsetting = 1,
.altset_idx = 1,
.attributes = 0x4,
.endpoint = 0x81,
.ep_attr = USB_ENDPOINT_XFER_ISOC |
USB_ENDPOINT_SYNC_ASYNC,
.maxpacksize = 0x130,
.rates = SNDRV_PCM_RATE_48000,
.rate_min = 48000,
.rate_max = 48000,
.nr_rates = 1,
.rate_table = (unsigned int[]) {
48000
}
}
},
@@ -2972,7 +2945,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.ifnum = -1
}
}
}
},
@@ -3201,6 +3173,46 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
{
/*
* ZOOM R16/24 in audio interface mode.
* Mixer descriptors are garbage, further quirks will be needed
* to make any of it functional, thus disabled for now.
* Playback stream appears to start and run fine but no sound
* is produced, so also disabled for now.
*/
USB_DEVICE(0x1686, 0x00dd),
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
.data = (const struct snd_usb_audio_quirk[]) {
{
/* Mixer */
.ifnum = 0,
.type = QUIRK_IGNORE_INTERFACE,
},
{
/* Playback */
.ifnum = 1,
.type = QUIRK_IGNORE_INTERFACE,
},
{
/* Capture */
.ifnum = 2,
.type = QUIRK_AUDIO_STANDARD_INTERFACE,
},
{
/* Midi */
.ifnum = 3,
.type = QUIRK_MIDI_STANDARD_INTERFACE
},
{
.ifnum = -1
},
}
}
},
{
/*
* Some USB MIDI devices don't have an audio control interface,

查看文件

@@ -43,12 +43,13 @@
static int create_composite_quirk(struct snd_usb_audio *chip,
struct usb_interface *iface,
struct usb_driver *driver,
const struct snd_usb_audio_quirk *quirk)
const struct snd_usb_audio_quirk *quirk_comp)
{
int probed_ifnum = get_iface_desc(iface->altsetting)->bInterfaceNumber;
const struct snd_usb_audio_quirk *quirk;
int err;
for (quirk = quirk->data; quirk->ifnum >= 0; ++quirk) {
for (quirk = quirk_comp->data; quirk->ifnum >= 0; ++quirk) {
iface = usb_ifnum_to_if(chip->dev, quirk->ifnum);
if (!iface)
continue;
@@ -58,9 +59,17 @@ static int create_composite_quirk(struct snd_usb_audio *chip,
err = snd_usb_create_quirk(chip, iface, driver, quirk);
if (err < 0)
return err;
if (quirk->ifnum != probed_ifnum)
}
for (quirk = quirk_comp->data; quirk->ifnum >= 0; ++quirk) {
iface = usb_ifnum_to_if(chip->dev, quirk->ifnum);
if (!iface)
continue;
if (quirk->ifnum != probed_ifnum &&
!usb_interface_claimed(iface))
usb_driver_claim_interface(driver, iface, (void *)-1L);
}
return 0;
}
@@ -1102,6 +1111,44 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
}
}
/* Marantz/Denon USB DACs need a vendor cmd to switch
* between PCM and native DSD mode
*/
int snd_usb_select_mode_quirk(struct snd_usb_substream *subs,
struct audioformat *fmt)
{
struct usb_device *dev = subs->dev;
int err;
switch (subs->stream->chip->usb_id) {
case USB_ID(0x154e, 0x3005): /* Marantz HD-DAC1 */
case USB_ID(0x154e, 0x3006): /* Marantz SA-14S1 */
/* First switch to alt set 0, otherwise the mode switch cmd
* will not be accepted by the DAC
*/
err = usb_set_interface(dev, fmt->iface, 0);
if (err < 0)
return err;
mdelay(20); /* Delay needed after setting the interface */
switch (fmt->altsetting) {
case 2: /* DSD mode requested */
case 1: /* PCM mode requested */
err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 0,
USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
fmt->altsetting - 1, 1, NULL, 0);
if (err < 0)
return err;
break;
}
mdelay(20);
}
return 0;
}
void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep)
{
/*
@@ -1160,6 +1207,14 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
break;
}
}
/* Zoom R16/24 needs a tiny delay here, otherwise requests like
* get/set frequency return as failed despite actually succeeding.
*/
if ((le16_to_cpu(dev->descriptor.idVendor) == 0x1686) &&
(le16_to_cpu(dev->descriptor.idProduct) == 0x00dd) &&
(requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
mdelay(1);
}
/*
@@ -1204,5 +1259,16 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
break;
}
/* Denon/Marantz devices with USB DAC functionality */
switch (chip->usb_id) {
case USB_ID(0x154e, 0x3005): /* Marantz HD-DAC1 */
case USB_ID(0x154e, 0x3006): /* Marantz SA-14S1 */
if (fp->altsetting == 2)
return SNDRV_PCM_FMTBIT_DSD_U32_BE;
break;
default:
break;
}
return 0;
}

查看文件

@@ -31,6 +31,9 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
__u8 request, __u8 requesttype, __u16 value,
__u16 index, void *data, __u16 size);
int snd_usb_select_mode_quirk(struct snd_usb_substream *subs,
struct audioformat *fmt);
u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
struct audioformat *fp,
unsigned int sample_bytes);

查看文件

@@ -272,13 +272,8 @@ static void usX2Y_clients_stop(struct usX2Ydev *usX2Y)
for (s = 0; s < 4; s++) {
struct snd_usX2Y_substream *subs = usX2Y->subs[s];
if (subs) {
if (atomic_read(&subs->state) >= state_PRERUNNING) {
unsigned long flags;
snd_pcm_stream_lock_irqsave(subs->pcm_substream, flags);
snd_pcm_stop(subs->pcm_substream, SNDRV_PCM_STATE_XRUN);
snd_pcm_stream_unlock_irqrestore(subs->pcm_substream, flags);
}
if (atomic_read(&subs->state) >= state_PRERUNNING)
snd_pcm_stop_xrun(subs->pcm_substream);
for (u = 0; u < NRURBS; u++) {
struct urb *urb = subs->urb[u];
if (NULL != urb)