aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb
diff options
context:
space:
mode:
authorEldad Zack <eldad@fogrefinery.com>2012-11-28 17:55:35 -0500
committerTakashi Iwai <tiwai@suse.de>2012-11-29 02:43:12 -0500
commit9f814105926cbeb003b1684cd5564612bccfe45c (patch)
tree3a80076a31997d21dcfa20a21a58747bf6675173 /sound/usb
parent28acb12014fb0c3e1edfdab1b1e3e266cf651550 (diff)
ALSA: usb-audio: add control index offset
Currently, channel IDs exceeding 31 (0x1f) cannot be used. The channel ID is derived from the cmask. Extending cmask to a 64-bit type would only allow it to go up to 63 (0x3f). Some devices have channel IDs exceeding that as well. To address that, add an offset to the mixer element which is then accounted for in the UAC set/get functions. Signed-off-by: Eldad Zack <eldad@fogrefinery.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/mixer.c4
-rw-r--r--sound/usb/mixer.h1
-rw-r--r--sound/usb/mixer_quirks.c16
3 files changed, 20 insertions, 1 deletions
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 298070e8f2d4..b0fc6ae037a2 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -382,6 +382,8 @@ error:
382 382
383static int get_ctl_value(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) 383static int get_ctl_value(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret)
384{ 384{
385 validx += cval->idx_off;
386
385 return (cval->mixer->protocol == UAC_VERSION_1) ? 387 return (cval->mixer->protocol == UAC_VERSION_1) ?
386 get_ctl_value_v1(cval, request, validx, value_ret) : 388 get_ctl_value_v1(cval, request, validx, value_ret) :
387 get_ctl_value_v2(cval, request, validx, value_ret); 389 get_ctl_value_v2(cval, request, validx, value_ret);
@@ -432,6 +434,8 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
432 unsigned char buf[2]; 434 unsigned char buf[2];
433 int idx = 0, val_len, err, timeout = 10; 435 int idx = 0, val_len, err, timeout = 10;
434 436
437 validx += cval->idx_off;
438
435 if (cval->mixer->protocol == UAC_VERSION_1) { 439 if (cval->mixer->protocol == UAC_VERSION_1) {
436 val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; 440 val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
437 } else { /* UAC_VERSION_2 */ 441 } else { /* UAC_VERSION_2 */
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
index a7f3d45a8acf..aab80df201bd 100644
--- a/sound/usb/mixer.h
+++ b/sound/usb/mixer.h
@@ -43,6 +43,7 @@ struct usb_mixer_elem_info {
43 unsigned int id; 43 unsigned int id;
44 unsigned int control; /* CS or ICN (high byte) */ 44 unsigned int control; /* CS or ICN (high byte) */
45 unsigned int cmask; /* channel mask bitmap: 0 = master */ 45 unsigned int cmask; /* channel mask bitmap: 0 = master */
46 unsigned int idx_off; /* Control index offset */
46 unsigned int ch_readonly; 47 unsigned int ch_readonly;
47 unsigned int master_readonly; 48 unsigned int master_readonly;
48 int channels; 49 int channels;
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index ae2b71435220..4199b97e76a1 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -63,11 +63,12 @@ static void usb_mixer_elem_free(struct snd_kcontrol *kctl)
63 * Since there doesn't seem to be a devices that needs a multichannel 63 * Since there doesn't seem to be a devices that needs a multichannel
64 * version, we keep it mono for simplicity. 64 * version, we keep it mono for simplicity.
65 */ 65 */
66static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer, 66static int snd_create_std_mono_ctl_offset(struct usb_mixer_interface *mixer,
67 unsigned int unitid, 67 unsigned int unitid,
68 unsigned int control, 68 unsigned int control,
69 unsigned int cmask, 69 unsigned int cmask,
70 int val_type, 70 int val_type,
71 unsigned int idx_off,
71 const char *name, 72 const char *name,
72 snd_kcontrol_tlv_rw_t *tlv_callback) 73 snd_kcontrol_tlv_rw_t *tlv_callback)
73{ 74{
@@ -85,6 +86,7 @@ static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer,
85 cval->channels = 1; 86 cval->channels = 1;
86 cval->control = control; 87 cval->control = control;
87 cval->cmask = cmask; 88 cval->cmask = cmask;
89 cval->idx_off = idx_off;
88 90
89 /* get_min_max() is called only for integer volumes later, 91 /* get_min_max() is called only for integer volumes later,
90 * so provide a short-cut for booleans */ 92 * so provide a short-cut for booleans */
@@ -120,6 +122,18 @@ static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer,
120 return 0; 122 return 0;
121} 123}
122 124
125static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer,
126 unsigned int unitid,
127 unsigned int control,
128 unsigned int cmask,
129 int val_type,
130 const char *name,
131 snd_kcontrol_tlv_rw_t *tlv_callback)
132{
133 return snd_create_std_mono_ctl_offset(mixer, unitid, control, cmask,
134 val_type, 0 /* Offset */, name, tlv_callback);
135}
136
123/* 137/*
124 * Create a set of standard UAC controls from a table 138 * Create a set of standard UAC controls from a table
125 */ 139 */