Merge branch 'topic/usb-audio' into for-linus
This commit is contained in:
@ -66,6 +66,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, 0x3048), 2, 2, 6, 6, 2, 0x6e91 }, /* Toshiba SB0500 */
|
||||
};
|
||||
|
||||
struct usb_mixer_interface {
|
||||
@ -109,6 +110,8 @@ struct mixer_build {
|
||||
const struct usbmix_selector_map *selector_map;
|
||||
};
|
||||
|
||||
#define MAX_CHANNELS 10 /* max logical channels */
|
||||
|
||||
struct usb_mixer_elem_info {
|
||||
struct usb_mixer_interface *mixer;
|
||||
struct usb_mixer_elem_info *next_id_elem; /* list of controls with same id */
|
||||
@ -119,6 +122,8 @@ struct usb_mixer_elem_info {
|
||||
int channels;
|
||||
int val_type;
|
||||
int min, max, res;
|
||||
int cached;
|
||||
int cache_val[MAX_CHANNELS];
|
||||
u8 initialized;
|
||||
};
|
||||
|
||||
@ -180,8 +185,6 @@ enum {
|
||||
USB_PROC_DCR_RELEASE = 6,
|
||||
};
|
||||
|
||||
#define MAX_CHANNELS 10 /* max logical channels */
|
||||
|
||||
|
||||
/*
|
||||
* manual mapping of mixer names
|
||||
@ -218,7 +221,10 @@ static int check_ignored_ctl(struct mixer_build *state, int unitid, int control)
|
||||
for (p = state->map; p->id; p++) {
|
||||
if (p->id == unitid && ! p->name &&
|
||||
(! control || ! p->control || control == p->control)) {
|
||||
// printk("ignored control %d:%d\n", unitid, control);
|
||||
/*
|
||||
printk(KERN_DEBUG "ignored control %d:%d\n",
|
||||
unitid, control);
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -375,11 +381,35 @@ static int get_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int *
|
||||
}
|
||||
|
||||
/* channel = 0: master, 1 = first channel */
|
||||
static inline int get_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int *value)
|
||||
static inline int get_cur_mix_raw(struct usb_mixer_elem_info *cval,
|
||||
int channel, int *value)
|
||||
{
|
||||
return get_ctl_value(cval, GET_CUR, (cval->control << 8) | channel, value);
|
||||
}
|
||||
|
||||
static int get_cur_mix_value(struct usb_mixer_elem_info *cval,
|
||||
int channel, int index, int *value)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (cval->cached & (1 << channel)) {
|
||||
*value = cval->cache_val[index];
|
||||
return 0;
|
||||
}
|
||||
err = get_cur_mix_raw(cval, channel, value);
|
||||
if (err < 0) {
|
||||
if (!cval->mixer->ignore_ctl_error)
|
||||
snd_printd(KERN_ERR "cannot get current value for "
|
||||
"control %d ch %d: err = %d\n",
|
||||
cval->control, channel, err);
|
||||
return err;
|
||||
}
|
||||
cval->cached |= 1 << channel;
|
||||
cval->cache_val[index] = *value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* set a mixer value
|
||||
*/
|
||||
@ -411,9 +441,17 @@ static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int v
|
||||
return set_ctl_value(cval, SET_CUR, validx, value);
|
||||
}
|
||||
|
||||
static inline int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int value)
|
||||
static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel,
|
||||
int index, int value)
|
||||
{
|
||||
return set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel, value);
|
||||
int err;
|
||||
err = set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel,
|
||||
value);
|
||||
if (err < 0)
|
||||
return err;
|
||||
cval->cached |= 1 << channel;
|
||||
cval->cache_val[index] = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -717,7 +755,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
|
||||
if (cval->min + cval->res < cval->max) {
|
||||
int last_valid_res = cval->res;
|
||||
int saved, test, check;
|
||||
get_cur_mix_value(cval, minchn, &saved);
|
||||
get_cur_mix_raw(cval, minchn, &saved);
|
||||
for (;;) {
|
||||
test = saved;
|
||||
if (test < cval->max)
|
||||
@ -725,8 +763,8 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
|
||||
else
|
||||
test -= cval->res;
|
||||
if (test < cval->min || test > cval->max ||
|
||||
set_cur_mix_value(cval, minchn, test) ||
|
||||
get_cur_mix_value(cval, minchn, &check)) {
|
||||
set_cur_mix_value(cval, minchn, 0, test) ||
|
||||
get_cur_mix_raw(cval, minchn, &check)) {
|
||||
cval->res = last_valid_res;
|
||||
break;
|
||||
}
|
||||
@ -734,7 +772,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
|
||||
break;
|
||||
cval->res *= 2;
|
||||
}
|
||||
set_cur_mix_value(cval, minchn, saved);
|
||||
set_cur_mix_value(cval, minchn, 0, saved);
|
||||
}
|
||||
|
||||
cval->initialized = 1;
|
||||
@ -774,35 +812,25 @@ static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e
|
||||
struct usb_mixer_elem_info *cval = kcontrol->private_data;
|
||||
int c, cnt, val, err;
|
||||
|
||||
ucontrol->value.integer.value[0] = cval->min;
|
||||
if (cval->cmask) {
|
||||
cnt = 0;
|
||||
for (c = 0; c < MAX_CHANNELS; c++) {
|
||||
if (cval->cmask & (1 << c)) {
|
||||
err = get_cur_mix_value(cval, c + 1, &val);
|
||||
if (err < 0) {
|
||||
if (cval->mixer->ignore_ctl_error) {
|
||||
ucontrol->value.integer.value[0] = cval->min;
|
||||
return 0;
|
||||
}
|
||||
snd_printd(KERN_ERR "cannot get current value for control %d ch %d: err = %d\n", cval->control, c + 1, err);
|
||||
return err;
|
||||
}
|
||||
val = get_relative_value(cval, val);
|
||||
ucontrol->value.integer.value[cnt] = val;
|
||||
cnt++;
|
||||
}
|
||||
if (!(cval->cmask & (1 << c)))
|
||||
continue;
|
||||
err = get_cur_mix_value(cval, c + 1, cnt, &val);
|
||||
if (err < 0)
|
||||
return cval->mixer->ignore_ctl_error ? 0 : err;
|
||||
val = get_relative_value(cval, val);
|
||||
ucontrol->value.integer.value[cnt] = val;
|
||||
cnt++;
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
/* master channel */
|
||||
err = get_cur_mix_value(cval, 0, &val);
|
||||
if (err < 0) {
|
||||
if (cval->mixer->ignore_ctl_error) {
|
||||
ucontrol->value.integer.value[0] = cval->min;
|
||||
return 0;
|
||||
}
|
||||
snd_printd(KERN_ERR "cannot get current value for control %d master ch: err = %d\n", cval->control, err);
|
||||
return err;
|
||||
}
|
||||
err = get_cur_mix_value(cval, 0, 0, &val);
|
||||
if (err < 0)
|
||||
return cval->mixer->ignore_ctl_error ? 0 : err;
|
||||
val = get_relative_value(cval, val);
|
||||
ucontrol->value.integer.value[0] = val;
|
||||
}
|
||||
@ -819,34 +847,28 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
|
||||
if (cval->cmask) {
|
||||
cnt = 0;
|
||||
for (c = 0; c < MAX_CHANNELS; c++) {
|
||||
if (cval->cmask & (1 << c)) {
|
||||
err = get_cur_mix_value(cval, c + 1, &oval);
|
||||
if (err < 0) {
|
||||
if (cval->mixer->ignore_ctl_error)
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
val = ucontrol->value.integer.value[cnt];
|
||||
val = get_abs_value(cval, val);
|
||||
if (oval != val) {
|
||||
set_cur_mix_value(cval, c + 1, val);
|
||||
changed = 1;
|
||||
}
|
||||
get_cur_mix_value(cval, c + 1, &val);
|
||||
cnt++;
|
||||
if (!(cval->cmask & (1 << c)))
|
||||
continue;
|
||||
err = get_cur_mix_value(cval, c + 1, cnt, &oval);
|
||||
if (err < 0)
|
||||
return cval->mixer->ignore_ctl_error ? 0 : 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);
|
||||
changed = 1;
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
} else {
|
||||
/* master channel */
|
||||
err = get_cur_mix_value(cval, 0, &oval);
|
||||
if (err < 0 && cval->mixer->ignore_ctl_error)
|
||||
return 0;
|
||||
err = get_cur_mix_value(cval, 0, 0, &oval);
|
||||
if (err < 0)
|
||||
return err;
|
||||
return cval->mixer->ignore_ctl_error ? 0 : err;
|
||||
val = ucontrol->value.integer.value[0];
|
||||
val = get_abs_value(cval, val);
|
||||
if (val != oval) {
|
||||
set_cur_mix_value(cval, 0, val);
|
||||
set_cur_mix_value(cval, 0, 0, val);
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
@ -1705,7 +1727,8 @@ static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer,
|
||||
break;
|
||||
/* live24ext: 4 = line-in jack */
|
||||
case 3: /* hp-out jack (may actuate Mute) */
|
||||
if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040))
|
||||
if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
|
||||
mixer->chip->usb_id == USB_ID(0x041e, 0x3048))
|
||||
snd_usb_mixer_notify_id(mixer, mixer->rc_cfg->mute_mixer_id);
|
||||
break;
|
||||
default:
|
||||
@ -1936,8 +1959,9 @@ static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer)
|
||||
int i, err;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) {
|
||||
if (i > 1 && /* Live24ext has 2 LEDs only */
|
||||
mixer->chip->usb_id == USB_ID(0x041e, 0x3040))
|
||||
if (i > 1 && /* Live24ext has 2 LEDs only */
|
||||
(mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
|
||||
mixer->chip->usb_id == USB_ID(0x041e, 0x3048)))
|
||||
break;
|
||||
err = snd_ctl_add(mixer->chip->card,
|
||||
snd_ctl_new1(&snd_audigy2nx_controls[i], mixer));
|
||||
@ -1974,7 +1998,8 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry,
|
||||
snd_iprintf(buffer, "%s jacks\n\n", mixer->chip->card->shortname);
|
||||
if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020))
|
||||
jacks = jacks_audigy2nx;
|
||||
else if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040))
|
||||
else if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
|
||||
mixer->chip->usb_id == USB_ID(0x041e, 0x3048))
|
||||
jacks = jacks_live24ext;
|
||||
else
|
||||
return;
|
||||
@ -2024,7 +2049,8 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
|
||||
goto _error;
|
||||
|
||||
if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020) ||
|
||||
mixer->chip->usb_id == USB_ID(0x041e, 0x3040)) {
|
||||
mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
|
||||
mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) {
|
||||
struct snd_info_entry *entry;
|
||||
|
||||
if ((err = snd_audigy2nx_controls_create(mixer)) < 0)
|
||||
|
Reference in New Issue
Block a user