diff options
author | Torsten Schenk <torsten.schenk@zoho.com> | 2012-02-22 09:21:23 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2012-02-22 09:51:16 -0500 |
commit | d97c735a1047fa06165e55da32154cf0e6b9419c (patch) | |
tree | 859d77d248e5d15442dd7282be51dc522a1ad74b /sound/usb | |
parent | f90ffbf3c68a69714b4273b203d4deb5ae81d8d6 (diff) |
ALSA: snd-usb-6fire: add mute control for analog outputs
Add a mute control for every analog output channel.
Signed-off-by: Torsten Schenk <torsten.schenk@zoho.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb')
-rw-r--r-- | sound/usb/6fire/control.c | 95 | ||||
-rw-r--r-- | sound/usb/6fire/control.h | 1 |
2 files changed, 96 insertions, 0 deletions
diff --git a/sound/usb/6fire/control.c b/sound/usb/6fire/control.c index c22cc29e33d7..a2bbf48c6413 100644 --- a/sound/usb/6fire/control.c +++ b/sound/usb/6fire/control.c | |||
@@ -74,6 +74,14 @@ static void usb6fire_control_output_vol_update(struct control_runtime *rt) | |||
74 | } | 74 | } |
75 | } | 75 | } |
76 | 76 | ||
77 | static void usb6fire_control_output_mute_update(struct control_runtime *rt) | ||
78 | { | ||
79 | struct comm_runtime *comm_rt = rt->chip->comm; | ||
80 | |||
81 | if (comm_rt) | ||
82 | comm_rt->write8(comm_rt, 0x12, 0x0e, ~rt->output_mute); | ||
83 | } | ||
84 | |||
77 | static void usb6fire_control_line_phono_update(struct control_runtime *rt) | 85 | static void usb6fire_control_line_phono_update(struct control_runtime *rt) |
78 | { | 86 | { |
79 | struct comm_runtime *comm_rt = rt->chip->comm; | 87 | struct comm_runtime *comm_rt = rt->chip->comm; |
@@ -208,6 +216,51 @@ static int usb6fire_control_output_vol_get(struct snd_kcontrol *kcontrol, | |||
208 | return 0; | 216 | return 0; |
209 | } | 217 | } |
210 | 218 | ||
219 | static int usb6fire_control_output_mute_put(struct snd_kcontrol *kcontrol, | ||
220 | struct snd_ctl_elem_value *ucontrol) | ||
221 | { | ||
222 | struct control_runtime *rt = snd_kcontrol_chip(kcontrol); | ||
223 | unsigned int ch = kcontrol->private_value; | ||
224 | u8 old = rt->output_mute; | ||
225 | u8 value = 0; | ||
226 | |||
227 | if (ch > 4) { | ||
228 | snd_printk(KERN_ERR PREFIX "Invalid channel in volume control."); | ||
229 | return -EINVAL; | ||
230 | } | ||
231 | |||
232 | rt->output_mute &= ~(3 << ch); | ||
233 | if (ucontrol->value.integer.value[0]) | ||
234 | value |= 1; | ||
235 | if (ucontrol->value.integer.value[1]) | ||
236 | value |= 2; | ||
237 | rt->output_mute |= value << ch; | ||
238 | |||
239 | if (rt->output_mute != old) | ||
240 | usb6fire_control_output_mute_update(rt); | ||
241 | |||
242 | return rt->output_mute != old; | ||
243 | } | ||
244 | |||
245 | static int usb6fire_control_output_mute_get(struct snd_kcontrol *kcontrol, | ||
246 | struct snd_ctl_elem_value *ucontrol) | ||
247 | { | ||
248 | struct control_runtime *rt = snd_kcontrol_chip(kcontrol); | ||
249 | unsigned int ch = kcontrol->private_value; | ||
250 | u8 value = rt->output_mute >> ch; | ||
251 | |||
252 | if (ch > 4) { | ||
253 | snd_printk(KERN_ERR PREFIX "Invalid channel in volume control."); | ||
254 | return -EINVAL; | ||
255 | } | ||
256 | |||
257 | ucontrol->value.integer.value[0] = 1 & value; | ||
258 | value >>= 1; | ||
259 | ucontrol->value.integer.value[1] = 1 & value; | ||
260 | |||
261 | return 0; | ||
262 | } | ||
263 | |||
211 | static int usb6fire_control_line_phono_info(struct snd_kcontrol *kcontrol, | 264 | static int usb6fire_control_line_phono_info(struct snd_kcontrol *kcontrol, |
212 | struct snd_ctl_elem_info *uinfo) | 265 | struct snd_ctl_elem_info *uinfo) |
213 | { | 266 | { |
@@ -339,6 +392,40 @@ static struct __devinitdata snd_kcontrol_new vol_elements[] = { | |||
339 | {} | 392 | {} |
340 | }; | 393 | }; |
341 | 394 | ||
395 | static struct __devinitdata snd_kcontrol_new mute_elements[] = { | ||
396 | { | ||
397 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
398 | .name = "Analog Playback Switch", | ||
399 | .index = 0, | ||
400 | .private_value = 0, | ||
401 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
402 | .info = snd_ctl_boolean_stereo_info, | ||
403 | .get = usb6fire_control_output_mute_get, | ||
404 | .put = usb6fire_control_output_mute_put, | ||
405 | }, | ||
406 | { | ||
407 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
408 | .name = "Analog Playback Switch", | ||
409 | .index = 1, | ||
410 | .private_value = 2, | ||
411 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
412 | .info = snd_ctl_boolean_stereo_info, | ||
413 | .get = usb6fire_control_output_mute_get, | ||
414 | .put = usb6fire_control_output_mute_put, | ||
415 | }, | ||
416 | { | ||
417 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
418 | .name = "Analog Playback Switch", | ||
419 | .index = 2, | ||
420 | .private_value = 4, | ||
421 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
422 | .info = snd_ctl_boolean_stereo_info, | ||
423 | .get = usb6fire_control_output_mute_get, | ||
424 | .put = usb6fire_control_output_mute_put, | ||
425 | }, | ||
426 | {} | ||
427 | }; | ||
428 | |||
342 | static struct __devinitdata snd_kcontrol_new elements[] = { | 429 | static struct __devinitdata snd_kcontrol_new elements[] = { |
343 | { | 430 | { |
344 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 431 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -430,13 +517,21 @@ int __devinit usb6fire_control_init(struct sfire_chip *chip) | |||
430 | usb6fire_control_opt_coax_update(rt); | 517 | usb6fire_control_opt_coax_update(rt); |
431 | usb6fire_control_line_phono_update(rt); | 518 | usb6fire_control_line_phono_update(rt); |
432 | usb6fire_control_output_vol_update(rt); | 519 | usb6fire_control_output_vol_update(rt); |
520 | usb6fire_control_output_mute_update(rt); | ||
433 | usb6fire_control_streaming_update(rt); | 521 | usb6fire_control_streaming_update(rt); |
434 | 522 | ||
435 | ret = usb6fire_control_add_virtual(rt, chip->card, | 523 | ret = usb6fire_control_add_virtual(rt, chip->card, |
436 | "Master Playback Volume", vol_elements); | 524 | "Master Playback Volume", vol_elements); |
437 | if (ret) { | 525 | if (ret) { |
526 | snd_printk(KERN_ERR PREFIX "cannot add control.\n"); | ||
438 | kfree(rt); | 527 | kfree(rt); |
528 | return ret; | ||
529 | } | ||
530 | ret = usb6fire_control_add_virtual(rt, chip->card, | ||
531 | "Master Playback Switch", mute_elements); | ||
532 | if (ret) { | ||
439 | snd_printk(KERN_ERR PREFIX "cannot add control.\n"); | 533 | snd_printk(KERN_ERR PREFIX "cannot add control.\n"); |
534 | kfree(rt); | ||
440 | return ret; | 535 | return ret; |
441 | } | 536 | } |
442 | 537 | ||
diff --git a/sound/usb/6fire/control.h b/sound/usb/6fire/control.h index ce024113c98f..9f9eb647bc6b 100644 --- a/sound/usb/6fire/control.h +++ b/sound/usb/6fire/control.h | |||
@@ -45,6 +45,7 @@ struct control_runtime { | |||
45 | bool usb_streaming; | 45 | bool usb_streaming; |
46 | u8 output_vol[6]; | 46 | u8 output_vol[6]; |
47 | u8 ovol_updated; | 47 | u8 ovol_updated; |
48 | u8 output_mute; | ||
48 | }; | 49 | }; |
49 | 50 | ||
50 | int __devinit usb6fire_control_init(struct sfire_chip *chip); | 51 | int __devinit usb6fire_control_init(struct sfire_chip *chip); |